From 56c41a614a5cb5ddcbbc6235c622d162d81d0220 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 26 Feb 2020 17:38:50 +0300 Subject: [PATCH 001/600] Remove CommentsPage component --- .../Online/TestSceneCommentsContainer.cs | 3 +- .../Visual/Online/TestSceneCommentsPage.cs | 232 ------------------ .../Overlays/Comments/CommentsContainer.cs | 134 ++++++++-- osu.Game/Overlays/Comments/CommentsPage.cs | 161 ------------ 4 files changed, 112 insertions(+), 418 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs delete mode 100644 osu.Game/Overlays/Comments/CommentsPage.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index ece280659c..b9938ab25b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -27,8 +27,7 @@ namespace osu.Game.Tests.Visual.Online typeof(OverlaySortTabControl<>), typeof(ShowChildrenButton), typeof(DeletedCommentsCounter), - typeof(VotePill), - typeof(CommentsPage), + typeof(VotePill) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs deleted file mode 100644 index a28a0107a1..0000000000 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs +++ /dev/null @@ -1,232 +0,0 @@ -// 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 osu.Game.Overlays.Comments; -using osu.Game.Overlays; -using osu.Framework.Allocation; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Users; -using osu.Game.Graphics.UserInterface; -using osu.Framework.Bindables; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics; -using osuTK; -using JetBrains.Annotations; -using NUnit.Framework; - -namespace osu.Game.Tests.Visual.Online -{ - public class TestSceneCommentsPage : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(DrawableComment), - typeof(CommentsPage), - }; - - [Cached] - private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); - - private readonly BindableBool showDeleted = new BindableBool(); - private readonly Container content; - - private TestCommentsPage commentsPage; - - public TestSceneCommentsPage() - { - Add(new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), - Children = new Drawable[] - { - new Container - { - AutoSizeAxes = Axes.Y, - Width = 200, - Child = new OsuCheckbox - { - Current = showDeleted, - LabelText = @"Show Deleted" - } - }, - content = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } - } - }); - } - - [Test] - public void TestAppendDuplicatedComment() - { - AddStep("Create page", () => createPage(getCommentBundle())); - AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10); - AddStep("Append existing comment", () => commentsPage?.AppendComments(getCommentSubBundle())); - AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10); - } - - [Test] - public void TestEmptyBundle() - { - AddStep("Create page", () => createPage(getEmptyCommentBundle())); - AddAssert("Dictionary length is 0", () => commentsPage?.DictionaryLength == 0); - } - - private void createPage(CommentBundle commentBundle) - { - commentsPage = null; - content.Clear(); - content.Add(commentsPage = new TestCommentsPage(commentBundle) - { - ShowDeleted = { BindTarget = showDeleted } - }); - } - - private CommentBundle getEmptyCommentBundle() => new CommentBundle - { - Comments = new List(), - }; - - private CommentBundle getCommentBundle() => new CommentBundle - { - Comments = new List - { - new Comment - { - Id = 1, - Message = "Simple test comment", - LegacyName = "TestUser1", - CreatedAt = DateTimeOffset.Now, - VotesCount = 5 - }, - new Comment - { - Id = 100, - Message = "This comment has \"load replies\" button because it has unloaded replies", - LegacyName = "TestUser1100", - CreatedAt = DateTimeOffset.Now, - VotesCount = 5, - RepliesCount = 2, - }, - new Comment - { - Id = 111, - Message = "This comment has \"Show More\" button because it has unloaded replies, but some of them are loaded", - LegacyName = "TestUser1111", - CreatedAt = DateTimeOffset.Now, - VotesCount = 100, - RepliesCount = 2, - }, - new Comment - { - Id = 112, - ParentId = 111, - Message = "I'm here to make my parent work", - LegacyName = "someone", - CreatedAt = DateTimeOffset.Now, - VotesCount = 2, - }, - new Comment - { - Id = 2, - Message = "This comment has been deleted :( but visible for admins", - LegacyName = "TestUser2", - CreatedAt = DateTimeOffset.Now, - DeletedAt = DateTimeOffset.Now, - VotesCount = 5 - }, - new Comment - { - Id = 3, - Message = "This comment is a top level", - LegacyName = "TestUser3", - CreatedAt = DateTimeOffset.Now, - RepliesCount = 2, - }, - new Comment - { - Id = 4, - ParentId = 3, - Message = "And this is a reply", - RepliesCount = 1, - LegacyName = "TestUser1", - CreatedAt = DateTimeOffset.Now, - }, - new Comment - { - Id = 15, - ParentId = 4, - Message = "Reply to reply", - LegacyName = "TestUser1", - CreatedAt = DateTimeOffset.Now, - }, - new Comment - { - Id = 6, - ParentId = 3, - LegacyName = "TestUser11515", - CreatedAt = DateTimeOffset.Now, - DeletedAt = DateTimeOffset.Now, - }, - new Comment - { - Id = 5, - Message = "This comment is voted and edited", - LegacyName = "BigBrainUser", - CreatedAt = DateTimeOffset.Now, - EditedAt = DateTimeOffset.Now, - VotesCount = 1000, - EditedById = 1, - } - }, - IncludedComments = new List(), - UserVotes = new List - { - 5 - }, - Users = new List - { - new User - { - Id = 1, - Username = "Good_Admin" - } - }, - }; - - private CommentBundle getCommentSubBundle() => new CommentBundle - { - Comments = new List - { - new Comment - { - Id = 1, - Message = "Simple test comment", - LegacyName = "TestUser1", - CreatedAt = DateTimeOffset.Now, - VotesCount = 5 - }, - }, - IncludedComments = new List(), - }; - - private class TestCommentsPage : CommentsPage - { - public TestCommentsPage(CommentBundle commentBundle) - : base(commentBundle) - { - } - - public new void AppendComments([NotNull] CommentBundle bundle) => base.AppendComments(bundle); - - public int DictionaryLength => CommentDictionary.Count; - } - } -} diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 591a9dc86e..ef833b9345 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -9,10 +9,12 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osu.Game.Online.API.Requests.Responses; -using System.Threading; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Users; +using System.Collections.Generic; +using JetBrains.Annotations; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -30,7 +32,6 @@ namespace osu.Game.Overlays.Comments private IAPIProvider api { get; set; } private GetCommentsRequest request; - private CancellationTokenSource loadCancellation; private int currentPage; private FillFlowContainer content; @@ -151,9 +152,8 @@ namespace osu.Game.Overlays.Comments return; request?.Cancel(); - loadCancellation?.Cancel(); request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0); - request.Success += onSuccess; + request.Success += response => Schedule(() => onSuccess(response)); api.PerformAsync(request); } @@ -166,44 +166,132 @@ namespace osu.Game.Overlays.Comments content.Clear(); } + private readonly Dictionary commentDictionary = new Dictionary(); + private void onSuccess(CommentBundle response) { - loadCancellation = new CancellationTokenSource(); - - LoadComponentAsync(new CommentsPage(response) + if (!response.Comments.Any()) { - ShowDeleted = { BindTarget = ShowDeleted }, - Sort = { BindTarget = Sort }, - Type = { BindTarget = type }, - CommentableId = { BindTarget = id } - }, loaded => + content.Add(new NoCommentsPlaceholder()); + return; + } + else { - content.Add(loaded); + appendComments(response); deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); + } - if (response.HasMore) + if (response.HasMore) + { + int loadedTopLevelComments = 0; + content.Children.OfType().ForEach(p => loadedTopLevelComments++); + + moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; + moreButton.IsLoading = false; + } + else + { + moreButton.Hide(); + } + } + + /// + /// Appends retrieved comments to the subtree rooted of comments in this page. + /// + /// The bundle of comments to add. + private void appendComments([NotNull] CommentBundle bundle) + { + var orphaned = new List(); + + foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) + { + // Exclude possible duplicated comments. + if (commentDictionary.ContainsKey(comment.Id)) + continue; + + addNewComment(comment); + } + + // Comments whose parents were seen later than themselves can now be added. + foreach (var o in orphaned) + addNewComment(o); + + void addNewComment(Comment comment) + { + var drawableComment = getDrawableComment(comment); + + if (comment.ParentId == null) { - int loadedTopLevelComments = 0; - content.Children.OfType().ForEach(p => loadedTopLevelComments += p.Children.OfType().Count()); - - moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; - moreButton.IsLoading = false; + // Comments that have no parent are added as top-level comments to the flow. + content.Add(drawableComment); + } + else if (commentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable)) + { + // The comment's parent has already been seen, so the parent<-> child links can be added. + comment.ParentComment = parentDrawable.Comment; + parentDrawable.Replies.Add(drawableComment); } else { - moreButton.Hide(); + // The comment's parent has not been seen yet, so keep it orphaned for the time being. This can occur if the comments arrive out of order. + // Since this comment has now been seen, any further children can be added to it without being orphaned themselves. + orphaned.Add(comment); } + } + } - commentCounter.Current.Value = response.Total; - }, loadCancellation.Token); + private DrawableComment getDrawableComment(Comment comment) + { + if (commentDictionary.TryGetValue(comment.Id, out var existing)) + return existing; + + return commentDictionary[comment.Id] = new DrawableComment(comment) + { + ShowDeleted = { BindTarget = ShowDeleted }, + Sort = { BindTarget = Sort }, + RepliesRequested = onCommentRepliesRequested + }; + } + + private void onCommentRepliesRequested(DrawableComment drawableComment, int page) + { + var request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, page, drawableComment.Comment.Id); + + request.Success += response => Schedule(() => appendComments(response)); + + api.PerformAsync(request); } protected override void Dispose(bool isDisposing) { request?.Cancel(); - loadCancellation?.Cancel(); base.Dispose(isDisposing); } + + private class NoCommentsPlaceholder : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Height = 80; + RelativeSizeAxes = Axes.X; + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background4 + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 50 }, + Text = @"No comments yet." + } + }); + } + } } } diff --git a/osu.Game/Overlays/Comments/CommentsPage.cs b/osu.Game/Overlays/Comments/CommentsPage.cs deleted file mode 100644 index 9b146b0a7d..0000000000 --- a/osu.Game/Overlays/Comments/CommentsPage.cs +++ /dev/null @@ -1,161 +0,0 @@ -// 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.Allocation; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics; -using osu.Framework.Bindables; -using osu.Game.Online.API.Requests.Responses; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Sprites; -using System.Linq; -using osu.Game.Online.API.Requests; -using osu.Game.Online.API; -using System.Collections.Generic; -using JetBrains.Annotations; - -namespace osu.Game.Overlays.Comments -{ - public class CommentsPage : CompositeDrawable - { - public readonly BindableBool ShowDeleted = new BindableBool(); - public readonly Bindable Sort = new Bindable(); - public readonly Bindable Type = new Bindable(); - public readonly BindableLong CommentableId = new BindableLong(); - - [Resolved] - private IAPIProvider api { get; set; } - - private readonly CommentBundle commentBundle; - private FillFlowContainer flow; - - public CommentsPage(CommentBundle commentBundle) - { - this.commentBundle = commentBundle; - } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - AddRangeInternal(new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background5 - }, - flow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - } - }); - - if (!commentBundle.Comments.Any()) - { - flow.Add(new NoCommentsPlaceholder()); - return; - } - - AppendComments(commentBundle); - } - - private DrawableComment getDrawableComment(Comment comment) - { - if (CommentDictionary.TryGetValue(comment.Id, out var existing)) - return existing; - - return CommentDictionary[comment.Id] = new DrawableComment(comment) - { - ShowDeleted = { BindTarget = ShowDeleted }, - Sort = { BindTarget = Sort }, - RepliesRequested = onCommentRepliesRequested - }; - } - - private void onCommentRepliesRequested(DrawableComment drawableComment, int page) - { - var request = new GetCommentsRequest(CommentableId.Value, Type.Value, Sort.Value, page, drawableComment.Comment.Id); - - request.Success += response => Schedule(() => AppendComments(response)); - - api.PerformAsync(request); - } - - protected readonly Dictionary CommentDictionary = new Dictionary(); - - /// - /// Appends retrieved comments to the subtree rooted of comments in this page. - /// - /// The bundle of comments to add. - protected void AppendComments([NotNull] CommentBundle bundle) - { - var orphaned = new List(); - - foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) - { - // Exclude possible duplicated comments. - if (CommentDictionary.ContainsKey(comment.Id)) - continue; - - addNewComment(comment); - } - - // Comments whose parents were seen later than themselves can now be added. - foreach (var o in orphaned) - addNewComment(o); - - void addNewComment(Comment comment) - { - var drawableComment = getDrawableComment(comment); - - if (comment.ParentId == null) - { - // Comments that have no parent are added as top-level comments to the flow. - flow.Add(drawableComment); - } - else if (CommentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable)) - { - // The comment's parent has already been seen, so the parent<-> child links can be added. - comment.ParentComment = parentDrawable.Comment; - parentDrawable.Replies.Add(drawableComment); - } - else - { - // The comment's parent has not been seen yet, so keep it orphaned for the time being. This can occur if the comments arrive out of order. - // Since this comment has now been seen, any further children can be added to it without being orphaned themselves. - orphaned.Add(comment); - } - } - } - - private class NoCommentsPlaceholder : CompositeDrawable - { - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - Height = 80; - RelativeSizeAxes = Axes.X; - AddRangeInternal(new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background4 - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Left = 50 }, - Text = @"No comments yet." - } - }); - } - } - } -} From ae4f5cdf371fbc3d8be399e47bb440ce2cb0f39f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 26 Feb 2020 18:00:48 +0300 Subject: [PATCH 002/600] Add async loading support --- .../Overlays/Comments/CommentsContainer.cs | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index ef833b9345..988b8cc4d4 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osu.Game.Online.API.Requests.Responses; +using System.Threading; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Users; @@ -32,6 +33,7 @@ namespace osu.Game.Overlays.Comments private IAPIProvider api { get; set; } private GetCommentsRequest request; + private CancellationTokenSource loadCancellation; private int currentPage; private FillFlowContainer content; @@ -152,6 +154,7 @@ namespace osu.Game.Overlays.Comments return; request?.Cancel(); + loadCancellation?.Cancel(); request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0); request.Success += response => Schedule(() => onSuccess(response)); api.PerformAsync(request); @@ -164,6 +167,7 @@ namespace osu.Game.Overlays.Comments moreButton.Show(); moreButton.IsLoading = true; content.Clear(); + commentDictionary.Clear(); } private readonly Dictionary commentDictionary = new Dictionary(); @@ -173,26 +177,33 @@ namespace osu.Game.Overlays.Comments if (!response.Comments.Any()) { content.Add(new NoCommentsPlaceholder()); + moreButton.Hide(); return; } else { - appendComments(response); + var topLevelComments = appendComments(response); - deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); - } + LoadComponentsAsync(topLevelComments, loaded => + { + content.AddRange(loaded); - if (response.HasMore) - { - int loadedTopLevelComments = 0; - content.Children.OfType().ForEach(p => loadedTopLevelComments++); + deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); + commentCounter.Current.Value = response.Total; - moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; - moreButton.IsLoading = false; - } - else - { - moreButton.Hide(); + if (response.HasMore) + { + int loadedTopLevelComments = 0; + content.Children.OfType().ForEach(p => loadedTopLevelComments++); + + moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; + moreButton.IsLoading = false; + } + else + { + moreButton.Hide(); + } + }, (loadCancellation = new CancellationTokenSource()).Token); } } @@ -200,8 +211,9 @@ namespace osu.Game.Overlays.Comments /// Appends retrieved comments to the subtree rooted of comments in this page. /// /// The bundle of comments to add. - private void appendComments([NotNull] CommentBundle bundle) + private List appendComments([NotNull] CommentBundle bundle) { + var topLevelComments = new List(); var orphaned = new List(); foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) @@ -217,6 +229,8 @@ namespace osu.Game.Overlays.Comments foreach (var o in orphaned) addNewComment(o); + return topLevelComments; + void addNewComment(Comment comment) { var drawableComment = getDrawableComment(comment); @@ -224,7 +238,7 @@ namespace osu.Game.Overlays.Comments if (comment.ParentId == null) { // Comments that have no parent are added as top-level comments to the flow. - content.Add(drawableComment); + topLevelComments.Add(drawableComment); } else if (commentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable)) { @@ -266,6 +280,7 @@ namespace osu.Game.Overlays.Comments protected override void Dispose(bool isDisposing) { request?.Cancel(); + loadCancellation?.Cancel(); base.Dispose(isDisposing); } From de10e502782f337c1c37c3b88ac96a98f3eb0091 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 26 Feb 2020 18:31:01 +0300 Subject: [PATCH 003/600] Add test scene to test local comment bundles --- .../TestSceneOfflineCommentsContainer.cs | 177 ++++++++++++++++++ .../Overlays/Comments/CommentsContainer.cs | 16 +- 2 files changed, 185 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs new file mode 100644 index 0000000000..b69cc46bb8 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -0,0 +1,177 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Overlays.Comments; +using osu.Game.Overlays; +using osu.Framework.Allocation; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneOfflineCommentsContainer : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(CommentsContainer), + typeof(CommentsHeader), + typeof(DrawableComment), + typeof(HeaderButton), + typeof(OverlaySortTabControl<>), + typeof(ShowChildrenButton), + typeof(DeletedCommentsCounter), + typeof(VotePill) + }; + + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + + private TestCommentsContainer comments; + + [SetUp] + public void SetUp() => Schedule(() => + { + Clear(); + Add(new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = comments = new TestCommentsContainer() + }); + }); + + [Test] + public void TestLocalCommentBundle() + { + AddStep("Add comment bundle", () => comments.ShowComments(getCommentBundle())); + AddStep("Add empty comment bundle", () => comments.ShowComments(getEmptyCommentBundle())); + } + + private CommentBundle getEmptyCommentBundle() => new CommentBundle + { + Comments = new List(), + }; + + private CommentBundle getCommentBundle() => new CommentBundle + { + Comments = new List + { + new Comment + { + Id = 1, + Message = "Simple test comment", + LegacyName = "TestUser1", + CreatedAt = DateTimeOffset.Now, + VotesCount = 5 + }, + new Comment + { + Id = 100, + Message = "This comment has \"load replies\" button because it has unloaded replies", + LegacyName = "TestUser1100", + CreatedAt = DateTimeOffset.Now, + VotesCount = 5, + RepliesCount = 2, + }, + new Comment + { + Id = 111, + Message = "This comment has \"Show More\" button because it has unloaded replies, but some of them are loaded", + LegacyName = "TestUser1111", + CreatedAt = DateTimeOffset.Now, + VotesCount = 100, + RepliesCount = 2, + }, + new Comment + { + Id = 112, + ParentId = 111, + Message = "I'm here to make my parent work", + LegacyName = "someone", + CreatedAt = DateTimeOffset.Now, + VotesCount = 2, + }, + new Comment + { + Id = 2, + Message = "This comment has been deleted :( but visible for admins", + LegacyName = "TestUser2", + CreatedAt = DateTimeOffset.Now, + DeletedAt = DateTimeOffset.Now, + VotesCount = 5 + }, + new Comment + { + Id = 3, + Message = "This comment is a top level", + LegacyName = "TestUser3", + CreatedAt = DateTimeOffset.Now, + RepliesCount = 2, + }, + new Comment + { + Id = 4, + ParentId = 3, + Message = "And this is a reply", + RepliesCount = 1, + LegacyName = "TestUser1", + CreatedAt = DateTimeOffset.Now, + }, + new Comment + { + Id = 15, + ParentId = 4, + Message = "Reply to reply", + LegacyName = "TestUser1", + CreatedAt = DateTimeOffset.Now, + }, + new Comment + { + Id = 6, + ParentId = 3, + LegacyName = "TestUser11515", + CreatedAt = DateTimeOffset.Now, + DeletedAt = DateTimeOffset.Now, + }, + new Comment + { + Id = 5, + Message = "This comment is voted and edited", + LegacyName = "BigBrainUser", + CreatedAt = DateTimeOffset.Now, + EditedAt = DateTimeOffset.Now, + VotesCount = 1000, + EditedById = 1, + } + }, + IncludedComments = new List(), + UserVotes = new List + { + 5 + }, + Users = new List + { + new User + { + Id = 1, + Username = "Good_Admin" + } + }, + Total = 10 + }; + + private class TestCommentsContainer : CommentsContainer + { + public void ShowComments(CommentBundle bundle) + { + CommentCounter.Current.Value = 0; + ClearComments(); + OnSuccess(bundle); + } + } + } +} diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 988b8cc4d4..00aa74f9ac 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Comments private FillFlowContainer content; private DeletedCommentsCounter deletedCommentsCounter; private CommentsShowMoreButton moreButton; - private TotalCommentsCounter commentCounter; + protected TotalCommentsCounter CommentCounter; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Comments Direction = FillDirection.Vertical, Children = new Drawable[] { - commentCounter = new TotalCommentsCounter(), + CommentCounter = new TotalCommentsCounter(), new CommentsHeader { Sort = { BindTarget = Sort }, @@ -137,14 +137,14 @@ namespace osu.Game.Overlays.Comments return; // only reset when changing ID/type. other refetch ops are generally just changing sort order. - commentCounter.Current.Value = 0; + CommentCounter.Current.Value = 0; refetchComments(); } private void refetchComments() { - clearComments(); + ClearComments(); getComments(); } @@ -156,11 +156,11 @@ namespace osu.Game.Overlays.Comments request?.Cancel(); loadCancellation?.Cancel(); request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0); - request.Success += response => Schedule(() => onSuccess(response)); + request.Success += response => Schedule(() => OnSuccess(response)); api.PerformAsync(request); } - private void clearComments() + protected void ClearComments() { currentPage = 1; deletedCommentsCounter.Count.Value = 0; @@ -172,7 +172,7 @@ namespace osu.Game.Overlays.Comments private readonly Dictionary commentDictionary = new Dictionary(); - private void onSuccess(CommentBundle response) + protected void OnSuccess(CommentBundle response) { if (!response.Comments.Any()) { @@ -189,7 +189,7 @@ namespace osu.Game.Overlays.Comments content.AddRange(loaded); deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); - commentCounter.Current.Value = response.Total; + CommentCounter.Current.Value = response.Total; if (response.HasMore) { From 1166d3d69624bad7e6ed645d5a5ac1c53201a92e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 26 Feb 2020 18:52:58 +0300 Subject: [PATCH 004/600] CI fixes --- .../Overlays/Comments/CommentsContainer.cs | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 00aa74f9ac..da2cdbc335 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -180,31 +180,29 @@ namespace osu.Game.Overlays.Comments moreButton.Hide(); return; } - else + + var topLevelComments = appendComments(response); + + LoadComponentsAsync(topLevelComments, loaded => { - var topLevelComments = appendComments(response); + content.AddRange(loaded); - LoadComponentsAsync(topLevelComments, loaded => + deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); + CommentCounter.Current.Value = response.Total; + + if (response.HasMore) { - content.AddRange(loaded); + int loadedTopLevelComments = 0; + content.Children.OfType().ForEach(p => loadedTopLevelComments++); - deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); - CommentCounter.Current.Value = response.Total; - - if (response.HasMore) - { - int loadedTopLevelComments = 0; - content.Children.OfType().ForEach(p => loadedTopLevelComments++); - - moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; - moreButton.IsLoading = false; - } - else - { - moreButton.Hide(); - } - }, (loadCancellation = new CancellationTokenSource()).Token); - } + moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; + moreButton.IsLoading = false; + } + else + { + moreButton.Hide(); + } + }, (loadCancellation = new CancellationTokenSource()).Token); } /// @@ -270,11 +268,11 @@ namespace osu.Game.Overlays.Comments private void onCommentRepliesRequested(DrawableComment drawableComment, int page) { - var request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, page, drawableComment.Comment.Id); + var req = new GetCommentsRequest(id.Value, type.Value, Sort.Value, page, drawableComment.Comment.Id); - request.Success += response => Schedule(() => appendComments(response)); + req.Success += response => Schedule(() => appendComments(response)); - api.PerformAsync(request); + api.PerformAsync(req); } protected override void Dispose(bool isDisposing) From 638d0601451c88872c727baf5c9cc653fcb5b7ec Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 26 Feb 2020 18:55:43 +0300 Subject: [PATCH 005/600] Fix incorrect character on RepliesButton --- 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 cb9e32f1ad..46f600615a 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -384,7 +384,7 @@ namespace osu.Game.Overlays.Comments protected override void OnExpandedChanged(ValueChangedEvent expanded) { - text.Text = $@"{(expanded.NewValue ? "[+]" : "[-]")} replies ({count})"; + text.Text = $@"{(expanded.NewValue ? "[-]" : "[+]")} replies ({count})"; } } From ddb494efb39d154d0dfae81fbd488395bbd5a16c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 27 Feb 2020 01:38:21 +0300 Subject: [PATCH 006/600] Add back regression test --- .../TestSceneOfflineCommentsContainer.cs | 29 +++++++++++++++++++ .../Overlays/Comments/CommentsContainer.cs | 18 ++++++------ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index b69cc46bb8..4040f36ef8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -51,6 +51,15 @@ namespace osu.Game.Tests.Visual.Online AddStep("Add empty comment bundle", () => comments.ShowComments(getEmptyCommentBundle())); } + [Test] + public void TestAppendDuplicatedComment() + { + AddStep("Add comment bundle", () => comments.ShowComments(getCommentBundle())); + AddUntilStep("Dictionary length is 10", () => comments.DictionaryLength == 10); + AddStep("Append existing comment", () => comments.AppendComments(getCommentSubBundle())); + AddAssert("Dictionary length is 10", () => comments.DictionaryLength == 10); + } + private CommentBundle getEmptyCommentBundle() => new CommentBundle { Comments = new List(), @@ -164,8 +173,28 @@ namespace osu.Game.Tests.Visual.Online Total = 10 }; + private CommentBundle getCommentSubBundle() => new CommentBundle + { + Comments = new List + { + new Comment + { + Id = 1, + Message = "Simple test comment", + LegacyName = "TestUser1", + CreatedAt = DateTimeOffset.Now, + VotesCount = 5 + }, + }, + IncludedComments = new List(), + }; + private class TestCommentsContainer : CommentsContainer { + public int DictionaryLength => CommentDictionary.Count; + + public new void AppendComments(CommentBundle bundle) => base.AppendComments(bundle); + public void ShowComments(CommentBundle bundle) { CommentCounter.Current.Value = 0; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index da2cdbc335..0381d73583 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -167,10 +167,10 @@ namespace osu.Game.Overlays.Comments moreButton.Show(); moreButton.IsLoading = true; content.Clear(); - commentDictionary.Clear(); + CommentDictionary.Clear(); } - private readonly Dictionary commentDictionary = new Dictionary(); + protected readonly Dictionary CommentDictionary = new Dictionary(); protected void OnSuccess(CommentBundle response) { @@ -181,7 +181,7 @@ namespace osu.Game.Overlays.Comments return; } - var topLevelComments = appendComments(response); + var topLevelComments = AppendComments(response); LoadComponentsAsync(topLevelComments, loaded => { @@ -209,7 +209,7 @@ namespace osu.Game.Overlays.Comments /// Appends retrieved comments to the subtree rooted of comments in this page. /// /// The bundle of comments to add. - private List appendComments([NotNull] CommentBundle bundle) + protected List AppendComments([NotNull] CommentBundle bundle) { var topLevelComments = new List(); var orphaned = new List(); @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Comments foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) { // Exclude possible duplicated comments. - if (commentDictionary.ContainsKey(comment.Id)) + if (CommentDictionary.ContainsKey(comment.Id)) continue; addNewComment(comment); @@ -238,7 +238,7 @@ namespace osu.Game.Overlays.Comments // Comments that have no parent are added as top-level comments to the flow. topLevelComments.Add(drawableComment); } - else if (commentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable)) + else if (CommentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable)) { // The comment's parent has already been seen, so the parent<-> child links can be added. comment.ParentComment = parentDrawable.Comment; @@ -255,10 +255,10 @@ namespace osu.Game.Overlays.Comments private DrawableComment getDrawableComment(Comment comment) { - if (commentDictionary.TryGetValue(comment.Id, out var existing)) + if (CommentDictionary.TryGetValue(comment.Id, out var existing)) return existing; - return commentDictionary[comment.Id] = new DrawableComment(comment) + return CommentDictionary[comment.Id] = new DrawableComment(comment) { ShowDeleted = { BindTarget = ShowDeleted }, Sort = { BindTarget = Sort }, @@ -270,7 +270,7 @@ namespace osu.Game.Overlays.Comments { var req = new GetCommentsRequest(id.Value, type.Value, Sort.Value, page, drawableComment.Comment.Id); - req.Success += response => Schedule(() => appendComments(response)); + req.Success += response => Schedule(() => AppendComments(response)); api.PerformAsync(req); } From 02fd85d485f232745df6296e30d56da410ec66cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 27 Feb 2020 01:42:55 +0300 Subject: [PATCH 007/600] CI fix --- .../TestSceneOfflineCommentsContainer.cs | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 4040f36ef8..1ba8bbf7c4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -11,6 +11,7 @@ using osu.Game.Overlays; using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; +using JetBrains.Annotations; namespace osu.Game.Tests.Visual.Online { @@ -44,13 +45,6 @@ namespace osu.Game.Tests.Visual.Online }); }); - [Test] - public void TestLocalCommentBundle() - { - AddStep("Add comment bundle", () => comments.ShowComments(getCommentBundle())); - AddStep("Add empty comment bundle", () => comments.ShowComments(getEmptyCommentBundle())); - } - [Test] public void TestAppendDuplicatedComment() { @@ -60,6 +54,13 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Dictionary length is 10", () => comments.DictionaryLength == 10); } + [Test] + public void TestLocalCommentBundle() + { + AddStep("Add comment bundle", () => comments.ShowComments(getCommentBundle())); + AddStep("Add empty comment bundle", () => comments.ShowComments(getEmptyCommentBundle())); + } + private CommentBundle getEmptyCommentBundle() => new CommentBundle { Comments = new List(), @@ -175,25 +176,25 @@ namespace osu.Game.Tests.Visual.Online private CommentBundle getCommentSubBundle() => new CommentBundle { - Comments = new List - { - new Comment - { - Id = 1, - Message = "Simple test comment", - LegacyName = "TestUser1", - CreatedAt = DateTimeOffset.Now, - VotesCount = 5 - }, - }, - IncludedComments = new List(), + Comments = new List + { + new Comment + { + Id = 1, + Message = "Simple test comment", + LegacyName = "TestUser1", + CreatedAt = DateTimeOffset.Now, + VotesCount = 5 + }, + }, + IncludedComments = new List(), }; private class TestCommentsContainer : CommentsContainer { - public int DictionaryLength => CommentDictionary.Count; + public new void AppendComments([NotNull] CommentBundle bundle) => base.AppendComments(bundle); - public new void AppendComments(CommentBundle bundle) => base.AppendComments(bundle); + public int DictionaryLength => CommentDictionary.Count; public void ShowComments(CommentBundle bundle) { From e2c495e8c28412d2d3fa2f530fc8409f516e54ce Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 27 Feb 2020 20:00:41 +0300 Subject: [PATCH 008/600] Move drawables loading to AppendComments() --- .../Overlays/Comments/CommentsContainer.cs | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 0381d73583..f7bf1e2b07 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -174,6 +174,8 @@ namespace osu.Game.Overlays.Comments protected void OnSuccess(CommentBundle response) { + CommentCounter.Current.Value = response.Total; + if (!response.Comments.Any()) { content.Add(new NoCommentsPlaceholder()); @@ -181,35 +183,14 @@ namespace osu.Game.Overlays.Comments return; } - var topLevelComments = AppendComments(response); - - LoadComponentsAsync(topLevelComments, loaded => - { - content.AddRange(loaded); - - deletedCommentsCounter.Count.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); - CommentCounter.Current.Value = response.Total; - - if (response.HasMore) - { - int loadedTopLevelComments = 0; - content.Children.OfType().ForEach(p => loadedTopLevelComments++); - - moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; - moreButton.IsLoading = false; - } - else - { - moreButton.Hide(); - } - }, (loadCancellation = new CancellationTokenSource()).Token); + AppendComments(response); } /// /// Appends retrieved comments to the subtree rooted of comments in this page. /// /// The bundle of comments to add. - protected List AppendComments([NotNull] CommentBundle bundle) + protected void AppendComments([NotNull] CommentBundle bundle) { var topLevelComments = new List(); var orphaned = new List(); @@ -227,7 +208,28 @@ namespace osu.Game.Overlays.Comments foreach (var o in orphaned) addNewComment(o); - return topLevelComments; + if (topLevelComments.Any()) + { + LoadComponentsAsync(topLevelComments, loaded => + { + content.AddRange(loaded); + + deletedCommentsCounter.Count.Value += topLevelComments.Select(d => d.Comment).Count(c => c.IsDeleted && c.IsTopLevel); + + if (bundle.HasMore) + { + int loadedTopLevelComments = 0; + content.Children.OfType().ForEach(p => loadedTopLevelComments++); + + moreButton.Current.Value = bundle.TopLevelCount - loadedTopLevelComments; + moreButton.IsLoading = false; + } + else + { + moreButton.Hide(); + } + }, (loadCancellation = new CancellationTokenSource()).Token); + } void addNewComment(Comment comment) { From 560a0174dff62173c2288a390a0324b9ddedfaf2 Mon Sep 17 00:00:00 2001 From: PercyDan54 <50285552+PercyDan54@users.noreply.github.com> Date: Fri, 18 Dec 2020 17:49:17 +0800 Subject: [PATCH 009/600] Make auto restart toggleable --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index ae71041a64..466fdccfb7 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -20,9 +22,11 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + [SettingSource("Restart on fail", "Automatically restarts when failed.")] + public BindableBool Restart { get; } = new BindableBool(); public bool PerformFail() => true; - public bool RestartOnFail => true; + public bool RestartOnFail => Restart.Value; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { From 2babb7ecb0b122555a339809ce158b748f0e3295 Mon Sep 17 00:00:00 2001 From: PercyDan54 <50285552+PercyDan54@users.noreply.github.com> Date: Fri, 18 Dec 2020 18:33:38 +0800 Subject: [PATCH 010/600] Fix CI --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 466fdccfb7..925844275b 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Restart on fail", "Automatically restarts when failed.")] public BindableBool Restart { get; } = new BindableBool(); + public bool PerformFail() => true; public bool RestartOnFail => Restart.Value; From 33615646bd6ff48c2894d73c34a8e66fcb8eef84 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 6 Jul 2021 18:10:40 +0900 Subject: [PATCH 011/600] Rename DrawableRoom test scene --- .../{TestSceneRoomStatus.cs => TestSceneDrawableRoom.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/Multiplayer/{TestSceneRoomStatus.cs => TestSceneDrawableRoom.cs} (95%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs similarity index 95% rename from osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index cec40635f3..1231e0f7d0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -10,9 +10,9 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneRoomStatus : OsuTestScene + public class TestSceneDrawableRoom : OsuTestScene { - public TestSceneRoomStatus() + public TestSceneDrawableRoom() { Child = new FillFlowContainer { From 1a832a4e6bb3dfd64587a7872fa841318a20006f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 6 Jul 2021 18:23:37 +0900 Subject: [PATCH 012/600] Add clickability to test --- .../Multiplayer/TestSceneDrawableRoom.cs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 1231e0f7d0..532ce6790f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Screens.OnlinePlay.Lounge.Components; @@ -20,32 +21,44 @@ namespace osu.Game.Tests.Visual.Multiplayer Width = 0.5f, Children = new Drawable[] { - new DrawableRoom(new Room + createDrawableRoom(new Room { Name = { Value = "Open - ending in 1 day" }, Status = { Value = new RoomStatusOpen() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) } - }) { MatchingFilter = true }, - new DrawableRoom(new Room + }), + createDrawableRoom(new Room { Name = { Value = "Playing - ending in 1 day" }, Status = { Value = new RoomStatusPlaying() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) } - }) { MatchingFilter = true }, - new DrawableRoom(new Room + }), + createDrawableRoom(new Room { Name = { Value = "Ended" }, Status = { Value = new RoomStatusEnded() }, EndDate = { Value = DateTimeOffset.Now } - }) { MatchingFilter = true }, - new DrawableRoom(new Room + }), + createDrawableRoom(new Room { Name = { Value = "Open" }, Status = { Value = new RoomStatusOpen() }, Category = { Value = RoomCategory.Realtime } - }) { MatchingFilter = true }, + }), } }; } + + private DrawableRoom createDrawableRoom(Room room) + { + var drawableRoom = new DrawableRoom(room) + { + MatchingFilter = true + }; + + drawableRoom.Action = () => drawableRoom.State = drawableRoom.State == SelectionState.Selected ? SelectionState.NotSelected : SelectionState.Selected; + + return drawableRoom; + } } } From c50e3fd31778c3ac476742d6e5897d586980c42b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 6 Jul 2021 18:24:06 +0900 Subject: [PATCH 013/600] Clean up selection box construction --- .../Lounge/Components/DrawableRoom.cs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 35782c6104..14fd715b69 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public event Action StateChanged; - private readonly Box selectionBox; + private Box selectionBox; [Resolved(canBeNull: true)] private OnlinePlayScreen parentScreen { get; set; } @@ -55,14 +55,18 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components get => state; set { - if (value == state) return; + if (value == state) + return; state = value; - if (state == SelectionState.Selected) - selectionBox.FadeIn(transition_duration); - else - selectionBox.FadeOut(transition_duration); + if (selectionBox != null) + { + if (state == SelectionState.Selected) + selectionBox.FadeIn(transition_duration); + else + selectionBox.FadeOut(transition_duration); + } StateChanged?.Invoke(State); } @@ -99,13 +103,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Height = height + SELECTION_BORDER_WIDTH * 2; CornerRadius = corner_radius + SELECTION_BORDER_WIDTH / 2; Masking = true; - - // create selectionBox here so State can be set before being loaded - selectionBox = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - }; } [BackgroundDependencyLoader] @@ -118,7 +115,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new StatusColouredContainer(transition_duration) { RelativeSizeAxes = Axes.Both, - Child = selectionBox + Child = selectionBox = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = state == SelectionState.Selected ? 1 : 0, + } }, new Container { From 14b6949456b2f7d7278839c9e40bb7a8b49956c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 6 Jul 2021 18:50:05 +0900 Subject: [PATCH 014/600] Shorten room status messages --- osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs | 2 +- osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs | 2 +- osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs index c852f86f6b..01f3ae368b 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.Rooms.RoomStatuses { public class RoomStatusEnded : RoomStatus { - public override string Message => @"Ended"; + public override string Message => "Ended"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.YellowDarker; } } diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs index 4f7f0d6f5d..686d4f4033 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.Rooms.RoomStatuses { public class RoomStatusOpen : RoomStatus { - public override string Message => @"Welcoming Players"; + public override string Message => "Open"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight; } } diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs index f04f1b23af..83f1acf52a 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.Rooms.RoomStatuses { public class RoomStatusPlaying : RoomStatus { - public override string Message => @"Now Playing"; + public override string Message => "Playing"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple; } } From 2ddfa15a80d0c6ea11c2fdb0d8499557e21565f8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 6 Jul 2021 18:50:27 +0900 Subject: [PATCH 015/600] Redesign RoomStatusInfo --- .../OnlinePlay/Components/RoomStatusInfo.cs | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs b/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs index bcc256bcff..900dea1e8c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs @@ -4,12 +4,16 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Components { @@ -23,26 +27,28 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - StatusPart statusPart; + StatusPill statusPill; EndDatePart endDatePart; InternalChild = new FillFlowContainer { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(2), Children = new Drawable[] { - statusPart = new StatusPart + statusPill = new StatusPill(), + endDatePart = new EndDatePart { - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14) - }, - endDatePart = new EndDatePart { Font = OsuFont.GetFont(size: 14) } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12) + } } }; - statusPart.EndDate.BindTo(EndDate); - statusPart.Status.BindTo(Status); - statusPart.Availability.BindTo(Availability); + statusPill.EndDate.BindTo(EndDate); + statusPill.Status.BindTo(Status); endDatePart.EndDate.BindTo(EndDate); } @@ -80,37 +86,49 @@ namespace osu.Game.Screens.OnlinePlay.Components } } - private class StatusPart : EndDatePart + private class StatusPill : CompositeDrawable { + public readonly IBindable EndDate = new Bindable(); public readonly IBindable Status = new Bindable(); - public readonly IBindable Availability = new Bindable(); [Resolved] private OsuColour colours { get; set; } - public StatusPart() + private Drawable background; + private SpriteText statusText; + + [BackgroundDependencyLoader] + private void load() { - EndDate.BindValueChanged(_ => Format()); - Status.BindValueChanged(_ => Format()); - Availability.BindValueChanged(_ => Format()); + Size = new Vector2(60, 16); + + InternalChildren = new[] + { + background = new Circle { RelativeSizeAxes = Axes.Both }, + statusText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), + Colour = Color4.Black + } + }; } protected override void LoadComplete() { base.LoadComplete(); - Text = Format(); + EndDate.BindValueChanged(_ => updateDisplay()); + Status.BindValueChanged(_ => updateDisplay(), true); } - protected override string Format() + private void updateDisplay() { - if (!IsLoaded) - return string.Empty; + RoomStatus status = EndDate.Value < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); - RoomStatus status = Date < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); - - this.FadeColour(status.GetAppropriateColour(colours), 100); - return $"{Availability.Value.GetDescription()}, {status.Message}"; + background.FadeColour(status.GetAppropriateColour(colours), 100); + statusText.Text = status.Message; } } } From 8929aa0ca70ca397e5f05c3a0157e68af3136c68 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 6 Jul 2021 20:04:32 +0900 Subject: [PATCH 016/600] Initial redesign of DrawableRoom --- .../Multiplayer/TestSceneDrawableRoom.cs | 14 ++- .../Lounge/Components/DrawableRoom.cs | 104 ++++++++---------- 2 files changed, 57 insertions(+), 61 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 532ce6790f..7fef5aba4d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -8,6 +8,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { @@ -17,31 +18,34 @@ namespace osu.Game.Tests.Visual.Multiplayer { Child = new FillFlowContainer { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Width = 0.5f, + Size = new Vector2(0.9f), + Spacing = new Vector2(10), Children = new Drawable[] { createDrawableRoom(new Room { - Name = { Value = "Open - ending in 1 day" }, + Name = { Value = "Room name: Open - ending in 1 day" }, Status = { Value = new RoomStatusOpen() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) } }), createDrawableRoom(new Room { - Name = { Value = "Playing - ending in 1 day" }, + Name = { Value = "Room name: Playing - ending in 1 day" }, Status = { Value = new RoomStatusPlaying() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) } }), createDrawableRoom(new Room { - Name = { Value = "Ended" }, + Name = { Value = "Room name: Ended" }, Status = { Value = new RoomStatusEnded() }, EndDate = { Value = DateTimeOffset.Now } }), createDrawableRoom(new Room { - Name = { Value = "Open" }, + Name = { Value = "Room name: Open" }, Status = { Value = new RoomStatusOpen() }, Category = { Value = RoomCategory.Realtime } }), diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 14fd715b69..062b83b66c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; @@ -29,16 +30,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public class DrawableRoom : OsuClickableContainer, IStateful, IFilterable, IHasContextMenu { public const float SELECTION_BORDER_WIDTH = 4; - private const float corner_radius = 5; + private const float corner_radius = 10; private const float transition_duration = 60; - private const float content_padding = 10; - private const float height = 110; - private const float side_strip_width = 5; - private const float cover_width = 145; + private const float height = 100; public event Action StateChanged; - private Box selectionBox; + private Drawable selectionBox; [Resolved(canBeNull: true)] private OnlinePlayScreen parentScreen { get; set; } @@ -108,23 +106,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - float stripWidth = side_strip_width * (Room.Category.Value == RoomCategory.Spotlight ? 2 : 1); - Children = new Drawable[] { - new StatusColouredContainer(transition_duration) - { - RelativeSizeAxes = Axes.Both, - Child = selectionBox = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = state == SelectionState.Selected ? 1 : 0, - } - }, new Container { + Name = @"Room content", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(SELECTION_BORDER_WIDTH), Child = new Container { RelativeSizeAxes = Axes.Both, @@ -141,69 +128,74 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"212121"), - }, - new StatusColouredContainer(transition_duration) - { - RelativeSizeAxes = Axes.Y, - Width = stripWidth, - Child = new Box { RelativeSizeAxes = Axes.Both } + Colour = Color4Extensions.FromHex(@"#27302E"), }, new Container { - RelativeSizeAxes = Axes.Y, - Width = cover_width, - Masking = true, - Margin = new MarginPadding { Left = stripWidth }, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, Child = new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both } }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + }, new Container { + Name = @"Left details", RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Vertical = content_padding, - Left = stripWidth + cover_width + content_padding, - Right = content_padding, + Left = 20, + Vertical = 5 }, Children = new Drawable[] { - new FillFlowContainer + new RoomStatusInfo(), + new RoomName { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(5f), - Children = new Drawable[] - { - new RoomName { Font = OsuFont.GetFont(size: 18) }, - new ParticipantInfo(), - }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 28) }, new FillFlowContainer { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Children = new Drawable[] { - new RoomStatusInfo(), - new BeatmapTitle { TextSize = 14 }, - }, - }, - new ModeTypeInfo - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - }, - }, + new StarRatingRangeDisplay { Scale = new Vector2(0.85f) } + } + } + } }, }, }, }, + new StatusColouredContainer(transition_duration) + { + RelativeSizeAxes = Axes.Both, + Child = selectionBox = new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = state == SelectionState.Selected ? 1 : 0, + Masking = true, + CornerRadius = corner_radius, + BorderThickness = SELECTION_BORDER_WIDTH, + BorderColour = Color4.White, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + }, }; } From b4b0b862ef98c9ec300ba97a5a45d2b8de345a20 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 14:07:21 +0900 Subject: [PATCH 017/600] Adjust some layout --- .../OnlinePlay/Components/RoomStatusInfo.cs | 2 +- .../Lounge/Components/DrawableRoom.cs | 30 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs b/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs index 900dea1e8c..adb823c68a 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(2), + Spacing = new Vector2(4), Children = new Drawable[] { statusPill = new StatusPill(), diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 062b83b66c..8eb3f24b0d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Room = room; RelativeSizeAxes = Axes.X; - Height = height + SELECTION_BORDER_WIDTH * 2; + Height = height; CornerRadius = corner_radius + SELECTION_BORDER_WIDTH / 2; Masking = true; } @@ -125,11 +125,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), - }, new Container { Anchor = Anchor.CentreRight, @@ -138,10 +133,29 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components FillMode = FillMode.Fill, Child = new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both } }, - new Box + new GridContainer { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Relative, 0.2f) + }, + Content = new[] + { + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + }, + } + } }, new Container { From 185e36bf97f1cf670be5f56340c8e4f44ce90cb6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 15:11:07 +0900 Subject: [PATCH 018/600] Split pill display into abstract class --- .../OnlinePlay/Components/EndDateInfo.cs | 65 +++++++++ .../OnlinePlay/Components/RoomInfoPill.cs | 78 ++++++++++ .../OnlinePlay/Components/RoomStatusInfo.cs | 135 ------------------ .../OnlinePlay/Components/RoomStatusPill.cs | 54 +++++++ .../Lounge/Components/DrawableRoom.cs | 13 +- .../OnlinePlay/Lounge/Components/RoomInfo.cs | 4 +- 6 files changed, 211 insertions(+), 138 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs diff --git a/osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs b/osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs new file mode 100644 index 0000000000..3f93279461 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class EndDateInfo : OnlinePlayComposite + { + public EndDateInfo() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new EndDatePart + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), + EndDate = { BindTarget = EndDate } + }; + } + + private class EndDatePart : DrawableDate + { + public readonly IBindable EndDate = new Bindable(); + + public EndDatePart() + : base(DateTimeOffset.UtcNow) + { + EndDate.BindValueChanged(date => + { + // If null, set a very large future date to prevent unnecessary schedules. + Date = date.NewValue ?? DateTimeOffset.Now.AddYears(1); + }, true); + } + + protected override string Format() + { + if (EndDate.Value == null) + return string.Empty; + + var diffToNow = Date.Subtract(DateTimeOffset.Now); + + if (diffToNow.TotalSeconds < -5) + return $"Closed {base.Format()}"; + + if (diffToNow.TotalSeconds < 0) + return "Closed"; + + if (diffToNow.TotalSeconds < 5) + return "Closing soon"; + + return $"Closing {base.Format()}"; + } + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs b/osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs new file mode 100644 index 0000000000..55de75cbcd --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs @@ -0,0 +1,78 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osuTK.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + /// + /// Abstract class for "pill" components displayed as part of s. + /// + public abstract class RoomInfoPill : OnlinePlayComposite + { + private const float padding = 8; + + protected Drawable Background { get; private set; } + + protected RoomInfoPill() + { + AutoSizeAxes = Axes.X; + Height = 16; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Masking = true, + Children = new[] + { + Background = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.5f + }, + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = padding }, + Child = new GridContainer + { + AutoSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize, minSize: 80 - 2 * padding) + }, + Content = new[] + { + new[] + { + CreateContent().With(d => + { + d.Anchor = Anchor.Centre; + d.Origin = Anchor.Centre; + }) + } + } + } + } + } + }; + } + + protected abstract Drawable CreateContent(); + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs b/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs deleted file mode 100644 index adb823c68a..0000000000 --- a/osu.Game/Screens/OnlinePlay/Components/RoomStatusInfo.cs +++ /dev/null @@ -1,135 +0,0 @@ -// 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.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Online.Rooms; -using osu.Game.Online.Rooms.RoomStatuses; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Screens.OnlinePlay.Components -{ - public class RoomStatusInfo : OnlinePlayComposite - { - public RoomStatusInfo() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - StatusPill statusPill; - EndDatePart endDatePart; - - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), - Children = new Drawable[] - { - statusPill = new StatusPill(), - endDatePart = new EndDatePart - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12) - } - } - }; - - statusPill.EndDate.BindTo(EndDate); - statusPill.Status.BindTo(Status); - endDatePart.EndDate.BindTo(EndDate); - } - - private class EndDatePart : DrawableDate - { - public readonly IBindable EndDate = new Bindable(); - - public EndDatePart() - : base(DateTimeOffset.UtcNow) - { - EndDate.BindValueChanged(date => - { - // If null, set a very large future date to prevent unnecessary schedules. - Date = date.NewValue ?? DateTimeOffset.Now.AddYears(1); - }, true); - } - - protected override string Format() - { - if (EndDate.Value == null) - return string.Empty; - - var diffToNow = Date.Subtract(DateTimeOffset.Now); - - if (diffToNow.TotalSeconds < -5) - return $"Closed {base.Format()}"; - - if (diffToNow.TotalSeconds < 0) - return "Closed"; - - if (diffToNow.TotalSeconds < 5) - return "Closing soon"; - - return $"Closing {base.Format()}"; - } - } - - private class StatusPill : CompositeDrawable - { - public readonly IBindable EndDate = new Bindable(); - public readonly IBindable Status = new Bindable(); - - [Resolved] - private OsuColour colours { get; set; } - - private Drawable background; - private SpriteText statusText; - - [BackgroundDependencyLoader] - private void load() - { - Size = new Vector2(60, 16); - - InternalChildren = new[] - { - background = new Circle { RelativeSizeAxes = Axes.Both }, - statusText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), - Colour = Color4.Black - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - EndDate.BindValueChanged(_ => updateDisplay()); - Status.BindValueChanged(_ => updateDisplay(), true); - } - - private void updateDisplay() - { - RoomStatus status = EndDate.Value < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); - - background.FadeColour(status.GetAppropriateColour(colours), 100); - statusText.Text = status.Message; - } - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs new file mode 100644 index 0000000000..6d9e84d618 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs @@ -0,0 +1,54 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Rooms; +using osu.Game.Online.Rooms.RoomStatuses; +using osuTK.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + /// + /// A pill that displays the room's current status. + /// + public class RoomStatusPill : RoomInfoPill + { + [Resolved] + private OsuColour colours { get; set; } + + private bool firstDisplay = true; + private SpriteText statusText; + + protected override void LoadComplete() + { + base.LoadComplete(); + + EndDate.BindValueChanged(_ => updateDisplay()); + Status.BindValueChanged(_ => updateDisplay(), true); + } + + private void updateDisplay() + { + RoomStatus status = EndDate.Value < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); + + Background.Alpha = 1; + Background.FadeColour(status.GetAppropriateColour(colours), firstDisplay ? 0 : 100); + statusText.Text = status.Message; + + firstDisplay = false; + } + + protected override Drawable CreateContent() => statusText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), + Colour = Color4.Black + }; + } +} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 8eb3f24b0d..56b3cfa11c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -181,9 +181,20 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Origin = Anchor.BottomLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), Children = new Drawable[] { - new StarRatingRangeDisplay { Scale = new Vector2(0.85f) } + new PlaylistInfoPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new StarRatingRangeDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Scale = new Vector2(0.85f) + } } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs index a0a7f2dc28..819e19ad1e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components AutoSizeAxes = Axes.Y; RoomLocalUserInfo localUserInfo; - RoomStatusInfo statusInfo; + EndDateInfo statusInfo; ModeTypeInfo typeInfo; ParticipantInfo participantInfo; @@ -47,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components AutoSizeAxes = Axes.Y, Children = new Drawable[] { - statusInfo = new RoomStatusInfo(), + statusInfo = new EndDateInfo(), typeInfo = new ModeTypeInfo { Anchor = Anchor.BottomRight, From a8cbffa57ea5620fc18e8095d6a4e61ee780a9fc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 15:11:53 +0900 Subject: [PATCH 019/600] Add playlist count pill --- .../Components/PlaylistCountPill.cs | 39 +++++++++++++++++++ .../Lounge/Components/DrawableRoom.cs | 22 ++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs new file mode 100644 index 0000000000..7a4a638c2a --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs @@ -0,0 +1,39 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Specialized; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + /// + /// A pill that displays the playlist item count. + /// + public class PlaylistCountPill : RoomInfoPill + { + private OsuTextFlowContainer count; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Playlist.BindCollectionChanged(updateCount, true); + } + + private void updateCount(object sender, NotifyCollectionChangedEventArgs e) + { + count.Clear(); + count.AddText(Playlist.Count.ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + count.AddText(" Maps"); + } + + protected override Drawable CreateContent() => count = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } +} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 56b3cfa11c..b795b74e04 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -168,7 +168,25 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Children = new Drawable[] { - new RoomStatusInfo(), + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), + Children = new Drawable[] + { + new RoomStatusPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new EndDateInfo + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + } + }, new RoomName { Anchor = Anchor.CentreLeft, @@ -184,7 +202,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Spacing = new Vector2(4), Children = new Drawable[] { - new PlaylistInfoPill + new PlaylistCountPill { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, From 435b4b0e6ed4400125d1e6ce512b76237dc15ff9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 15:18:38 +0900 Subject: [PATCH 020/600] Remove pill inheritance --- .../{RoomInfoPill.cs => PillContainer.cs} | 27 +++++++------- .../Components/PlaylistCountPill.cs | 29 ++++++++++----- .../OnlinePlay/Components/RoomStatusPill.cs | 35 +++++++++++++------ 3 files changed, 57 insertions(+), 34 deletions(-) rename osu.Game/Screens/OnlinePlay/Components/{RoomInfoPill.cs => PillContainer.cs} (72%) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs b/osu.Game/Screens/OnlinePlay/Components/PillContainer.cs similarity index 72% rename from osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs rename to osu.Game/Screens/OnlinePlay/Components/PillContainer.cs index 55de75cbcd..10a14d16da 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomInfoPill.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PillContainer.cs @@ -5,21 +5,27 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Components { /// - /// Abstract class for "pill" components displayed as part of s. + /// Displays contents in a "pill". /// - public abstract class RoomInfoPill : OnlinePlayComposite + public class PillContainer : Container { private const float padding = 8; - protected Drawable Background { get; private set; } + public Drawable Background { get; private set; } - protected RoomInfoPill() + protected override Container Content { get; } = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + }; + + public PillContainer() { AutoSizeAxes = Axes.X; Height = 16; @@ -58,21 +64,12 @@ namespace osu.Game.Screens.OnlinePlay.Components }, Content = new[] { - new[] - { - CreateContent().With(d => - { - d.Anchor = Anchor.Centre; - d.Origin = Anchor.Centre; - }) - } + new[] { Content } } } } } }; } - - protected abstract Drawable CreateContent(); } } diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs index 7a4a638c2a..2d9e7c143c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Specialized; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -11,10 +12,29 @@ namespace osu.Game.Screens.OnlinePlay.Components /// /// A pill that displays the playlist item count. /// - public class PlaylistCountPill : RoomInfoPill + public class PlaylistCountPill : OnlinePlayComposite { private OsuTextFlowContainer count; + public PlaylistCountPill() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new PillContainer + { + Child = count = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + protected override void LoadComplete() { base.LoadComplete(); @@ -28,12 +48,5 @@ namespace osu.Game.Screens.OnlinePlay.Components count.AddText(Playlist.Count.ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); count.AddText(" Maps"); } - - protected override Drawable CreateContent() => count = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; } } diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs index 6d9e84d618..d18eb1bd94 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs @@ -16,14 +16,35 @@ namespace osu.Game.Screens.OnlinePlay.Components /// /// A pill that displays the room's current status. /// - public class RoomStatusPill : RoomInfoPill + public class RoomStatusPill : OnlinePlayComposite { [Resolved] private OsuColour colours { get; set; } private bool firstDisplay = true; + private PillContainer pill; private SpriteText statusText; + public RoomStatusPill() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = pill = new PillContainer + { + Child = statusText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), + Colour = Color4.Black + } + }; + } + protected override void LoadComplete() { base.LoadComplete(); @@ -36,19 +57,11 @@ namespace osu.Game.Screens.OnlinePlay.Components { RoomStatus status = EndDate.Value < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); - Background.Alpha = 1; - Background.FadeColour(status.GetAppropriateColour(colours), firstDisplay ? 0 : 100); + pill.Background.Alpha = 1; + pill.Background.FadeColour(status.GetAppropriateColour(colours), firstDisplay ? 0 : 100); statusText.Text = status.Message; firstDisplay = false; } - - protected override Drawable CreateContent() => statusText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), - Colour = Color4.Black - }; } } From 4ac812de86da47906a1be2c6d267eefed697ef10 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 16:15:26 +0900 Subject: [PATCH 021/600] Add rank range pill --- .../Multiplayer/TestSceneRankRangePill.cs | 67 ++++++++++++++++ .../OnlinePlay/Components/RankRangePill.cs | 77 +++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs new file mode 100644 index 0000000000..d6bbaabfa6 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -0,0 +1,67 @@ +// 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.Framework.Graphics; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneRankRangePill : MultiplayerTestScene + { + [SetUp] + public new void Setup() => Schedule(() => + { + Child = new RankRangePill + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + }); + + [Test] + public void TestSingleUser() + { + AddStep("add user", () => + { + Client.AddUser(new User + { + Id = 2, + Statistics = { GlobalRank = 1234 } + }); + + // Remove the local user so only the one above is displayed. + Client.RemoveUser(API.LocalUser.Value); + }); + } + + [Test] + public void TestMultipleUsers() + { + AddStep("add users", () => + { + Client.AddUser(new User + { + Id = 2, + Statistics = { GlobalRank = 1234 } + }); + + Client.AddUser(new User + { + Id = 3, + Statistics = { GlobalRank = 3333 } + }); + + Client.AddUser(new User + { + Id = 4, + Statistics = { GlobalRank = 4321 } + }); + + // Remove the local user so only the ones above are displayed. + Client.RemoveUser(API.LocalUser.Value); + }); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs b/osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs new file mode 100644 index 0000000000..d7bdf13f6a --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs @@ -0,0 +1,77 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Screens.OnlinePlay.Multiplayer; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class RankRangePill : MultiplayerRoomComposite + { + private OsuTextFlowContainer rankFlow; + + public RankRangePill() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new PillContainer + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(4), + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(8), + Icon = FontAwesome.Solid.User + }, + rankFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + } + } + } + }; + } + + protected override void OnRoomUpdated() + { + base.OnRoomUpdated(); + + rankFlow.Clear(); + + if (Room == null || Room.Users.All(u => u.User == null)) + { + rankFlow.AddText("-"); + return; + } + + rankFlow.AddText("#"); + rankFlow.AddText(Room.Users.Select(u => u.User?.Statistics.GlobalRank ?? 0).DefaultIfEmpty(0).Min().ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + + rankFlow.AddText(" - "); + + rankFlow.AddText("#"); + rankFlow.AddText(Room.Users.Select(u => u.User?.Statistics.GlobalRank ?? 0).DefaultIfEmpty(0).Max().ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + } + } +} From aba09b20a5ffea00f513566ca35c7ec07fb6ee94 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 16:28:22 +0900 Subject: [PATCH 022/600] Add host under room title --- .../Multiplayer/TestSceneDrawableRoom.cs | 21 +++++--- .../Lounge/Components/DrawableRoom.cs | 52 +++++++++++++++++-- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 7fef5aba4d..3d65b5afda 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -8,6 +8,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Users; using osuTK; namespace osu.Game.Tests.Visual.Multiplayer @@ -27,27 +28,31 @@ namespace osu.Game.Tests.Visual.Multiplayer { createDrawableRoom(new Room { - Name = { Value = "Room name: Open - ending in 1 day" }, + Name = { Value = "Room 1" }, Status = { Value = new RoomStatusOpen() }, - EndDate = { Value = DateTimeOffset.Now.AddDays(1) } + EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, + Host = { Value = new User { Username = "peppy", Id = 2 } } }), createDrawableRoom(new Room { - Name = { Value = "Room name: Playing - ending in 1 day" }, + Name = { Value = "Room 2" }, Status = { Value = new RoomStatusPlaying() }, - EndDate = { Value = DateTimeOffset.Now.AddDays(1) } + EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, + Host = { Value = new User { Username = "peppy", Id = 2 } } }), createDrawableRoom(new Room { - Name = { Value = "Room name: Ended" }, + Name = { Value = "Room 3" }, Status = { Value = new RoomStatusEnded() }, - EndDate = { Value = DateTimeOffset.Now } + EndDate = { Value = DateTimeOffset.Now }, + Host = { Value = new User { Username = "peppy", Id = 2 } } }), createDrawableRoom(new Room { - Name = { Value = "Room name: Open" }, + Name = { Value = "Room 4" }, Status = { Value = new RoomStatusOpen() }, - Category = { Value = RoomCategory.Realtime } + Category = { Value = RoomCategory.Realtime }, + Host = { Value = new User { Username = "peppy", Id = 2 } } }), } }; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index b795b74e04..4c7847cef0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -187,11 +187,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, } }, - new RoomName + new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 28) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new RoomNameText(), + new RoomHostText() + } }, new FillFlowContainer { @@ -262,11 +268,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected override bool ShouldBeConsideredForInput(Drawable child) => state == SelectionState.Selected; - private class RoomName : OsuSpriteText + private class RoomNameText : OsuSpriteText { [Resolved(typeof(Room), nameof(Online.Rooms.Room.Name))] private Bindable name { get; set; } + public RoomNameText() + { + Font = OsuFont.GetFont(size: 24); + } + [BackgroundDependencyLoader] private void load() { @@ -274,6 +285,41 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + private class RoomHostText : OnlinePlayComposite + { + private LinkFlowContainer hostText; + + public RoomHostText() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = hostText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + { + AutoSizeAxes = Axes.Both + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Host.BindValueChanged(host => + { + hostText.Clear(); + + if (host.NewValue != null) + { + hostText.AddText("hosted by "); + hostText.AddUserLink(host.NewValue); + } + }, true); + } + } + public MenuItem[] ContextMenuItems => new MenuItem[] { new OsuMenuItem("Create copy", MenuItemType.Standard, () => From c1fba3da6b49ed30abf2892fd63ab4eb2ff28fa7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Jul 2021 16:30:34 +0900 Subject: [PATCH 023/600] Add solid background --- .../Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 4c7847cef0..a1f90f2d89 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -125,6 +125,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Children = new Drawable[] { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, new Container { Anchor = Anchor.CentreRight, From 8c4a257742060336bb022edd6f379aa938467f05 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Jul 2021 15:10:44 +0900 Subject: [PATCH 024/600] Add recent participants --- .../Multiplayer/TestSceneDrawableRoom.cs | 20 +- .../TestSceneRecentParticipantsList.cs | 93 +++++++ .../Components/RecentParticipantsList.cs | 238 ++++++++++++++++++ .../Lounge/Components/DrawableRoom.cs | 38 +++ 4 files changed, 381 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 3d65b5afda..0970085c25 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -31,28 +32,24 @@ namespace osu.Game.Tests.Visual.Multiplayer Name = { Value = "Room 1" }, Status = { Value = new RoomStatusOpen() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, - Host = { Value = new User { Username = "peppy", Id = 2 } } }), createDrawableRoom(new Room { Name = { Value = "Room 2" }, Status = { Value = new RoomStatusPlaying() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, - Host = { Value = new User { Username = "peppy", Id = 2 } } }), createDrawableRoom(new Room { Name = { Value = "Room 3" }, Status = { Value = new RoomStatusEnded() }, EndDate = { Value = DateTimeOffset.Now }, - Host = { Value = new User { Username = "peppy", Id = 2 } } }), createDrawableRoom(new Room { Name = { Value = "Room 4" }, Status = { Value = new RoomStatusOpen() }, Category = { Value = RoomCategory.Realtime }, - Host = { Value = new User { Username = "peppy", Id = 2 } } }), } }; @@ -60,11 +57,18 @@ namespace osu.Game.Tests.Visual.Multiplayer private DrawableRoom createDrawableRoom(Room room) { - var drawableRoom = new DrawableRoom(room) - { - MatchingFilter = true - }; + room.Host.Value ??= new User { Username = "peppy", Id = 2 }; + if (room.RecentParticipants.Count == 0) + { + room.RecentParticipants.AddRange(Enumerable.Range(0, 20).Select(i => new User + { + Id = i, + Username = $"User {i}" + })); + } + + var drawableRoom = new DrawableRoom(room) { MatchingFilter = true }; drawableRoom.Action = () => drawableRoom.State = drawableRoom.State == SelectionState.Selected ? SelectionState.NotSelected : SelectionState.Selected; return drawableRoom; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs new file mode 100644 index 0000000000..ca8dc74759 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -0,0 +1,93 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Tests.Visual.OnlinePlay; +using osu.Game.Users; +using osu.Game.Users.Drawables; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneRecentParticipantsList : OnlinePlayTestScene + { + private RecentParticipantsList list; + + [SetUp] + public new void Setup() => Schedule(() => + { + SelectedRoom.Value = new Room { Name = { Value = "test room" } }; + + Child = list = new RecentParticipantsList + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + NumberOfAvatars = 3 + }; + }); + + [Test] + public void TestAvatarCount() + { + AddStep("add 50 users", () => + { + for (int i = 0; i < 50; i++) + { + SelectedRoom.Value.RecentParticipants.Add(new User + { + Id = i, + Username = $"User {i}" + }); + } + }); + + AddStep("set 3 avatars", () => list.NumberOfAvatars = 3); + AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("47 hidden users", () => list.ChildrenOfType().Single().Count == 47); + + AddStep("set 10 avatars", () => list.NumberOfAvatars = 10); + AddAssert("10 avatars displayed", () => list.ChildrenOfType().Count() == 10); + AddAssert("40 hidden users", () => list.ChildrenOfType().Single().Count == 40); + } + + [Test] + public void TestAddAndRemoveUsers() + { + AddStep("add 50 users", () => + { + for (int i = 0; i < 50; i++) + { + SelectedRoom.Value.RecentParticipants.Add(new User + { + Id = i, + Username = $"User {i}" + }); + } + }); + + AddStep("remove from start", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0)); + AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("46 hidden users", () => list.ChildrenOfType().Single().Count == 46); + + AddStep("remove from end", () => SelectedRoom.Value.RecentParticipants.RemoveAt(SelectedRoom.Value.RecentParticipants.Count - 1)); + AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("45 hidden users", () => list.ChildrenOfType().Single().Count == 45); + + AddRepeatStep("remove 45 users", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0), 45); + AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); + AddAssert("hidden users bubble hidden", () => list.ChildrenOfType().Single().Alpha < 0.5f); + + AddStep("remove another user", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0)); + AddAssert("2 avatars displayed", () => list.ChildrenOfType().Count() == 2); + AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); + + AddRepeatStep("remove the remaining two users", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0), 2); + AddAssert("0 avatars displayed", () => !list.ChildrenOfType().Any()); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs new file mode 100644 index 0000000000..d73387342a --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs @@ -0,0 +1,238 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Specialized; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; +using osu.Game.Users; +using osu.Game.Users.Drawables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class RecentParticipantsList : OnlinePlayComposite + { + private const float avatar_size = 36; + + private FillFlowContainer avatarFlow; + private HiddenUserCount hiddenUsers; + + public RecentParticipantsList() + { + AutoSizeAxes = Axes.X; + Height = 60; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + MaskingSmoothness = 2, + CornerRadius = 10, + Shear = new Vector2(0.2f, 0), + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#2E3835") + } + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), + Padding = new MarginPadding { Left = 8, Right = 16 }, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(16), + Icon = FontAwesome.Solid.User, + }, + avatarFlow = new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4) + }, + hiddenUsers = new HiddenUserCount + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + RecentParticipants.BindCollectionChanged(onParticipantsChanged, true); + } + + private int numberOfAvatars = 3; + + public int NumberOfAvatars + { + get => numberOfAvatars; + set + { + numberOfAvatars = value; + + if (LoadState < LoadState.Loaded) + return; + + // Reinitialising the list looks janky, but this is unlikely to be used in a setting where it's visible. + clearUsers(); + foreach (var u in RecentParticipants) + addUser(u); + } + } + + private void onParticipantsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (var added in e.NewItems.OfType()) + addUser(added); + break; + + case NotifyCollectionChangedAction.Remove: + foreach (var removed in e.OldItems.OfType()) + removeUser(removed); + break; + + case NotifyCollectionChangedAction.Reset: + clearUsers(); + break; + + case NotifyCollectionChangedAction.Replace: + case NotifyCollectionChangedAction.Move: + // Easiest is to just reinitialise the whole list. These are unlikely to ever be use cases. + clearUsers(); + foreach (var u in RecentParticipants) + addUser(u); + break; + } + } + + private void addUser(User user) + { + if (avatarFlow.Count < NumberOfAvatars) + avatarFlow.Add(new CircularAvatar { User = user }); + else + hiddenUsers.Count++; + } + + private void removeUser(User user) + { + if (avatarFlow.RemoveAll(a => a.User == user) > 0) + { + if (RecentParticipants.Count >= NumberOfAvatars) + { + avatarFlow.Add(new CircularAvatar { User = RecentParticipants.First(u => avatarFlow.All(a => a.User != u)) }); + hiddenUsers.Count--; + } + } + else + hiddenUsers.Count--; + } + + private void clearUsers() + { + avatarFlow.Clear(); + hiddenUsers.Count = 0; + } + + private class CircularAvatar : CompositeDrawable + { + public User User + { + get => avatar.User; + set => avatar.User = value; + } + + private readonly UpdateableAvatar avatar; + + public CircularAvatar() + { + Size = new Vector2(avatar_size); + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = avatar = new UpdateableAvatar(showUsernameTooltip: true) { RelativeSizeAxes = Axes.Both } + }; + } + } + + public class HiddenUserCount : CompositeDrawable + { + public int Count + { + get => count; + set + { + count = value; + countText.Text = $"+{count}"; + + if (count > 0) + Show(); + else + Hide(); + } + } + + private int count; + + private readonly SpriteText countText; + + public HiddenUserCount() + { + Size = new Vector2(avatar_size); + Alpha = 0; + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + countText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + }; + } + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index a1f90f2d89..9385c3cae8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -91,6 +91,22 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + private int numberOfAvatars = 3; + + public int NumberOfAvatars + { + get => numberOfAvatars; + set + { + numberOfAvatars = value; + + if (recentParticipantsList != null) + recentParticipantsList.NumberOfAvatars = value; + } + } + + private RecentParticipantsList recentParticipantsList; + public bool FilteringActive { get; set; } public DrawableRoom(Room room) @@ -228,6 +244,28 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } }, + new FillFlowContainer + { + Name = "Right content", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding + { + Right = 10, + Vertical = 5 + }, + Children = new Drawable[] + { + recentParticipantsList = new RecentParticipantsList + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + NumberOfAvatars = NumberOfAvatars + } + } + } }, }, }, From 689cee832c6f8ea2574d8bac1debd817d4e44cf9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Jul 2021 15:50:46 +0900 Subject: [PATCH 025/600] Fix 1px gaps in DrawableRoom background --- .../Lounge/Components/DrawableRoom.cs | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 9385c3cae8..f7f846ecfb 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -141,41 +141,49 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Children = new Drawable[] { - new Box + // This resolves 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. + new BufferedContainer { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fill, - Child = new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both } - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Children = new Drawable[] { - new Dimension(GridSizeMode.Relative, 0.2f) - }, - Content = new[] - { - new Drawable[] + new Box { - new Box + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + Child = new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both } + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), + new Dimension(GridSizeMode.Relative, 0.2f) }, - new Box + Content = new[] { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) - }, - } + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + }, + } + } + }, } }, new Container From ab282b9e59ca187954ca18ba0082ffa9e4e5b8c1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Jul 2021 16:00:42 +0900 Subject: [PATCH 026/600] Remove RoomInspector from the lounge --- .../Multiplayer/TestSceneLoungeRoomInfo.cs | 49 ---------- .../Lounge/Components/ParticipantInfo.cs | 88 ------------------ .../OnlinePlay/Lounge/Components/RoomInfo.cs | 86 ------------------ .../Lounge/Components/RoomInspector.cs | 91 ------------------- .../Lounge/Components/RoomsContainer.cs | 2 +- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 33 +++---- 6 files changed, 12 insertions(+), 337 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/ParticipantInfo.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInspector.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs deleted file mode 100644 index 471d0b6c98..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 NUnit.Framework; -using osu.Framework.Graphics; -using osu.Game.Online.Rooms; -using osu.Game.Online.Rooms.RoomStatuses; -using osu.Game.Screens.OnlinePlay.Lounge.Components; -using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestSceneLoungeRoomInfo : OnlinePlayTestScene - { - [SetUp] - public new void Setup() => Schedule(() => - { - SelectedRoom.Value = new Room(); - - Child = new RoomInfo - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 500 - }; - }); - - [Test] - public void TestNonSelectedRoom() - { - AddStep("set null room", () => SelectedRoom.Value.RoomID.Value = null); - } - - [Test] - public void TestOpenRoom() - { - AddStep("set open room", () => - { - SelectedRoom.Value.RoomID.Value = 0; - SelectedRoom.Value.Name.Value = "Room 0"; - SelectedRoom.Value.Host.Value = new User { Username = "peppy", Id = 2 }; - SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMonths(1); - SelectedRoom.Value.Status.Value = new RoomStatusOpen(); - }); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/ParticipantInfo.cs deleted file mode 100644 index bc4506b78e..0000000000 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/ParticipantInfo.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using Humanizer; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Users.Drawables; -using osuTK; - -namespace osu.Game.Screens.OnlinePlay.Lounge.Components -{ - public class ParticipantInfo : OnlinePlayComposite - { - public ParticipantInfo() - { - RelativeSizeAxes = Axes.X; - Height = 15f; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - OsuSpriteText summary; - Container flagContainer; - LinkFlowContainer hostText; - - InternalChildren = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - Children = new Drawable[] - { - flagContainer = new Container - { - Width = 22f, - RelativeSizeAxes = Axes.Y, - }, - hostText = new LinkFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both - } - }, - }, - new FillFlowContainer - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Colour = colours.Gray9, - Children = new[] - { - summary = new OsuSpriteText - { - Text = "0 participants", - } - }, - }, - }; - - Host.BindValueChanged(host => - { - hostText.Clear(); - flagContainer.Clear(); - - if (host.NewValue != null) - { - hostText.AddText("hosted by "); - hostText.AddUserLink(host.NewValue, s => s.Font = s.Font.With(Typeface.Torus, weight: FontWeight.Bold, italics: true)); - - flagContainer.Child = new UpdateableFlag(host.NewValue.Country) { RelativeSizeAxes = Axes.Both }; - } - }, true); - - ParticipantCount.BindValueChanged(count => summary.Text = "participant".ToQuantity(count.NewValue), true); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs deleted file mode 100644 index 819e19ad1e..0000000000 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInfo.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Screens.OnlinePlay.Components; -using osuTK; - -namespace osu.Game.Screens.OnlinePlay.Lounge.Components -{ - public class RoomInfo : OnlinePlayComposite - { - private readonly List statusElements = new List(); - private readonly OsuTextFlowContainer roomName; - - public RoomInfo() - { - AutoSizeAxes = Axes.Y; - - RoomLocalUserInfo localUserInfo; - EndDateInfo statusInfo; - ModeTypeInfo typeInfo; - ParticipantInfo participantInfo; - - InternalChild = new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - Spacing = new Vector2(0, 10), - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - roomName = new OsuTextFlowContainer(t => t.Font = OsuFont.GetFont(size: 30)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - participantInfo = new ParticipantInfo(), - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - statusInfo = new EndDateInfo(), - typeInfo = new ModeTypeInfo - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight - } - } - }, - localUserInfo = new RoomLocalUserInfo(), - } - }; - - statusElements.AddRange(new Drawable[] - { - statusInfo, typeInfo, participantInfo, localUserInfo - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - if (RoomID.Value == null) - statusElements.ForEach(e => e.FadeOut()); - RoomID.BindValueChanged(id => - { - if (id.NewValue == null) - statusElements.ForEach(e => e.FadeOut(100)); - else - statusElements.ForEach(e => e.FadeIn(100)); - }, true); - RoomName.BindValueChanged(name => - { - roomName.Text = name.NewValue ?? "No room selected"; - }, true); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInspector.cs deleted file mode 100644 index c28354c753..0000000000 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomInspector.cs +++ /dev/null @@ -1,91 +0,0 @@ -// 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.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Screens.OnlinePlay.Components; -using osuTK.Graphics; - -namespace osu.Game.Screens.OnlinePlay.Lounge.Components -{ - public class RoomInspector : OnlinePlayComposite - { - private const float transition_duration = 100; - - private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; - - [Resolved] - private BeatmapManager beatmaps { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - OverlinedHeader participantsHeader; - - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.25f - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 30 }, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new RoomInfo - { - RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Vertical = 60 }, - }, - participantsHeader = new OverlinedHeader("Recent Participants"), - new ParticipantsDisplay(Direction.Vertical) - { - RelativeSizeAxes = Axes.X, - Height = ParticipantsList.TILE_SIZE * 3, - Details = { BindTarget = participantsHeader.Details } - } - } - } - }, - new Drawable[] { new OverlinedPlaylistHeader(), }, - new Drawable[] - { - new DrawableRoomPlaylist(false, false) - { - RelativeSizeAxes = Axes.Both, - Items = { BindTarget = Playlist } - }, - }, - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } - } - } - }; - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 5f135a3e90..0c6c84e656 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Spacing = new Vector2(2), + Spacing = new Vector2(10), } }; } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index f24577a8a5..9004fe8dcc 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -57,31 +57,20 @@ namespace osu.Game.Screens.OnlinePlay.Lounge content = new Container { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Child = new Container { - new Container + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Width = 0.55f, - Children = new Drawable[] + scrollContainer = new OsuScrollContainer { - scrollContainer = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - ScrollbarOverlapsContent = false, - Padding = new MarginPadding(10), - Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } - }, - loadingLayer = new LoadingLayer(true), - } - }, - new RoomInspector - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Both, - Width = 0.45f, - }, + RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, + Padding = new MarginPadding(10), + Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } + }, + loadingLayer = new LoadingLayer(true), + } }, }, filter = CreateFilterControl().With(d => From 0cb80e105b22c3f4dc8ba7ba24a78d4c10a01b77 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Jul 2021 16:02:18 +0900 Subject: [PATCH 027/600] Renamespace classes --- osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs | 2 +- .../Visual/Multiplayer/TestSceneRecentParticipantsList.cs | 2 +- .../Screens/OnlinePlay/{ => Lounge}/Components/EndDateInfo.cs | 2 +- .../Screens/OnlinePlay/{ => Lounge}/Components/PillContainer.cs | 2 +- .../OnlinePlay/{ => Lounge}/Components/PlaylistCountPill.cs | 2 +- .../Screens/OnlinePlay/{ => Lounge}/Components/RankRangePill.cs | 2 +- .../{ => Lounge}/Components/RecentParticipantsList.cs | 2 +- .../OnlinePlay/{ => Lounge}/Components/RoomStatusPill.cs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game/Screens/OnlinePlay/{ => Lounge}/Components/EndDateInfo.cs (97%) rename osu.Game/Screens/OnlinePlay/{ => Lounge}/Components/PillContainer.cs (97%) rename osu.Game/Screens/OnlinePlay/{ => Lounge}/Components/PlaylistCountPill.cs (96%) rename osu.Game/Screens/OnlinePlay/{ => Lounge}/Components/RankRangePill.cs (97%) rename osu.Game/Screens/OnlinePlay/{ => Lounge}/Components/RecentParticipantsList.cs (99%) rename osu.Game/Screens/OnlinePlay/{ => Lounge}/Components/RoomStatusPill.cs (97%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs index d6bbaabfa6..5e28b3f8e5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs index ca8dc74759..c9959b3467 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -6,7 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Online.Rooms; -using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; using osu.Game.Users.Drawables; diff --git a/osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs similarity index 97% rename from osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs rename to osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs index 3f93279461..3207d373db 100644 --- a/osu.Game/Screens/OnlinePlay/Components/EndDateInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs @@ -7,7 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics; -namespace osu.Game.Screens.OnlinePlay.Components +namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public class EndDateInfo : OnlinePlayComposite { diff --git a/osu.Game/Screens/OnlinePlay/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs similarity index 97% rename from osu.Game/Screens/OnlinePlay/Components/PillContainer.cs rename to osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index 10a14d16da..15a532eaf3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; -namespace osu.Game.Screens.OnlinePlay.Components +namespace osu.Game.Screens.OnlinePlay.Lounge.Components { /// /// Displays contents in a "pill". diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs similarity index 96% rename from osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs rename to osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 2d9e7c143c..8d8309fcaa 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -namespace osu.Game.Screens.OnlinePlay.Components +namespace osu.Game.Screens.OnlinePlay.Lounge.Components { /// /// A pill that displays the playlist item count. diff --git a/osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs similarity index 97% rename from osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs rename to osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs index d7bdf13f6a..8f685ba033 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RankRangePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Screens.OnlinePlay.Multiplayer; using osuTK; -namespace osu.Game.Screens.OnlinePlay.Components +namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public class RankRangePill : MultiplayerRoomComposite { diff --git a/osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs similarity index 99% rename from osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs rename to osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index d73387342a..bbea1ea1c3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -15,7 +15,7 @@ using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.OnlinePlay.Components +namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public class RecentParticipantsList : OnlinePlayComposite { diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs similarity index 97% rename from osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs rename to osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index d18eb1bd94..ae17a80705 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -11,7 +11,7 @@ using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osuTK.Graphics; -namespace osu.Game.Screens.OnlinePlay.Components +namespace osu.Game.Screens.OnlinePlay.Lounge.Components { /// /// A pill that displays the room's current status. From b5d4b9444fbffcf2b2e202145a405d2559c7a5c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Jul 2021 16:51:29 +0900 Subject: [PATCH 028/600] wip --- .../Lounge/Components/FilterControl.cs | 70 ++++++++----------- .../Components/PlaylistsFilterControl.cs | 10 ++- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs index 7fc1c670ca..1827efb4a2 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs @@ -5,19 +5,21 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; -using osuTK.Graphics; +using osuTK; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public abstract class FilterControl : CompositeDrawable { protected const float VERTICAL_PADDING = 10; - protected const float HORIZONTAL_PADDING = 80; + protected const float HORIZONTAL_PADDING = 20; + + protected readonly FillFlowContainer Filters; [Resolved(CanBeNull = true)] private Bindable filter { get; set; } @@ -25,60 +27,50 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [Resolved] private IBindable ruleset { get; set; } - private readonly Box tabStrip; private readonly SearchTextBox search; - private readonly PageTabControl tabs; + private readonly Dropdown statusDropdown; protected FilterControl() { - InternalChildren = new Drawable[] + InternalChild = new Container { - new Box + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.25f, + Top = VERTICAL_PADDING, + Horizontal = HORIZONTAL_PADDING }, - tabStrip = new Box + Children = new Drawable[] { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + search = new FilterSearchTextBox { - Top = VERTICAL_PADDING, - Horizontal = HORIZONTAL_PADDING + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.X, + Width = 0.6f, }, - Children = new Drawable[] + Filters = new FillFlowContainer { - search = new FilterSearchTextBox + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10), + Padding = new MarginPadding { Vertical = 30 }, + Child = statusDropdown = new SlimEnumDropdown { - RelativeSizeAxes = Axes.X, - }, - tabs = new PageTabControl - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - }, - } + Anchor = Anchor.BottomRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.None, + Width = 160, + } + }, } }; - - tabs.Current.Value = RoomStatusFilter.Open; - tabs.Current.TriggerChange(); } [BackgroundDependencyLoader] private void load(OsuColour colours) { filter ??= new Bindable(); - tabStrip.Colour = colours.Yellow; } protected override void LoadComplete() @@ -87,7 +79,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components search.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - tabs.Current.BindValueChanged(_ => UpdateFilter(), true); + statusDropdown.Current.BindValueChanged(_ => UpdateFilter(), true); } private ScheduledDelegate scheduledFilterUpdate; @@ -106,7 +98,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components var criteria = CreateCriteria(); criteria.SearchString = search.Current.Value; - criteria.Status = tabs.Current.Value; + criteria.Status = statusDropdown.Current.Value; criteria.Ruleset = ruleset.Value; filter.Value = criteria; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs index a463742097..e6309a8e06 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs @@ -9,18 +9,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public class PlaylistsFilterControl : FilterControl { - private readonly Dropdown dropdown; + private readonly Dropdown categoryDropdown; public PlaylistsFilterControl() { - AddInternal(dropdown = new SlimEnumDropdown + Filters.Add(categoryDropdown = new SlimEnumDropdown { Anchor = Anchor.BottomRight, Origin = Anchor.TopRight, RelativeSizeAxes = Axes.None, Width = 160, - X = -HORIZONTAL_PADDING, - Y = -30 }); } @@ -28,14 +26,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - dropdown.Current.BindValueChanged(_ => UpdateFilter()); + categoryDropdown.Current.BindValueChanged(_ => UpdateFilter()); } protected override FilterCriteria CreateCriteria() { var criteria = base.CreateCriteria(); - switch (dropdown.Current.Value) + switch (categoryDropdown.Current.Value) { case PlaylistsCategory.Normal: criteria.Category = "normal"; From 0e89bafd178f5d180357ec0ae8102f8462e226b2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 16:48:53 +0900 Subject: [PATCH 029/600] Add special category pill + secondary background --- .../Multiplayer/TestSceneDrawableRoom.cs | 8 +- .../Lounge/Components/DrawableRoom.cs | 266 ++++++++++-------- .../Lounge/Components/PillContainer.cs | 7 +- .../Components/RoomSpecialCategoryPill.cs | 49 ++++ .../Screens/OnlinePlay/OnlinePlayComposite.cs | 3 + 5 files changed, 209 insertions(+), 124 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 0970085c25..ee84a6b6cc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -47,10 +47,16 @@ namespace osu.Game.Tests.Visual.Multiplayer }), createDrawableRoom(new Room { - Name = { Value = "Room 4" }, + Name = { Value = "Room 4 (realtime)" }, Status = { Value = new RoomStatusOpen() }, Category = { Value = RoomCategory.Realtime }, }), + createDrawableRoom(new Room + { + Name = { Value = "Room 4 (spotlight)" }, + Status = { Value = new RoomStatusOpen() }, + Category = { Value = RoomCategory.Spotlight }, + }), } }; } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index f7f846ecfb..d36f0275df 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -105,7 +105,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + private readonly Bindable roomCategory = new Bindable(); + private RecentParticipantsList recentParticipantsList; + private RoomSpecialCategoryPill specialCategoryPill; + private Drawable spotlightGlow; public bool FilteringActive { get; set; } @@ -126,156 +130,169 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { new Container { - Name = @"Room content", RelativeSizeAxes = Axes.Both, - Child = new Container + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = corner_radius, - EdgeEffect = new EdgeEffectParameters + new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(40), - Radius = 5, + RelativeSizeAxes = Axes.Both }, - Children = new Drawable[] + new Container { - // This resolves 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. - new BufferedContainer + Name = @"Room content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 20, Vertical = -0.5f }, + Child = new Container { RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = corner_radius, Children = new Drawable[] { - new Box + // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. + new BufferedContainer { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, + new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) + { + RelativeSizeAxes = Axes.Both + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Relative, 0.2f) + }, + Content = new[] + { + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + }, + } + } + }, + spotlightGlow = new Box + { + RelativeSizeAxes = Axes.Y, + Width = 50, + Colour = ColourInfo.GradientHorizontal(colours.Pink.Opacity(0.5f), colours.Pink.Opacity(0)) + } + }, }, new Container { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, + Name = @"Left details", RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fill, - Child = new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both } - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Padding = new MarginPadding { - new Dimension(GridSizeMode.Relative, 0.2f) + Left = 20, + Vertical = 5 }, - Content = new[] + Children = new Drawable[] { - new Drawable[] + new FillFlowContainer { - new Box + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) - }, - } - } - }, - } - }, - new Container - { - Name = @"Left details", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Left = 20, - Vertical = 5 - }, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), - Children = new Drawable[] - { - new RoomStatusPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft + new RoomStatusPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + specialCategoryPill = new RoomSpecialCategoryPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new EndDateInfo + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + } }, - new EndDateInfo - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - } - }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new RoomNameText(), - new RoomHostText() - } - }, - new FillFlowContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), - Children = new Drawable[] - { - new PlaylistCountPill + new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new RoomNameText(), + new RoomHostText() + } }, - new StarRatingRangeDisplay + new FillFlowContainer { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Scale = new Vector2(0.85f) + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), + Children = new Drawable[] + { + new PlaylistCountPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new StarRatingRangeDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Scale = new Vector2(0.85f) + } + } } } - } - } - }, - new FillFlowContainer - { - Name = "Right content", - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Right = 10, - Vertical = 5 - }, - Children = new Drawable[] - { - recentParticipantsList = new RecentParticipantsList + }, + new FillFlowContainer { + Name = "Right content", Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - NumberOfAvatars = NumberOfAvatars + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding + { + Right = 10, + Vertical = 5 + }, + Children = new Drawable[] + { + recentParticipantsList = new RecentParticipantsList + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + NumberOfAvatars = NumberOfAvatars + } + } } - } - } + }, + }, }, - }, + } }, new StatusColouredContainer(transition_duration) { @@ -315,6 +332,21 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components this.FadeInFromZero(transition_duration); else Alpha = 0; + + roomCategory.BindTo(Room.Category); + roomCategory.BindValueChanged(c => + { + if (c.NewValue == RoomCategory.Spotlight) + { + specialCategoryPill.Show(); + spotlightGlow.Show(); + } + else + { + specialCategoryPill.Hide(); + spotlightGlow.Hide(); + } + }, true); } protected override bool ShouldBeConsideredForInput(Drawable child) => state == SelectionState.Selected; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index 15a532eaf3..ca153f7e9a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -16,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { private const float padding = 8; - public Drawable Background { get; private set; } + public readonly Drawable Background; protected override Container Content { get; } = new Container { @@ -29,11 +28,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { AutoSizeAxes = Axes.X; Height = 16; - } - [BackgroundDependencyLoader] - private void load() - { InternalChild = new CircularContainer { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs new file mode 100644 index 0000000000..6cdbeb2af4 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -0,0 +1,49 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Lounge.Components +{ + public class RoomSpecialCategoryPill : OnlinePlayComposite + { + private SpriteText text; + + public RoomSpecialCategoryPill() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChild = new PillContainer + { + Background = + { + Colour = colours.Pink, + Alpha = 1 + }, + Child = text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), + Colour = Color4.Black + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Category.BindValueChanged(c => text.Text = c.NewValue.ToString(), true); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index eb0b23f13f..ffaeb8fc97 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -35,6 +35,9 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(typeof(Room))] protected BindableList Playlist { get; private set; } + [Resolved(typeof(Room))] + protected Bindable Category { get; private set; } + [Resolved(typeof(Room))] protected BindableList RecentParticipants { get; private set; } From e0c61c24b1529654bf9a891384b8ed3660d84940 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 16:51:20 +0900 Subject: [PATCH 030/600] Remove spotlights glow --- .../Lounge/Components/DrawableRoom.cs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index d36f0275df..63dffe432b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; @@ -109,7 +108,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private RecentParticipantsList recentParticipantsList; private RoomSpecialCategoryPill specialCategoryPill; - private Drawable spotlightGlow; public bool FilteringActive { get; set; } @@ -153,7 +151,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new BufferedContainer { RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { new Box { @@ -188,12 +186,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } }, - spotlightGlow = new Box - { - RelativeSizeAxes = Axes.Y, - Width = 50, - Colour = ColourInfo.GradientHorizontal(colours.Pink.Opacity(0.5f), colours.Pink.Opacity(0)) - } }, }, new Container @@ -336,16 +328,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomCategory.BindTo(Room.Category); roomCategory.BindValueChanged(c => { + // Todo: Tournament category... if (c.NewValue == RoomCategory.Spotlight) - { specialCategoryPill.Show(); - spotlightGlow.Show(); - } else - { specialCategoryPill.Hide(); - spotlightGlow.Hide(); - } }, true); } From da3b40a4ddd8081e4d626dac0f44d2ce417e5548 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 16:56:39 +0900 Subject: [PATCH 031/600] Add default background to panel, reduce nesting --- .../Lounge/Components/DrawableRoom.cs | 248 +++++++++--------- 1 file changed, 127 insertions(+), 121 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 63dffe432b..1e8ea86eb7 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -126,165 +126,171 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { Children = new Drawable[] { - new Container + // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. + new BufferedContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both }, - new Container + } + }, + new Container + { + Name = @"Room content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 20, Vertical = -0.5f }, + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = corner_radius, + Children = new Drawable[] { - Name = @"Room content", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 20, Vertical = -0.5f }, - Child = new Container + // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. + new BufferedContainer { RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = corner_radius, Children = new Drawable[] { - // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. - new BufferedContainer + new Box { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), - }, - new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) - { - RelativeSizeAxes = Axes.Both - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Relative, 0.2f) - }, - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) - }, - } - } - }, - }, + Colour = Color4Extensions.FromHex(@"#27302E"), }, - new Container + new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) + { + RelativeSizeAxes = Axes.Both + }, + new GridContainer { - Name = @"Left details", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + ColumnDimensions = new[] { - Left = 20, - Vertical = 5 + new Dimension(GridSizeMode.Relative, 0.2f) }, + Content = new[] + { + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"#27302E"), + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + }, + } + } + }, + }, + }, + new Container + { + Name = @"Left details", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Left = 20, + Vertical = 5 + }, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), Children = new Drawable[] { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), - Children = new Drawable[] - { - new RoomStatusPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - specialCategoryPill = new RoomSpecialCategoryPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - new EndDateInfo - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - } - }, - new FillFlowContainer + new RoomStatusPill { Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new RoomNameText(), - new RoomHostText() - } + Origin = Anchor.CentreLeft }, - new FillFlowContainer + specialCategoryPill = new RoomSpecialCategoryPill { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), - Children = new Drawable[] - { - new PlaylistCountPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - new StarRatingRangeDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Scale = new Vector2(0.85f) - } - } - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new EndDateInfo + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, } }, new FillFlowContainer { - Name = "Right content", - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Right = 10, - Vertical = 5 - }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, Children = new Drawable[] { - recentParticipantsList = new RecentParticipantsList + new RoomNameText(), + new RoomHostText() + } + }, + new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), + Children = new Drawable[] + { + new PlaylistCountPill { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - NumberOfAvatars = NumberOfAvatars + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new StarRatingRangeDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Scale = new Vector2(0.85f) } } } - }, + } }, + new FillFlowContainer + { + Name = "Right content", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding + { + Right = 10, + Vertical = 5 + }, + Children = new Drawable[] + { + recentParticipantsList = new RecentParticipantsList + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + NumberOfAvatars = NumberOfAvatars + } + } + } }, - } + }, }, new StatusColouredContainer(transition_duration) { From f6b81b76e88cc4c6b4307719150ba42cc93fbecc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 17:46:32 +0900 Subject: [PATCH 032/600] Add shadow --- .../OnlinePlay/Lounge/Components/DrawableRoom.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 1e8ea86eb7..441b33abf0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; @@ -117,8 +118,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.X; Height = height; - CornerRadius = corner_radius + SELECTION_BORDER_WIDTH / 2; + Masking = true; + CornerRadius = corner_radius + SELECTION_BORDER_WIDTH / 2; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(40), + Radius = 5, + }; } [BackgroundDependencyLoader] From 0bfaf11d515b45c12ca6c1196ffd2a46bca71b4a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 17:46:45 +0900 Subject: [PATCH 033/600] Remove/fix paddings in lounge --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 9004fe8dcc..4930c432d8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -52,32 +52,49 @@ namespace osu.Game.Screens.OnlinePlay.Lounge RoomsContainer roomsContainer; OsuScrollContainer scrollContainer; - InternalChildren = new Drawable[] + InternalChild = content = new Container { - content = new Container + RelativeSizeAxes = Axes.Both, + Child = new GridContainer { RelativeSizeAxes = Axes.Both, - Child = new Container + RowDimensions = new[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 10) + }, + Content = new[] + { + new Drawable[] { - scrollContainer = new OsuScrollContainer + filter = CreateFilterControl().With(d => + { + d.RelativeSizeAxes = Axes.X; + d.Height = 80; + d.Depth = -1; + }), + }, + null, + new Drawable[] + { + new Container { RelativeSizeAxes = Axes.Both, - ScrollbarOverlapsContent = false, - Padding = new MarginPadding(10), - Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } + Children = new Drawable[] + { + scrollContainer = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, + Padding = new MarginPadding(10), + Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } + }, + loadingLayer = new LoadingLayer(true), + } }, - loadingLayer = new LoadingLayer(true), } - }, + } }, - filter = CreateFilterControl().With(d => - { - d.RelativeSizeAxes = Axes.X; - d.Height = 80; - }) }; // scroll selected room into view on selection. @@ -109,9 +126,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge content.Padding = new MarginPadding { - Top = filter.DrawHeight, - Left = WaveOverlayContainer.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH + HORIZONTAL_OVERFLOW_PADDING, - Right = WaveOverlayContainer.WIDTH_PADDING + HORIZONTAL_OVERFLOW_PADDING, + Left = WaveOverlayContainer.WIDTH_PADDING, + Right = WaveOverlayContainer.WIDTH_PADDING, }; } From c64230315f083a9b4e5c9c2bfaca668846d4991c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 18:10:59 +0900 Subject: [PATCH 034/600] Adjust layouts --- .../Lounge/Components/FilterControl.cs | 18 +++++-------- .../Components/PlaylistsFilterControl.cs | 2 +- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 27 ++++++------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs index 1827efb4a2..36fba68a0c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs @@ -16,9 +16,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public abstract class FilterControl : CompositeDrawable { - protected const float VERTICAL_PADDING = 10; - protected const float HORIZONTAL_PADDING = 20; - protected readonly FillFlowContainer Filters; [Resolved(CanBeNull = true)] @@ -32,14 +29,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected FilterControl() { - InternalChild = new Container + RelativeSizeAxes = Axes.X; + Height = 70; + + InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Top = VERTICAL_PADDING, - Horizontal = HORIZONTAL_PADDING - }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), Children = new Drawable[] { search = new FilterSearchTextBox @@ -54,10 +51,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(10), - Padding = new MarginPadding { Vertical = 30 }, Child = statusDropdown = new SlimEnumDropdown { - Anchor = Anchor.BottomRight, + Anchor = Anchor.TopRight, Origin = Anchor.TopRight, RelativeSizeAxes = Axes.None, Width = 160, diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs index e6309a8e06..bbf34d3893 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { Filters.Add(categoryDropdown = new SlimEnumDropdown { - Anchor = Anchor.BottomRight, + Anchor = Anchor.TopRight, Origin = Anchor.TopRight, RelativeSizeAxes = Axes.None, Width = 160, diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 4930c432d8..492473e550 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -55,24 +55,25 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChild = content = new Container { RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Top = 20, + Left = WaveOverlayContainer.WIDTH_PADDING, + Right = WaveOverlayContainer.WIDTH_PADDING, + }, Child = new GridContainer { RelativeSizeAxes = Axes.Both, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, 10) + new Dimension(GridSizeMode.Absolute, 20) }, Content = new[] { new Drawable[] { - filter = CreateFilterControl().With(d => - { - d.RelativeSizeAxes = Axes.X; - d.Height = 80; - d.Depth = -1; - }), + filter = CreateFilterControl().With(d => d.Depth = -1), }, null, new Drawable[] @@ -86,7 +87,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { RelativeSizeAxes = Axes.Both, ScrollbarOverlapsContent = false, - Padding = new MarginPadding(10), Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } }, loadingLayer = new LoadingLayer(true), @@ -120,17 +120,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } } - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - content.Padding = new MarginPadding - { - Left = WaveOverlayContainer.WIDTH_PADDING, - Right = WaveOverlayContainer.WIDTH_PADDING, - }; - } - protected override void OnFocus(FocusEvent e) { filter.TakeFocus(); From 3e6b9bd48d595d3753c5f52c35f23802eb7bfbf1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 18:24:30 +0900 Subject: [PATCH 035/600] Add filter background --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 70 +++++++++++-------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 492473e550..068bc34a6c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Screens; using osu.Game.Graphics.Containers; @@ -17,6 +18,7 @@ using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge { @@ -52,49 +54,59 @@ namespace osu.Game.Screens.OnlinePlay.Lounge RoomsContainer roomsContainer; OsuScrollContainer scrollContainer; - InternalChild = content = new Container + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + new Box { - Top = 20, - Left = WaveOverlayContainer.WIDTH_PADDING, - Right = WaveOverlayContainer.WIDTH_PADDING, + RelativeSizeAxes = Axes.X, + Height = 100, + Colour = Color4.Black, + Alpha = 0.5f, }, - Child = new GridContainer + content = new Container { RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + Padding = new MarginPadding { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, 20) + Top = 20, + Left = WaveOverlayContainer.WIDTH_PADDING, + Right = WaveOverlayContainer.WIDTH_PADDING, }, - Content = new[] + Child = new GridContainer { - new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - filter = CreateFilterControl().With(d => d.Depth = -1), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 20) }, - null, - new Drawable[] + Content = new[] { - new Container + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - scrollContainer = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - ScrollbarOverlapsContent = false, - Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } - }, - loadingLayer = new LoadingLayer(true), - } + filter = CreateFilterControl().With(d => d.Depth = -1), }, + null, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + scrollContainer = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, + Child = roomsContainer = new RoomsContainer { JoinRequested = joinRequested } + }, + loadingLayer = new LoadingLayer(true), + } + }, + } } - } - }, + }, + } }; // scroll selected room into view on selection. From dfe7cc40a9a39d113e9f1362124e54871dccc3f7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Jul 2021 18:55:01 +0900 Subject: [PATCH 036/600] Move create room button into the lounge --- .../Multiplayer/TestSceneMultiplayer.cs | 6 +-- .../Navigation/TestSceneScreenNavigation.cs | 4 +- .../Lounge/Components/DrawableRoom.cs | 4 +- .../Lounge/Components/FilterControl.cs | 4 +- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 41 +++++++++++++++++-- .../CreateMultiplayerMatchButton.cs | 1 + .../OnlinePlay/Multiplayer/Multiplayer.cs | 11 ----- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 19 +++++++-- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 30 -------------- .../Playlists/CreatePlaylistsRoomButton.cs | 1 + .../Screens/OnlinePlay/Playlists/Playlists.cs | 9 ---- .../Playlists/PlaylistsLoungeSubScreen.cs | 13 ++++++ 12 files changed, 79 insertions(+), 64 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 7673efb78f..2808127bb8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -249,10 +249,8 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createRoom(Func room) { - AddStep("open room", () => - { - multiplayerScreen.OpenNewRoom(room()); - }); + AddUntilStep("wait for lounge", () => multiplayerScreen.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); + AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().OpenNewRoom(room())); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddWaitStep("wait for transition", 2); diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 52401d32e5..72d01ddd2a 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -16,6 +16,7 @@ using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Screens.Select; @@ -316,7 +317,8 @@ namespace osu.Game.Tests.Visual.Navigation PushAndConfirm(() => multiplayer = new TestMultiplayer()); - AddStep("open room", () => multiplayer.OpenNewRoom()); + AddUntilStep("wait for lounge", () => multiplayer.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); + AddStep("open room", () => multiplayer.ChildrenOfType().Single().OpenNewRoom()); AddStep("press back button", () => Game.ChildrenOfType().First().Action()); AddWaitStep("wait two frames", 2); } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 441b33abf0..9bfec72942 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private Drawable selectionBox; [Resolved(canBeNull: true)] - private OnlinePlayScreen parentScreen { get; set; } + private LoungeSubScreen loungeScreen { get; set; } [Resolved] private BeatmapManager beatmaps { get; set; } @@ -408,7 +408,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { new OsuMenuItem("Create copy", MenuItemType.Standard, () => { - parentScreen?.OpenNewRoom(Room.CreateCopy()); + loungeScreen?.OpenNewRoom(Room.CreateCopy()); }) }; } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs index 36fba68a0c..e2f02fca68 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs @@ -48,7 +48,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Filters = new FillFlowContainer { - RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(10), Child = statusDropdown = new SlimEnumDropdown diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 068bc34a6c..115dddafec 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -18,6 +18,7 @@ using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; +using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge @@ -29,11 +30,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); + protected Container Buttons { get; } = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both + }; + private readonly IBindable initialRoomsReceived = new Bindable(); private readonly IBindable operationInProgress = new Bindable(); private FilterControl filter; - private Container content; private LoadingLayer loadingLayer; [Resolved] @@ -63,7 +70,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Colour = Color4.Black, Alpha = 0.5f, }, - content = new Container + new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding @@ -84,7 +91,21 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { new Drawable[] { - filter = CreateFilterControl().With(d => d.Depth = -1), + new Container + { + RelativeSizeAxes = Axes.X, + Height = 70, + Depth = -1, + Children = new Drawable[] + { + filter = CreateFilterControl(), + Buttons.WithChild(CreateNewRoomButton().With(d => + { + d.Size = new Vector2(150, 25); + d.Action = () => OpenNewRoom(); + })) + } + } }, null, new Drawable[] @@ -216,6 +237,20 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected abstract FilterControl CreateFilterControl(); + /// + /// Creates and opens the newly-created room. + /// + /// An optional template to use when creating the room. + public void OpenNewRoom(Room room = null) => Open(room ?? CreateNewRoom()); + + protected abstract OsuButton CreateNewRoomButton(); + + /// + /// Creates a new room. + /// + /// The created . + protected abstract Room CreateNewRoom(); + protected abstract RoomSubScreen CreateRoomSubScreen(Room room); } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs index cc51b5b691..edf846f0f8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs @@ -23,6 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private void load() { Triangles.TriangleScale = 1.5f; + SpriteText.Font = SpriteText.Font.With(size: 14); Text = "Create room"; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index dbac826954..45928505bb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -4,9 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Logging; using osu.Framework.Screens; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; -using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; @@ -54,19 +52,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})"); } - protected override Room CreateNewRoom() => - new Room - { - Name = { Value = $"{API.LocalUser}'s awesome room" }, - Category = { Value = RoomCategory.Realtime } - }; - protected override string ScreenTitle => "Multiplayer"; protected override RoomManager CreateRoomManager() => new MultiplayerRoomManager(); protected override LoungeSubScreen CreateLounge() => new MultiplayerLoungeSubScreen(); - - protected override OsuButton CreateNewMultiplayerGameButton() => new CreateMultiplayerMatchButton(); } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 4d20652465..dd5290f127 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -3,6 +3,8 @@ using osu.Framework.Allocation; using osu.Framework.Logging; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Lounge; @@ -13,13 +15,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { public class MultiplayerLoungeSubScreen : LoungeSubScreen { - protected override FilterControl CreateFilterControl() => new MultiplayerFilterControl(); - - protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); + [Resolved] + private IAPIProvider api { get; set; } [Resolved] private MultiplayerClient client { get; set; } + protected override FilterControl CreateFilterControl() => new MultiplayerFilterControl(); + + protected override OsuButton CreateNewRoomButton() => new CreateMultiplayerMatchButton(); + + protected override Room CreateNewRoom() => new Room + { + Name = { Value = $"{api.LocalUser}'s awesome room" }, + Category = { Value = RoomCategory.Realtime } + }; + + protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); + public override void Open(Room room) { if (!client.IsConnected.Value) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index ceee002c6e..3a229ecd4a 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -12,7 +12,6 @@ using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; @@ -23,7 +22,6 @@ using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; -using osuTK; namespace osu.Game.Screens.OnlinePlay { @@ -38,7 +36,6 @@ namespace osu.Game.Screens.OnlinePlay private readonly MultiplayerWaveContainer waves; - private readonly OsuButton createButton; private readonly LoungeSubScreen loungeSubScreen; private readonly ScreenStack screenStack; @@ -132,18 +129,6 @@ namespace osu.Game.Screens.OnlinePlay } }, new Header(ScreenTitle, screenStack), - createButton = CreateNewMultiplayerGameButton().With(button => - { - button.Anchor = Anchor.TopRight; - button.Origin = Anchor.TopRight; - button.Size = new Vector2(150, Header.HEIGHT - 20); - button.Margin = new MarginPadding - { - Top = 10, - Right = 10 + HORIZONTAL_OVERFLOW_PADDING, - }; - button.Action = () => OpenNewRoom(); - }), RoomManager = CreateRoomManager(), ongoingOperationTracker = new OngoingOperationTracker() } @@ -278,18 +263,6 @@ namespace osu.Game.Screens.OnlinePlay logo.Delay(WaveContainer.DISAPPEAR_DURATION / 2).FadeOut(); } - /// - /// Creates and opens the newly-created room. - /// - /// An optional template to use when creating the room. - public void OpenNewRoom(Room room = null) => loungeSubScreen.Open(room ?? CreateNewRoom()); - - /// - /// Creates a new room. - /// - /// The created . - protected abstract Room CreateNewRoom(); - private void screenPushed(IScreen lastScreen, IScreen newScreen) { subScreenChanged(lastScreen, newScreen); @@ -325,7 +298,6 @@ namespace osu.Game.Screens.OnlinePlay ((IBindable)Activity).BindTo(newOsuScreen.Activity); UpdatePollingRate(isIdle.Value); - createButton.FadeTo(newScreen is LoungeSubScreen ? 1 : 0, 200); } protected IScreen CurrentSubScreen => screenStack.CurrentScreen; @@ -336,8 +308,6 @@ namespace osu.Game.Screens.OnlinePlay protected abstract LoungeSubScreen CreateLounge(); - protected abstract OsuButton CreateNewMultiplayerGameButton(); - private class MultiplayerWaveContainer : WaveContainer { protected override bool StartHidden => true; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs index fcb773f8be..a2c649f10b 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs @@ -12,6 +12,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private void load() { Triangles.TriangleScale = 1.5f; + SpriteText.Font = SpriteText.Font.With(size: 14); Text = "Create playlist"; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index 5b132c97fd..6a78e24ba1 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -3,8 +3,6 @@ using osu.Framework.Logging; using osu.Framework.Screens; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Match; @@ -46,17 +44,10 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Logger.Log($"Polling adjusted (listing: {playlistsManager.TimeBetweenListingPolls.Value}, selection: {playlistsManager.TimeBetweenSelectionPolls.Value})"); } - protected override Room CreateNewRoom() - { - return new Room { Name = { Value = $"{API.LocalUser}'s awesome playlist" } }; - } - protected override string ScreenTitle => "Playlists"; protected override RoomManager CreateRoomManager() => new PlaylistsRoomManager(); protected override LoungeSubScreen CreateLounge() => new PlaylistsLoungeSubScreen(); - - protected override OsuButton CreateNewMultiplayerGameButton() => new CreatePlaylistsRoomButton(); } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index bfbff4240c..21113af828 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -1,6 +1,9 @@ // 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.Allocation; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; @@ -10,8 +13,18 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { public class PlaylistsLoungeSubScreen : LoungeSubScreen { + [Resolved] + private IAPIProvider api { get; set; } + protected override FilterControl CreateFilterControl() => new PlaylistsFilterControl(); + protected override OsuButton CreateNewRoomButton() => new CreatePlaylistsRoomButton(); + + protected override Room CreateNewRoom() + { + return new Room { Name = { Value = $"{api.LocalUser}'s awesome playlist" } }; + } + protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room); } } From ba9b51c12d5a4c49b96a9e2db71760290cb546c8 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 17 Jul 2021 19:25:25 +0800 Subject: [PATCH 037/600] Add localisation for WikiHeader Co-authored-by: huoyaoyuan --- osu.Game/Localisation/WikiStrings.cs | 29 ++++++++++++++++++++++++++++ osu.Game/Overlays/Wiki/WikiHeader.cs | 24 +++++++++++++---------- 2 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Localisation/WikiStrings.cs diff --git a/osu.Game/Localisation/WikiStrings.cs b/osu.Game/Localisation/WikiStrings.cs new file mode 100644 index 0000000000..6176fd4e85 --- /dev/null +++ b/osu.Game/Localisation/WikiStrings.cs @@ -0,0 +1,29 @@ +// 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 WikiStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.Wiki"; + + /// + /// "index" + /// + public static LocalisableString IndexPageString => new TranslatableString(getKey(@"index_page"), @"index"); + + /// + /// "wiki" + /// + public static LocalisableString HeaderTitle => new TranslatableString(getKey(@"header_title"), @"wiki"); + + /// + /// "knowledge base" + /// + public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"knowledge base"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 6b8cba48b4..4bec42b6ce 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -5,14 +5,18 @@ using System; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Wiki { public class WikiHeader : BreadcrumbControlOverlayHeader { - private const string index_page_string = "index"; private const string index_path = "Main_Page"; + public static LocalisableString IndexPageString => WikiStrings.IndexPageString; + public static LocalisableString HeaderTitle => WikiStrings.HeaderTitle; + public static LocalisableString HeaderDescription => WikiStrings.HeaderDescription; public readonly Bindable WikiPageData = new Bindable(); @@ -21,8 +25,8 @@ namespace osu.Game.Overlays.Wiki public WikiHeader() { - TabControl.AddItem(index_page_string); - Current.Value = index_page_string; + TabControl.AddItem(IndexPageString); + Current.Value = IndexPageString; WikiPageData.BindValueChanged(onWikiPageChange); Current.BindValueChanged(onCurrentChange); @@ -34,13 +38,13 @@ namespace osu.Game.Overlays.Wiki return; TabControl.Clear(); - Current.Value = null; + Current.Value = string.Empty; - TabControl.AddItem(index_page_string); + TabControl.AddItem(IndexPageString); if (e.NewValue.Path == index_path) { - Current.Value = index_page_string; + Current.Value = IndexPageString; return; } @@ -51,12 +55,12 @@ namespace osu.Game.Overlays.Wiki Current.Value = e.NewValue.Title; } - private void onCurrentChange(ValueChangedEvent e) + private void onCurrentChange(ValueChangedEvent e) { if (e.NewValue == TabControl.Items.LastOrDefault()) return; - if (e.NewValue == index_page_string) + if (e.NewValue == IndexPageString) { ShowIndexPage?.Invoke(); return; @@ -73,8 +77,8 @@ namespace osu.Game.Overlays.Wiki { public WikiHeaderTitle() { - Title = "wiki"; - Description = "knowledge base"; + Title = HeaderTitle; + Description = HeaderDescription; IconTexture = "Icons/Hexacons/wiki"; } } From 51742da89a91ba318f7d2cee74a3458ec87801e8 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 17 Jul 2021 19:28:27 +0800 Subject: [PATCH 038/600] Add localisation for NewsHeader Co-authored-by: huoyaoyuan --- osu.Game/Localisation/NewsStrings.cs | 29 ++++++++++++++++++++++++++++ osu.Game/Overlays/News/NewsHeader.cs | 16 +++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Localisation/NewsStrings.cs diff --git a/osu.Game/Localisation/NewsStrings.cs b/osu.Game/Localisation/NewsStrings.cs new file mode 100644 index 0000000000..8cad6015cf --- /dev/null +++ b/osu.Game/Localisation/NewsStrings.cs @@ -0,0 +1,29 @@ +// 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 NewsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.News"; + + /// + /// "frontpage" + /// + public static LocalisableString FrontPageString => new TranslatableString(getKey(@"front_page"), @"frontpage"); + + /// + /// "news" + /// + public static LocalisableString HeaderTitle => new TranslatableString(getKey(@"header_title"), @"news"); + + /// + /// "join the real-time discussion" + /// + public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"get up-to-date on community happenings"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 56c54425bd..0b0277f984 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -4,12 +4,16 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Overlays.News { public class NewsHeader : BreadcrumbControlOverlayHeader { - private const string front_page_string = "frontpage"; + public static LocalisableString FrontPageString => NewsStrings.FrontPageString; + public static LocalisableString HeaderTitle => NewsStrings.HeaderTitle; + public static LocalisableString HeaderDescription => NewsStrings.HeaderDescription; public Action ShowFrontPage; @@ -17,7 +21,7 @@ namespace osu.Game.Overlays.News public NewsHeader() { - TabControl.AddItem(front_page_string); + TabControl.AddItem(FrontPageString); article.BindValueChanged(onArticleChanged, true); } @@ -28,7 +32,7 @@ namespace osu.Game.Overlays.News Current.BindValueChanged(e => { - if (e.NewValue == front_page_string) + if (e.NewValue == FrontPageString) ShowFrontPage?.Invoke(); }); } @@ -49,7 +53,7 @@ namespace osu.Game.Overlays.News } else { - Current.Value = front_page_string; + Current.Value = FrontPageString; } } @@ -61,8 +65,8 @@ namespace osu.Game.Overlays.News { public NewsHeaderTitle() { - Title = "news"; - Description = "get up-to-date on community happenings"; + Title = HeaderTitle; + Description = HeaderDescription; IconTexture = "Icons/Hexacons/news"; } } From 1b4bff0d9fa52dec5b18f33158b4201bcb1ed2e2 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 00:28:32 +0800 Subject: [PATCH 039/600] Optimize code style Co-authored-by: frenzibyte Co-authored-by: bdach --- osu.Game/Localisation/NewsStrings.cs | 10 ---------- osu.Game/Localisation/WikiStrings.cs | 29 ---------------------------- osu.Game/Overlays/News/NewsHeader.cs | 11 ++++------- osu.Game/Overlays/Wiki/WikiHeader.cs | 10 ++++------ 4 files changed, 8 insertions(+), 52 deletions(-) delete mode 100644 osu.Game/Localisation/WikiStrings.cs diff --git a/osu.Game/Localisation/NewsStrings.cs b/osu.Game/Localisation/NewsStrings.cs index 8cad6015cf..4f1fe6e776 100644 --- a/osu.Game/Localisation/NewsStrings.cs +++ b/osu.Game/Localisation/NewsStrings.cs @@ -9,16 +9,6 @@ namespace osu.Game.Localisation { private const string prefix = @"osu.Game.Resources.Localisation.News"; - /// - /// "frontpage" - /// - public static LocalisableString FrontPageString => new TranslatableString(getKey(@"front_page"), @"frontpage"); - - /// - /// "news" - /// - public static LocalisableString HeaderTitle => new TranslatableString(getKey(@"header_title"), @"news"); - /// /// "join the real-time discussion" /// diff --git a/osu.Game/Localisation/WikiStrings.cs b/osu.Game/Localisation/WikiStrings.cs deleted file mode 100644 index 6176fd4e85..0000000000 --- a/osu.Game/Localisation/WikiStrings.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 WikiStrings - { - private const string prefix = @"osu.Game.Resources.Localisation.Wiki"; - - /// - /// "index" - /// - public static LocalisableString IndexPageString => new TranslatableString(getKey(@"index_page"), @"index"); - - /// - /// "wiki" - /// - public static LocalisableString HeaderTitle => new TranslatableString(getKey(@"header_title"), @"wiki"); - - /// - /// "knowledge base" - /// - public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"knowledge base"); - - private static string getKey(string key) => $"{prefix}:{key}"; - } -} diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 0b0277f984..7f08300912 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -5,16 +5,13 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; -using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.News { public class NewsHeader : BreadcrumbControlOverlayHeader { - public static LocalisableString FrontPageString => NewsStrings.FrontPageString; - public static LocalisableString HeaderTitle => NewsStrings.HeaderTitle; - public static LocalisableString HeaderDescription => NewsStrings.HeaderDescription; - + public LocalisableString FrontPageString => osu.Game.Resources.Localisation.Web.NewsStrings.IndexTitleInfo; public Action ShowFrontPage; private readonly Bindable article = new Bindable(); @@ -65,8 +62,8 @@ namespace osu.Game.Overlays.News { public NewsHeaderTitle() { - Title = HeaderTitle; - Description = HeaderDescription; + Title = LayoutStrings.MenuHomeNewsIndex; + Description = osu.Game.Localisation.NewsStrings.HeaderDescription; IconTexture = "Icons/Hexacons/news"; } } diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 4bec42b6ce..f24d59a8d3 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -6,17 +6,15 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; -using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Wiki { public class WikiHeader : BreadcrumbControlOverlayHeader { private const string index_path = "Main_Page"; - public static LocalisableString IndexPageString => WikiStrings.IndexPageString; - public static LocalisableString HeaderTitle => WikiStrings.HeaderTitle; - public static LocalisableString HeaderDescription => WikiStrings.HeaderDescription; + public LocalisableString IndexPageString => LayoutStrings.HeaderHelpIndex; public readonly Bindable WikiPageData = new Bindable(); @@ -77,8 +75,8 @@ namespace osu.Game.Overlays.Wiki { public WikiHeaderTitle() { - Title = HeaderTitle; - Description = HeaderDescription; + Title = LayoutStrings.MenuHelpGetWiki; + Description = PageTitleStrings.MainWikiControllerDefault; IconTexture = "Icons/Hexacons/wiki"; } } From 53fe61504cbc53fd77207a4caec081cc76855d63 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 01:35:54 +0800 Subject: [PATCH 040/600] Add localisation for ChangelogHeader --- osu.Game/Localisation/ChangelogStrings.cs | 19 +++++++++++++++++++ .../Overlays/Changelog/ChangelogHeader.cs | 14 ++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Localisation/ChangelogStrings.cs diff --git a/osu.Game/Localisation/ChangelogStrings.cs b/osu.Game/Localisation/ChangelogStrings.cs new file mode 100644 index 0000000000..b720670ded --- /dev/null +++ b/osu.Game/Localisation/ChangelogStrings.cs @@ -0,0 +1,19 @@ +// 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 ChangelogStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.Changelog"; + + /// + /// "track recent dev updates in the osu! ecosystem" + /// + public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"track recent dev updates in the osu! ecosystem"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index f4be4328e7..c1c81046ed 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -9,7 +9,9 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Changelog { @@ -21,16 +23,16 @@ namespace osu.Game.Overlays.Changelog public ChangelogUpdateStreamControl Streams; - private const string listing_string = "listing"; + public LocalisableString ListingString => LayoutStrings.HeaderChangelogIndex; private Box streamsBackground; public ChangelogHeader() { - TabControl.AddItem(listing_string); + TabControl.AddItem(ListingString); Current.ValueChanged += e => { - if (e.NewValue == listing_string) + if (e.NewValue == ListingString) ListingSelected?.Invoke(); }; @@ -63,7 +65,7 @@ namespace osu.Game.Overlays.Changelog } else { - Current.Value = listing_string; + Current.Value = ListingString; Streams.Current.Value = null; } } @@ -114,8 +116,8 @@ namespace osu.Game.Overlays.Changelog { public ChangelogHeaderTitle() { - Title = "changelog"; - Description = "track recent dev updates in the osu! ecosystem"; + Title = LayoutStrings.MenuHomeChangelogIndex; + Description = osu.Game.Localisation.ChangelogStrings.HeaderDescription; IconTexture = "Icons/Hexacons/devtools"; } } From 224c37bdc3e67e0f110c3c679080dddcaa0113b6 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 02:15:14 +0800 Subject: [PATCH 041/600] Add localisation for RankingOverlay --- .../Rankings/RankingsOverlayHeader.cs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 92e22f5873..4766d1ab3c 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Bindables; +using osu.Framework.Localisation; using osu.Game.Rulesets; +using osu.Game.Resources.Localisation.Web; using osu.Game.Users; namespace osu.Game.Overlays.Rankings @@ -29,13 +32,14 @@ namespace osu.Game.Overlays.Rankings { public RankingsTitle() { - Title = "ranking"; + Title = LayoutStrings.MenuRankingsDefault; Description = "find out who's the best right now"; IconTexture = "Icons/Hexacons/rankings"; } } } + [LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))] public enum RankingsScope { Performance, @@ -43,4 +47,29 @@ namespace osu.Game.Overlays.Rankings Score, Country } + + public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(RankingsScope value) + { + switch (value) + { + case RankingsScope.Performance: + return LayoutStrings.MenuRankingsIndex; + + case RankingsScope.Spotlights: + return LayoutStrings.MenuRankingsCharts; + + case RankingsScope.Score: + return LayoutStrings.MenuRankingsScore; + + case RankingsScope.Country: + return LayoutStrings.MenuRankingsCountry; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } + } From 93e79d122fe04e0ab5080eb8e042c313ac27c17d Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 02:23:12 +0800 Subject: [PATCH 042/600] Move strings together --- ...Strings.cs => HeaderDescriptionStrings.cs} | 11 ++++++++--- osu.Game/Localisation/NewsStrings.cs | 19 ------------------- .../Overlays/Changelog/ChangelogHeader.cs | 3 ++- osu.Game/Overlays/News/NewsHeader.cs | 3 ++- 4 files changed, 12 insertions(+), 24 deletions(-) rename osu.Game/Localisation/{ChangelogStrings.cs => HeaderDescriptionStrings.cs} (50%) delete mode 100644 osu.Game/Localisation/NewsStrings.cs diff --git a/osu.Game/Localisation/ChangelogStrings.cs b/osu.Game/Localisation/HeaderDescriptionStrings.cs similarity index 50% rename from osu.Game/Localisation/ChangelogStrings.cs rename to osu.Game/Localisation/HeaderDescriptionStrings.cs index b720670ded..6dbc28a619 100644 --- a/osu.Game/Localisation/ChangelogStrings.cs +++ b/osu.Game/Localisation/HeaderDescriptionStrings.cs @@ -5,14 +5,19 @@ using osu.Framework.Localisation; namespace osu.Game.Localisation { - public static class ChangelogStrings + public static class HeaderDescriptionStrings { - private const string prefix = @"osu.Game.Resources.Localisation.Changelog"; + private const string prefix = @"osu.Game.Resources.Localisation.HeaderDescription"; /// /// "track recent dev updates in the osu! ecosystem" /// - public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"track recent dev updates in the osu! ecosystem"); + public static LocalisableString Changelog => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); + + /// + /// "get up-to-date on community happenings" + /// + public static LocalisableString News => new TranslatableString(getKey(@"news"), @"get up-to-date on community happenings"); private static string getKey(string key) => $"{prefix}:{key}"; } diff --git a/osu.Game/Localisation/NewsStrings.cs b/osu.Game/Localisation/NewsStrings.cs deleted file mode 100644 index 4f1fe6e776..0000000000 --- a/osu.Game/Localisation/NewsStrings.cs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 NewsStrings - { - private const string prefix = @"osu.Game.Resources.Localisation.News"; - - /// - /// "join the real-time discussion" - /// - public static LocalisableString HeaderDescription => new TranslatableString(getKey(@"header_description"), @"get up-to-date on community happenings"); - - private static string getKey(string key) => $"{prefix}:{key}"; - } -} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index c1c81046ed..a282c77bd6 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; @@ -117,7 +118,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeaderTitle() { Title = LayoutStrings.MenuHomeChangelogIndex; - Description = osu.Game.Localisation.ChangelogStrings.HeaderDescription; + Description = HeaderDescriptionStrings.Changelog; IconTexture = "Icons/Hexacons/devtools"; } } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 7f08300912..b6e49811ad 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.News @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.News public NewsHeaderTitle() { Title = LayoutStrings.MenuHomeNewsIndex; - Description = osu.Game.Localisation.NewsStrings.HeaderDescription; + Description = HeaderDescriptionStrings.News; IconTexture = "Icons/Hexacons/news"; } } From 3b48975f1e7f1b0ed760c56a964bdc8aea75ed34 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 02:32:23 +0800 Subject: [PATCH 043/600] Add localisation for RankingOverlayHeader --- osu.Game/Localisation/HeaderDescriptionStrings.cs | 5 +++++ osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/HeaderDescriptionStrings.cs b/osu.Game/Localisation/HeaderDescriptionStrings.cs index 6dbc28a619..88ee4a0d75 100644 --- a/osu.Game/Localisation/HeaderDescriptionStrings.cs +++ b/osu.Game/Localisation/HeaderDescriptionStrings.cs @@ -14,6 +14,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Changelog => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); + /// + /// "find out who's the best right now" + /// + public static LocalisableString Rankings => new TranslatableString(getKey(@"rankings"), @"find out who's the best right now"); + /// /// "get up-to-date on community happenings" /// diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 4766d1ab3c..92750d8806 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Rulesets; using osu.Game.Resources.Localisation.Web; using osu.Game.Users; @@ -33,7 +34,7 @@ namespace osu.Game.Overlays.Rankings public RankingsTitle() { Title = LayoutStrings.MenuRankingsDefault; - Description = "find out who's the best right now"; + Description = HeaderDescriptionStrings.Rankings; IconTexture = "Icons/Hexacons/rankings"; } } From f588607ed978aeb333e3f06e69ed833b7b2525f6 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 02:38:15 +0800 Subject: [PATCH 044/600] Add localisation for BeatmapListingHeader --- osu.Game/Localisation/HeaderDescriptionStrings.cs | 5 +++++ osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/HeaderDescriptionStrings.cs b/osu.Game/Localisation/HeaderDescriptionStrings.cs index 88ee4a0d75..c84822de53 100644 --- a/osu.Game/Localisation/HeaderDescriptionStrings.cs +++ b/osu.Game/Localisation/HeaderDescriptionStrings.cs @@ -9,6 +9,11 @@ namespace osu.Game.Localisation { private const string prefix = @"osu.Game.Resources.Localisation.HeaderDescription"; + /// + /// "browse for new beatmaps" + /// + public static LocalisableString BeatmapListing => new TranslatableString(getKey(@"beatmap_listing"), @"browse for new beatmaps"); + /// /// "track recent dev updates in the osu! ecosystem" /// diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index 6a9a71210a..48ecbce7c1 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; + namespace osu.Game.Overlays.BeatmapListing { public class BeatmapListingHeader : OverlayHeader @@ -11,8 +14,8 @@ namespace osu.Game.Overlays.BeatmapListing { public BeatmapListingTitle() { - Title = "beatmap listing"; - Description = "browse for new beatmaps"; + Title = PageTitleStrings.MainBeatmapsetsControllerIndex; + Description = HeaderDescriptionStrings.BeatmapListing; IconTexture = "Icons/Hexacons/beatmap"; } } From f80b18377775e3bf52b4370d0bd7459dc383112c Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 02:44:09 +0800 Subject: [PATCH 045/600] Add localisation for DashboardOverlayHeader --- osu.Game/Localisation/HeaderDescriptionStrings.cs | 5 +++++ osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/HeaderDescriptionStrings.cs b/osu.Game/Localisation/HeaderDescriptionStrings.cs index c84822de53..6ed703191a 100644 --- a/osu.Game/Localisation/HeaderDescriptionStrings.cs +++ b/osu.Game/Localisation/HeaderDescriptionStrings.cs @@ -19,6 +19,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Changelog => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); + /// + /// "view your friends and other information" + /// + public static LocalisableString Dashboard => new TranslatableString(getKey(@"dashboard"), @"view your friends and other information"); + /// /// "find out who's the best right now" /// diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 056d4ad6f7..284e95ad84 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard @@ -17,7 +18,7 @@ namespace osu.Game.Overlays.Dashboard public DashboardTitle() { Title = HomeStrings.UserTitle; - Description = "view your friends and other information"; + Description = HeaderDescriptionStrings.Dashboard; IconTexture = "Icons/Hexacons/social"; } } From 1cc9e504cf2bc922a19253a007d12be80646380d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Jul 2021 02:17:21 +0900 Subject: [PATCH 046/600] Remove incorrectly added null coalesce --- osu.Game/Overlays/Wiki/WikiHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 4eac60f0eb..811e654387 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Wiki private void onCurrentChange(ValueChangedEvent e) { - if (e?.NewValue == TabControl.Items.LastOrDefault()) + if (e.NewValue == TabControl.Items.LastOrDefault()) return; if (e.NewValue == IndexPageString) From 5fc13975643b0d517634358c70a56dad974737b5 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 09:55:40 +0800 Subject: [PATCH 047/600] Apply suggestion from code review Co-authored-by: frenzibyte --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 3 ++- osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs | 1 - osu.Game/Overlays/Wiki/WikiHeader.cs | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index a282c77bd6..56e852fe80 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogUpdateStreamControl Streams; - public LocalisableString ListingString => LayoutStrings.HeaderChangelogIndex; + public static LocalisableString ListingString => LayoutStrings.HeaderChangelogIndex; private Box streamsBackground; diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index b6e49811ad..7e10d855fe 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -12,7 +12,8 @@ namespace osu.Game.Overlays.News { public class NewsHeader : BreadcrumbControlOverlayHeader { - public LocalisableString FrontPageString => osu.Game.Resources.Localisation.Web.NewsStrings.IndexTitleInfo; + public static LocalisableString FrontPageString => NewsStrings.IndexTitleInfo; + public Action ShowFrontPage; private readonly Bindable article = new Bindable(); diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 92750d8806..ba88eec6aa 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -72,5 +72,4 @@ namespace osu.Game.Overlays.Rankings } } } - } diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index f24d59a8d3..286711c518 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -14,7 +14,8 @@ namespace osu.Game.Overlays.Wiki public class WikiHeader : BreadcrumbControlOverlayHeader { private const string index_path = "Main_Page"; - public LocalisableString IndexPageString => LayoutStrings.HeaderHelpIndex; + + public static LocalisableString IndexPageString => LayoutStrings.HeaderHelpIndex; public readonly Bindable WikiPageData = new Bindable(); From 57eed886018810be9f83c198ee8240b25ffa3595 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sun, 18 Jul 2021 10:12:24 +0800 Subject: [PATCH 048/600] symbol renaming Co-authored-by: frenzibyte --- ...nStrings.cs => NamedOverlayComponentStrings.cs} | 14 +++++++------- .../BeatmapListing/BeatmapListingHeader.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- .../Overlays/Dashboard/DashboardOverlayHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 2 +- .../Overlays/Rankings/RankingsOverlayHeader.cs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) rename osu.Game/Localisation/{HeaderDescriptionStrings.cs => NamedOverlayComponentStrings.cs} (50%) diff --git a/osu.Game/Localisation/HeaderDescriptionStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs similarity index 50% rename from osu.Game/Localisation/HeaderDescriptionStrings.cs rename to osu.Game/Localisation/NamedOverlayComponentStrings.cs index 6ed703191a..6cd19a0977 100644 --- a/osu.Game/Localisation/HeaderDescriptionStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -5,34 +5,34 @@ using osu.Framework.Localisation; namespace osu.Game.Localisation { - public static class HeaderDescriptionStrings + public static class NamedOverlayComponentStrings { - private const string prefix = @"osu.Game.Resources.Localisation.HeaderDescription"; + private const string prefix = @"osu.Game.Resources.Localisation.NamedOverlayComponent"; /// /// "browse for new beatmaps" /// - public static LocalisableString BeatmapListing => new TranslatableString(getKey(@"beatmap_listing"), @"browse for new beatmaps"); + public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing"), @"browse for new beatmaps"); /// /// "track recent dev updates in the osu! ecosystem" /// - public static LocalisableString Changelog => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); + public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); /// /// "view your friends and other information" /// - public static LocalisableString Dashboard => new TranslatableString(getKey(@"dashboard"), @"view your friends and other information"); + public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard"), @"view your friends and other information"); /// /// "find out who's the best right now" /// - public static LocalisableString Rankings => new TranslatableString(getKey(@"rankings"), @"find out who's the best right now"); + public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings"), @"find out who's the best right now"); /// /// "get up-to-date on community happenings" /// - public static LocalisableString News => new TranslatableString(getKey(@"news"), @"get up-to-date on community happenings"); + public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news"), @"get up-to-date on community happenings"); private static string getKey(string key) => $"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index 48ecbce7c1..3568fe9e4f 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.BeatmapListing public BeatmapListingTitle() { Title = PageTitleStrings.MainBeatmapsetsControllerIndex; - Description = HeaderDescriptionStrings.BeatmapListing; + Description = NamedOverlayComponentStrings.BeatmapListingDescription; IconTexture = "Icons/Hexacons/beatmap"; } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 56e852fe80..ef174298c2 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -118,7 +118,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeaderTitle() { Title = LayoutStrings.MenuHomeChangelogIndex; - Description = HeaderDescriptionStrings.Changelog; + Description = NamedOverlayComponentStrings.ChangelogDescription; IconTexture = "Icons/Hexacons/devtools"; } } diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 284e95ad84..5e69caad6e 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Dashboard public DashboardTitle() { Title = HomeStrings.UserTitle; - Description = HeaderDescriptionStrings.Dashboard; + Description = NamedOverlayComponentStrings.DashboardDescription; IconTexture = "Icons/Hexacons/social"; } } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 7e10d855fe..23fab6faaf 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.News public NewsHeaderTitle() { Title = LayoutStrings.MenuHomeNewsIndex; - Description = HeaderDescriptionStrings.News; + Description = NamedOverlayComponentStrings.NewsDescription; IconTexture = "Icons/Hexacons/news"; } } diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index ba88eec6aa..812c2f2182 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Rankings public RankingsTitle() { Title = LayoutStrings.MenuRankingsDefault; - Description = HeaderDescriptionStrings.Rankings; + Description = NamedOverlayComponentStrings.RankingsDescription; IconTexture = "Icons/Hexacons/rankings"; } } From 765881d8b0c2c89b6d0934f9d734d81670047643 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Mon, 19 Jul 2021 19:23:26 +0800 Subject: [PATCH 049/600] Move strings --- .../NamedOverlayComponentStrings.cs | 22 +++++++++++++++++++ .../BeatmapListing/BeatmapListingHeader.cs | 3 +-- .../Overlays/Changelog/ChangelogHeader.cs | 2 +- .../Dashboard/DashboardOverlayHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 2 +- .../Rankings/RankingsOverlayHeader.cs | 2 +- osu.Game/Overlays/Wiki/WikiHeader.cs | 5 +++-- 7 files changed, 30 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/NamedOverlayComponentStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs index 6cd19a0977..0167a1b030 100644 --- a/osu.Game/Localisation/NamedOverlayComponentStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Localisation { @@ -9,31 +10,52 @@ namespace osu.Game.Localisation { private const string prefix = @"osu.Game.Resources.Localisation.NamedOverlayComponent"; + /// + public static LocalisableString BeatmapListingTitle => PageTitleStrings.MainBeatmapsetsControllerIndex; + /// /// "browse for new beatmaps" /// public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing"), @"browse for new beatmaps"); + /// + public static LocalisableString ChangelogTitle => PageTitleStrings.MainChangelogControllerDefault; + /// /// "track recent dev updates in the osu! ecosystem" /// public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); + /// + public static LocalisableString DashboardTitle => PageTitleStrings.MainHomeControllerIndex; + /// /// "view your friends and other information" /// public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard"), @"view your friends and other information"); + /// + public static LocalisableString RankingsTitle => PageTitleStrings.MainRankingControllerDefault; + /// /// "find out who's the best right now" /// public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings"), @"find out who's the best right now"); + /// + public static LocalisableString NewsTitle => PageTitleStrings.MainNewsControllerDefault; + /// /// "get up-to-date on community happenings" /// public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news"), @"get up-to-date on community happenings"); + /// + public static LocalisableString WikiTitle => LayoutStrings.MenuHelpGetWiki; + + /// + public static LocalisableString WikiDescription => PageTitleStrings.MainWikiControllerDefault; + private static string getKey(string key) => $"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index 3568fe9e4f..fa2ee0d735 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Localisation; -using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { @@ -14,7 +13,7 @@ namespace osu.Game.Overlays.BeatmapListing { public BeatmapListingTitle() { - Title = PageTitleStrings.MainBeatmapsetsControllerIndex; + Title = NamedOverlayComponentStrings.BeatmapListingTitle; Description = NamedOverlayComponentStrings.BeatmapListingDescription; IconTexture = "Icons/Hexacons/beatmap"; } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index ef174298c2..8707883ddd 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -117,7 +117,7 @@ namespace osu.Game.Overlays.Changelog { public ChangelogHeaderTitle() { - Title = LayoutStrings.MenuHomeChangelogIndex; + Title = NamedOverlayComponentStrings.ChangelogTitle; Description = NamedOverlayComponentStrings.ChangelogDescription; IconTexture = "Icons/Hexacons/devtools"; } diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 5e69caad6e..05c9f30ff3 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Dashboard { public DashboardTitle() { - Title = HomeStrings.UserTitle; + Title = NamedOverlayComponentStrings.DashboardTitle; Description = NamedOverlayComponentStrings.DashboardDescription; IconTexture = "Icons/Hexacons/social"; } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 23fab6faaf..bf739e1e8e 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.News { public NewsHeaderTitle() { - Title = LayoutStrings.MenuHomeNewsIndex; + Title = NamedOverlayComponentStrings.NewsTitle; Description = NamedOverlayComponentStrings.NewsDescription; IconTexture = "Icons/Hexacons/news"; } diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 812c2f2182..b6c16d398d 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Rankings { public RankingsTitle() { - Title = LayoutStrings.MenuRankingsDefault; + Title = NamedOverlayComponentStrings.RankingsTitle; Description = NamedOverlayComponentStrings.RankingsDescription; IconTexture = "Icons/Hexacons/rankings"; } diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 286711c518..4c90551d35 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; @@ -76,8 +77,8 @@ namespace osu.Game.Overlays.Wiki { public WikiHeaderTitle() { - Title = LayoutStrings.MenuHelpGetWiki; - Description = PageTitleStrings.MainWikiControllerDefault; + Title = NamedOverlayComponentStrings.WikiTitle; + Description = NamedOverlayComponentStrings.WikiDescription; IconTexture = "Icons/Hexacons/wiki"; } } From 3a4da6b86795c22cabe94028a75f99875574d3a4 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Mon, 19 Jul 2021 20:02:39 +0800 Subject: [PATCH 050/600] use same code style Co-authored-by: frenzibyte --- osu.Game/Localisation/NamedOverlayComponentStrings.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Localisation/NamedOverlayComponentStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs index 0167a1b030..6694d8c008 100644 --- a/osu.Game/Localisation/NamedOverlayComponentStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -51,10 +51,12 @@ namespace osu.Game.Localisation public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news"), @"get up-to-date on community happenings"); /// - public static LocalisableString WikiTitle => LayoutStrings.MenuHelpGetWiki; + public static LocalisableString WikiTitle => PageTitleStrings.MainWikiControllerDefault; - /// - public static LocalisableString WikiDescription => PageTitleStrings.MainWikiControllerDefault; + /// + /// "knowledge base" + /// + public static LocalisableString WikiDescription => new TranslatableString(getKey(@"wiki"), @"knowledge base"); private static string getKey(string key) => $"{prefix}:{key}"; } From fe7aa73aad810d08608dc8722a53de9587c9dc02 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Mon, 19 Jul 2021 20:45:03 +0800 Subject: [PATCH 051/600] Add localisation for BeatmapSetHeader --- osu.Game/Localisation/NamedOverlayComponentStrings.cs | 3 +++ osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/NamedOverlayComponentStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs index 6694d8c008..f40b97e605 100644 --- a/osu.Game/Localisation/NamedOverlayComponentStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -18,6 +18,9 @@ namespace osu.Game.Localisation /// public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing"), @"browse for new beatmaps"); + /// + public static LocalisableString BeatmapSetTitle => PageTitleStrings.MainBeatmapsetsControllerShow; + /// public static LocalisableString ChangelogTitle => PageTitleStrings.MainChangelogControllerDefault; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs index 4b26b02a8e..4fd24d9819 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; using osu.Game.Beatmaps; +using osu.Game.Localisation; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -54,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet { public BeatmapHeaderTitle() { - Title = "beatmap info"; + Title = NamedOverlayComponentStrings.BeatmapSetTitle; IconTexture = "Icons/Hexacons/beatmap"; } } From ccc782ea7eb718aa46248244590760aecd29954c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 20 Jul 2021 02:24:02 +0300 Subject: [PATCH 052/600] Add `description` to key names of description strings --- .../Localisation/NamedOverlayComponentStrings.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Localisation/NamedOverlayComponentStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs index f40b97e605..b09e128a2b 100644 --- a/osu.Game/Localisation/NamedOverlayComponentStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -16,7 +16,7 @@ namespace osu.Game.Localisation /// /// "browse for new beatmaps" /// - public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing"), @"browse for new beatmaps"); + public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing_description"), @"browse for new beatmaps"); /// public static LocalisableString BeatmapSetTitle => PageTitleStrings.MainBeatmapsetsControllerShow; @@ -27,7 +27,7 @@ namespace osu.Game.Localisation /// /// "track recent dev updates in the osu! ecosystem" /// - public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog"), @"track recent dev updates in the osu! ecosystem"); + public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog_description"), @"track recent dev updates in the osu! ecosystem"); /// public static LocalisableString DashboardTitle => PageTitleStrings.MainHomeControllerIndex; @@ -35,7 +35,7 @@ namespace osu.Game.Localisation /// /// "view your friends and other information" /// - public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard"), @"view your friends and other information"); + public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard_description"), @"view your friends and other information"); /// public static LocalisableString RankingsTitle => PageTitleStrings.MainRankingControllerDefault; @@ -43,7 +43,7 @@ namespace osu.Game.Localisation /// /// "find out who's the best right now" /// - public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings"), @"find out who's the best right now"); + public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings_description"), @"find out who's the best right now"); /// public static LocalisableString NewsTitle => PageTitleStrings.MainNewsControllerDefault; @@ -51,7 +51,7 @@ namespace osu.Game.Localisation /// /// "get up-to-date on community happenings" /// - public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news"), @"get up-to-date on community happenings"); + public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news_description"), @"get up-to-date on community happenings"); /// public static LocalisableString WikiTitle => PageTitleStrings.MainWikiControllerDefault; @@ -59,7 +59,7 @@ namespace osu.Game.Localisation /// /// "knowledge base" /// - public static LocalisableString WikiDescription => new TranslatableString(getKey(@"wiki"), @"knowledge base"); + public static LocalisableString WikiDescription => new TranslatableString(getKey(@"wiki_description"), @"knowledge base"); private static string getKey(string key) => $"{prefix}:{key}"; } From 944bf2c4f946eeed89ea7e1b29cf654eab1dbbc3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 20 Jul 2021 02:25:15 +0300 Subject: [PATCH 053/600] Fix incorrect property xmldoc inherited --- osu.Game/Localisation/NamedOverlayComponentStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/NamedOverlayComponentStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs index b09e128a2b..f160ee57c7 100644 --- a/osu.Game/Localisation/NamedOverlayComponentStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -53,7 +53,7 @@ namespace osu.Game.Localisation /// public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news_description"), @"get up-to-date on community happenings"); - /// + /// public static LocalisableString WikiTitle => PageTitleStrings.MainWikiControllerDefault; /// From 456f4e6f1fce118405e0947f73705e90d1c30306 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 20 Jul 2021 02:29:35 +0300 Subject: [PATCH 054/600] Move `RankingsScope` to own file and fix mapper strings --- .../Rankings/RankingsOverlayHeader.cs | 36 ---------------- osu.Game/Overlays/Rankings/RankingsScope.cs | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 osu.Game/Overlays/Rankings/RankingsScope.cs diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index b6c16d398d..c0f77049de 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -1,13 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Graphics; using osu.Framework.Bindables; -using osu.Framework.Localisation; using osu.Game.Localisation; using osu.Game.Rulesets; -using osu.Game.Resources.Localisation.Web; using osu.Game.Users; namespace osu.Game.Overlays.Rankings @@ -39,37 +36,4 @@ namespace osu.Game.Overlays.Rankings } } } - - [LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))] - public enum RankingsScope - { - Performance, - Spotlights, - Score, - Country - } - - public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(RankingsScope value) - { - switch (value) - { - case RankingsScope.Performance: - return LayoutStrings.MenuRankingsIndex; - - case RankingsScope.Spotlights: - return LayoutStrings.MenuRankingsCharts; - - case RankingsScope.Score: - return LayoutStrings.MenuRankingsScore; - - case RankingsScope.Country: - return LayoutStrings.MenuRankingsCountry; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/Rankings/RankingsScope.cs b/osu.Game/Overlays/Rankings/RankingsScope.cs new file mode 100644 index 0000000000..684408d3a2 --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsScope.cs @@ -0,0 +1,42 @@ +// 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.Localisation; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Overlays.Rankings +{ + [LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))] + public enum RankingsScope + { + Performance, + Spotlights, + Score, + Country + } + + public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(RankingsScope value) + { + switch (value) + { + case RankingsScope.Performance: + return RankingsStrings.TypePerformance; + + case RankingsScope.Spotlights: + return RankingsStrings.TypeCharts; + + case RankingsScope.Score: + return RankingsStrings.TypeScore; + + case RankingsScope.Country: + return RankingsStrings.TypeCountry; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } +} From 51b056bf664332c963a05494071dab530be774ce Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 20 Jul 2021 02:36:04 +0300 Subject: [PATCH 055/600] Fix `WikiHeader` setting `string.Empty` rather than `null` on breadcrumb That's supposed to be fixed already in the base PR, but somehow it continued to exist here. --- osu.Game/Overlays/Wiki/WikiHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 29ab385cd8..b57bffb3d8 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Wiki return; TabControl.Clear(); - Current.Value = string.Empty; + Current.Value = null; TabControl.AddItem(IndexPageString); From 6a8c16d3ef9e215a2021b801f4dd4471dbb031f6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 20 Jul 2021 03:29:32 +0300 Subject: [PATCH 056/600] Fix news/wiki tests checking against incorrect constant string --- osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs | 4 ++-- osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs index 78288bf6e4..994c4fce53 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestControl() { - AddAssert("Front page selected", () => header.Current.Value == "frontpage"); + AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString); AddAssert("1 tab total", () => header.TabCount == 1); AddStep("Set article 1", () => header.SetArticle("1")); @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("2 tabs total", () => header.TabCount == 2); AddStep("Set front page", () => header.SetFrontPage()); - AddAssert("Front page selected", () => header.Current.Value == "frontpage"); + AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString); AddAssert("1 tab total", () => header.TabCount == 1); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs index e7e6030c66..08e61d19f4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestWikiHeader() { - AddAssert("Current is index", () => checkCurrent("index")); + AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString)); AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage { @@ -54,8 +54,8 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Current is welcome", () => checkCurrent("Welcome")); AddAssert("Check breadcrumb", checkBreadcrumb); - AddStep("Change current to index", () => header.Current.Value = "index"); - AddAssert("Current is index", () => checkCurrent("index")); + AddStep("Change current to index", () => header.Current.Value = WikiHeader.IndexPageString); + AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString)); AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage { @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Check breadcrumb", checkBreadcrumb); } - private bool checkCurrent(string expectedCurrent) => header.Current.Value == expectedCurrent; + private bool checkCurrent(LocalisableString expectedCurrent) => header.Current.Value == expectedCurrent; private bool checkBreadcrumb() { From 283d953c4fc5da054b875c4c958ce75c238740fd Mon Sep 17 00:00:00 2001 From: aitani9 <55509723+aitani9@users.noreply.github.com> Date: Wed, 21 Jul 2021 14:07:00 -0700 Subject: [PATCH 057/600] Fix blinds moving when barrel roll mod is active --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 35 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 636cd63c69..f37058564e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -2,6 +2,7 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield.HitObjectContainer, drawableRuleset.Beatmap)); + drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield, drawableRuleset.Beatmap, drawableRuleset.Mods)); } public void ApplyToHealthProcessor(HealthProcessor healthProcessor) @@ -67,6 +68,8 @@ namespace osu.Game.Rulesets.Osu.Mods private readonly CompositeDrawable restrictTo; + private readonly bool barrelRollActive; + /// /// /// Percentage of playfield to extend blinds over. Basically moves the origin points where the blinds start. @@ -80,13 +83,24 @@ namespace osu.Game.Rulesets.Osu.Mods /// private const float leniency = 0.1f; - public DrawableOsuBlinds(CompositeDrawable restrictTo, Beatmap beatmap) + public DrawableOsuBlinds(CompositeDrawable restrictTo, Beatmap beatmap, IEnumerable mods) { this.restrictTo = restrictTo; this.beatmap = beatmap; targetBreakMultiplier = 0; easing = 1; + + barrelRollActive = false; + + foreach (Mod mod in mods) + { + if (mod is OsuModBarrelRoll) + { + barrelRollActive = true; + break; + } + } } [BackgroundDependencyLoader] @@ -128,8 +142,21 @@ namespace osu.Game.Rulesets.Osu.Mods protected override void Update() { - float start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; - float end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; + float start, end; + + if (barrelRollActive) + { + float origin = restrictTo.ToSpaceOfOtherDrawable(restrictTo.OriginPosition, Parent).X; + float halfDiagonal = MathF.Sqrt(MathF.Pow(restrictTo.DrawWidth / 2, 2) + MathF.Pow(restrictTo.DrawHeight / 2, 2)); + + start = origin - halfDiagonal; + end = origin + halfDiagonal; + } + else + { + start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; + end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; + } float rawWidth = end - start; From e6b28e1386a481ee8e06aef41ae30ef1fae61370 Mon Sep 17 00:00:00 2001 From: aitani9 <55509723+aitani9@users.noreply.github.com> Date: Thu, 22 Jul 2021 14:01:31 -0700 Subject: [PATCH 058/600] Rename `origin` to `center` for clarity --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index f37058564e..c4872aaf64 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -146,11 +146,11 @@ namespace osu.Game.Rulesets.Osu.Mods if (barrelRollActive) { - float origin = restrictTo.ToSpaceOfOtherDrawable(restrictTo.OriginPosition, Parent).X; + float center = restrictTo.ToSpaceOfOtherDrawable(restrictTo.OriginPosition, Parent).X; float halfDiagonal = MathF.Sqrt(MathF.Pow(restrictTo.DrawWidth / 2, 2) + MathF.Pow(restrictTo.DrawHeight / 2, 2)); - start = origin - halfDiagonal; - end = origin + halfDiagonal; + start = center - halfDiagonal; + end = center + halfDiagonal; } else { From 80cb7c77b911f380a7fd558d375509bc3e729bf4 Mon Sep 17 00:00:00 2001 From: aitani9 <55509723+aitani9@users.noreply.github.com> Date: Thu, 22 Jul 2021 14:04:01 -0700 Subject: [PATCH 059/600] Calculate the diagonal length using `Vector2.LengthFast` instead of manually --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index c4872aaf64..09d73566a1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Osu.Mods if (barrelRollActive) { float center = restrictTo.ToSpaceOfOtherDrawable(restrictTo.OriginPosition, Parent).X; - float halfDiagonal = MathF.Sqrt(MathF.Pow(restrictTo.DrawWidth / 2, 2) + MathF.Pow(restrictTo.DrawHeight / 2, 2)); + float halfDiagonal = (restrictTo.DrawSize / 2).LengthFast; start = center - halfDiagonal; end = center + halfDiagonal; From 715f3e3f7c1240baed2b64c2c096923f9fcec180 Mon Sep 17 00:00:00 2001 From: aitani9 <55509723+aitani9@users.noreply.github.com> Date: Thu, 22 Jul 2021 14:07:41 -0700 Subject: [PATCH 060/600] Make blinds move correctly whenever the playfield is rotated --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 31 +++++++--------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 09d73566a1..3102db270e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -2,13 +2,13 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield, drawableRuleset.Beatmap, drawableRuleset.Mods)); + drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield, drawableRuleset.Beatmap)); } public void ApplyToHealthProcessor(HealthProcessor healthProcessor) @@ -68,8 +68,6 @@ namespace osu.Game.Rulesets.Osu.Mods private readonly CompositeDrawable restrictTo; - private readonly bool barrelRollActive; - /// /// /// Percentage of playfield to extend blinds over. Basically moves the origin points where the blinds start. @@ -83,24 +81,13 @@ namespace osu.Game.Rulesets.Osu.Mods /// private const float leniency = 0.1f; - public DrawableOsuBlinds(CompositeDrawable restrictTo, Beatmap beatmap, IEnumerable mods) + public DrawableOsuBlinds(CompositeDrawable restrictTo, Beatmap beatmap) { this.restrictTo = restrictTo; this.beatmap = beatmap; targetBreakMultiplier = 0; easing = 1; - - barrelRollActive = false; - - foreach (Mod mod in mods) - { - if (mod is OsuModBarrelRoll) - { - barrelRollActive = true; - break; - } - } } [BackgroundDependencyLoader] @@ -144,7 +131,12 @@ namespace osu.Game.Rulesets.Osu.Mods { float start, end; - if (barrelRollActive) + if (Precision.AlmostEquals(restrictTo.Rotation, 0)) + { + start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; + end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; + } + else { float center = restrictTo.ToSpaceOfOtherDrawable(restrictTo.OriginPosition, Parent).X; float halfDiagonal = (restrictTo.DrawSize / 2).LengthFast; @@ -152,11 +144,6 @@ namespace osu.Game.Rulesets.Osu.Mods start = center - halfDiagonal; end = center + halfDiagonal; } - else - { - start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; - end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; - } float rawWidth = end - start; From eb585a612039f6d6a8da0b738e5a55f13e427d18 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Sun, 25 Jul 2021 20:40:50 -0400 Subject: [PATCH 061/600] Add "Mirror" mod --- osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 35 ++++++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + osu.Game/Rulesets/Mods/ModMirror.cs | 14 +++++++++ 3 files changed, 50 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs create mode 100644 osu.Game/Rulesets/Mods/ModMirror.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs new file mode 100644 index 0000000000..5eff999343 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModMirror : ModMirror, IApplicableToHitObject + { + public void ApplyToHitObject(HitObject hitObject) + { + var osuObject = (OsuHitObject)hitObject; + + osuObject.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - osuObject.X, osuObject.Position.Y); + + if (!(hitObject is Slider slider)) + return; + + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); + + var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); + foreach (var point in controlPoints) + point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); + + slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 5f37b0d040..27794d6010 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -166,6 +166,7 @@ namespace osu.Game.Rulesets.Osu new OsuModDifficultyAdjust(), new OsuModClassic(), new OsuModRandom(), + new OsuModMirror(), }; case ModType.Automation: diff --git a/osu.Game/Rulesets/Mods/ModMirror.cs b/osu.Game/Rulesets/Mods/ModMirror.cs new file mode 100644 index 0000000000..c4a7738303 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModMirror.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModMirror : Mod + { + public override string Name => "Mirror"; + public override string Acronym => "MR"; + public override ModType Type => ModType.Conversion; + public override string Description => "Flips the beatmap horizontally."; + public override double ScoreMultiplier => 1; + } +} From 2e1cd4a389e8dce86a3f865b99dbed5c0b4b438d Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Sun, 25 Jul 2021 21:26:21 -0400 Subject: [PATCH 062/600] remove accidental tab characters --- osu.Game/Rulesets/Mods/ModMirror.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModMirror.cs b/osu.Game/Rulesets/Mods/ModMirror.cs index c4a7738303..4b03d6795d 100644 --- a/osu.Game/Rulesets/Mods/ModMirror.cs +++ b/osu.Game/Rulesets/Mods/ModMirror.cs @@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Mods public override string Acronym => "MR"; public override ModType Type => ModType.Conversion; public override string Description => "Flips the beatmap horizontally."; - public override double ScoreMultiplier => 1; + public override double ScoreMultiplier => 1; } } From 04c8ea2813659627ad7fac3a7ac05c86533d00cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jul 2021 16:33:56 +0900 Subject: [PATCH 063/600] Add failing test for the global ruleset being set to an invalid value --- osu.Game.Tests/Visual/TestSceneOsuGame.cs | 44 +++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs index 4e5e8517a4..c52d846a68 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; +using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -32,6 +33,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { [TestFixture] + [HeadlessTest] public class TestSceneOsuGame : OsuTestScene { private IReadOnlyList requiredGameDependencies => new[] @@ -83,10 +85,15 @@ namespace osu.Game.Tests.Visual typeof(PreviewTrackManager), }; + private OsuGame game; + + [Resolved] + private OsuGameBase gameBase { get; set; } + [BackgroundDependencyLoader] - private void load(GameHost host, OsuGameBase gameBase) + private void load(GameHost host) { - OsuGame game = new OsuGame(); + game = new OsuGame(); game.SetHost(host); Children = new Drawable[] @@ -100,7 +107,39 @@ namespace osu.Game.Tests.Visual }; AddUntilStep("wait for load", () => game.IsLoaded); + } + [Test] + public void TestNullRulesetHandled() + { + RulesetInfo ruleset = null; + + AddStep("store current ruleset", () => ruleset = Ruleset.Value); + AddStep("set global ruleset to null value", () => Ruleset.Value = null); + + AddAssert("ruleset still valid", () => Ruleset.Value.Available); + AddAssert("ruleset unchanged", () => ReferenceEquals(Ruleset.Value, ruleset)); + } + + [Test] + public void TestUnavailableRulesetHandled() + { + RulesetInfo ruleset = null; + + AddStep("store current ruleset", () => ruleset = Ruleset.Value); + AddStep("set global ruleset to invalid value", () => Ruleset.Value = new RulesetInfo + { + Name = "unavailable", + Available = false, + }); + + AddAssert("ruleset still valid", () => Ruleset.Value.Available); + AddAssert("ruleset unchanged", () => ReferenceEquals(Ruleset.Value, ruleset)); + } + + [Test] + public void TestAvailableDependencies() + { AddAssert("check OsuGame DI members", () => { foreach (var type in requiredGameDependencies) @@ -111,6 +150,7 @@ namespace osu.Game.Tests.Visual return true; }); + AddAssert("check OsuGameBase DI members", () => { foreach (var type in requiredGameBaseDependencies) From 046f30a268bfa27ed72bd2ebec4b71b87fd1d597 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jul 2021 16:34:38 +0900 Subject: [PATCH 064/600] Reject invalid global ruleset values --- osu.Game/OsuGameBase.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4b5fa4f62e..a7fac24351 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -476,13 +476,17 @@ namespace osu.Game private void onRulesetChanged(ValueChangedEvent r) { + if (r.NewValue?.Available != true) + { + // reject the change if the ruleset is not available. + Ruleset.Value = r.OldValue; + return; + } + var dict = new Dictionary>(); - if (r.NewValue?.Available == true) - { - foreach (ModType type in Enum.GetValues(typeof(ModType))) - dict[type] = r.NewValue.CreateInstance().GetModsFor(type).ToList(); - } + foreach (ModType type in Enum.GetValues(typeof(ModType))) + dict[type] = r.NewValue.CreateInstance().GetModsFor(type).ToList(); if (!SelectedMods.Disabled) SelectedMods.Value = Array.Empty(); From bb046fa3b8694a68e694e1a02aa363a44f3b78aa Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 26 Jul 2021 17:46:56 +0900 Subject: [PATCH 065/600] Move catcher trail generation logic to `Catcher` It resolves mutual dependency of `Catcher` and `CatcherTrailDisplay`. Trail generation logic is moved to `Catcher`. The generation logic no longer uses delayed scheduling because the hidden state is hard to manage. Instead, the last time a trail is generated is calculated and used. The new logic has a different behavior when the dash key is pressed in succession under 50ms, but it is not noticeable for normal plays. --- .../TestSceneCatchSkinConfiguration.cs | 2 +- .../TestSceneCatcher.cs | 12 ++-- .../TestSceneCatcherArea.cs | 6 +- .../TestSceneHyperDashColouring.cs | 12 ++-- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 7 +-- osu.Game.Rulesets.Catch/UI/Catcher.cs | 51 ++++++---------- .../UI/CatcherTrailDisplay.cs | 59 +++++++------------ 7 files changed, 56 insertions(+), 93 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs index 83f28086e6..58ff97d563 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests var skin = new TestSkin { FlipCatcherPlate = flip }; container.Child = new SkinProvidingContainer(skin) { - Child = catcher = new Catcher(new Container(), new DroppedObjectContainer()) + Child = catcher = new Catcher(new CatcherTrailDisplay(), new DroppedObjectContainer()) { Anchor = Anchor.Centre } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index b4282e6784..1e582bd9e8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Tests [Resolved] private OsuConfigManager config { get; set; } - private Container trailContainer; + private CatcherTrailDisplay trailDisplay; private DroppedObjectContainer droppedObjectContainer; @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests CircleSize = 0, }; - trailContainer = new Container(); + trailDisplay = new CatcherTrailDisplay(); droppedObjectContainer = new DroppedObjectContainer(); Child = new Container @@ -54,8 +54,8 @@ namespace osu.Game.Rulesets.Catch.Tests Children = new Drawable[] { droppedObjectContainer, - catcher = new TestCatcher(trailContainer, droppedObjectContainer, difficulty), - trailContainer, + catcher = new TestCatcher(trailDisplay, droppedObjectContainer, difficulty), + trailDisplay, } }; }); @@ -294,8 +294,8 @@ namespace osu.Game.Rulesets.Catch.Tests { public IEnumerable CaughtObjects => this.ChildrenOfType(); - public TestCatcher(Container trailsTarget, DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty) - : base(trailsTarget, droppedObjectTarget, difficulty) + public TestCatcher(CatcherTrailDisplay trails, DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty) + : base(trails, droppedObjectTarget, difficulty) { } } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 6a518cf0ef..c97e6bf9ee 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -121,11 +121,13 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestCatcherArea(BeatmapDifficulty beatmapDifficulty) { - var droppedObjectContainer = new DroppedObjectContainer(); + var trailDisplay = new CatcherTrailDisplay { Depth = -1 }; + Add(trailDisplay); + var droppedObjectContainer = new DroppedObjectContainer(); Add(droppedObjectContainer); - Catcher = new Catcher(this, droppedObjectContainer, beatmapDifficulty) + Catcher = new Catcher(trailDisplay, droppedObjectContainer, beatmapDifficulty) { X = CatchPlayfield.CENTER_X }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 73797d0a6a..88ddc7e8a8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -113,30 +113,28 @@ namespace osu.Game.Rulesets.Catch.Tests private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedEndGlowColour = null) { - Container trailsContainer = null; - Catcher catcher = null; CatcherTrailDisplay trails = null; + Catcher catcher = null; AddStep("create hyper-dashing catcher", () => { - trailsContainer = new Container(); + trails = new CatcherTrailDisplay(); Child = setupSkinHierarchy(new Container { Anchor = Anchor.Centre, Children = new Drawable[] { - catcher = new Catcher(trailsContainer, new DroppedObjectContainer()) + catcher = new Catcher(trails, new DroppedObjectContainer()) { Scale = new Vector2(4) }, - trailsContainer + trails } }, skin); }); - AddStep("get trails container", () => + AddStep("start hyper-dash", () => { - trails = trailsContainer.OfType().Single(); catcher.SetHyperDashState(2); }); diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index b43815a8bd..bcbe7c776e 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; @@ -45,14 +44,14 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - var trailContainer = new Container + var trailDisplay = new CatcherTrailDisplay { Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft }; var droppedObjectContainer = new DroppedObjectContainer(); - Catcher = new Catcher(trailContainer, droppedObjectContainer, difficulty) + Catcher = new Catcher(trailDisplay, droppedObjectContainer, difficulty) { X = CENTER_X }; @@ -70,7 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI Origin = Anchor.TopLeft, Catcher = Catcher, }, - trailContainer, + trailDisplay, HitObjectContainer, }); diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 49508b1caf..f8b0dabeb9 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -71,10 +71,10 @@ namespace osu.Game.Rulesets.Catch.UI /// private const float caught_fruit_scale_adjust = 0.5f; - [NotNull] - private readonly Container trailsTarget; - - private CatcherTrailDisplay trails; + /// + /// Contains trails and afterimages (also called "end glow" in code) of the catcher. + /// + private readonly CatcherTrailDisplay trails; /// /// Contains caught objects on the plate. @@ -92,20 +92,7 @@ namespace osu.Game.Rulesets.Catch.UI private set => Body.AnimationState.Value = value; } - private bool dashing; - - public bool Dashing - { - get => dashing; - set - { - if (value == dashing) return; - - dashing = value; - - updateTrailVisibility(); - } - } + public bool Dashing { get; set; } /// /// The currently facing direction. @@ -138,9 +125,9 @@ namespace osu.Game.Rulesets.Catch.UI private readonly DrawablePool caughtBananaPool; private readonly DrawablePool caughtDropletPool; - public Catcher([NotNull] Container trailsTarget, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null) + public Catcher([NotNull] CatcherTrailDisplay trails, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null) { - this.trailsTarget = trailsTarget; + this.trails = trails; this.droppedObjectTarget = droppedObjectTarget; Origin = Anchor.TopCentre; @@ -177,15 +164,6 @@ namespace osu.Game.Rulesets.Catch.UI private void load(OsuConfigManager config) { hitLighting = config.GetBindable(OsuSetting.HitLighting); - trails = new CatcherTrailDisplay(this); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - // don't add in above load as we may potentially modify a parent in an unsafe manner. - trailsTarget.Add(trails); } /// @@ -313,7 +291,7 @@ namespace osu.Game.Rulesets.Catch.UI if (!wasHyperDashing) { - trails.DisplayEndGlow(); + trails.DisplayEndGlow(CurrentState, X, Scale * Body.Scale); runHyperDashStateTransition(true); } } @@ -331,13 +309,9 @@ namespace osu.Game.Rulesets.Catch.UI private void runHyperDashStateTransition(bool hyperDashing) { - updateTrailVisibility(); - this.FadeColour(hyperDashing ? hyperDashColour : Color4.White, HYPER_DASH_TRANSITION_DURATION, Easing.OutQuint); } - private void updateTrailVisibility() => trails.DisplayTrail = Dashing || HyperDashing; - protected override void SkinChanged(ISkinSource skin) { base.SkinChanged(skin); @@ -373,6 +347,15 @@ namespace osu.Game.Rulesets.Catch.UI X = hyperDashTargetPosition; SetHyperDashState(); } + + if (Dashing || HyperDashing) + { + double lastTrailTime = trails.LastDashTrail?.LifetimeStart ?? double.NegativeInfinity; + double generationInterval = HyperDashing ? 25 : 50; + + if (Time.Current - lastTrailTime >= generationInterval) + trails.DisplayDashTrail(CurrentState, X, Scale * Body.Scale, HyperDashing); + } } private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index b59fabcb70..347df5f114 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -1,7 +1,7 @@ // 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.Linq; using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,7 +17,10 @@ namespace osu.Game.Rulesets.Catch.UI /// public class CatcherTrailDisplay : CompositeDrawable { - private readonly Catcher catcher; + [CanBeNull] + public CatcherTrail LastDashTrail => dashTrails.Concat(hyperDashTrails) + .OrderByDescending(trail => trail.LifetimeStart) + .FirstOrDefault(); private readonly DrawablePool trailPool; @@ -55,30 +58,8 @@ namespace osu.Game.Rulesets.Catch.UI } } - private bool trail; - - /// - /// Whether to start displaying trails following the catcher. - /// - public bool DisplayTrail + public CatcherTrailDisplay() { - get => trail; - set - { - if (trail == value) - return; - - trail = value; - - if (trail) - displayTrail(); - } - } - - public CatcherTrailDisplay([NotNull] Catcher catcher) - { - this.catcher = catcher ?? throw new ArgumentNullException(nameof(catcher)); - RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] @@ -93,9 +74,11 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Displays a single end-glow catcher sprite. /// - public void DisplayEndGlow() + public void DisplayEndGlow(CatcherAnimationState animationState, float x, Vector2 scale) { - var endGlow = createTrailSprite(endGlowSprites); + var endGlow = createTrail(animationState, x, scale); + + endGlowSprites.Add(endGlow); endGlow.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); endGlow.ScaleTo(endGlow.Scale * 0.95f).ScaleTo(endGlow.Scale * 1.2f, 1200, Easing.In); @@ -103,28 +86,26 @@ namespace osu.Game.Rulesets.Catch.UI endGlow.Expire(true); } - private void displayTrail() + public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing) { - if (!DisplayTrail) - return; + var sprite = createTrail(animationState, x, scale); - var sprite = createTrailSprite(catcher.HyperDashing ? hyperDashTrails : dashTrails); + if (hyperDashing) + hyperDashTrails.Add(sprite); + else + dashTrails.Add(sprite); sprite.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); sprite.Expire(true); - - Scheduler.AddDelayed(displayTrail, catcher.HyperDashing ? 25 : 50); } - private CatcherTrail createTrailSprite(Container target) + private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale) { CatcherTrail sprite = trailPool.Get(); - sprite.AnimationState = catcher.CurrentState; - sprite.Scale = catcher.Scale * catcher.Body.Scale; - sprite.Position = catcher.Position; - - target.Add(sprite); + sprite.AnimationState = animationState; + sprite.Scale = scale; + sprite.Position = new Vector2(x, 0); return sprite; } From c08130398cd604aa6a2235879ffc2601e8aa5c8e Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 26 Jul 2021 17:50:10 +0900 Subject: [PATCH 066/600] Add some comments --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 3 +++ osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index f8b0dabeb9..fa444fdad7 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -92,6 +92,9 @@ namespace osu.Game.Rulesets.Catch.UI private set => Body.AnimationState.Value = value; } + /// + /// Whether the catcher is currently dashing. + /// public bool Dashing { get; set; } /// diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index 347df5f114..00f2a76bde 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -17,6 +17,10 @@ namespace osu.Game.Rulesets.Catch.UI /// public class CatcherTrailDisplay : CompositeDrawable { + /// + /// The most recent dash trail added in this container. + /// Only alive (not faded out) trails are considered. + /// [CanBeNull] public CatcherTrail LastDashTrail => dashTrails.Concat(hyperDashTrails) .OrderByDescending(trail => trail.LifetimeStart) From 428244227818b5267021734ab907074e49c919cb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 26 Jul 2021 17:50:52 +0900 Subject: [PATCH 067/600] Make `Catcher.body` private as it is no longer needed by `CatcherTrailDisplay` --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index fa444fdad7..e7c26ee44f 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -88,8 +88,8 @@ namespace osu.Game.Rulesets.Catch.UI public CatcherAnimationState CurrentState { - get => Body.AnimationState.Value; - private set => Body.AnimationState.Value = value; + get => body.AnimationState.Value; + private set => body.AnimationState.Value = value; } /// @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Catch.UI /// private readonly float catchWidth; - internal readonly SkinnableCatcher Body; + private readonly SkinnableCatcher body; private Color4 hyperDashColour = DEFAULT_HYPER_DASH_COLOUR; private Color4 hyperDashEndGlowColour = DEFAULT_HYPER_DASH_COLOUR; @@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Catch.UI // offset fruit vertically to better place "above" the plate. Y = -5 }, - Body = new SkinnableCatcher(), + body = new SkinnableCatcher(), hitExplosionContainer = new HitExplosionContainer { Anchor = Anchor.TopCentre, @@ -294,7 +294,7 @@ namespace osu.Game.Rulesets.Catch.UI if (!wasHyperDashing) { - trails.DisplayEndGlow(CurrentState, X, Scale * Body.Scale); + trails.DisplayEndGlow(CurrentState, X, Scale * body.Scale); runHyperDashStateTransition(true); } } @@ -340,7 +340,7 @@ namespace osu.Game.Rulesets.Catch.UI base.Update(); var scaleFromDirection = new Vector2((int)VisualDirection, 1); - Body.Scale = scaleFromDirection; + body.Scale = scaleFromDirection; caughtObjectContainer.Scale = hitExplosionContainer.Scale = flipCatcherPlate ? scaleFromDirection : Vector2.One; // Correct overshooting. @@ -357,7 +357,7 @@ namespace osu.Game.Rulesets.Catch.UI double generationInterval = HyperDashing ? 25 : 50; if (Time.Current - lastTrailTime >= generationInterval) - trails.DisplayDashTrail(CurrentState, X, Scale * Body.Scale, HyperDashing); + trails.DisplayDashTrail(CurrentState, X, Scale * body.Scale, HyperDashing); } } From 0fbe950a3c452f645f811147d624836c4ca9c996 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 14 Jun 2021 16:26:39 +0900 Subject: [PATCH 068/600] Modify catcher autoplay test pattern to see more variety movement --- osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index f552c3c27b..0ca0ddfcb1 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -27,9 +27,9 @@ namespace osu.Game.Rulesets.Catch.Tests } }; - for (int i = 0; i < 100; i++) + for (int i = 0; i < 12; i++) { - float width = (i % 10 + 1) / 20f * CatchPlayfield.WIDTH; + float width = (i + 1) / 20f * CatchPlayfield.WIDTH; beatmap.HitObjects.Add(new JuiceStream { @@ -39,8 +39,8 @@ namespace osu.Game.Rulesets.Catch.Tests Vector2.Zero, new Vector2(width, 0) }), - StartTime = i * 2000, - NewCombo = i % 8 == 0, + StartTime = i * 1000, + NewCombo = i % 5 == 0, Samples = new List(new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 100) From 55e8a44db605f24af80cc71c53c372b5289bc989 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 26 Jul 2021 18:15:59 +0700 Subject: [PATCH 069/600] add test for DrawableComment Can reproduce the issue at https://github.com/ppy/osu/issues/13993 --- .../Visual/Online/TestSceneDrawableComment.cs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs new file mode 100644 index 0000000000..26580d02d8 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -0,0 +1,75 @@ +// 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 NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.Comments; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneDrawableComment : OsuTestScene + { + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + + private Container container; + + [SetUp] + public void SetUp() => Schedule(() => + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background4, + }, + container = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + }; + }); + + [TestCaseSource(nameof(comments))] + public void TestComment(string description, string text) + { + AddStep(description, () => + { + comment.Message = text; + container.Add(new DrawableComment(comment)); + }); + } + + private static readonly Comment comment = new Comment + { + Id = 1, + LegacyName = "Test User", + CreatedAt = DateTimeOffset.Now, + VotesCount = 0, + }; + + private static object[] comments = + { + new[] { "Plain", "This is plain comment" }, + // Taken from https://github.com/ppy/osu/issues/13993#issuecomment-885994077 + new[] + { + "Problematic", @"My tablet doesn't work :( +It's a Huion 420 and it's apparently incompatible with OpenTablet Driver. The warning I get is: ""DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"" and it repeats 4 times on the notification before logging subsequent warnings. +Checking the logs, it looks for other Huion tablets before sending the notification (e.g. + ""2021-07-23 03:52:33 [verbose]: Detect: Searching for tablet 'Huion WH1409 V2' + 20 2021-07-23 03:52:33 [error]: DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"") +I use an Arch based installation of Linux and the tablet runs perfectly with Digimend kernel driver, with area configuration, pen pressure, etc. On osu!lazer the cursor disappears until I set it to ""Borderless"" instead of ""Fullscreen"" and even after it shows up, it goes to the bottom left corner as soon as a map starts. +I have honestly 0 idea of whats going on at this point." + } + }; + } +} From 43100c5288099d7c7eadb5306d61d23080cf2008 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 26 Jul 2021 18:18:33 +0700 Subject: [PATCH 070/600] initial CommentMarkdownContainer --- .../Comments/CommentMarkdownContainer.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 osu.Game/Overlays/Comments/CommentMarkdownContainer.cs diff --git a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs new file mode 100644 index 0000000000..0b0d4d9a58 --- /dev/null +++ b/osu.Game/Overlays/Comments/CommentMarkdownContainer.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 Markdig.Syntax.Inlines; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Game.Graphics.Containers.Markdown; + +namespace osu.Game.Overlays.Comments +{ + public class CommentMarkdownContainer : OsuMarkdownContainer + { + public override MarkdownTextFlowContainer CreateTextFlow() => new CommentMarkdownTextFlowContainer(); + + private class CommentMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer + { + // Don't render image in comment for now + protected override void AddImage(LinkInline linkInline) { } + } + } +} From 2a6aeb5310809d58bcf969958ab105d47a749265 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 26 Jul 2021 18:18:55 +0700 Subject: [PATCH 071/600] use CommentMarkdownContainer in DrawableContainer --- osu.Game/Overlays/Comments/DrawableComment.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index d94f8c4b8b..3520b15b1e 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using System.Linq; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Chat; using osu.Framework.Allocation; using System.Collections.Generic; using System; @@ -61,7 +60,7 @@ namespace osu.Game.Overlays.Comments { LinkFlowContainer username; FillFlowContainer info; - LinkFlowContainer message; + CommentMarkdownContainer message; GridContainer content; VotePill votePill; @@ -153,10 +152,12 @@ namespace osu.Game.Overlays.Comments } } }, - message = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + message = new CommentMarkdownContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y + AutoSizeAxes = Axes.Y, + DocumentMargin = new MarginPadding(0), + DocumentPadding = new MarginPadding(0), }, info = new FillFlowContainer { @@ -275,10 +276,7 @@ namespace osu.Game.Overlays.Comments } if (Comment.HasMessage) - { - var formattedSource = MessageFormatter.FormatText(Comment.Message); - message.AddLinks(formattedSource.Text, formattedSource.Links); - } + message.Text = Comment.Message; if (Comment.IsDeleted) { From f80c46e2a01d94e6dd5939da4ed7eab5e1863d80 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 26 Jul 2021 21:02:57 +0700 Subject: [PATCH 072/600] add heading test --- .../Visual/Online/TestSceneDrawableComment.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index 26580d02d8..b93e7a1739 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -59,6 +59,17 @@ namespace osu.Game.Tests.Visual.Online private static object[] comments = { new[] { "Plain", "This is plain comment" }, + + new[] + { + "Heading", @"# Heading 1 +## Heading 2 +### Heading 3 +#### Heading 4 +##### Heading 5 +###### Heading 6" + }, + // Taken from https://github.com/ppy/osu/issues/13993#issuecomment-885994077 new[] { From 6631f0de1958755724c8f5c375b544e79def2ec6 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 26 Jul 2021 21:07:35 +0700 Subject: [PATCH 073/600] add CommentMarkdownHeading --- .../Comments/CommentMarkdownContainer.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs index 0b0d4d9a58..aeab292b0d 100644 --- a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs +++ b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using Markdig.Syntax; using Markdig.Syntax.Inlines; using osu.Framework.Graphics.Containers.Markdown; using osu.Game.Graphics.Containers.Markdown; @@ -11,10 +12,37 @@ namespace osu.Game.Overlays.Comments { public override MarkdownTextFlowContainer CreateTextFlow() => new CommentMarkdownTextFlowContainer(); + protected override MarkdownHeading CreateHeading(HeadingBlock headingBlock) => new CommentMarkdownHeading(headingBlock); + private class CommentMarkdownTextFlowContainer : OsuMarkdownTextFlowContainer { // Don't render image in comment for now protected override void AddImage(LinkInline linkInline) { } } + + private class CommentMarkdownHeading : OsuMarkdownHeading + { + public CommentMarkdownHeading(HeadingBlock headingBlock) + : base(headingBlock) + { + } + + protected override float GetFontSizeByLevel(int level) + { + var defaultFontSize = base.GetFontSizeByLevel(6); + + switch (level) + { + case 1: + return 1.2f * defaultFontSize; + + case 2: + return 1.1f * defaultFontSize; + + default: + return defaultFontSize; + } + } + } } } From dc864abbd896662ee4d2c7f4f6aeff1e08cd500f Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 26 Jul 2021 21:08:57 +0700 Subject: [PATCH 074/600] add link test --- osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index b93e7a1739..7b741accbb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -59,6 +59,7 @@ namespace osu.Game.Tests.Visual.Online private static object[] comments = { new[] { "Plain", "This is plain comment" }, + new[] { "Link", "Please visit https://osu.ppy.sh" }, new[] { From 49160e4482a0cf54f1ccd783b773b1a35ad1d1da Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:46:41 -0400 Subject: [PATCH 075/600] review modifications: maniamodmirror inheritance, reflection utilities, vertical flip option --- .../Mods/ManiaModMirror.cs | 6 +-- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 15 +----- osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 30 ++++++----- .../Utils/OsuHitObjectGenerationUtils.cs | 52 +++++++++++++++++++ osu.Game/Rulesets/Mods/ModMirror.cs | 1 - 5 files changed, 71 insertions(+), 33 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index cf404cc98e..f01884c97f 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -10,13 +10,9 @@ using osu.Game.Rulesets.Mania.Beatmaps; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModMirror : Mod, IApplicableToBeatmap + public class ManiaModMirror : ModMirror, IApplicableToBeatmap { - public override string Name => "Mirror"; - public override string Acronym => "MR"; - public override ModType Type => ModType.Conversion; public override string Description => "Notes are flipped horizontally."; - public override double ScoreMultiplier => 1; public void ApplyToBeatmap(IBeatmap beatmap) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 16c166257a..a693e50016 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Osu.Utils; using osuTK; namespace osu.Game.Rulesets.Osu.Mods @@ -19,19 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods { var osuObject = (OsuHitObject)hitObject; - osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); - - if (!(hitObject is Slider slider)) - return; - - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - - var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); - foreach (var point in controlPoints) - point.Position.Value = new Vector2(point.Position.Value.X, -point.Position.Value.Y); - - slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index 5eff999343..a8cf72a5c7 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -2,34 +2,36 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Bindables; +using osu.Game.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Osu.Utils; using osuTK; namespace osu.Game.Rulesets.Osu.Mods { public class OsuModMirror : ModMirror, IApplicableToHitObject { + public override string Description => "Reflect the playfield."; + + [SettingSource("Reflect Horizontally", "Reflect the playfield horizontally.")] + public Bindable ReflectY { get; } = new BindableBool(true); + [SettingSource("Reflect Vertically", "Reflect the playfield vertically.")] + public Bindable ReflectX { get; } = new BindableBool(false); + public void ApplyToHitObject(HitObject hitObject) { + if (!(ReflectY.Value || ReflectX.Value)) + return; // TODO deselect the mod if possible so replays and submissions don't have purposeless mods attached. var osuObject = (OsuHitObject)hitObject; - - osuObject.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - osuObject.X, osuObject.Position.Y); - - if (!(hitObject is Slider slider)) - return; - - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); - - var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); - foreach (var point in controlPoints) - point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); - - slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + if (ReflectY.Value) + OsuHitObjectGenerationUtils.ReflectOsuHitObjectHorizontally(osuObject); + if (ReflectX.Value) + OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); } } } diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index 06b964a647..f4ab60367e 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -2,7 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; using osuTK; namespace osu.Game.Rulesets.Osu.Utils @@ -100,5 +104,53 @@ namespace osu.Game.Rulesets.Osu.Utils initial.Length * MathF.Sin(finalAngleRad) ); } + + /// + /// Reflects an OsuHitObject's position horizontally (over the 'y axis'). + /// + /// The OsuHitObject to be reflected. + /// The reflected OsuHitObject. + public static OsuHitObject ReflectOsuHitObjectHorizontally(OsuHitObject osuObject) + { + osuObject.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - osuObject.X, osuObject.Position.Y); + + if (!(osuObject is Slider slider)) + return osuObject; + + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); + + var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); + foreach (var point in controlPoints) + point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); + + slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + + return osuObject; + } + + /// + /// Reflects an OsuHitObject's position vertically (over the 'x axis'). + /// + /// The OsuHitObject to be reflected. + /// The reflected OsuHitObject. + public static OsuHitObject ReflectOsuHitObjectVertically(OsuHitObject osuObject) + { + osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); + + if (!(osuObject is Slider slider)) + return osuObject; + + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + + var controlPoints = slider.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); + foreach (var point in controlPoints) + point.Position.Value = new Vector2(point.Position.Value.X, -point.Position.Value.Y); + + slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); + + return osuObject; + } } } diff --git a/osu.Game/Rulesets/Mods/ModMirror.cs b/osu.Game/Rulesets/Mods/ModMirror.cs index 4b03d6795d..3c4b7d0c60 100644 --- a/osu.Game/Rulesets/Mods/ModMirror.cs +++ b/osu.Game/Rulesets/Mods/ModMirror.cs @@ -8,7 +8,6 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Mirror"; public override string Acronym => "MR"; public override ModType Type => ModType.Conversion; - public override string Description => "Flips the beatmap horizontally."; public override double ScoreMultiplier => 1; } } From 5b06a9d120e494fe5cabd55734cc9716ef399125 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Jul 2021 03:55:49 +0900 Subject: [PATCH 076/600] Apply changes required for AudioMixer --- osu.Game/Audio/PreviewTrackManager.cs | 11 +++++++---- osu.Game/Tests/Visual/OsuTestScene.cs | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index d88fd1e62b..e2c4657057 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -7,6 +7,7 @@ using System.IO; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Mixing; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -30,11 +31,11 @@ namespace osu.Game.Audio private readonly BindableNumber globalTrackVolumeAdjust = new BindableNumber(OsuGameBase.GLOBAL_TRACK_VOLUME_ADJUST); [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audioManager) { // this is a temporary solution to get around muting ourselves. // todo: update this once we have a BackgroundTrackManager or similar. - trackStore = new PreviewTrackStore(new OnlineStore()); + trackStore = new PreviewTrackStore(audioManager.Mixer, new OnlineStore()); audio.AddItem(trackStore); trackStore.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust); @@ -118,10 +119,12 @@ namespace osu.Game.Audio private class PreviewTrackStore : AudioCollectionManager, ITrackStore { + private readonly AudioMixer defaultMixer; private readonly IResourceStore store; - internal PreviewTrackStore(IResourceStore store) + internal PreviewTrackStore(AudioMixer defaultMixer, IResourceStore store) { + this.defaultMixer = defaultMixer; this.store = store; } @@ -145,7 +148,7 @@ namespace osu.Game.Audio if (dataStream == null) return null; - Track track = new TrackBass(dataStream); + Track track = new TrackBass(dataStream, (IBassAudioMixer)defaultMixer); AddItem(track); return track; } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 57e400a77e..242c3298e8 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -10,6 +10,7 @@ using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Mixing; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -290,6 +291,7 @@ namespace osu.Game.Tests.Visual private bool running; public TrackVirtualManual(IFrameBasedClock referenceClock) + : base(new NullAudioMixer()) { this.referenceClock = referenceClock; Length = double.PositiveInfinity; From c7c261ba037f02449d5f7dcabf9b1837839fa581 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:48:03 -0400 Subject: [PATCH 077/600] review modifications: change xmldoc wording, configure with enum instead of bool, declare incompatibility with hr --- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 3 ++ osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 34 +++++++++++++------ .../Utils/OsuHitObjectGenerationUtils.cs | 4 +-- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index a693e50016..82b8959456 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -1,6 +1,7 @@ // 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.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mods; @@ -16,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Mods { public override double ScoreMultiplier => 1.06; + public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModDifficultyAdjust), typeof(ModMirror) }; + public void ApplyToHitObject(HitObject hitObject) { var osuObject = (OsuHitObject)hitObject; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index a8cf72a5c7..fd1d685fd1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -1,6 +1,7 @@ // 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.Linq; using osu.Framework.Bindables; using osu.Game.Configuration; @@ -17,21 +18,34 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModMirror : ModMirror, IApplicableToHitObject { public override string Description => "Reflect the playfield."; + public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - [SettingSource("Reflect Horizontally", "Reflect the playfield horizontally.")] - public Bindable ReflectY { get; } = new BindableBool(true); - [SettingSource("Reflect Vertically", "Reflect the playfield vertically.")] - public Bindable ReflectX { get; } = new BindableBool(false); + [SettingSource("Reflection", "Change the type of reflection.")] + public Bindable Reflection { get; } = new Bindable(); public void ApplyToHitObject(HitObject hitObject) { - if (!(ReflectY.Value || ReflectX.Value)) - return; // TODO deselect the mod if possible so replays and submissions don't have purposeless mods attached. var osuObject = (OsuHitObject)hitObject; - if (ReflectY.Value) - OsuHitObjectGenerationUtils.ReflectOsuHitObjectHorizontally(osuObject); - if (ReflectX.Value) - OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); + switch (Reflection.Value) + { + case MirrorType.Horizontal: + OsuHitObjectGenerationUtils.ReflectOsuHitObjectHorizontally(osuObject); + break; + case MirrorType.Vertical: + OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); + break; + case MirrorType.Both: + OsuHitObjectGenerationUtils.ReflectOsuHitObjectHorizontally(osuObject); + OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); + break; + } + } + + public enum MirrorType + { + Horizontal, + Vertical, + Both } } } diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index f4ab60367e..bf55898901 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -106,7 +106,7 @@ namespace osu.Game.Rulesets.Osu.Utils } /// - /// Reflects an OsuHitObject's position horizontally (over the 'y axis'). + /// Reflects an OsuHitObject's position horizontally. /// /// The OsuHitObject to be reflected. /// The reflected OsuHitObject. @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Osu.Utils } /// - /// Reflects an OsuHitObject's position vertically (over the 'x axis'). + /// Reflects an OsuHitObject's position vertically. /// /// The OsuHitObject to be reflected. /// The reflected OsuHitObject. From 34c671f712d71c8a3e3821d7dc45e46f055e8f1b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Jul 2021 12:06:52 +0900 Subject: [PATCH 078/600] Temporary changes to compile with latest framework --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 4 +++- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 3 ++- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 5 +++-- osu.Game/Screens/Edit/EditorTable.cs | 4 +++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index ddd1dfa6cd..4b44c34c6d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -8,6 +8,8 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.EnumExtensions; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -215,7 +217,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class HeaderText : OsuSpriteText { - public HeaderText(string text) + public HeaderText(LocalisableString text) { Text = text.ToUpper(); Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold); diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 585b5c22aa..3f8779b97b 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -10,6 +10,7 @@ using osu.Framework.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Localisation; using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; @@ -109,7 +110,7 @@ namespace osu.Game.Overlays.Rankings.Tables { private readonly bool isHighlighted; - public HeaderText(string text, bool isHighlighted) + public HeaderText(LocalisableString text, bool isHighlighted) { this.isHighlighted = isHighlighted; diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index a6969f483f..a77ce81c23 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Users; @@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected virtual IEnumerable GradeColumns => new List { "SS", "S", "A" }; + protected virtual IEnumerable GradeColumns => new List { "SS", "S", "A" }; protected override TableColumn[] CreateAdditionalHeaders() => new[] { @@ -66,7 +67,7 @@ namespace osu.Game.Overlays.Rankings.Tables private class UserTableHeaderText : HeaderText { - public UserTableHeaderText(string text, bool isHighlighted, bool isGrade) + public UserTableHeaderText(LocalisableString text, bool isHighlighted, bool isGrade) : base(text, isHighlighted) { Margin = new MarginPadding diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index 9578b96897..77c3a2f26c 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -46,7 +48,7 @@ namespace osu.Game.Screens.Edit private class HeaderText : OsuSpriteText { - public HeaderText(string text) + public HeaderText(LocalisableString text) { Text = text.ToUpper(); Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold); From d9d9db6f621ea2353e11906bf334a1e9d98d962c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 27 Jul 2021 19:00:08 +0900 Subject: [PATCH 079/600] Revert "Modify catcher autoplay test pattern to see more variety movement" I found `TestSceneHyperDash` is useful for visual inspection of hyper dash trails. This reverts commit 0fbe950a --- osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 0ca0ddfcb1..f552c3c27b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -27,9 +27,9 @@ namespace osu.Game.Rulesets.Catch.Tests } }; - for (int i = 0; i < 12; i++) + for (int i = 0; i < 100; i++) { - float width = (i + 1) / 20f * CatchPlayfield.WIDTH; + float width = (i % 10 + 1) / 20f * CatchPlayfield.WIDTH; beatmap.HitObjects.Add(new JuiceStream { @@ -39,8 +39,8 @@ namespace osu.Game.Rulesets.Catch.Tests Vector2.Zero, new Vector2(width, 0) }), - StartTime = i * 1000, - NewCombo = i % 5 == 0, + StartTime = i * 2000, + NewCombo = i % 8 == 0, Samples = new List(new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 100) From de68fd12b3ef0f0e9a6df12a6fc05ff3eb0a53ce Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 27 Jul 2021 18:48:31 +0900 Subject: [PATCH 080/600] Move catcher trail colouring logic to `CatcherTrailDisplay` --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 8 ---- .../UI/CatcherTrailDisplay.cs | 46 ++++++------------- 2 files changed, 15 insertions(+), 39 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index e7c26ee44f..a5f51374c4 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -115,7 +115,6 @@ namespace osu.Game.Rulesets.Catch.UI private readonly SkinnableCatcher body; private Color4 hyperDashColour = DEFAULT_HYPER_DASH_COLOUR; - private Color4 hyperDashEndGlowColour = DEFAULT_HYPER_DASH_COLOUR; private double hyperDashModifier = 1; private int hyperDashDirection; @@ -323,13 +322,6 @@ namespace osu.Game.Rulesets.Catch.UI skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? DEFAULT_HYPER_DASH_COLOUR; - hyperDashEndGlowColour = - skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value ?? - hyperDashColour; - - trails.HyperDashTrailsColour = hyperDashColour; - trails.EndGlowSpritesColour = hyperDashEndGlowColour; - flipCatcherPlate = skin.GetConfig(CatchSkinConfiguration.FlipCatcherPlate)?.Value ?? true; runHyperDashStateTransition(HyperDashing); diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index 00f2a76bde..9931ef8f64 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -6,6 +6,8 @@ using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; +using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -15,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.UI /// Represents a component responsible for displaying /// the appropriate catcher trails when requested to. /// - public class CatcherTrailDisplay : CompositeDrawable + public class CatcherTrailDisplay : SkinReloadableDrawable { /// /// The most recent dash trail added in this container. @@ -26,42 +28,16 @@ namespace osu.Game.Rulesets.Catch.UI .OrderByDescending(trail => trail.LifetimeStart) .FirstOrDefault(); + public Color4 HyperDashTrailsColour => hyperDashTrails.Colour; + + public Color4 EndGlowSpritesColour => endGlowSprites.Colour; + private readonly DrawablePool trailPool; private readonly Container dashTrails; private readonly Container hyperDashTrails; private readonly Container endGlowSprites; - private Color4 hyperDashTrailsColour = Catcher.DEFAULT_HYPER_DASH_COLOUR; - - public Color4 HyperDashTrailsColour - { - get => hyperDashTrailsColour; - set - { - if (hyperDashTrailsColour == value) - return; - - hyperDashTrailsColour = value; - hyperDashTrails.Colour = hyperDashTrailsColour; - } - } - - private Color4 endGlowSpritesColour = Catcher.DEFAULT_HYPER_DASH_COLOUR; - - public Color4 EndGlowSpritesColour - { - get => endGlowSpritesColour; - set - { - if (endGlowSpritesColour == value) - return; - - endGlowSpritesColour = value; - endGlowSprites.Colour = endGlowSpritesColour; - } - } - public CatcherTrailDisplay() { RelativeSizeAxes = Axes.Both; @@ -75,6 +51,14 @@ namespace osu.Game.Rulesets.Catch.UI }; } + protected override void SkinChanged(ISkinSource skin) + { + base.SkinChanged(skin); + + hyperDashTrails.Colour = skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR; + endGlowSprites.Colour = skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour; + } + /// /// Displays a single end-glow catcher sprite. /// From da69867fd4b452bc2765b43006ba3bbedc86cf6b Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 27 Jul 2021 18:59:55 +0900 Subject: [PATCH 081/600] Move catcher trail generation logic to `CatcherArea` --- .../TestSceneCatchSkinConfiguration.cs | 2 +- .../TestSceneCatcher.cs | 10 ++-- .../TestSceneCatcherArea.cs | 5 +- .../TestSceneHyperDashColouring.cs | 10 ++-- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 8 +--- osu.Game.Rulesets.Catch/UI/Catcher.cs | 22 ++------- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 48 +++++++++++++------ 7 files changed, 48 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs index 58ff97d563..8ae2bcca0e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests var skin = new TestSkin { FlipCatcherPlate = flip }; container.Child = new SkinProvidingContainer(skin) { - Child = catcher = new Catcher(new CatcherTrailDisplay(), new DroppedObjectContainer()) + Child = catcher = new Catcher(new DroppedObjectContainer()) { Anchor = Anchor.Centre } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 1e582bd9e8..540f02580f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -31,8 +31,6 @@ namespace osu.Game.Rulesets.Catch.Tests [Resolved] private OsuConfigManager config { get; set; } - private CatcherTrailDisplay trailDisplay; - private DroppedObjectContainer droppedObjectContainer; private TestCatcher catcher; @@ -45,7 +43,6 @@ namespace osu.Game.Rulesets.Catch.Tests CircleSize = 0, }; - trailDisplay = new CatcherTrailDisplay(); droppedObjectContainer = new DroppedObjectContainer(); Child = new Container @@ -54,8 +51,7 @@ namespace osu.Game.Rulesets.Catch.Tests Children = new Drawable[] { droppedObjectContainer, - catcher = new TestCatcher(trailDisplay, droppedObjectContainer, difficulty), - trailDisplay, + catcher = new TestCatcher(droppedObjectContainer, difficulty), } }; }); @@ -294,8 +290,8 @@ namespace osu.Game.Rulesets.Catch.Tests { public IEnumerable CaughtObjects => this.ChildrenOfType(); - public TestCatcher(CatcherTrailDisplay trails, DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty) - : base(trails, droppedObjectTarget, difficulty) + public TestCatcher(DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty) + : base(droppedObjectTarget, difficulty) { } } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index c97e6bf9ee..a3307c9224 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -121,13 +121,10 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestCatcherArea(BeatmapDifficulty beatmapDifficulty) { - var trailDisplay = new CatcherTrailDisplay { Depth = -1 }; - Add(trailDisplay); - var droppedObjectContainer = new DroppedObjectContainer(); Add(droppedObjectContainer); - Catcher = new Catcher(trailDisplay, droppedObjectContainer, beatmapDifficulty) + Catcher = new Catcher(droppedObjectContainer, beatmapDifficulty) { X = CatchPlayfield.CENTER_X }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 88ddc7e8a8..4524086b02 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -118,19 +118,19 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("create hyper-dashing catcher", () => { - trails = new CatcherTrailDisplay(); + CatcherArea catcherArea; Child = setupSkinHierarchy(new Container { Anchor = Anchor.Centre, - Children = new Drawable[] + Child = catcherArea = new CatcherArea { - catcher = new Catcher(trails, new DroppedObjectContainer()) + Catcher = catcher = new Catcher(new DroppedObjectContainer()) { Scale = new Vector2(4) - }, - trails + } } }, skin); + trails = catcherArea.CatcherTrails; }); AddStep("start hyper-dash", () => diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index bcbe7c776e..1e20643a08 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -44,14 +44,9 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - var trailDisplay = new CatcherTrailDisplay - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.TopLeft - }; var droppedObjectContainer = new DroppedObjectContainer(); - Catcher = new Catcher(trailDisplay, droppedObjectContainer, difficulty) + Catcher = new Catcher(droppedObjectContainer, difficulty) { X = CENTER_X }; @@ -69,7 +64,6 @@ namespace osu.Game.Rulesets.Catch.UI Origin = Anchor.TopLeft, Catcher = Catcher, }, - trailDisplay, HitObjectContainer, }); diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index a5f51374c4..dd6d8626d0 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -71,11 +71,6 @@ namespace osu.Game.Rulesets.Catch.UI /// private const float caught_fruit_scale_adjust = 0.5f; - /// - /// Contains trails and afterimages (also called "end glow" in code) of the catcher. - /// - private readonly CatcherTrailDisplay trails; - /// /// Contains caught objects on the plate. /// @@ -102,6 +97,8 @@ namespace osu.Game.Rulesets.Catch.UI /// public Direction VisualDirection { get; set; } = Direction.Right; + public Vector2 BodyScale => Scale * body.Scale; + /// /// Whether the contents of the catcher plate should be visually flipped when the catcher direction is changed. /// @@ -127,9 +124,8 @@ namespace osu.Game.Rulesets.Catch.UI private readonly DrawablePool caughtBananaPool; private readonly DrawablePool caughtDropletPool; - public Catcher([NotNull] CatcherTrailDisplay trails, [NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null) + public Catcher([NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null) { - this.trails = trails; this.droppedObjectTarget = droppedObjectTarget; Origin = Anchor.TopCentre; @@ -292,10 +288,7 @@ namespace osu.Game.Rulesets.Catch.UI hyperDashTargetPosition = targetPosition; if (!wasHyperDashing) - { - trails.DisplayEndGlow(CurrentState, X, Scale * body.Scale); runHyperDashStateTransition(true); - } } } @@ -342,15 +335,6 @@ namespace osu.Game.Rulesets.Catch.UI X = hyperDashTargetPosition; SetHyperDashState(); } - - if (Dashing || HyperDashing) - { - double lastTrailTime = trails.LastDashTrail?.LifetimeStart ?? double.NegativeInfinity; - double generationInterval = HyperDashing ? 25 : 50; - - if (Time.Current - lastTrailTime >= generationInterval) - trails.DisplayDashTrail(CurrentState, X, Scale * body.Scale, HyperDashing); - } } private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index de0ace9817..bcf4b36c9c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -25,15 +25,13 @@ namespace osu.Game.Rulesets.Catch.UI public Catcher Catcher { get => catcher; - set - { - if (catcher != null) - Remove(catcher); - - Add(catcher = value); - } + set => catcherContainer.Child = catcher = value; } + internal CatcherTrailDisplay CatcherTrails { get; } + + private readonly Container catcherContainer; + private readonly CatchComboDisplay comboDisplay; private Catcher catcher; @@ -45,20 +43,28 @@ namespace osu.Game.Rulesets.Catch.UI /// private int currentDirection; + // TODO: support replay rewind + private bool lastHyperDashState; + /// /// must be set before loading. /// public CatcherArea() { Size = new Vector2(CatchPlayfield.WIDTH, Catcher.BASE_SIZE); - Child = comboDisplay = new CatchComboDisplay + Children = new Drawable[] { - RelativeSizeAxes = Axes.None, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopLeft, - Origin = Anchor.Centre, - Margin = new MarginPadding { Bottom = 350f }, - X = CatchPlayfield.CENTER_X + catcherContainer = new Container { RelativeSizeAxes = Axes.Both }, + CatcherTrails = new CatcherTrailDisplay(), + comboDisplay = new CatchComboDisplay + { + RelativeSizeAxes = Axes.None, + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopLeft, + Origin = Anchor.Centre, + Margin = new MarginPadding { Bottom = 350f }, + X = CatchPlayfield.CENTER_X + } }; } @@ -102,6 +108,20 @@ namespace osu.Game.Rulesets.Catch.UI base.UpdateAfterChildren(); comboDisplay.X = Catcher.X; + + if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) + CatcherTrails.DisplayEndGlow(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); + + if (Catcher.Dashing || Catcher.HyperDashing) + { + double lastTrailTime = CatcherTrails.LastDashTrail?.LifetimeStart ?? double.NegativeInfinity; + double generationInterval = Catcher.HyperDashing ? 25 : 50; + + if (Time.Current - lastTrailTime >= generationInterval) + CatcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); + } + + lastHyperDashState = Catcher.HyperDashing; } public void SetCatcherPosition(float X) From 846f539428ac75afcc2fb8a1ca4f1ea933dc78f1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 27 Jul 2021 19:11:08 +0900 Subject: [PATCH 082/600] Avoid usage of LINQ in last dash trail computation --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 3 +-- .../UI/CatcherTrailDisplay.cs | 24 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index bcf4b36c9c..9eb692c875 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -114,10 +114,9 @@ namespace osu.Game.Rulesets.Catch.UI if (Catcher.Dashing || Catcher.HyperDashing) { - double lastTrailTime = CatcherTrails.LastDashTrail?.LifetimeStart ?? double.NegativeInfinity; double generationInterval = Catcher.HyperDashing ? 25 : 50; - if (Time.Current - lastTrailTime >= generationInterval) + if (Time.Current - CatcherTrails.LastDashTrailTime >= generationInterval) CatcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index 9931ef8f64..31b7a6e0ed 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.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. -using System.Linq; -using JetBrains.Annotations; +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; @@ -20,13 +19,11 @@ namespace osu.Game.Rulesets.Catch.UI public class CatcherTrailDisplay : SkinReloadableDrawable { /// - /// The most recent dash trail added in this container. + /// The most recent time a dash trail was added to this container. /// Only alive (not faded out) trails are considered. + /// Returns if no dash trail is alive. /// - [CanBeNull] - public CatcherTrail LastDashTrail => dashTrails.Concat(hyperDashTrails) - .OrderByDescending(trail => trail.LifetimeStart) - .FirstOrDefault(); + public double LastDashTrailTime => getLastDashTrailTime(); public Color4 HyperDashTrailsColour => hyperDashTrails.Colour; @@ -97,5 +94,18 @@ namespace osu.Game.Rulesets.Catch.UI return sprite; } + + private double getLastDashTrailTime() + { + double maxTime = double.NegativeInfinity; + + foreach (var trail in dashTrails) + maxTime = Math.Max(maxTime, trail.LifetimeStart); + + foreach (var trail in hyperDashTrails) + maxTime = Math.Max(maxTime, trail.LifetimeStart); + + return maxTime; + } } } From c741366c72a559663d0358a317f40c149e7d0e4c Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 27 Jul 2021 09:01:01 -0400 Subject: [PATCH 083/600] review modifications: change xmldocs, change reflection method name, remove reflection method returns, simplify incompat. mod list --- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 10 +++++---- .../Utils/OsuHitObjectGenerationUtils.cs | 22 +++++++------------ 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 82b8959456..c94bafe6af 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -17,13 +17,13 @@ namespace osu.Game.Rulesets.Osu.Mods { public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModDifficultyAdjust), typeof(ModMirror) }; + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModMirror)).ToArray(); public void ApplyToHitObject(HitObject hitObject) { var osuObject = (OsuHitObject)hitObject; - OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); + OsuHitObjectGenerationUtils.ReflectVertically(osuObject); } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index fd1d685fd1..9b4614c9b2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -29,14 +29,16 @@ namespace osu.Game.Rulesets.Osu.Mods switch (Reflection.Value) { case MirrorType.Horizontal: - OsuHitObjectGenerationUtils.ReflectOsuHitObjectHorizontally(osuObject); + OsuHitObjectGenerationUtils.ReflectHorizontally(osuObject); break; + case MirrorType.Vertical: - OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); + OsuHitObjectGenerationUtils.ReflectVertically(osuObject); break; + case MirrorType.Both: - OsuHitObjectGenerationUtils.ReflectOsuHitObjectHorizontally(osuObject); - OsuHitObjectGenerationUtils.ReflectOsuHitObjectVertically(osuObject); + OsuHitObjectGenerationUtils.ReflectHorizontally(osuObject); + OsuHitObjectGenerationUtils.ReflectVertically(osuObject); break; } } diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index bf55898901..fcd5fb4a31 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -106,16 +106,15 @@ namespace osu.Game.Rulesets.Osu.Utils } /// - /// Reflects an OsuHitObject's position horizontally. + /// Reflects the position of the in the playfield vertically. /// - /// The OsuHitObject to be reflected. - /// The reflected OsuHitObject. - public static OsuHitObject ReflectOsuHitObjectHorizontally(OsuHitObject osuObject) + /// The object to reflect. + public static void ReflectHorizontally(OsuHitObject osuObject) { osuObject.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - osuObject.X, osuObject.Position.Y); if (!(osuObject is Slider slider)) - return osuObject; + return; slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(OsuPlayfield.BASE_SIZE.X - h.Position.X, h.Position.Y)); @@ -125,21 +124,18 @@ namespace osu.Game.Rulesets.Osu.Utils point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); - - return osuObject; } /// - /// Reflects an OsuHitObject's position vertically. + /// Reflects the position of the in the playfield horizontally. /// - /// The OsuHitObject to be reflected. - /// The reflected OsuHitObject. - public static OsuHitObject ReflectOsuHitObjectVertically(OsuHitObject osuObject) + /// The object to reflect. + public static void ReflectVertically(OsuHitObject osuObject) { osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); if (!(osuObject is Slider slider)) - return osuObject; + return; slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); @@ -149,8 +145,6 @@ namespace osu.Game.Rulesets.Osu.Utils point.Position.Value = new Vector2(point.Position.Value.X, -point.Position.Value.Y); slider.Path = new SliderPath(controlPoints, slider.Path.ExpectedDistance.Value); - - return osuObject; } } } From ed903c60eadb700b9a8005584ebb4ca8139f46be Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Jul 2021 18:14:05 +0300 Subject: [PATCH 084/600] Fix code style issues and remove unused using directives --- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 3 --- osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index c94bafe6af..007820b016 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -3,13 +3,10 @@ using System; using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.Utils; -using osuTK; namespace osu.Game.Rulesets.Osu.Mods { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index 9b4614c9b2..a59ae33523 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -2,16 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Bindables; using osu.Game.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.Utils; -using osuTK; namespace osu.Game.Rulesets.Osu.Mods { @@ -26,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToHitObject(HitObject hitObject) { var osuObject = (OsuHitObject)hitObject; + switch (Reflection.Value) { case MirrorType.Horizontal: From 5cb02002d78a96879fb8e948c7a236a64ad07d74 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Jul 2021 18:22:32 +0300 Subject: [PATCH 085/600] Fix flipped xmldoc --- osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index fcd5fb4a31..57ec51cf64 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -106,7 +106,7 @@ namespace osu.Game.Rulesets.Osu.Utils } /// - /// Reflects the position of the in the playfield vertically. + /// Reflects the position of the in the playfield horizontally. /// /// The object to reflect. public static void ReflectHorizontally(OsuHitObject osuObject) @@ -127,7 +127,7 @@ namespace osu.Game.Rulesets.Osu.Utils } /// - /// Reflects the position of the in the playfield horizontally. + /// Reflects the position of the in the playfield vertically. /// /// The object to reflect. public static void ReflectVertically(OsuHitObject osuObject) From 94877117b9868e00ec8c95c9b482d92a25f7bc35 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 27 Jul 2021 18:22:47 +0200 Subject: [PATCH 086/600] Apply changes in-line with framework changes. --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 4 +++- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 3 ++- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 5 +++-- osu.Game/Screens/Edit/EditorTable.cs | 4 +++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index ddd1dfa6cd..22033f14cd 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -18,6 +18,8 @@ using osu.Game.Scoring; using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; +using osu.Framework.Localisation; +using osu.Framework.Extensions.LocalisationExtensions; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -215,7 +217,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class HeaderText : OsuSpriteText { - public HeaderText(string text) + public HeaderText(LocalisableString text) { Text = text.ToUpper(); Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold); diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 585b5c22aa..0da48c6f88 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -13,6 +13,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; +using osu.Framework.Localisation; namespace osu.Game.Overlays.Rankings.Tables { @@ -109,7 +110,7 @@ namespace osu.Game.Overlays.Rankings.Tables { private readonly bool isHighlighted; - public HeaderText(string text, bool isHighlighted) + public HeaderText(LocalisableString text, bool isHighlighted) { this.isHighlighted = isHighlighted; diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index a6969f483f..e3081491f4 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Users; using osu.Game.Scoring; +using osu.Framework.Localisation; namespace osu.Game.Overlays.Rankings.Tables { @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable CreateHeader(int index, TableColumn column) { var title = column?.Header ?? string.Empty; - return new UserTableHeaderText(title, HighlightedColumn == title, GradeColumns.Contains(title)); + return new UserTableHeaderText(title, HighlightedColumn == title, GradeColumns.Contains(title.ToString())); } protected sealed override Country GetCountry(UserStatistics item) => item.User.Country; @@ -66,7 +67,7 @@ namespace osu.Game.Overlays.Rankings.Tables private class UserTableHeaderText : HeaderText { - public UserTableHeaderText(string text, bool isHighlighted, bool isGrade) + public UserTableHeaderText(LocalisableString text, bool isHighlighted, bool isGrade) : base(text, isHighlighted) { Margin = new MarginPadding diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index 9578b96897..77c3a2f26c 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -46,7 +48,7 @@ namespace osu.Game.Screens.Edit private class HeaderText : OsuSpriteText { - public HeaderText(string text) + public HeaderText(LocalisableString text) { Text = text.ToUpper(); Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold); From 239b38a0ab1776fa4d38bbe35dddb0ec9114f3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 27 Jul 2021 21:42:34 +0200 Subject: [PATCH 087/600] Reduce implicit conversions by using `default` --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 2 +- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 2 +- osu.Game/Screens/Edit/EditorTable.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 22033f14cd..fee0e62315 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -213,7 +213,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return content.ToArray(); } - protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? default); private class HeaderText : OsuSpriteText { diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 0da48c6f88..f568aae59c 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable CreateHeader(int index, TableColumn column) { - var title = column?.Header ?? string.Empty; + var title = column?.Header ?? default; return new HeaderText(title, title == HighlightedColumn); } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index e3081491f4..56814244c0 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable CreateHeader(int index, TableColumn column) { - var title = column?.Header ?? string.Empty; + var title = column?.Header ?? default; return new UserTableHeaderText(title, HighlightedColumn == title, GradeColumns.Contains(title.ToString())); } diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index 77c3a2f26c..756339405c 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Edit }); } - protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? default); private class HeaderText : OsuSpriteText { From 712bc578dcc03a8be8649bba5fd56c483f41aa05 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Tue, 27 Jul 2021 17:45:52 -0400 Subject: [PATCH 088/600] update setting name and description --- osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index a59ae33523..1770e79d3f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Reflect the playfield."; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - [SettingSource("Reflection", "Change the type of reflection.")] + [SettingSource("Mirrored axes", "Choose which of the playfield's axes are mirrored.")] public Bindable Reflection { get; } = new Bindable(); public void ApplyToHitObject(HitObject hitObject) From 0bf04ece34698217162e22a40db73a603410cf27 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 28 Jul 2021 18:13:43 +0900 Subject: [PATCH 089/600] Avoid `internal` property by using `ChildrenOfType` --- .../TestSceneHyperDashColouring.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 4524086b02..82b69716a8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Catch.Tests } } }, skin); - trails = catcherArea.CatcherTrails; + trails = catcherArea.ChildrenOfType().Single(); }); AddStep("start hyper-dash", () => diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 9eb692c875..2d6d7fb8d8 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -28,12 +28,12 @@ namespace osu.Game.Rulesets.Catch.UI set => catcherContainer.Child = catcher = value; } - internal CatcherTrailDisplay CatcherTrails { get; } - private readonly Container catcherContainer; private readonly CatchComboDisplay comboDisplay; + private readonly CatcherTrailDisplay catcherTrails; + private Catcher catcher; /// @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI Children = new Drawable[] { catcherContainer = new Container { RelativeSizeAxes = Axes.Both }, - CatcherTrails = new CatcherTrailDisplay(), + catcherTrails = new CatcherTrailDisplay(), comboDisplay = new CatchComboDisplay { RelativeSizeAxes = Axes.None, @@ -110,14 +110,14 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = Catcher.X; if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) - CatcherTrails.DisplayEndGlow(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); + catcherTrails.DisplayEndGlow(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); if (Catcher.Dashing || Catcher.HyperDashing) { double generationInterval = Catcher.HyperDashing ? 25 : 50; - if (Time.Current - CatcherTrails.LastDashTrailTime >= generationInterval) - CatcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); + if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval) + catcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); } lastHyperDashState = Catcher.HyperDashing; From a960a28d0679b74fd7c28b21e14a41941a1a5e1b Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 28 Jul 2021 19:02:24 +0900 Subject: [PATCH 090/600] Replace "end glow" terminology with "hyper-dash after-image" Because the is "end glow" is when a hyper-dash is *started*, the name was confusing. The "after-image" was already used in the code as a synonym of "end glow" inconsistently. --- .../TestSceneHyperDashColouring.cs | 8 +++---- osu.Game.Rulesets.Catch/UI/Catcher.cs | 3 +-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- .../UI/CatcherTrailDisplay.cs | 24 +++++++++---------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 82b69716a8..70b2c8c82a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Tests } [Test] - public void TestCustomEndGlowColour() + public void TestCustomAfterImageColour() { var skin = new TestSkin { @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Catch.Tests } [Test] - public void TestCustomEndGlowColourPriority() + public void TestCustomAfterImageColourPriority() { var skin = new TestSkin { @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Catch.Tests checkHyperDashFruitColour(skin, skin.HyperDashColour); } - private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedEndGlowColour = null) + private void checkHyperDashCatcherColour(ISkin skin, Color4 expectedCatcherColour, Color4? expectedAfterImageColour = null) { CatcherTrailDisplay trails = null; Catcher catcher = null; @@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddUntilStep("catcher colour is correct", () => catcher.Colour == expectedCatcherColour); AddAssert("catcher trails colours are correct", () => trails.HyperDashTrailsColour == expectedCatcherColour); - AddAssert("catcher end-glow colours are correct", () => trails.EndGlowSpritesColour == (expectedEndGlowColour ?? expectedCatcherColour)); + AddAssert("catcher after-image colours are correct", () => trails.HyperDashAfterImageColour == (expectedAfterImageColour ?? expectedCatcherColour)); AddStep("finish hyper-dashing", () => { diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index b42e5352dd..9fd4610e6e 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -36,8 +36,7 @@ namespace osu.Game.Rulesets.Catch.UI public const float ALLOWED_CATCH_RANGE = 0.8f; /// - /// The default colour used to tint hyper-dash fruit, along with the moving catcher, its trail - /// and end glow/after-image during a hyper-dash. + /// The default colour used to tint hyper-dash fruit, along with the moving catcher, its trail and after-image during a hyper-dash. /// public static readonly Color4 DEFAULT_HYPER_DASH_COLOUR = Color4.Red; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2d6d7fb8d8..78f7e34649 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = Catcher.X; if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) - catcherTrails.DisplayEndGlow(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); + catcherTrails.DisplayHyperDashAfterImage(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); if (Catcher.Dashing || Catcher.HyperDashing) { diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index 31b7a6e0ed..c7e576d970 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -27,13 +27,13 @@ namespace osu.Game.Rulesets.Catch.UI public Color4 HyperDashTrailsColour => hyperDashTrails.Colour; - public Color4 EndGlowSpritesColour => endGlowSprites.Colour; + public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour; private readonly DrawablePool trailPool; private readonly Container dashTrails; private readonly Container hyperDashTrails; - private readonly Container endGlowSprites; + private readonly Container hyperDashAfterImages; public CatcherTrailDisplay() { @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Catch.UI trailPool = new DrawablePool(30), dashTrails = new Container { RelativeSizeAxes = Axes.Both }, hyperDashTrails = new Container { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR }, - endGlowSprites = new Container { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR }, + hyperDashAfterImages = new Container { RelativeSizeAxes = Axes.Both, Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR }, }; } @@ -53,22 +53,22 @@ namespace osu.Game.Rulesets.Catch.UI base.SkinChanged(skin); hyperDashTrails.Colour = skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR; - endGlowSprites.Colour = skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour; + hyperDashAfterImages.Colour = skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour; } /// - /// Displays a single end-glow catcher sprite. + /// Displays a hyper-dash after-image of the catcher. /// - public void DisplayEndGlow(CatcherAnimationState animationState, float x, Vector2 scale) + public void DisplayHyperDashAfterImage(CatcherAnimationState animationState, float x, Vector2 scale) { - var endGlow = createTrail(animationState, x, scale); + var trail = createTrail(animationState, x, scale); - endGlowSprites.Add(endGlow); + hyperDashAfterImages.Add(trail); - endGlow.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); - endGlow.ScaleTo(endGlow.Scale * 0.95f).ScaleTo(endGlow.Scale * 1.2f, 1200, Easing.In); - endGlow.FadeOut(1200); - endGlow.Expire(true); + trail.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); + trail.ScaleTo(trail.Scale * 0.95f).ScaleTo(trail.Scale * 1.2f, 1200, Easing.In); + trail.FadeOut(1200); + trail.Expire(true); } public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing) From 90f3611ed059dc581229756885faf799a4bebc99 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 28 Jul 2021 19:05:48 +0900 Subject: [PATCH 091/600] Replace "sprite" variable names in `CatcherTrailDisplay` The `CatcherTrail` was originally named `CatcherTrailSprite`, but it is not a sprite anymore. --- .../UI/CatcherTrailDisplay.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index c7e576d970..abc76fc925 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -73,26 +73,26 @@ namespace osu.Game.Rulesets.Catch.UI public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing) { - var sprite = createTrail(animationState, x, scale); + var trail = createTrail(animationState, x, scale); if (hyperDashing) - hyperDashTrails.Add(sprite); + hyperDashTrails.Add(trail); else - dashTrails.Add(sprite); + dashTrails.Add(trail); - sprite.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); - sprite.Expire(true); + trail.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); + trail.Expire(true); } private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale) { - CatcherTrail sprite = trailPool.Get(); + CatcherTrail trail = trailPool.Get(); - sprite.AnimationState = animationState; - sprite.Scale = scale; - sprite.Position = new Vector2(x, 0); + trail.AnimationState = animationState; + trail.Scale = scale; + trail.Position = new Vector2(x, 0); - return sprite; + return trail; } private double getLastDashTrailTime() From 4a4d9b0dc6ef79a48c5718ae6d3e211095f0aa02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Jul 2021 19:19:28 +0900 Subject: [PATCH 092/600] Update description to match mania mirror implementation --- osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index 1770e79d3f..3faca0b01f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -13,10 +13,10 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModMirror : ModMirror, IApplicableToHitObject { - public override string Description => "Reflect the playfield."; + public override string Description => "Flip objects on the chosen axes."; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - [SettingSource("Mirrored axes", "Choose which of the playfield's axes are mirrored.")] + [SettingSource("Mirrored axes", "Choose which axes objects are mirrored over.")] public Bindable Reflection { get; } = new Bindable(); public void ApplyToHitObject(HitObject hitObject) From 58bbe9db7e3128b80a3fa694a5d6f27628e4c8d7 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Wed, 28 Jul 2021 18:21:08 +0800 Subject: [PATCH 093/600] Added muted mod --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 31 ++++--- osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs | 11 +++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 21 +++-- osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs | 11 +++ osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs | 12 +++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 37 ++++---- osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs | 11 +++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 31 ++++--- osu.Game/Overlays/MusicController.cs | 11 ++- osu.Game/Rulesets/Mods/ModMuted.cs | 93 +++++++++++++++++++ 10 files changed, 208 insertions(+), 61 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs create mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs create mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs create mode 100644 osu.Game/Rulesets/Mods/ModMuted.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 76863acc78..c77caf0cef 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -1,30 +1,30 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Rulesets.Catch.Mods; -using osu.Game.Rulesets.Catch.UI; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; +using System; using System.Collections.Generic; +using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Catch.Replays; -using osu.Game.Rulesets.Replays.Types; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; +using osu.Game.Graphics; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Difficulty; -using osu.Game.Rulesets.Catch.Scoring; -using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; -using System; -using osu.Framework.Extensions.EnumExtensions; using osu.Game.Rulesets.Catch.Edit; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Catch.Skinning.Legacy; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch @@ -130,7 +130,8 @@ namespace osu.Game.Rulesets.Catch return new Mod[] { new MultiMod(new ModWindUp(), new ModWindDown()), - new CatchModFloatingFruits() + new CatchModFloatingFruits(), + new CatchModMuted(), }; default: diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs new file mode 100644 index 0000000000..4c73a6a21f --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModMuted : ModMuted + { + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index fe736766d9..3615d7e660 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -2,22 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mania.Mods; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Replays; -using osu.Game.Rulesets.Replays.Types; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; +using osu.Game.Graphics; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; @@ -27,12 +21,18 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Skinning.Legacy; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Skinning; +using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania { @@ -253,7 +253,8 @@ namespace osu.Game.Rulesets.Mania case ModType.Fun: return new Mod[] { - new MultiMod(new ModWindUp(), new ModWindDown()) + new MultiMod(new ModWindUp(), new ModWindDown()), + new ManiaModMuted(), }; default: diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs new file mode 100644 index 0000000000..e0b98e491e --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModMuted : ModMuted + { + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs new file mode 100644 index 0000000000..5e3ee37b61 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModMuted : ModMuted + { + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 5f37b0d040..30f56cdc7d 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,39 +1,39 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.UI; +using System; using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Osu.Edit; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Rulesets.Replays.Types; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; -using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; -using osu.Game.Skinning; -using System; -using System.Linq; -using osu.Framework.Extensions.EnumExtensions; +using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.Statistics; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu { @@ -188,6 +188,7 @@ namespace osu.Game.Rulesets.Osu new OsuModTraceable(), new OsuModBarrelRoll(), new OsuModApproachDifferent(), + new OsuModMuted(), }; case ModType.System: diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs new file mode 100644 index 0000000000..d6bd7c4ee8 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModMuted : ModMuted + { + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index ab5fcf6336..428ae66a31 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -1,32 +1,32 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Taiko.Mods; -using osu.Game.Rulesets.Taiko.UI; -using osu.Game.Rulesets.UI; +using System; using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; +using osu.Game.Graphics; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; -using osu.Game.Rulesets.Taiko.Scoring; -using osu.Game.Scoring; -using System; -using System.Linq; -using osu.Framework.Extensions.EnumExtensions; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Taiko.Edit; +using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.Taiko.Skinning.Legacy; +using osu.Game.Rulesets.Taiko.UI; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; using osu.Game.Skinning; @@ -149,7 +149,8 @@ namespace osu.Game.Rulesets.Taiko case ModType.Fun: return new Mod[] { - new MultiMod(new ModWindUp(), new ModWindDown()) + new MultiMod(new ModWindUp(), new ModWindDown()), + new TaikoModMuted(), }; default: diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index a15f80ca21..0325fa588f 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -12,8 +12,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; -using osu.Framework.Utils; using osu.Framework.Threading; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; @@ -419,15 +419,20 @@ namespace osu.Game.Overlays } /// - /// Resets the speed adjustments currently applied on and applies the mod adjustments if is true. + /// Resets the track adjustments currently applied on and applies the mod adjustments if is true. /// /// - /// Does not reset speed adjustments applied directly to the beatmap track. + /// Does not reset any adjustments applied directly to the beatmap track. /// public void ResetTrackAdjustments() { CurrentTrack.ResetSpeedAdjustments(); + // Adjustments other than speed should also be reset + // e.g. ModMuted may apply volume adjustments + CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Balance); + CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Volume); + if (allowRateAdjustments) { foreach (var mod in mods.Value.OfType()) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs new file mode 100644 index 0000000000..dff3982041 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -0,0 +1,93 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Audio; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModMuted : Mod + { + public override string Name => "Muted"; + public override string Acronym => "MU"; + public override IconUsage? Icon => FontAwesome.Solid.VolumeMute; + public override string Description => "Who needs music in a rhythm game?"; + public override ModType Type => ModType.Fun; + public override double ScoreMultiplier => 1; + } + + public abstract class ModMuted : ModMuted, IApplicableToDrawableRuleset, IApplicableToTrack + where TObject : HitObject + { + private readonly BindableNumber volumeAdjust = new BindableDouble(); + + [SettingSource("Enable metronome", "Add a metronome to help you keep track of the rhythm.")] + public BindableBool EnableMetronome { get; } = new BindableBool + { + Default = true, + Value = true + }; + + public void ApplyToTrack(ITrack track) + { + track.AddAdjustment(AdjustableProperty.Volume, volumeAdjust); + } + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + if (EnableMetronome.Value) + drawableRuleset.Overlays.Add(new MetronomeBeatContainer(drawableRuleset.Beatmap.HitObjects.First().StartTime)); + } + + public class MetronomeBeatContainer : BeatSyncedContainer + { + private readonly double firstHitTime; + + private PausableSkinnableSound sample; + + public MetronomeBeatContainer(double firstHitTime) + { + this.firstHitTime = firstHitTime; + AllowMistimedEventFiring = false; + Divisor = 1; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana")) + }; + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) + { + base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); + + if (!IsBeatSyncedWithTrack) return; + + int timeSignature = (int)timingPoint.TimeSignature; + + // play metronome from one measure before the first object. + if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature) + return; + + sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f; + sample.Play(); + } + } + } +} From 22d83c75e3a612d77ab681c704aa3596c7d3834e Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Wed, 28 Jul 2021 18:32:38 +0800 Subject: [PATCH 094/600] Revert imports re-ordering Out of the scope of this PR --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 26 +++++++++--------- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 18 ++++++------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 36 ++++++++++++------------- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 32 +++++++++++----------- osu.Game/Overlays/MusicController.cs | 2 +- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index c77caf0cef..eafa1b9b9d 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -1,30 +1,30 @@ // 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.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; using System.Collections.Generic; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; -using osu.Game.Graphics; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Difficulty; -using osu.Game.Rulesets.Catch.Edit; -using osu.Game.Rulesets.Catch.Mods; -using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Scoring; -using osu.Game.Rulesets.Catch.Skinning.Legacy; -using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using System; +using osu.Framework.Extensions.EnumExtensions; +using osu.Game.Rulesets.Catch.Edit; +using osu.Game.Rulesets.Catch.Skinning.Legacy; +using osu.Game.Rulesets.Edit; using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 3615d7e660..f4b6e10af4 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -2,16 +2,22 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; -using osu.Game.Graphics; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; @@ -21,18 +27,12 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; -using osu.Game.Rulesets.Mania.Mods; -using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Skinning.Legacy; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; +using osu.Game.Skinning; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 30f56cdc7d..21a49f9495 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,39 +1,39 @@ // 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.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.UI; using System.Collections.Generic; -using System.Linq; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; -using osu.Game.Graphics; -using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; -using osu.Game.Rulesets.Osu.Edit; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Skinning; +using System; +using System.Linq; +using osu.Framework.Extensions.EnumExtensions; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.Statistics; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu { diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 428ae66a31..adc924ba38 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -1,32 +1,32 @@ // 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.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.UI; +using osu.Game.Rulesets.UI; using System.Collections.Generic; -using System.Linq; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Legacy; -using osu.Game.Graphics; -using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; -using osu.Game.Rulesets.Taiko.Edit; -using osu.Game.Rulesets.Taiko.Mods; -using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Scoring; -using osu.Game.Rulesets.Taiko.Skinning.Legacy; -using osu.Game.Rulesets.Taiko.UI; -using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using System; +using System.Linq; +using osu.Framework.Extensions.EnumExtensions; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Taiko.Edit; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Skinning.Legacy; using osu.Game.Screens.Ranking.Statistics; using osu.Game.Skinning; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 0325fa588f..3978d2aa6e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -12,8 +12,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; -using osu.Framework.Threading; using osu.Framework.Utils; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; From 1ed4fdd5f559554a947e1889ef06c4d3366eeaf1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Jul 2021 20:13:40 +0900 Subject: [PATCH 095/600] Avoid deserialisation JSON request content when error is not present (or not relevant) --- osu.Game/Online/API/APIRequest.cs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index e6bfca166e..df0901fd93 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -171,19 +171,24 @@ namespace osu.Game.Online.API WebRequest?.Abort(); - string responseString = WebRequest?.GetResponseString(); - - if (!string.IsNullOrEmpty(responseString)) + // in the case of a cancellation we don't care about whether there's an error in the response. + if (!(e is OperationCanceledException)) { - try - { - // attempt to decode a displayable error string. - var error = JsonConvert.DeserializeObject(responseString); - if (error != null) - e = new APIException(error.ErrorMessage, e); - } - catch + string responseString = WebRequest?.GetResponseString(); + + // naive check whether there's an error in the response to avoid unnecessary JSON deserialisation. + if (!string.IsNullOrEmpty(responseString) && responseString.Contains(@"""error""")) { + try + { + // attempt to decode a displayable error string. + var error = JsonConvert.DeserializeObject(responseString); + if (error != null) + e = new APIException(error.ErrorMessage, e); + } + catch + { + } } } From cd2a1af6de82dcb4c382890e6e176e8fbd479065 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Jul 2021 20:46:02 +0900 Subject: [PATCH 096/600] Fix `HubClientConnector` reconnecting with no delay on server-triggered error --- osu.Game/Online/HubClientConnector.cs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index 3839762e46..90049a6501 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -116,10 +116,7 @@ namespace osu.Game.Online } catch (Exception e) { - Logger.Log($"{clientName} connection error: {e}", LoggingTarget.Network); - - // retry on any failure. - await Task.Delay(5000, cancellationToken).ConfigureAwait(false); + await handleErrorAndDelay(e, cancellationToken).ConfigureAwait(false); } } } @@ -129,6 +126,15 @@ namespace osu.Game.Online } } + /// + /// Handles an exception and delays an async flow. + /// + private async Task handleErrorAndDelay(Exception exception, CancellationToken cancellationToken) + { + Logger.Log($"{clientName} connection error: {exception}", LoggingTarget.Network); + await Task.Delay(5000, cancellationToken).ConfigureAwait(false); + } + private HubConnection buildConnection(CancellationToken cancellationToken) { var builder = new HubConnectionBuilder() @@ -155,17 +161,18 @@ namespace osu.Game.Online return newConnection; } - private Task onConnectionClosed(Exception? ex, CancellationToken cancellationToken) + private async Task onConnectionClosed(Exception? ex, CancellationToken cancellationToken) { isConnected.Value = false; - Logger.Log(ex != null ? $"{clientName} lost connection: {ex}" : $"{clientName} disconnected", LoggingTarget.Network); + if (ex != null) + await handleErrorAndDelay(ex, cancellationToken).ConfigureAwait(false); + else + Logger.Log($"{clientName} disconnected", LoggingTarget.Network); // make sure a disconnect wasn't triggered (and this is still the active connection). if (!cancellationToken.IsCancellationRequested) - Task.Run(connect, default); - - return Task.CompletedTask; + await Task.Run(connect, default).ConfigureAwait(false); } private async Task disconnect(bool takeLock) From 89f0739a4ad7d3bd190825e45cf2bc28a8ab09fc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Jul 2021 21:54:11 +0900 Subject: [PATCH 097/600] Update with framework changes --- osu.Game/Audio/PreviewTrackManager.cs | 6 +++++- osu.Game/Tests/Visual/OsuTestScene.cs | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index e2c4657057..dab5fcbe5f 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -148,8 +148,12 @@ namespace osu.Game.Audio if (dataStream == null) return null; - Track track = new TrackBass(dataStream, (IBassAudioMixer)defaultMixer); + // Todo: This is quite unsafe. TrackBass shouldn't be exposed as public. + Track track = new TrackBass(dataStream); + + defaultMixer.Add(track); AddItem(track); + return track; } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 242c3298e8..57e400a77e 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -10,7 +10,6 @@ using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Mixing; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -291,7 +290,6 @@ namespace osu.Game.Tests.Visual private bool running; public TrackVirtualManual(IFrameBasedClock referenceClock) - : base(new NullAudioMixer()) { this.referenceClock = referenceClock; Length = double.PositiveInfinity; From e89f33483dd796572fc89db8d267bb1a23d05c2a Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Wed, 28 Jul 2021 21:52:01 +0800 Subject: [PATCH 098/600] Code formatting fixes --- osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs | 1 + osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs index 4c73a6a21f..6d2565440a 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs @@ -1,5 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. + using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs index e0b98e491e..33ebcf303a 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs @@ -1,5 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. + using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs index d6bd7c4ee8..0f1e0b2885 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs @@ -1,5 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Objects; From fbd02dc8301446a380e479b9ed19a71ac116ee54 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 28 Jul 2021 18:24:29 +0200 Subject: [PATCH 099/600] Update framework. --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 3a9fdfebab..1c180a6b39 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4baaf89c67..2efcfeb278 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 66cae06713..2630614c03 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 3a5324c94794af9e3985c2ef128cc80e66295bf3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Jul 2021 23:58:57 +0900 Subject: [PATCH 100/600] Fix aborting an `APIRequest` potentially resulting in incorrect success --- osu.Game/Online/API/APIRequest.cs | 90 +++++++++++++------------------ 1 file changed, 38 insertions(+), 52 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index df0901fd93..e117293ce6 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -86,8 +86,6 @@ namespace osu.Game.Online.API /// private APIRequestCompletionState completionState; - private Action pendingFailure; - public void Perform(IAPIProvider api) { if (!(api is APIAccess apiAccess)) @@ -99,29 +97,23 @@ namespace osu.Game.Online.API API = apiAccess; User = apiAccess.LocalUser.Value; - if (checkAndScheduleFailure()) - return; + if (isFailing) return; WebRequest = CreateWebRequest(); WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); - if (checkAndScheduleFailure()) - return; + if (isFailing) return; - if (!WebRequest.Aborted) // could have been aborted by a Cancel() call - { - Logger.Log($@"Performing request {this}", LoggingTarget.Network); - WebRequest.Perform(); - } + Logger.Log($@"Performing request {this}", LoggingTarget.Network); + WebRequest.Perform(); - if (checkAndScheduleFailure()) - return; + if (isFailing) return; PostProcess(); - API.Schedule(TriggerSuccess); + TriggerSuccess(); } /// @@ -141,7 +133,10 @@ namespace osu.Game.Online.API completionState = APIRequestCompletionState.Completed; } - Success?.Invoke(); + if (API == null) + Success?.Invoke(); + else + API.Schedule(() => Success?.Invoke()); } internal void TriggerFailure(Exception e) @@ -154,7 +149,10 @@ namespace osu.Game.Online.API completionState = APIRequestCompletionState.Failed; } - Failure?.Invoke(e); + if (API == null) + Failure?.Invoke(e); + else + API.Schedule(() => Failure?.Invoke(e)); } public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled")); @@ -163,59 +161,47 @@ namespace osu.Game.Online.API { lock (completionStateLock) { - // while it doesn't matter if code following this check is run more than once, - // this avoids unnecessarily performing work where we are already sure the user has been informed. if (completionState != APIRequestCompletionState.Waiting) return; - } - WebRequest?.Abort(); + WebRequest?.Abort(); - // in the case of a cancellation we don't care about whether there's an error in the response. - if (!(e is OperationCanceledException)) - { - string responseString = WebRequest?.GetResponseString(); - - // naive check whether there's an error in the response to avoid unnecessary JSON deserialisation. - if (!string.IsNullOrEmpty(responseString) && responseString.Contains(@"""error""")) + // in the case of a cancellation we don't care about whether there's an error in the response. + if (!(e is OperationCanceledException)) { - try - { - // attempt to decode a displayable error string. - var error = JsonConvert.DeserializeObject(responseString); - if (error != null) - e = new APIException(error.ErrorMessage, e); - } - catch + string responseString = WebRequest?.GetResponseString(); + + // naive check whether there's an error in the response to avoid unnecessary JSON deserialisation. + if (!string.IsNullOrEmpty(responseString) && responseString.Contains(@"""error""")) { + try + { + // attempt to decode a displayable error string. + var error = JsonConvert.DeserializeObject(responseString); + if (error != null) + e = new APIException(error.ErrorMessage, e); + } + catch + { + } } } - } - Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network); - pendingFailure = () => TriggerFailure(e); - checkAndScheduleFailure(); + Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network); + TriggerFailure(e); + } } /// - /// Checked for cancellation or error. Also queues up the Failed event if we can. + /// Whether this request is in a failing or failed state. /// - /// Whether we are in a failed or cancelled state. - private bool checkAndScheduleFailure() + private bool isFailing { - lock (completionStateLock) + get { - if (pendingFailure == null) + lock (completionStateLock) return completionState == APIRequestCompletionState.Failed; } - - if (API == null) - pendingFailure(); - else - API.Schedule(pendingFailure); - - pendingFailure = null; - return true; } private class DisplayableError From 0620cd130e6427b3c468c03b8a4a0a19a1854b42 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Thu, 29 Jul 2021 14:41:47 +0800 Subject: [PATCH 101/600] Change mod description --- osu.Game/Rulesets/Mods/ModMuted.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index dff3982041..aa2006cf73 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Muted"; public override string Acronym => "MU"; public override IconUsage? Icon => FontAwesome.Solid.VolumeMute; - public override string Description => "Who needs music in a rhythm game?"; + public override string Description => "Can you still feel the rhythm without music?"; public override ModType Type => ModType.Fun; public override double ScoreMultiplier => 1; } From 18e760ee91916bcca6071a51cdca628498dd8439 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Thu, 29 Jul 2021 14:52:18 +0800 Subject: [PATCH 102/600] Extract metronome from `OsuModTarget` --- osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs | 45 +--------------- .../Rulesets/Mods/MetronomeBeatContainer.cs | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 44 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index e21d1da009..576cc2da13 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; @@ -16,7 +14,6 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; using osu.Game.Configuration; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -29,7 +26,6 @@ using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.Utils; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -341,46 +337,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.Overlays.Add(new TargetBeatContainer(drawableRuleset.Beatmap.HitObjects.First().StartTime)); - } - - public class TargetBeatContainer : BeatSyncedContainer - { - private readonly double firstHitTime; - - private PausableSkinnableSound sample; - - public TargetBeatContainer(double firstHitTime) - { - this.firstHitTime = firstHitTime; - AllowMistimedEventFiring = false; - Divisor = 1; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChildren = new Drawable[] - { - sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana")) - }; - } - - protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) - { - base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - - if (!IsBeatSyncedWithTrack) return; - - int timeSignature = (int)timingPoint.TimeSignature; - - // play metronome from one measure before the first object. - if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature) - return; - - sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f; - sample.Play(); - } + drawableRuleset.Overlays.Add(new MetronomeBeatContainer(drawableRuleset.Beatmap.HitObjects.First().StartTime)); } #endregion diff --git a/osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs b/osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs new file mode 100644 index 0000000000..c5bb2c918f --- /dev/null +++ b/osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs @@ -0,0 +1,53 @@ +// 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.Allocation; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics; +using osu.Game.Audio; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Containers; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Mods +{ + public class MetronomeBeatContainer : BeatSyncedContainer + { + private readonly double firstHitTime; + + private PausableSkinnableSound sample; + + /// Start time of the first hit object, used for providing a count down. + public MetronomeBeatContainer(double firstHitTime) + { + this.firstHitTime = firstHitTime; + AllowMistimedEventFiring = false; + Divisor = 1; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana")) + }; + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) + { + base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); + + if (!IsBeatSyncedWithTrack) return; + + int timeSignature = (int)timingPoint.TimeSignature; + + // play metronome from one measure before the first object. + if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature) + return; + + sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f; + sample.Play(); + } + } +} From 0196141335b11d0f5b21d0bf700eb86e1024bd0f Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Thu, 29 Jul 2021 14:52:40 +0800 Subject: [PATCH 103/600] Remove unused constants --- osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index 576cc2da13..615700e6b9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -63,11 +63,6 @@ namespace osu.Game.Rulesets.Osu.Mods /// private const float distance_cap = 380f; - // The distances from the hit objects to the borders of the playfield they start to "turn around" and curve towards the middle. - // The closer the hit objects draw to the border, the sharper the turn - private const byte border_distance_x = 192; - private const byte border_distance_y = 144; - /// /// The extent of rotation towards playfield centre when a circle is near the edge /// From 935984d20016d19ee0de9e057a19ae0f3f137a44 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Thu, 29 Jul 2021 15:17:21 +0800 Subject: [PATCH 104/600] Rename `MetronomeBeatContainer` to `Metronome` --- osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs | 2 +- .../Rulesets/Mods/{MetronomeBeatContainer.cs => Metronome.cs} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Rulesets/Mods/{MetronomeBeatContainer.cs => Metronome.cs} (93%) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index 615700e6b9..210d5e0403 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -332,7 +332,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.Overlays.Add(new MetronomeBeatContainer(drawableRuleset.Beatmap.HitObjects.First().StartTime)); + drawableRuleset.Overlays.Add(new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime)); } #endregion diff --git a/osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs b/osu.Game/Rulesets/Mods/Metronome.cs similarity index 93% rename from osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs rename to osu.Game/Rulesets/Mods/Metronome.cs index c5bb2c918f..ee0a42b4bc 100644 --- a/osu.Game/Rulesets/Mods/MetronomeBeatContainer.cs +++ b/osu.Game/Rulesets/Mods/Metronome.cs @@ -11,14 +11,14 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mods { - public class MetronomeBeatContainer : BeatSyncedContainer + public class Metronome : BeatSyncedContainer { private readonly double firstHitTime; private PausableSkinnableSound sample; /// Start time of the first hit object, used for providing a count down. - public MetronomeBeatContainer(double firstHitTime) + public Metronome(double firstHitTime) { this.firstHitTime = firstHitTime; AllowMistimedEventFiring = false; From 89e8296eb1b17a42eae1f24422bf099a76a1ac37 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Thu, 29 Jul 2021 15:39:26 +0800 Subject: [PATCH 105/600] Reset all types of adjustments in `MusicController`; Rename `AllowRateAdjustments` to `AllowTrackAdjustments` --- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/MusicController.cs | 23 +++++++++++-------- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/IOsuScreen.cs | 4 ++-- osu.Game/Screens/Menu/MainMenu.cs | 2 +- .../Spectate/MultiSpectatorScreen.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/StartupScreen.cs | 2 +- 9 files changed, 22 insertions(+), 19 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 8e32b2e6a7..3cfa2cc755 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1058,7 +1058,7 @@ namespace osu.Game OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); API.Activity.BindTo(newOsuScreen.Activity); - MusicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments; + MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments; if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index a15f80ca21..8fd50c3df2 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -400,35 +400,38 @@ namespace osu.Game.Overlays NextTrack(); } - private bool allowRateAdjustments; + private bool allowTrackAdjustments; /// - /// Whether mod rate adjustments are allowed to be applied. + /// Whether mod track adjustments are allowed to be applied. /// - public bool AllowRateAdjustments + public bool AllowTrackAdjustments { - get => allowRateAdjustments; + get => allowTrackAdjustments; set { - if (allowRateAdjustments == value) + if (allowTrackAdjustments == value) return; - allowRateAdjustments = value; + allowTrackAdjustments = value; ResetTrackAdjustments(); } } /// - /// Resets the speed adjustments currently applied on and applies the mod adjustments if is true. + /// Resets the adjustments currently applied on and applies the mod adjustments if is true. /// /// - /// Does not reset speed adjustments applied directly to the beatmap track. + /// Does not reset any adjustments applied directly to the beatmap track. /// public void ResetTrackAdjustments() { - CurrentTrack.ResetSpeedAdjustments(); + CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Balance); + CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Frequency); + CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Tempo); + CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Volume); - if (allowRateAdjustments) + if (allowTrackAdjustments) { foreach (var mod in mods.Value.OfType()) mod.ApplyToTrack(CurrentTrack); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b6dc97a7f6..61a3b0f5cc 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit public override bool DisallowExternalBeatmapRulesetChanges => true; - public override bool AllowRateAdjustments => false; + public override bool AllowTrackAdjustments => false; protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash; diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 0434135547..17384c161c 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -59,9 +59,9 @@ namespace osu.Game.Screens Bindable Ruleset { get; } /// - /// Whether mod rate adjustments are allowed to be applied. + /// Whether mod track adjustments are allowed to be applied. /// - bool AllowRateAdjustments { get; } + bool AllowTrackAdjustments { get; } /// /// Invoked when the back button has been pressed to close any overlays before exiting this . diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index e53b46f391..1d0182a945 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Menu public override bool AllowExternalScreenChange => true; - public override bool AllowRateAdjustments => false; + public override bool AllowTrackAdjustments => false; private Screen songSelect; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 2a2759e0dd..56ed7a9564 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public override bool DisallowExternalBeatmapRulesetChanges => true; // We are managing our own adjustments. For now, this happens inside the Player instances themselves. - public override bool AllowRateAdjustments => false; + public override bool AllowTrackAdjustments => false; /// /// Whether all spectating players have finished loading. diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index c3b2612e79..e3fe14a585 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; - public virtual bool AllowRateAdjustments => true; + public virtual bool AllowTrackAdjustments => true; public Bindable Beatmap { get; private set; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0e4d38660b..d76d44767a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; // We are managing our own adjustments (see OnEntering/OnExiting). - public override bool AllowRateAdjustments => false; + public override bool AllowTrackAdjustments => false; private readonly IBindable gameActive = new Bindable(true); diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index e5e134fd39..15f75d7cff 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens public override bool CursorVisible => false; - public override bool AllowRateAdjustments => false; + public override bool AllowTrackAdjustments => false; protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; } From 81f23e111100ca6ee6a5a4858ec9b63c01560a7f Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 29 Jul 2021 17:12:01 +0900 Subject: [PATCH 106/600] Manage catcher trails by lifetime entries --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 6 +- osu.Game.Rulesets.Catch/UI/CatcherTrail.cs | 44 +++++++--- .../UI/CatcherTrailAnimation.cs | 12 +++ .../UI/CatcherTrailDisplay.cs | 80 ++++++++++++------- .../UI/CatcherTrailEntry.cs | 31 +++++++ 5 files changed, 133 insertions(+), 40 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs create mode 100644 osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 78f7e34649..21bf049ccc 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -110,14 +110,14 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = Catcher.X; if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) - catcherTrails.DisplayHyperDashAfterImage(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); + displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterimage); if (Catcher.Dashing || Catcher.HyperDashing) { double generationInterval = Catcher.HyperDashing ? 25 : 50; if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval) - catcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); + displayCatcherTrail(Catcher.HyperDashing ? CatcherTrailAnimation.HyperDashing : CatcherTrailAnimation.Dashing); } lastHyperDashState = Catcher.HyperDashing; @@ -173,5 +173,7 @@ namespace osu.Game.Rulesets.Catch.UI break; } } + + private void displayCatcherTrail(CatcherTrailAnimation animation) => catcherTrails.Add(new CatcherTrailEntry(Time.Current, Catcher.CurrentState, Catcher.X, Catcher.BodyScale, animation)); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs index ff1a7d7a61..a7a2941a7a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Pooling; using osu.Framework.Timing; +using osu.Game.Rulesets.Objects.Pooling; using osuTK; namespace osu.Game.Rulesets.Catch.UI @@ -12,13 +12,8 @@ namespace osu.Game.Rulesets.Catch.UI /// A trail of the catcher. /// It also represents a hyper dash afterimage. /// - public class CatcherTrail : PoolableDrawable + public class CatcherTrail : PoolableDrawableWithLifetime { - public CatcherAnimationState AnimationState - { - set => body.AnimationState.Value = value; - } - private readonly SkinnableCatcher body; public CatcherTrail() @@ -34,11 +29,40 @@ namespace osu.Game.Rulesets.Catch.UI }; } - protected override void FreeAfterUse() + protected override void OnApply(CatcherTrailEntry entry) + { + Scale = entry.Scale; + Position = new Vector2(entry.Position, 0); + Alpha = 1; + + body.AnimationState.Value = entry.CatcherState; + + using (BeginAbsoluteSequence(entry.LifetimeStart, false)) + applyTransforms(entry.Animation); + } + + protected override void OnFree(CatcherTrailEntry entry) { ClearTransforms(); - Alpha = 1; - base.FreeAfterUse(); + } + + private void applyTransforms(CatcherTrailAnimation animation) + { + switch (animation) + { + case CatcherTrailAnimation.Dashing: + case CatcherTrailAnimation.HyperDashing: + this.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); + break; + + case CatcherTrailAnimation.HyperDashAfterimage: + this.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); + this.ScaleTo(Scale * 0.95f).ScaleTo(Scale * 1.2f, 1200, Easing.In); + this.FadeOut(1200); + break; + } + + Expire(); } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs new file mode 100644 index 0000000000..3ea99badc1 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Catch.UI +{ + public enum CatcherTrailAnimation + { + Dashing, + HyperDashing, + HyperDashAfterimage + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index abc76fc925..f451f84c95 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -2,12 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Skinning; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.UI @@ -16,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.UI /// Represents a component responsible for displaying /// the appropriate catcher trails when requested to. /// - public class CatcherTrailDisplay : SkinReloadableDrawable + public class CatcherTrailDisplay : PooledDrawableWithLifetimeContainer { /// /// The most recent time a dash trail was added to this container. @@ -29,12 +30,17 @@ namespace osu.Game.Rulesets.Catch.UI public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour; + protected override bool RemoveRewoundEntry => true; + private readonly DrawablePool trailPool; private readonly Container dashTrails; private readonly Container hyperDashTrails; private readonly Container hyperDashAfterImages; + [Resolved] + private ISkinSource skin { get; set; } + public CatcherTrailDisplay() { RelativeSizeAxes = Axes.Both; @@ -48,50 +54,60 @@ namespace osu.Game.Rulesets.Catch.UI }; } - protected override void SkinChanged(ISkinSource skin) + protected override void LoadComplete() { - base.SkinChanged(skin); + base.LoadComplete(); + skin.SourceChanged += skinSourceChanged; + skinSourceChanged(); + } + + private void skinSourceChanged() + { hyperDashTrails.Colour = skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR; hyperDashAfterImages.Colour = skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour; } - /// - /// Displays a hyper-dash after-image of the catcher. - /// - public void DisplayHyperDashAfterImage(CatcherAnimationState animationState, float x, Vector2 scale) + protected override void AddDrawable(CatcherTrailEntry entry, CatcherTrail drawable) { - var trail = createTrail(animationState, x, scale); + switch (entry.Animation) + { + case CatcherTrailAnimation.Dashing: + dashTrails.Add(drawable); + break; - hyperDashAfterImages.Add(trail); + case CatcherTrailAnimation.HyperDashing: + hyperDashTrails.Add(drawable); + break; - trail.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); - trail.ScaleTo(trail.Scale * 0.95f).ScaleTo(trail.Scale * 1.2f, 1200, Easing.In); - trail.FadeOut(1200); - trail.Expire(true); + case CatcherTrailAnimation.HyperDashAfterimage: + hyperDashAfterImages.Add(drawable); + break; + } } - public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing) + protected override void RemoveDrawable(CatcherTrailEntry entry, CatcherTrail drawable) { - var trail = createTrail(animationState, x, scale); + switch (entry.Animation) + { + case CatcherTrailAnimation.Dashing: + dashTrails.Remove(drawable); + break; - if (hyperDashing) - hyperDashTrails.Add(trail); - else - dashTrails.Add(trail); + case CatcherTrailAnimation.HyperDashing: + hyperDashTrails.Remove(drawable); + break; - trail.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); - trail.Expire(true); + case CatcherTrailAnimation.HyperDashAfterimage: + hyperDashAfterImages.Remove(drawable); + break; + } } - private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale) + protected override CatcherTrail GetDrawable(CatcherTrailEntry entry) { CatcherTrail trail = trailPool.Get(); - - trail.AnimationState = animationState; - trail.Scale = scale; - trail.Position = new Vector2(x, 0); - + trail.Apply(entry); return trail; } @@ -107,5 +123,13 @@ namespace osu.Game.Rulesets.Catch.UI return maxTime; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (skin != null) + skin.SourceChanged -= skinSourceChanged; + } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs new file mode 100644 index 0000000000..3a40ab26cc --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs @@ -0,0 +1,31 @@ +// 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.Graphics.Performance; +using osuTK; + +namespace osu.Game.Rulesets.Catch.UI +{ + public class CatcherTrailEntry : LifetimeEntry + { + public readonly CatcherAnimationState CatcherState; + + public readonly float Position; + + /// + /// The scaling of the catcher body. It also represents a flipped catcher (negative x component). + /// + public readonly Vector2 Scale; + + public readonly CatcherTrailAnimation Animation; + + public CatcherTrailEntry(double startTime, CatcherAnimationState catcherState, float position, Vector2 scale, CatcherTrailAnimation animation) + { + LifetimeStart = startTime; + CatcherState = catcherState; + Position = position; + Scale = scale; + Animation = animation; + } + } +} From a204ef39dd1663de2e191d29e8e96cd1ca772b2a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 29 Jul 2021 17:32:20 +0900 Subject: [PATCH 107/600] Prevent catcher trail generation while rewinding --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 21bf049ccc..e99d33cd1b 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -109,7 +109,15 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = Catcher.X; - if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) + if (Time.Elapsed <= 0) + { + // This is probably a wrong value, but currently the true value is not recorded. + // Setting `true` will prevent generation of false-positive after-images (with more false-positives). + lastHyperDashState = true; + return; + } + + if (!lastHyperDashState && Catcher.HyperDashing) displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterimage); if (Catcher.Dashing || Catcher.HyperDashing) From 888e8f1c8052c2abef891f60eecd18c079881eed Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Thu, 29 Jul 2021 21:18:07 +0800 Subject: [PATCH 108/600] Use shared metronome class --- osu.Game/Rulesets/Mods/ModMuted.cs | 47 +----------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index aa2006cf73..9e69bc1386 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -2,19 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Audio; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; -using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Mods { @@ -48,46 +42,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { if (EnableMetronome.Value) - drawableRuleset.Overlays.Add(new MetronomeBeatContainer(drawableRuleset.Beatmap.HitObjects.First().StartTime)); - } - - public class MetronomeBeatContainer : BeatSyncedContainer - { - private readonly double firstHitTime; - - private PausableSkinnableSound sample; - - public MetronomeBeatContainer(double firstHitTime) - { - this.firstHitTime = firstHitTime; - AllowMistimedEventFiring = false; - Divisor = 1; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChildren = new Drawable[] - { - sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana")) - }; - } - - protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) - { - base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - - if (!IsBeatSyncedWithTrack) return; - - int timeSignature = (int)timingPoint.TimeSignature; - - // play metronome from one measure before the first object. - if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature) - return; - - sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f; - sample.Play(); - } + drawableRuleset.Overlays.Add(new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime)); } } } From 5c5e33f4d744676baa7116aec7b576e950d61e41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 01:53:08 +0900 Subject: [PATCH 109/600] Split out common logic for tournament game host tests --- .../NonVisual/CustomTourneyDirectoryTest.cs | 32 +++--------------- .../NonVisual/IPCLocationTest.cs | 28 ++-------------- .../NonVisual/TournamentHostTest.cs | 33 +++++++++++++++++++ 3 files changed, 41 insertions(+), 52 deletions(-) create mode 100644 osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs diff --git a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs index d2369056e1..fcc9f44f0c 100644 --- a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs @@ -1,21 +1,18 @@ // 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.IO; -using System.Threading; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Platform; -using osu.Game.Tournament.Configuration; using osu.Game.Tests; +using osu.Game.Tournament.Configuration; namespace osu.Game.Tournament.Tests.NonVisual { [TestFixture] - public class CustomTourneyDirectoryTest + public class CustomTourneyDirectoryTest : TournamentHostTest { [Test] public void TestDefaultDirectory() @@ -24,7 +21,7 @@ namespace osu.Game.Tournament.Tests.NonVisual { try { - var osu = loadOsu(host); + var osu = LoadTournament(host); var storage = osu.Dependencies.Get(); Assert.That(storage.GetFullPath("."), Is.EqualTo(Path.Combine(host.Storage.GetFullPath("."), "tournaments", "default"))); @@ -54,7 +51,7 @@ namespace osu.Game.Tournament.Tests.NonVisual try { - var osu = loadOsu(host); + var osu = LoadTournament(host); storage = osu.Dependencies.Get(); @@ -111,7 +108,7 @@ namespace osu.Game.Tournament.Tests.NonVisual try { - var osu = loadOsu(host); + var osu = LoadTournament(host); var storage = osu.Dependencies.Get(); @@ -151,25 +148,6 @@ namespace osu.Game.Tournament.Tests.NonVisual } } - private TournamentGameBase loadOsu(GameHost host) - { - var osu = new TournamentGameBase(); - Task.Run(() => host.Run(osu)) - .ContinueWith(t => Assert.Fail($"Host threw exception {t.Exception}"), TaskContinuationOptions.OnlyOnFaulted); - waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); - return osu; - } - - private static void waitForOrAssert(Func result, string failureMessage, int timeout = 90000) - { - Task task = Task.Run(() => - { - while (!result()) Thread.Sleep(200); - }); - - Assert.IsTrue(task.Wait(timeout), failureMessage); - } - private string basePath(string testInstance) => Path.Combine(RuntimeInfo.StartupDirectory, "headless", testInstance); } } diff --git a/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs b/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs index e4eb5a36fb..eaa009c180 100644 --- a/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs @@ -1,10 +1,7 @@ // 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.IO; -using System.Threading; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework; using osu.Framework.Allocation; @@ -15,7 +12,7 @@ using osu.Game.Tournament.IPC; namespace osu.Game.Tournament.Tests.NonVisual { [TestFixture] - public class IPCLocationTest + public class IPCLocationTest : TournamentHostTest { [Test] public void CheckIPCLocation() @@ -34,11 +31,11 @@ namespace osu.Game.Tournament.Tests.NonVisual try { - var osu = loadOsu(host); + var osu = LoadTournament(host); TournamentStorage storage = (TournamentStorage)osu.Dependencies.Get(); FileBasedIPC ipc = null; - waitForOrAssert(() => (ipc = osu.Dependencies.Get() as FileBasedIPC) != null, @"ipc could not be populated in a reasonable amount of time"); + WaitForOrAssert(() => (ipc = osu.Dependencies.Get() as FileBasedIPC) != null, @"ipc could not be populated in a reasonable amount of time"); Assert.True(ipc.SetIPCLocation(testStableInstallDirectory)); Assert.True(storage.AllTournaments.Exists("stable.json")); @@ -51,24 +48,5 @@ namespace osu.Game.Tournament.Tests.NonVisual } } } - - private TournamentGameBase loadOsu(GameHost host) - { - var osu = new TournamentGameBase(); - Task.Run(() => host.Run(osu)) - .ContinueWith(t => Assert.Fail($"Host threw exception {t.Exception}"), TaskContinuationOptions.OnlyOnFaulted); - waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); - return osu; - } - - private static void waitForOrAssert(Func result, string failureMessage, int timeout = 90000) - { - Task task = Task.Run(() => - { - while (!result()) Thread.Sleep(200); - }); - - Assert.IsTrue(task.Wait(timeout), failureMessage); - } } } diff --git a/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs b/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs new file mode 100644 index 0000000000..b14684200f --- /dev/null +++ b/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs @@ -0,0 +1,33 @@ +// 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.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Platform; + +namespace osu.Game.Tournament.Tests.NonVisual +{ + public abstract class TournamentHostTest + { + public static TournamentGameBase LoadTournament(GameHost host, TournamentGameBase tournament = null) + { + tournament ??= new TournamentGameBase(); + Task.Run(() => host.Run(tournament)) + .ContinueWith(t => Assert.Fail($"Host threw exception {t.Exception}"), TaskContinuationOptions.OnlyOnFaulted); + WaitForOrAssert(() => tournament.IsLoaded, @"osu! failed to start in a reasonable amount of time"); + return tournament; + } + + public static void WaitForOrAssert(Func result, string failureMessage, int timeout = 90000) + { + Task task = Task.Run(() => + { + while (!result()) Thread.Sleep(200); + }); + + Assert.IsTrue(task.Wait(timeout), failureMessage); + } + } +} From 0b8ca667a94c5c5d962bbd66726e464deca21422 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 01:53:25 +0900 Subject: [PATCH 110/600] Add failing test coverage of loading with an unavailable ruleset --- .../NonVisual/DataLoadTest.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs diff --git a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs new file mode 100644 index 0000000000..692cb3870c --- /dev/null +++ b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Platform; +using osu.Game.Rulesets; +using osu.Game.Tests; + +namespace osu.Game.Tournament.Tests.NonVisual +{ + public class DataLoadTest : TournamentHostTest + { + [Test] + public void TestUnavailableRuleset() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestUnavailableRuleset))) + { + try + { + var osu = new TestTournament(); + + LoadTournament(host, osu); + var storage = osu.Dependencies.Get(); + + Assert.That(storage.GetFullPath("."), Is.EqualTo(Path.Combine(host.Storage.GetFullPath("."), "tournaments", "default"))); + } + finally + { + host.Exit(); + } + } + } + + public class TestTournament : TournamentGameBase + { + [BackgroundDependencyLoader] + private void load() + { + Ruleset.Value = new RulesetInfo(); // not available + } + } + } +} From 46c72334fbd3d8427a92960cdffbc83d260439fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 01:54:30 +0900 Subject: [PATCH 111/600] Fix stack overflow in ruleset change rejection logic --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a7fac24351..f2d575550a 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -479,7 +479,7 @@ namespace osu.Game if (r.NewValue?.Available != true) { // reject the change if the ruleset is not available. - Ruleset.Value = r.OldValue; + Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First(); return; } From ceec74aacaa709e907b64c59833f999981ab28aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 02:00:07 +0900 Subject: [PATCH 112/600] Avoid throwing / logging an error when `drawings.txt` is missing --- .../Screens/Drawings/Components/StorageBackedTeamList.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index f96ec01cbb..5d035a4028 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -27,6 +27,9 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { var teams = new List(); + if (!storage.Exists(teams_filename)) + return teams; + try { using (Stream stream = storage.GetStream(teams_filename, FileAccess.Read, FileMode.Open)) From 77b354bfba5ad6ecf4675a359a8a6b45359b16a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 02:12:03 +0900 Subject: [PATCH 113/600] Resolve ruleset from store after loading tournament ladder --- osu.Game.Tournament/TournamentGameBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 92eb7ac713..531da00faf 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -66,7 +66,9 @@ namespace osu.Game.Tournament } ladder ??= new LadderInfo(); - ladder.Ruleset.Value ??= RulesetStore.AvailableRulesets.First(); + + ladder.Ruleset.Value = RulesetStore.GetRuleset(ladder.Ruleset.Value?.ShortName) + ?? RulesetStore.AvailableRulesets.First(); bool addedInfo = false; From 59a33b5d028fb688bb86956abe1e3eeac83a59c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 27 Jul 2021 18:46:49 +0200 Subject: [PATCH 114/600] Uncouple display logic from text in rankings overlay tables --- .../Rankings/Tables/CountriesTable.cs | 14 ++++---- .../Rankings/Tables/PerformanceTable.cs | 4 +-- .../Overlays/Rankings/Tables/RankingsTable.cs | 32 ++++++++++++------- .../Overlays/Rankings/Tables/ScoresTable.cs | 8 ++--- .../Rankings/Tables/UserBasedTable.cs | 32 +++++++++++-------- 5 files changed, 50 insertions(+), 40 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index c5e413c7fa..b28bf07adc 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -19,14 +19,14 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected override TableColumn[] CreateAdditionalHeaders() => new[] + protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[] { - new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true), + new RankingsTableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; protected override Country GetCountry(CountryStatistics item) => item.Country; diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 1e6b2307e0..ddf4bdcfeb 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -15,9 +15,9 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected override TableColumn[] CreateUniqueHeaders() => new[] + protected override RankingsTableColumn[] CreateUniqueHeaders() => new[] { - new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true), }; protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index f568aae59c..0cdff0a77f 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -55,29 +55,24 @@ namespace osu.Game.Overlays.Rankings.Tables rankings.ForEach(_ => backgroundFlow.Add(new TableRowBackground { Height = row_height })); - Columns = mainHeaders.Concat(CreateAdditionalHeaders()).ToArray(); + Columns = mainHeaders.Concat(CreateAdditionalHeaders()).Cast().ToArray(); Content = rankings.Select((s, i) => createContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); } private Drawable[] createContent(int index, TModel item) => new Drawable[] { createIndexDrawable(index), createMainContent(item) }.Concat(CreateAdditionalContent(item)).ToArray(); - private static TableColumn[] mainHeaders => new[] + private static RankingsTableColumn[] mainHeaders => new[] { - new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 40)), // place - new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension()), // flag and username (country name) + new RankingsTableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 40)), // place + new RankingsTableColumn(string.Empty, Anchor.CentreLeft, new Dimension()), // flag and username (country name) }; - protected abstract TableColumn[] CreateAdditionalHeaders(); + protected abstract RankingsTableColumn[] CreateAdditionalHeaders(); protected abstract Drawable[] CreateAdditionalContent(TModel item); - protected virtual string HighlightedColumn => @"Performance"; - - protected override Drawable CreateHeader(int index, TableColumn column) - { - var title = column?.Header ?? default; - return new HeaderText(title, title == HighlightedColumn); - } + protected sealed override Drawable CreateHeader(int index, TableColumn column) + => (column as RankingsTableColumn)?.CreateHeaderText() ?? new HeaderText(column?.Header ?? default, false); protected abstract Country GetCountry(TModel item); @@ -106,6 +101,19 @@ namespace osu.Game.Overlays.Rankings.Tables } }; + protected class RankingsTableColumn : TableColumn + { + protected readonly bool Highlighted; + + public RankingsTableColumn(LocalisableString? header = null, Anchor anchor = Anchor.TopLeft, Dimension dimension = null, bool highlighted = false) + : base(header, anchor, dimension) + { + Highlighted = highlighted; + } + + public virtual HeaderText CreateHeaderText() => new HeaderText(Header, Highlighted); + } + protected class HeaderText : OsuSpriteText { private readonly bool isHighlighted; diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 9fae8e1897..508ad51112 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -15,10 +15,10 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected override TableColumn[] CreateUniqueHeaders() => new[] + protected override RankingsTableColumn[] CreateUniqueHeaders() => new[] { - new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)) + new RankingsTableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true) }; protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] @@ -32,7 +32,5 @@ namespace osu.Game.Overlays.Rankings.Tables Text = $@"{item.RankedScore:N0}", } }; - - protected override string HighlightedColumn => @"Ranked Score"; } } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 56814244c0..131ee86d44 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -22,20 +22,14 @@ namespace osu.Game.Overlays.Rankings.Tables protected virtual IEnumerable GradeColumns => new List { "SS", "S", "A" }; - protected override TableColumn[] CreateAdditionalHeaders() => new[] + protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[] { - new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }.Concat(CreateUniqueHeaders()) - .Concat(GradeColumns.Select(grade => new TableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)))) + .Concat(GradeColumns.Select(grade => new GradeTableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)))) .ToArray(); - protected override Drawable CreateHeader(int index, TableColumn column) - { - var title = column?.Header ?? default; - return new UserTableHeaderText(title, HighlightedColumn == title, GradeColumns.Contains(title.ToString())); - } - protected sealed override Country GetCountry(UserStatistics item) => item.User.Country; protected sealed override Drawable CreateFlagContent(UserStatistics item) @@ -61,19 +55,29 @@ namespace osu.Game.Overlays.Rankings.Tables new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.A]:N0}", } }).ToArray(); - protected abstract TableColumn[] CreateUniqueHeaders(); + protected abstract RankingsTableColumn[] CreateUniqueHeaders(); protected abstract Drawable[] CreateUniqueContent(UserStatistics item); - private class UserTableHeaderText : HeaderText + private class GradeTableColumn : RankingsTableColumn { - public UserTableHeaderText(LocalisableString text, bool isHighlighted, bool isGrade) + public GradeTableColumn(LocalisableString? header = null, Anchor anchor = Anchor.TopLeft, Dimension dimension = null, bool highlighted = false) + : base(header, anchor, dimension, highlighted) + { + } + + public override HeaderText CreateHeaderText() => new GradeHeaderText(Header, Highlighted); + } + + private class GradeHeaderText : HeaderText + { + public GradeHeaderText(LocalisableString text, bool isHighlighted) : base(text, isHighlighted) { Margin = new MarginPadding { // Grade columns have extra horizontal padding for readibility - Horizontal = isGrade ? 20 : 10, + Horizontal = 20, Vertical = 5 }; } From 0691c0dd63d26238396c602332fc12fd90c4688e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 20 Jun 2021 19:37:09 +0200 Subject: [PATCH 115/600] Switch `Colour{Display,Palette}` to use `Colour4` --- .../UserInterface/TestSceneLabelledColourPalette.cs | 10 +++++----- osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs | 8 +++----- osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs | 3 +-- .../Graphics/UserInterfaceV2/LabelledColourPalette.cs | 4 ++-- osu.Game/Screens/Edit/Setup/ColoursSection.cs | 3 ++- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs index 826da17ca8..d7af47a835 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs @@ -53,15 +53,15 @@ namespace osu.Game.Tests.Visual.UserInterface component.Colours.AddRange(new[] { - Color4.DarkRed, - Color4.Aquamarine, - Color4.Goldenrod, - Color4.Gainsboro + Colour4.DarkRed, + Colour4.Aquamarine, + Colour4.Goldenrod, + Colour4.Gainsboro }); }); } - private Color4 randomColour() => new Color4( + private Colour4 randomColour() => new Color4( RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index 01d91f7cfd..dfdc76687f 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -11,22 +10,21 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; using osuTK; -using osuTK.Graphics; namespace osu.Game.Graphics.UserInterfaceV2 { /// /// A component which displays a colour along with related description text. /// - public class ColourDisplay : CompositeDrawable, IHasCurrentValue + public class ColourDisplay : CompositeDrawable, IHasCurrentValue { - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); private Box fill; private OsuSpriteText colourHexCode; private OsuSpriteText colourName; - public Bindable Current + public Bindable Current { get => current.Current; set => current.Current = value; diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index ba950048dc..a32257ef79 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; -using osuTK.Graphics; namespace osu.Game.Graphics.UserInterfaceV2 { @@ -17,7 +16,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// public class ColourPalette : CompositeDrawable { - public BindableList Colours { get; } = new BindableList(); + public BindableList Colours { get; } = new BindableList(); private string colourNamePrefix = "Colour"; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs index 58443953bc..8970ef1115 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osuTK.Graphics; +using osu.Framework.Graphics; namespace osu.Game.Graphics.UserInterfaceV2 { @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { } - public BindableList Colours => Component.Colours; + public BindableList Colours => Component.Colours; public string ColourNamePrefix { diff --git a/osu.Game/Screens/Edit/Setup/ColoursSection.cs b/osu.Game/Screens/Edit/Setup/ColoursSection.cs index 4a81959a54..d7e16645f2 100644 --- a/osu.Game/Screens/Edit/Setup/ColoursSection.cs +++ b/osu.Game/Screens/Edit/Setup/ColoursSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.Edit.Setup var colours = Beatmap.BeatmapSkin?.GetConfig>(GlobalSkinColours.ComboColours)?.Value; if (colours != null) - comboColours.Colours.AddRange(colours); + comboColours.Colours.AddRange(colours.Select(c => (Colour4)c)); } } } From c8891d4504145b07e97b8f34b7bb9e5f68e912c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 20 Jun 2021 20:20:46 +0200 Subject: [PATCH 116/600] Integrate editor colour display with colour picker & popover --- .../Graphics/UserInterfaceV2/ColourDisplay.cs | 19 +++++++++++++++--- .../Graphics/UserInterfaceV2/ColourPalette.cs | 20 ++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index dfdc76687f..25f89fdcaa 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -3,11 +3,14 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; @@ -16,7 +19,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// /// A component which displays a colour along with related description text. /// - public class ColourDisplay : CompositeDrawable, IHasCurrentValue + public class ColourDisplay : CompositeDrawable, IHasCurrentValue, IHasPopover { private readonly BindableWithCurrent current = new BindableWithCurrent(); @@ -60,10 +63,11 @@ namespace osu.Game.Graphics.UserInterfaceV2 Spacing = new Vector2(0, 10), Children = new Drawable[] { - new CircularContainer + new OsuClickableContainer { RelativeSizeAxes = Axes.X, Height = 100, + CornerRadius = 50, Masking = true, Children = new Drawable[] { @@ -77,7 +81,8 @@ namespace osu.Game.Graphics.UserInterfaceV2 Origin = Anchor.Centre, Font = OsuFont.Default.With(size: 12) } - } + }, + Action = this.ShowPopover }, colourName = new OsuSpriteText { @@ -101,5 +106,13 @@ namespace osu.Game.Graphics.UserInterfaceV2 colourHexCode.Text = current.Value.ToHex(); colourHexCode.Colour = OsuColour.ForegroundTextColourFor(current.Value); } + + public Popover GetPopover() => new OsuPopover(false) + { + Child = new OsuColourPicker + { + Current = { BindTarget = Current } + } + }; } } diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index a32257ef79..d8edd00c16 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -72,14 +73,17 @@ namespace osu.Game.Graphics.UserInterfaceV2 { base.LoadComplete(); - Colours.BindCollectionChanged((_, __) => updatePalette(), true); + Colours.BindCollectionChanged((_, args) => updatePalette(args), true); FinishTransforms(true); } private const int fade_duration = 200; - private void updatePalette() + private void updatePalette(NotifyCollectionChangedEventArgs args) { + if (args.Action == NotifyCollectionChangedAction.Replace) + return; + palette.Clear(); if (Colours.Any()) @@ -93,12 +97,18 @@ namespace osu.Game.Graphics.UserInterfaceV2 placeholder.FadeIn(fade_duration, Easing.OutQuint); } - foreach (var item in Colours) + for (int i = 0; i < Colours.Count; ++i) { - palette.Add(new ColourDisplay + // copy to avoid accesses to modified closure. + int colourIndex = i; + ColourDisplay display; + + palette.Add(display = new ColourDisplay { - Current = { Value = item } + Current = { Value = Colours[colourIndex] } }); + + display.Current.BindValueChanged(colour => Colours[colourIndex] = colour.NewValue); } reindexItems(); From 3a347188a5f20e79b6bdaeb16d79cbcd432efcb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 13:21:26 +0900 Subject: [PATCH 117/600] Allow `LinkFlowContainer` to still open external URLs when `OsuGame` is not available --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 5ff2fdf6b2..85ef779e48 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Framework.Platform; using osu.Game.Graphics.Sprites; using osu.Game.Users; @@ -25,6 +26,9 @@ namespace osu.Game.Graphics.Containers [Resolved(CanBeNull = true)] private OsuGame game { get; set; } + [Resolved] + private GameHost host { get; set; } + public void AddLinks(string text, List links) { if (string.IsNullOrEmpty(text) || links == null) @@ -91,8 +95,11 @@ namespace osu.Game.Graphics.Containers { if (action != null) action(); - else - game?.HandleLink(link); + else if (game != null) + game.HandleLink(link); + // fallback to handle cases where OsuGame is not available, ie. tournament client. + else if (link.Action == LinkAction.External) + host.OpenUrlExternally(link.Argument); }, }); } From 6249ce0ea3ebbd12718b3688a3d3dc9aff6bea43 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 13:21:50 +0900 Subject: [PATCH 118/600] Add a warning and link for more information on `drawings.txt` population --- .../Screens/Drawings/DrawingsScreen.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 4c3adeae76..d02e0ebf86 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -9,11 +9,13 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Drawings.Components; @@ -51,6 +53,29 @@ namespace osu.Game.Tournament.Screens.Drawings if (!TeamList.Teams.Any()) { + LinkFlowContainer links; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = 0.3f, + }, + new WarningBox("No drawings.txt file found. Please create one and restart the client."), + links = new LinkFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = 60, + AutoSizeAxes = Axes.Both + } + }; + + links.AddLink("Click for details on the file format", "https://osu.ppy.sh/wiki/en/Tournament_Drawings", t => t.Colour = Color4.White); return; } From 665bd3690aa67f3746e8bd0d5f0ddd2a05907ff4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 15:27:24 +0900 Subject: [PATCH 119/600] Add a few cases of missing `ConfigureAwait` calls in tests project --- .../Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs | 4 ++-- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index 42848ffc0c..7e7e5ebc45 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -168,8 +168,8 @@ namespace osu.Game.Tests.Online public override async Task Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) { - await AllowImport.Task; - return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)); + await AllowImport.Task.ConfigureAwait(false); + return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false); } } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 449401c0bf..66ac700c51 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -143,9 +143,9 @@ namespace osu.Game.Tests.Visual.SongSelect public override async Task GetDifficultyAsync(BeatmapInfo beatmapInfo, RulesetInfo rulesetInfo = null, IEnumerable mods = null, CancellationToken cancellationToken = default) { if (blockCalculation) - await calculationBlocker.Task; + await calculationBlocker.Task.ConfigureAwait(false); - return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken); + return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken).ConfigureAwait(false); } } } From 451c65a2c894e05f57b03a593fc3d8ccfc740828 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 29 Jul 2021 23:41:01 -0700 Subject: [PATCH 120/600] Fix song progress graph not being correctly hidden --- osu.Game/Screens/Play/SongProgress.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index bd861dc598..f28622f42e 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Play float barHeight = bottom_bar_height + handle_size.Y; bar.ResizeHeightTo(ShowGraph.Value ? barHeight + graph_height : barHeight, transition_duration, Easing.In); - graph.MoveToY(ShowGraph.Value ? 0 : bottom_bar_height + graph_height, transition_duration, Easing.In); + graph.FadeTo(ShowGraph.Value ? 1 : 0, transition_duration, Easing.In); updateInfoMargin(); } From 4e2f928d65ab6d962cc8026ade8473dbad4c206f Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 30 Jul 2021 15:44:09 +0900 Subject: [PATCH 121/600] Fix comment --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index e99d33cd1b..9422d6d51b 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Catch.UI if (Time.Elapsed <= 0) { // This is probably a wrong value, but currently the true value is not recorded. - // Setting `true` will prevent generation of false-positive after-images (with more false-positives). + // Setting `true` will prevent generation of false-positive after-images (with more false-negatives). lastHyperDashState = true; return; } From a2f3edbfc0cfda19ce03fa388ab0436c96d43904 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 15:49:11 +0900 Subject: [PATCH 122/600] Fade track volume out as combo increases --- osu.Game/Rulesets/Mods/ModMuted.cs | 48 ++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 9e69bc1386..a39d798bc4 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -1,14 +1,18 @@ // 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.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { @@ -22,10 +26,15 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1; } - public abstract class ModMuted : ModMuted, IApplicableToDrawableRuleset, IApplicableToTrack + public abstract class ModMuted : ModMuted, IApplicableToDrawableRuleset, IApplicableToTrack, IApplicableToScoreProcessor where TObject : HitObject { - private readonly BindableNumber volumeAdjust = new BindableDouble(); + private readonly BindableNumber trackVolumeAdjust = new BindableDouble(0.5); + private readonly BindableNumber metronomeVolumeAdjust = new BindableDouble(0.5); + + private BindableNumber currentCombo; + + private AudioContainer metronomeContainer; [SettingSource("Enable metronome", "Add a metronome to help you keep track of the rhythm.")] public BindableBool EnableMetronome { get; } = new BindableBool @@ -34,15 +43,44 @@ namespace osu.Game.Rulesets.Mods Value = true }; + [SettingSource("Muted at combo", "The combo count at which point the music is completely muted.")] + public BindableInt MuteComboCount { get; } = new BindableInt + { + Default = 100, + Value = 100, + MinValue = 0, + MaxValue = 500, + }; + public void ApplyToTrack(ITrack track) { - track.AddAdjustment(AdjustableProperty.Volume, volumeAdjust); + track.AddAdjustment(AdjustableProperty.Volume, trackVolumeAdjust); } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - if (EnableMetronome.Value) - drawableRuleset.Overlays.Add(new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime)); + if (!EnableMetronome.Value) return; + + drawableRuleset.Overlays.Add(metronomeContainer = new AudioContainer + { + Child = new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime) + }); + + metronomeContainer.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust); } + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + currentCombo = scoreProcessor.Combo.GetBoundCopy(); + currentCombo.BindValueChanged(combo => + { + double dimFactor = Math.Min(1, (double)combo.NewValue / MuteComboCount.Value); + + metronomeVolumeAdjust.Value = dimFactor; + trackVolumeAdjust.Value = 1 - dimFactor; + }, true); + } + + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } } From b399ddaea047ce22092566f46685bc984f5bfcc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 16:10:10 +0900 Subject: [PATCH 123/600] Add inverse setting --- osu.Game/Rulesets/Mods/ModMuted.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index a39d798bc4..5fc9ab1eda 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -52,6 +52,13 @@ namespace osu.Game.Rulesets.Mods MaxValue = 500, }; + [SettingSource("Start muted", "Increase volume as combo builds.")] + public BindableBool InverseMuting { get; } = new BindableBool + { + Default = false, + Value = false + }; + public void ApplyToTrack(ITrack track) { track.AddAdjustment(AdjustableProperty.Volume, trackVolumeAdjust); @@ -78,6 +85,8 @@ namespace osu.Game.Rulesets.Mods metronomeVolumeAdjust.Value = dimFactor; trackVolumeAdjust.Value = 1 - dimFactor; + if (InverseMuting.Value) + dimFactor = 1 - dimFactor; }, true); } From 3cfd235b7f53b14c63fadd21b4775ad865c971c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 16:10:20 +0900 Subject: [PATCH 124/600] Add tween when missing to avoid sudden volume difference --- osu.Game/Rulesets/Mods/ModMuted.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 5fc9ab1eda..469f3073d6 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; @@ -43,7 +44,7 @@ namespace osu.Game.Rulesets.Mods Value = true }; - [SettingSource("Muted at combo", "The combo count at which point the music is completely muted.")] + [SettingSource("Final volume at combo", "The combo count at which point the music reaches its final volume.")] public BindableInt MuteComboCount { get; } = new BindableInt { Default = 100, @@ -83,10 +84,19 @@ namespace osu.Game.Rulesets.Mods { double dimFactor = Math.Min(1, (double)combo.NewValue / MuteComboCount.Value); - metronomeVolumeAdjust.Value = dimFactor; - trackVolumeAdjust.Value = 1 - dimFactor; if (InverseMuting.Value) dimFactor = 1 - dimFactor; + + if (combo.NewValue < combo.OldValue) + { + scoreProcessor.TransformBindableTo(metronomeVolumeAdjust, dimFactor, 200, Easing.OutQuint); + scoreProcessor.TransformBindableTo(trackVolumeAdjust, 1 - dimFactor, 200, Easing.OutQuint); + } + else + { + metronomeVolumeAdjust.Value = dimFactor; + trackVolumeAdjust.Value = 1 - dimFactor; + } }, true); } From 0c3f1195e91329c4dce028797c085c2354f63657 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 16:47:07 +0900 Subject: [PATCH 125/600] Allow audio adjustments to be applied to `DrawableRuleset`s --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 43 +++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index daf46dcdcc..b3242a8b4b 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -1,29 +1,29 @@ // 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.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.Cursor; using osu.Game.Input.Handlers; using osu.Game.Overlays; using osu.Game.Replays; using osu.Game.Rulesets.Configuration; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; @@ -98,6 +98,14 @@ namespace osu.Game.Rulesets.UI private DrawableRulesetDependencies dependencies; + /// + /// An audio container which can be used to apply adjustments to playfield content. + /// + /// + /// Does not affect . + /// + public AudioContainer AudioContainer { get; private set; } + /// /// Creates a ruleset visualisation for the provided ruleset and beatmap. /// @@ -155,21 +163,22 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load(CancellationToken? cancellationToken) { - InternalChildren = new Drawable[] + InternalChild = frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) { - frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) + FrameStablePlayback = FrameStablePlayback, + Children = new Drawable[] { - FrameStablePlayback = FrameStablePlayback, - Children = new Drawable[] + FrameStableComponents, + AudioContainer = new AudioContainer { - FrameStableComponents, - KeyBindingInputManager + RelativeSizeAxes = Axes.Both, + Child = KeyBindingInputManager .WithChild(CreatePlayfieldAdjustmentContainer() .WithChild(Playfield) ), - Overlays, - } - }, + }, + Overlays, + } }; if ((ResumeOverlay = CreateResumeOverlay()) != null) From bdc5eb6d3dcd9a4e75e1cd301886cd163d4560ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 16:46:42 +0900 Subject: [PATCH 126/600] Add ability to also mute hitsounds --- osu.Game/Rulesets/Mods/ModMuted.cs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 469f3073d6..e29c1166e4 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModMuted : ModMuted, IApplicableToDrawableRuleset, IApplicableToTrack, IApplicableToScoreProcessor where TObject : HitObject { - private readonly BindableNumber trackVolumeAdjust = new BindableDouble(0.5); + private readonly BindableNumber mainVolumeAdjust = new BindableDouble(0.5); private readonly BindableNumber metronomeVolumeAdjust = new BindableDouble(0.5); private BindableNumber currentCombo; @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mods Value = true }; - [SettingSource("Final volume at combo", "The combo count at which point the music reaches its final volume.")] + [SettingSource("Final volume at combo", "The combo count at which point the track reaches its final volume.")] public BindableInt MuteComboCount { get; } = new BindableInt { Default = 100, @@ -60,9 +60,16 @@ namespace osu.Game.Rulesets.Mods Value = false }; + [SettingSource("Mute hit sounds", "Hit sounds are also muted alongside the track.")] + public BindableBool AffectsHitSounds { get; } = new BindableBool + { + Default = false, + Value = false + }; + public void ApplyToTrack(ITrack track) { - track.AddAdjustment(AdjustableProperty.Volume, trackVolumeAdjust); + track.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) @@ -75,6 +82,9 @@ namespace osu.Game.Rulesets.Mods }); metronomeContainer.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust); + + if (AffectsHitSounds.Value) + drawableRuleset.AudioContainer.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); } public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -90,12 +100,12 @@ namespace osu.Game.Rulesets.Mods if (combo.NewValue < combo.OldValue) { scoreProcessor.TransformBindableTo(metronomeVolumeAdjust, dimFactor, 200, Easing.OutQuint); - scoreProcessor.TransformBindableTo(trackVolumeAdjust, 1 - dimFactor, 200, Easing.OutQuint); + scoreProcessor.TransformBindableTo(mainVolumeAdjust, 1 - dimFactor, 200, Easing.OutQuint); } else { metronomeVolumeAdjust.Value = dimFactor; - trackVolumeAdjust.Value = 1 - dimFactor; + mainVolumeAdjust.Value = 1 - dimFactor; } }, true); } From d5e68f53b5e005bf93d359f6e81521d17dbd15d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 17:38:04 +0900 Subject: [PATCH 127/600] Change some defaults and always tween --- osu.Game/Rulesets/Mods/ModMuted.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index e29c1166e4..0ec45f4fbb 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mods private AudioContainer metronomeContainer; - [SettingSource("Enable metronome", "Add a metronome to help you keep track of the rhythm.")] + [SettingSource("Enable metronome", "Add a metronome beat to help you keep track of the rhythm.")] public BindableBool EnableMetronome { get; } = new BindableBool { Default = true, @@ -63,8 +63,8 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Mute hit sounds", "Hit sounds are also muted alongside the track.")] public BindableBool AffectsHitSounds { get; } = new BindableBool { - Default = false, - Value = false + Default = true, + Value = true }; public void ApplyToTrack(ITrack track) @@ -97,16 +97,8 @@ namespace osu.Game.Rulesets.Mods if (InverseMuting.Value) dimFactor = 1 - dimFactor; - if (combo.NewValue < combo.OldValue) - { - scoreProcessor.TransformBindableTo(metronomeVolumeAdjust, dimFactor, 200, Easing.OutQuint); - scoreProcessor.TransformBindableTo(mainVolumeAdjust, 1 - dimFactor, 200, Easing.OutQuint); - } - else - { - metronomeVolumeAdjust.Value = dimFactor; - mainVolumeAdjust.Value = 1 - dimFactor; - } + scoreProcessor.TransformBindableTo(metronomeVolumeAdjust, dimFactor, 500, Easing.OutQuint); + scoreProcessor.TransformBindableTo(mainVolumeAdjust, 1 - dimFactor, 500, Easing.OutQuint); }, true); } From 185ea776f5e1f88855fbde040b27848bfc6e82c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 18:11:35 +0900 Subject: [PATCH 128/600] Fix incorrect authorisation loss exception handling with recent changes --- osu.Game/Online/API/APIAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index eb3abff2b7..b35dfa11cb 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -150,7 +150,7 @@ namespace osu.Game.Online.API userReq.Failure += ex => { - if (ex.InnerException is WebException webException && webException.Message == @"Unauthorized") + if (ex is WebException webException && webException.Message == @"Unauthorized") { log.Add(@"Login no longer valid"); Logout(); From cd516c4ac7644689e9fdd8b8f3758ed06a9547de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 19:38:43 +0900 Subject: [PATCH 129/600] Fix regressed metronome handling --- osu.Game/Rulesets/Mods/ModMuted.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 0ec45f4fbb..5454483571 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -74,14 +74,15 @@ namespace osu.Game.Rulesets.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - if (!EnableMetronome.Value) return; - - drawableRuleset.Overlays.Add(metronomeContainer = new AudioContainer + if (EnableMetronome.Value) { - Child = new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime) - }); + drawableRuleset.Overlays.Add(metronomeContainer = new AudioContainer + { + Child = new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime) + }); - metronomeContainer.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust); + metronomeContainer.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust); + } if (AffectsHitSounds.Value) drawableRuleset.AudioContainer.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); From fcfa6d5bd10773ae4a5533de6166b4b95c4b7a21 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 14:17:43 +0200 Subject: [PATCH 130/600] Localise rankings overlay header. --- .../Rankings/RankingsOverlayHeader.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 92e22f5873..4edd8ab1a7 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -5,6 +5,9 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Rulesets; using osu.Game.Users; +using osu.Game.Resources.Localisation.Web; +using osu.Framework.Localisation; +using System; namespace osu.Game.Overlays.Rankings { @@ -29,13 +32,14 @@ namespace osu.Game.Overlays.Rankings { public RankingsTitle() { - Title = "ranking"; + Title = PageTitleStrings.MainRankingControllerDefault; Description = "find out who's the best right now"; IconTexture = "Icons/Hexacons/rankings"; } } } + [LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))] public enum RankingsScope { Performance, @@ -43,4 +47,28 @@ namespace osu.Game.Overlays.Rankings Score, Country } + + public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(RankingsScope value) + { + switch (value) + { + case RankingsScope.Performance: + return RankingsStrings.TypePerformance; + + case RankingsScope.Spotlights: + return RankingsStrings.TypeCharts; + + case RankingsScope.Score: + return RankingsStrings.TypeScore; + + case RankingsScope.Country: + return RankingsStrings.TypeCountry; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } From 9515a67f57ff5ae73100c75c6a4ce042fa047449 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 14:35:25 +0200 Subject: [PATCH 131/600] Localise ranking sort tab control. --- .../Rankings/RankingsSortTabControl.cs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs index c0bbf46e30..782055181f 100644 --- a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs +++ b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs @@ -1,19 +1,42 @@ // 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.Localisation; +using osu.Game.Resources.Localisation.Web; + namespace osu.Game.Overlays.Rankings { public class RankingsSortTabControl : OverlaySortTabControl { public RankingsSortTabControl() { - Title = "Show"; + Title = RankingsStrings.FilterTitle; } } + [LocalisableEnum(typeof(RankingsSortCriteriaEnumLocalisationMapper))] public enum RankingsSortCriteria { All, Friends } + + public class RankingsSortCriteriaEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(RankingsSortCriteria value) + { + switch (value) + { + case RankingsSortCriteria.All: + return SortStrings.All; + + case RankingsSortCriteria.Friends: + return SortStrings.Friends; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } From be3c02ff7ffef7454e7246b587f86af3e5b39ddc Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Thu, 29 Jul 2021 20:29:11 +0900 Subject: [PATCH 132/600] Remove 'Soft' select sample variant usage (soft is the new default) --- osu.Game/Graphics/UserInterface/HoverSampleSet.cs | 2 -- .../Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs | 2 +- osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs | 2 +- osu.Game/Screens/Edit/EditorTable.cs | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs index b4afb4831f..e7b8625175 100644 --- a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs +++ b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs @@ -10,8 +10,6 @@ namespace osu.Game.Graphics.UserInterface [Description("default")] Default, - [Description("soft")] - Soft, [Description("button")] Button, diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs index 794c728e56..618c7dabfa 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { Depth = 1 }, - new HoverClickSounds(HoverSampleSet.Soft) + new HoverClickSounds() }); } diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs index e4c78e723d..3d09d09833 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs @@ -57,7 +57,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { Depth = 1 }, - new HoverClickSounds(HoverSampleSet.Soft) + new HoverClickSounds() }); } diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index 756339405c..d0a83e94a1 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -67,7 +67,6 @@ namespace osu.Game.Screens.Edit private EditorClock clock { get; set; } public RowBackground(object item) - : base(HoverSampleSet.Soft) { Item = item; From c1d8a7e2ad6b3d7aeb5794048c55dd4e8f04566f Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 30 Jul 2021 21:23:49 +0900 Subject: [PATCH 133/600] Add and use 'Submit' select sample variant for particular components --- osu.Game/Graphics/UserInterface/DialogButton.cs | 1 + osu.Game/Graphics/UserInterface/HoverSampleSet.cs | 2 ++ osu.Game/Online/Chat/DrawableLinkCompiler.cs | 1 + osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs | 1 + osu.Game/Overlays/News/NewsCard.cs | 2 ++ .../Overlays/Profile/Sections/BeatmapMetadataContainer.cs | 2 ++ osu.Game/Screens/Edit/EditorTable.cs | 1 - osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs | 2 ++ osu.Game/Users/Drawables/ClickableAvatar.cs | 6 ++++++ osu.Game/Users/UserPanel.cs | 1 + 10 files changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 2d75dad828..2f9e4dae51 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -56,6 +56,7 @@ namespace osu.Game.Graphics.UserInterface private Vector2 hoverSpacing => new Vector2(3f, 0f); public DialogButton() + : base(HoverSampleSet.Submit) { RelativeSizeAxes = Axes.X; diff --git a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs index e7b8625175..a5ea6fcfbf 100644 --- a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs +++ b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs @@ -10,6 +10,8 @@ namespace osu.Game.Graphics.UserInterface [Description("default")] Default, + [Description("submit")] + Submit, [Description("button")] Button, diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index 53ea1d6f99..4df60eba69 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -31,6 +31,7 @@ namespace osu.Game.Online.Chat protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts); public DrawableLinkCompiler(IEnumerable parts) + : base(HoverSampleSet.Submit) { Parts = parts.ToList(); } diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs index afb5eeda36..9ff39ce1dd 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs @@ -50,6 +50,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels protected Action ViewBeatmap; protected BeatmapPanel(BeatmapSetInfo setInfo) + : base(HoverSampleSet.Submit) { Debug.Assert(setInfo.OnlineBeatmapSetID != null); diff --git a/osu.Game/Overlays/News/NewsCard.cs b/osu.Game/Overlays/News/NewsCard.cs index 599b45fa78..cc2fa7e1e1 100644 --- a/osu.Game/Overlays/News/NewsCard.cs +++ b/osu.Game/Overlays/News/NewsCard.cs @@ -14,6 +14,7 @@ using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.News @@ -28,6 +29,7 @@ namespace osu.Game.Overlays.News private TextFlowContainer main; public NewsCard(APINewsPost post) + : base(HoverSampleSet.Submit) { this.post = post; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 67a976fe6f..a8a4cfc365 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Profile.Sections { @@ -17,6 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections private readonly BeatmapInfo beatmap; protected BeatmapMetadataContainer(BeatmapInfo beatmap) + : base(HoverSampleSet.Submit) { this.beatmap = beatmap; diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index d0a83e94a1..ab8bd6a3bc 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -11,7 +11,6 @@ using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osuTK.Graphics; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 845c0a914e..6ecb96f723 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Select.Options { @@ -76,6 +77,7 @@ namespace osu.Game.Screens.Select.Options public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos); public BeatmapOptionsButton() + : base(HoverSampleSet.Submit) { Width = width; RelativeSizeAxes = Axes.Y; diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index f73489ac61..c8af8d80e4 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Users.Drawables { @@ -71,6 +72,11 @@ namespace osu.Game.Users.Drawables { private LocalisableString tooltip = default_tooltip_text; + public ClickableArea() + : base(HoverSampleSet.Submit) + { + } + public override LocalisableString TooltipText { get => Enabled.Value ? tooltip : default; diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 0981136dba..ff0d03a036 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -31,6 +31,7 @@ namespace osu.Game.Users protected Drawable Background { get; private set; } protected UserPanel(User user) + : base(HoverSampleSet.Submit) { if (user == null) throw new ArgumentNullException(nameof(user)); From 7dc1de74233897eb49f2a0c76b7d8e1042aa598d Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 30 Jul 2021 21:25:44 +0900 Subject: [PATCH 134/600] Use 'Submit' select sample variant for back button --- osu.Game/Graphics/UserInterface/BackButton.cs | 2 +- osu.Game/Graphics/UserInterface/TwoLayerButton.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index b941e5fcbd..b8196c6360 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -20,7 +20,7 @@ namespace osu.Game.Graphics.UserInterface { Size = TwoLayerButton.SIZE_EXTENDED; - Child = button = new TwoLayerButton + Child = button = new TwoLayerButton(HoverSampleSet.Submit) { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 8f03c7073c..969309bc79 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -71,7 +71,8 @@ namespace osu.Game.Graphics.UserInterface } } - public TwoLayerButton() + public TwoLayerButton(HoverSampleSet sampleSet = HoverSampleSet.Default) + : base(sampleSet) { Size = SIZE_RETRACTED; Shear = shear; From 9b7bb3724444930716569814d73aa8d9124a3e16 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 30 Jul 2021 21:32:08 +0900 Subject: [PATCH 135/600] Add hover+select sounds to some components that are missing them --- .../Containers/OsuRearrangeableListItem.cs | 47 ++++++++++--------- .../UserInterface/ExternalLinkButton.cs | 16 +++++-- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 19 +++++++- .../Chat/Tabs/PrivateChannelTabItem.cs | 7 ++- .../Settings/Sections/Input/KeyBindingRow.cs | 4 +- osu.Game/Users/Drawables/UpdateableFlag.cs | 11 ++++- 6 files changed, 70 insertions(+), 34 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs index 911d47704a..d43c3a608b 100644 --- a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; @@ -59,33 +60,37 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader] private void load() { - InternalChild = new GridContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Content = new[] + new GridContainer { - new[] + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] { - handleContainer = new Container + new[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 5 }, - Child = handle = new PlaylistItemHandle + handleContainer = new Container { - Size = new Vector2(12), - Colour = HandleColour, - AlwaysPresent = true, - Alpha = 0 - } - }, - CreateContent() - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 5 }, + Child = handle = new PlaylistItemHandle + { + Size = new Vector2(12), + Colour = HandleColour, + AlwaysPresent = true, + Alpha = 0 + } + }, + CreateContent() + } + }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + new HoverClickSounds() }; } diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 6ad88eaaba..0df69a5b54 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -23,14 +23,20 @@ namespace osu.Game.Graphics.UserInterface [Resolved] private GameHost host { get; set; } + private readonly SpriteIcon linkIcon; + public ExternalLinkButton(string link = null) { Link = link; Size = new Vector2(12); - InternalChild = new SpriteIcon + InternalChildren = new Drawable[] { - Icon = FontAwesome.Solid.ExternalLinkAlt, - RelativeSizeAxes = Axes.Both + linkIcon = new SpriteIcon + { + Icon = FontAwesome.Solid.ExternalLinkAlt, + RelativeSizeAxes = Axes.Both + }, + new HoverClickSounds(HoverSampleSet.Submit) }; } @@ -42,13 +48,13 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - InternalChild.FadeColour(hoverColour, 500, Easing.OutQuint); + linkIcon.FadeColour(hoverColour, 500, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - InternalChild.FadeColour(Color4.White, 500, Easing.OutQuint); + linkIcon.FadeColour(Color4.White, 500, Easing.OutQuint); base.OnHoverLost(e); } diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index cca4dc33e5..58b402c164 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -3,6 +3,9 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,6 +16,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Chat; using osuTK; using osuTK.Graphics; @@ -39,6 +43,8 @@ namespace osu.Game.Overlays.Chat.Tabs protected override Container Content => content; + private Sample sampleTabSwitched; + public ChannelTabItem(Channel value) : base(value) { @@ -112,6 +118,7 @@ namespace osu.Game.Overlays.Chat.Tabs }, }, }, + new HoverSounds() }; } @@ -152,11 +159,12 @@ namespace osu.Game.Overlays.Chat.Tabs } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, AudioManager audio) { BackgroundActive = colours.ChatBlue; BackgroundInactive = colours.Gray4; backgroundHover = colours.Gray7; + sampleTabSwitched = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select"); highlightBox.Colour = colours.Yellow; } @@ -217,7 +225,14 @@ namespace osu.Game.Overlays.Chat.Tabs Text.Font = Text.Font.With(weight: FontWeight.Medium); } - protected override void OnActivated() => updateState(); + protected override void OnActivated() + { + if (IsLoaded) + sampleTabSwitched?.Play(); + + updateState(); + } + protected override void OnDeactivated() => updateState(); } } diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 7c82420e08..d01aec630e 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Chat.Tabs if (value.Type != ChannelType.PM) throw new ArgumentException("Argument value needs to have the targettype user!"); - ClickableAvatar avatar; + DrawableAvatar avatar; AddRange(new Drawable[] { @@ -48,10 +48,9 @@ namespace osu.Game.Overlays.Chat.Tabs Anchor = Anchor.Centre, Origin = Anchor.Centre, Masking = true, - Child = new DelayedLoadWrapper(avatar = new ClickableAvatar(value.Users.First()) + Child = new DelayedLoadWrapper(avatar = new DrawableAvatar(value.Users.First()) { - RelativeSizeAxes = Axes.Both, - OpenOnClick = false, + RelativeSizeAxes = Axes.Both }) { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 4f7deebb5b..6e018597be 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -138,7 +138,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, } } - } + }, + new HoverClickSounds() }; foreach (var b in bindings) @@ -458,6 +459,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.Centre, Text = keyBinding.KeyCombination.ReadableString(), }, + new HoverSounds() }; } diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index 1d30720889..7db834bf83 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; namespace osu.Game.Users.Drawables @@ -32,9 +33,17 @@ namespace osu.Game.Users.Drawables if (country == null && !ShowPlaceholderOnNull) return null; - return new DrawableFlag(country) + return new Container { RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new DrawableFlag(country) + { + RelativeSizeAxes = Axes.Both + }, + new HoverClickSounds(HoverSampleSet.Submit) + } }; } From 9538c4c7f29d2d9692fb7f4259b19b1fcfb95507 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 30 Jul 2021 21:35:07 +0900 Subject: [PATCH 136/600] Make the news collapsable month sections sound like dropdowns, because they pseudo kinda are --- .../Overlays/News/Sidebar/MonthSection.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index b300a755f9..cd6ab224a9 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -15,13 +15,18 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Diagnostics; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Platform; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.News.Sidebar { public class MonthSection : CompositeDrawable { private const int animation_duration = 250; + private Sample sampleOpen; + private Sample sampleClose; public readonly BindableBool Expanded = new BindableBool(); @@ -51,6 +56,21 @@ namespace osu.Game.Overlays.News.Sidebar } } }; + + Expanded.ValueChanged += expanded => + { + if (expanded.NewValue) + sampleOpen?.Play(); + else + sampleClose?.Play(); + }; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleOpen = audio.Samples.Get(@"UI/dropdown-open"); + sampleClose = audio.Samples.Get(@"UI/dropdown-close"); } private class DropdownHeader : OsuClickableContainer @@ -59,6 +79,8 @@ namespace osu.Game.Overlays.News.Sidebar private readonly SpriteIcon icon; + protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(); + public DropdownHeader(int month, int year) { var date = new DateTime(year, month, 1); @@ -104,6 +126,7 @@ namespace osu.Game.Overlays.News.Sidebar private readonly APINewsPost post; public PostButton(APINewsPost post) + : base(HoverSampleSet.Submit) { this.post = post; From 971728196902b9cd905e967363a7265ce71b576e Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 14:51:16 +0200 Subject: [PATCH 137/600] Localise rankings Spotlight selector. --- .../Overlays/Rankings/SpotlightSelector.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 89dd4eafdd..7f642c1832 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -16,6 +16,8 @@ using System.Collections.Generic; using osu.Framework.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings { @@ -92,10 +94,10 @@ namespace osu.Game.Overlays.Rankings Margin = new MarginPadding { Bottom = 5 }, Children = new Drawable[] { - startDateColumn = new InfoColumn(@"Start Date"), - endDateColumn = new InfoColumn(@"End Date"), - mapCountColumn = new InfoColumn(@"Map Count"), - participantsColumn = new InfoColumn(@"Participants") + startDateColumn = new InfoColumn(RankingsStrings.SpotlightStartDate), + endDateColumn = new InfoColumn(RankingsStrings.SpotlightEndDate), + mapCountColumn = new InfoColumn(RankingsStrings.SpotlightMapCount), + participantsColumn = new InfoColumn(RankingsStrings.SpotlightParticipants) } }, new RankingsSortTabControl @@ -123,21 +125,21 @@ namespace osu.Game.Overlays.Rankings startDateColumn.Value = dateToString(response.Spotlight.StartDate); endDateColumn.Value = dateToString(response.Spotlight.EndDate); mapCountColumn.Value = response.BeatmapSets.Count.ToString(); - participantsColumn.Value = response.Spotlight.Participants?.ToString("N0"); + participantsColumn.Value = response.Spotlight.Participants?.ToLocalisableString("N0"); } - private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); + private LocalisableString dateToString(DateTimeOffset date) => date.ToLocalisableString("yyyy-MM-dd"); private class InfoColumn : FillFlowContainer { - public string Value + public LocalisableString Value { set => valueText.Text = value; } private readonly OsuSpriteText valueText; - public InfoColumn(string name) + public InfoColumn(LocalisableString name) { AutoSizeAxes = Axes.Both; Direction = FillDirection.Vertical; From db1ed873e42e6a43fdf4589ee2ade961a9d86b85 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 15:24:10 +0200 Subject: [PATCH 138/600] Localise ranking tables. --- .../Rankings/Tables/CountriesTable.cs | 26 ++++++++++--------- .../Rankings/Tables/PerformanceTable.cs | 6 +++-- .../Overlays/Rankings/Tables/RankingsTable.cs | 2 +- .../Overlays/Rankings/Tables/ScoresTable.cs | 10 ++++--- .../Rankings/Tables/UserBasedTable.cs | 17 ++++++------ 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index b28bf07adc..a09629de57 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -9,6 +9,8 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Game.Resources.Localisation.Web; +using osu.Framework.Localisation; namespace osu.Game.Overlays.Rankings.Tables { @@ -21,12 +23,12 @@ namespace osu.Game.Overlays.Rankings.Tables protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[] { - new RankingsTableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new RankingsTableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new RankingsTableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new RankingsTableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new RankingsTableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true), - new RankingsTableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatActiveUsers, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatPlayCount, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatRankedScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatAverageScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatPerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true), + new RankingsTableColumn(RankingsStrings.StatAveragePerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; protected override Country GetCountry(CountryStatistics item) => item.Country; @@ -37,27 +39,27 @@ namespace osu.Game.Overlays.Rankings.Tables { new ColoredRowText { - Text = $@"{item.ActiveUsers:N0}", + Text = item.ActiveUsers.ToLocalisableString("N0") }, new ColoredRowText { - Text = $@"{item.PlayCount:N0}", + Text = item.PlayCount.ToLocalisableString("N0") }, new ColoredRowText { - Text = $@"{item.RankedScore:N0}", + Text = item.RankedScore.ToLocalisableString("N0") }, new ColoredRowText { - Text = $@"{item.RankedScore / Math.Max(item.ActiveUsers, 1):N0}", + Text = (item.RankedScore / Math.Max(item.ActiveUsers, 1)).ToLocalisableString("N0") }, new RowText { - Text = $@"{item.Performance:N0}", + Text = item.Performance.ToLocalisableString("N0") }, new ColoredRowText { - Text = $@"{item.Performance / Math.Max(item.ActiveUsers, 1):N0}", + Text = (item.Performance / Math.Max(item.ActiveUsers, 1)).ToLocalisableString("N0") } }; diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index ddf4bdcfeb..ae49445702 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables @@ -17,12 +19,12 @@ namespace osu.Game.Overlays.Rankings.Tables protected override RankingsTableColumn[] CreateUniqueHeaders() => new[] { - new RankingsTableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true), + new RankingsTableColumn(RankingsStrings.StatPerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true), }; protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { - new RowText { Text = $@"{item.PP:N0}", } + new RowText { Text = item.PP.ToLocalisableString("N0"), } }; } } diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 0cdff0a77f..59f38920d6 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Rankings.Tables private OsuSpriteText createIndexDrawable(int index) => new RowText { - Text = $"#{index + 1}", + Text = (index + 1).ToLocalisableString("\\##"), Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.SemiBold) }; diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 508ad51112..4cf75eda81 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables @@ -17,19 +19,19 @@ namespace osu.Game.Overlays.Rankings.Tables protected override RankingsTableColumn[] CreateUniqueHeaders() => new[] { - new RankingsTableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new RankingsTableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true) + new RankingsTableColumn(RankingsStrings.StatTotalScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatRankedScore, Anchor.Centre, new Dimension(GridSizeMode.AutoSize), true) }; protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { new ColoredRowText { - Text = $@"{item.TotalScore:N0}", + Text = item.TotalScore.ToLocalisableString("N0"), }, new RowText { - Text = $@"{item.RankedScore:N0}", + Text = item.RankedScore.ToLocalisableString("N0") } }; } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 131ee86d44..a7fa6899f8 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Users; using osu.Game.Scoring; using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings.Tables { @@ -20,12 +21,12 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected virtual IEnumerable GradeColumns => new List { "SS", "S", "A" }; + protected virtual IEnumerable GradeColumns => new List { RankingsStrings.Statss, RankingsStrings.Stats, RankingsStrings.Stata }; protected override RankingsTableColumn[] CreateAdditionalHeaders() => new[] { - new RankingsTableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new RankingsTableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatAccuracy, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new RankingsTableColumn(RankingsStrings.StatPlayCount, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }.Concat(CreateUniqueHeaders()) .Concat(GradeColumns.Select(grade => new GradeTableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)))) .ToArray(); @@ -47,12 +48,12 @@ namespace osu.Game.Overlays.Rankings.Tables protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] { new ColoredRowText { Text = item.DisplayAccuracy, }, - new ColoredRowText { Text = $@"{item.PlayCount:N0}", }, + new ColoredRowText { Text = item.PlayCount.ToLocalisableString("N0") }, }.Concat(CreateUniqueContent(item)).Concat(new[] { - new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]:N0}", }, - new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]:N0}", }, - new ColoredRowText { Text = $@"{item.GradesCount[ScoreRank.A]:N0}", } + new ColoredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString("N0"), }, + new ColoredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString("N0"), }, + new ColoredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString("N0"), } }).ToArray(); protected abstract RankingsTableColumn[] CreateUniqueHeaders(); @@ -78,7 +79,7 @@ namespace osu.Game.Overlays.Rankings.Tables { // Grade columns have extra horizontal padding for readibility Horizontal = 20, - Vertical = 5 + Vertical = 150 }; } } From 8a42d88793fe0592aa17c684f3c9e87a25c6a3ee Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 16:28:18 +0200 Subject: [PATCH 139/600] Fix whitespace inspections. --- osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 4edd8ab1a7..1d6d884d58 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Rankings { case RankingsScope.Performance: return RankingsStrings.TypePerformance; - + case RankingsScope.Spotlights: return RankingsStrings.TypeCharts; From 7e870235576dffb34f2282bc0660bb8c364ed10a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 23:57:40 +0900 Subject: [PATCH 140/600] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 1c180a6b39..c1075cfb17 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2efcfeb278..936fe8db94 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 2630614c03..7b7d5f80fe 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 5381e11880be447bef613b0c1a9af7e34b5c0eb1 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 19:06:25 +0200 Subject: [PATCH 141/600] Revert unintentional change. --- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index a7fa6899f8..60c3c76a34 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.Rankings.Tables { // Grade columns have extra horizontal padding for readibility Horizontal = 20, - Vertical = 150 + Vertical = 5 }; } } From 652fe6c413aec6f3bd5f0e6be18d0c8d7ea1188f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 19:07:49 +0200 Subject: [PATCH 142/600] Uppercase sort filter control text. --- osu.Game/Overlays/Rankings/RankingsSortTabControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs index 782055181f..c04eb5bdd1 100644 --- a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs +++ b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -11,7 +12,7 @@ namespace osu.Game.Overlays.Rankings { public RankingsSortTabControl() { - Title = RankingsStrings.FilterTitle; + Title = RankingsStrings.FilterTitle.ToUpper(); } } From c7e9d09ce3747a95f91e0264c3648e277bff5a32 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 30 Jul 2021 19:08:27 +0200 Subject: [PATCH 143/600] Localise left over numeric value. --- osu.Game/Overlays/Rankings/SpotlightSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 7f642c1832..89d40277fc 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -124,7 +124,7 @@ namespace osu.Game.Overlays.Rankings { startDateColumn.Value = dateToString(response.Spotlight.StartDate); endDateColumn.Value = dateToString(response.Spotlight.EndDate); - mapCountColumn.Value = response.BeatmapSets.Count.ToString(); + mapCountColumn.Value = response.BeatmapSets.Count.ToLocalisableString("N0"); participantsColumn.Value = response.Spotlight.Participants?.ToLocalisableString("N0"); } From 3409bc6b27550580e8de777ff1e88200aeddc862 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 31 Jul 2021 01:38:54 +0300 Subject: [PATCH 144/600] Update mapper usages with `LocalisableDescription` --- osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs | 52 ++++-------- .../Overlays/BeatmapListing/SearchCategory.cs | 55 ++++--------- .../Overlays/BeatmapListing/SearchExplicit.cs | 23 +----- .../Overlays/BeatmapListing/SearchExtra.cs | 22 +---- .../Overlays/BeatmapListing/SearchGeneral.cs | 26 +----- .../Overlays/BeatmapListing/SearchGenre.cs | 81 ++++++------------- .../Overlays/BeatmapListing/SearchLanguage.cs | 74 ++++------------- .../Overlays/BeatmapListing/SearchPlayed.cs | 28 ++----- .../Overlays/BeatmapListing/SortCriteria.cs | 53 ++++-------- .../Dashboard/DashboardOverlayHeader.cs | 21 +---- .../Dashboard/Friends/OnlineStatus.cs | 28 ++----- .../Dashboard/Friends/UserSortTabControl.cs | 28 ++----- .../OverlayPanelDisplayStyleControl.cs | 28 ++----- osu.Game/Scoring/ScoreRank.cs | 46 ++--------- 14 files changed, 120 insertions(+), 445 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs index 6003e23a84..edaf044466 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs @@ -1,22 +1,34 @@ // 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.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps { - [LocalisableEnum(typeof(BeatmapSetOnlineStatusEnumLocalisationMapper))] public enum BeatmapSetOnlineStatus { None = -3, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusGraveyard))] Graveyard = -2, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusWip))] WIP = -1, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusPending))] Pending = 0, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusRanked))] Ranked = 1, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusApproved))] Approved = 2, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusQualified))] Qualified = 3, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusLoved))] Loved = 4, } @@ -25,40 +37,4 @@ namespace osu.Game.Beatmaps public static bool GrantsPerformancePoints(this BeatmapSetOnlineStatus status) => status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; } - - public class BeatmapSetOnlineStatusEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(BeatmapSetOnlineStatus value) - { - switch (value) - { - case BeatmapSetOnlineStatus.None: - return string.Empty; - - case BeatmapSetOnlineStatus.Graveyard: - return BeatmapsetsStrings.ShowStatusGraveyard; - - case BeatmapSetOnlineStatus.WIP: - return BeatmapsetsStrings.ShowStatusWip; - - case BeatmapSetOnlineStatus.Pending: - return BeatmapsetsStrings.ShowStatusPending; - - case BeatmapSetOnlineStatus.Ranked: - return BeatmapsetsStrings.ShowStatusRanked; - - case BeatmapSetOnlineStatus.Approved: - return BeatmapsetsStrings.ShowStatusApproved; - - case BeatmapSetOnlineStatus.Qualified: - return BeatmapsetsStrings.ShowStatusQualified; - - case BeatmapSetOnlineStatus.Loved: - return BeatmapsetsStrings.ShowStatusLoved; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs index 8a9df76af3..d6ae41aba1 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs @@ -1,69 +1,42 @@ // 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.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchCategoryEnumLocalisationMapper))] public enum SearchCategory { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusAny))] Any, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusLeaderboard))] [Description("Has Leaderboard")] Leaderboard, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusRanked))] Ranked, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusQualified))] Qualified, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusLoved))] Loved, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusFavourites))] Favourites, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusPending))] [Description("Pending & WIP")] Pending, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusGraveyard))] Graveyard, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusMine))] [Description("My Maps")] Mine, } - - public class SearchCategoryEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchCategory value) - { - switch (value) - { - case SearchCategory.Any: - return BeatmapsStrings.StatusAny; - - case SearchCategory.Leaderboard: - return BeatmapsStrings.StatusLeaderboard; - - case SearchCategory.Ranked: - return BeatmapsStrings.StatusRanked; - - case SearchCategory.Qualified: - return BeatmapsStrings.StatusQualified; - - case SearchCategory.Loved: - return BeatmapsStrings.StatusLoved; - - case SearchCategory.Favourites: - return BeatmapsStrings.StatusFavourites; - - case SearchCategory.Pending: - return BeatmapsStrings.StatusPending; - - case SearchCategory.Graveyard: - return BeatmapsStrings.StatusGraveyard; - - case SearchCategory.Mine: - return BeatmapsStrings.StatusMine; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs index 78e6a4e094..80482b32a0 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs @@ -1,34 +1,17 @@ // 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.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchExplicitEnumLocalisationMapper))] public enum SearchExplicit { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.NsfwExclude))] Hide, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.NsfwInclude))] Show } - - public class SearchExplicitEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchExplicit value) - { - switch (value) - { - case SearchExplicit.Hide: - return BeatmapsStrings.NsfwExclude; - - case SearchExplicit.Show: - return BeatmapsStrings.NsfwInclude; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs index 4b3fb6e833..e54632acd8 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs @@ -1,38 +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 System; using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchExtraEnumLocalisationMapper))] public enum SearchExtra { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ExtraVideo))] [Description("Has Video")] Video, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ExtraStoryboard))] [Description("Has Storyboard")] Storyboard } - - public class SearchExtraEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchExtra value) - { - switch (value) - { - case SearchExtra.Video: - return BeatmapsStrings.ExtraVideo; - - case SearchExtra.Storyboard: - return BeatmapsStrings.ExtraStoryboard; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs index b4c629f7fa..d334b82e88 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs @@ -1,44 +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 System; using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchGeneralEnumLocalisationMapper))] public enum SearchGeneral { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GeneralRecommended))] [Description("Recommended difficulty")] Recommended, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GeneralConverts))] [Description("Include converted beatmaps")] Converts, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GeneralFollows))] [Description("Subscribed mappers")] Follows } - - public class SearchGeneralEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchGeneral value) - { - switch (value) - { - case SearchGeneral.Recommended: - return BeatmapsStrings.GeneralRecommended; - - case SearchGeneral.Converts: - return BeatmapsStrings.GeneralConverts; - - case SearchGeneral.Follows: - return BeatmapsStrings.GeneralFollows; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs index b2709ecd2e..08855284cb 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs @@ -1,87 +1,56 @@ // 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.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchGenreEnumLocalisationMapper))] public enum SearchGenre { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreAny))] Any = 0, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreUnspecified))] Unspecified = 1, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreVideoGame))] [Description("Video Game")] VideoGame = 2, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreAnime))] Anime = 3, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreRock))] Rock = 4, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenrePop))] Pop = 5, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreOther))] Other = 6, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreNovelty))] Novelty = 7, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreHipHop))] [Description("Hip Hop")] HipHop = 9, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreElectronic))] Electronic = 10, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreMetal))] Metal = 11, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreClassical))] Classical = 12, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreFolk))] Folk = 13, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreJazz))] Jazz = 14 } - - public class SearchGenreEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchGenre value) - { - switch (value) - { - case SearchGenre.Any: - return BeatmapsStrings.GenreAny; - - case SearchGenre.Unspecified: - return BeatmapsStrings.GenreUnspecified; - - case SearchGenre.VideoGame: - return BeatmapsStrings.GenreVideoGame; - - case SearchGenre.Anime: - return BeatmapsStrings.GenreAnime; - - case SearchGenre.Rock: - return BeatmapsStrings.GenreRock; - - case SearchGenre.Pop: - return BeatmapsStrings.GenrePop; - - case SearchGenre.Other: - return BeatmapsStrings.GenreOther; - - case SearchGenre.Novelty: - return BeatmapsStrings.GenreNovelty; - - case SearchGenre.HipHop: - return BeatmapsStrings.GenreHipHop; - - case SearchGenre.Electronic: - return BeatmapsStrings.GenreElectronic; - - case SearchGenre.Metal: - return BeatmapsStrings.GenreMetal; - - case SearchGenre.Classical: - return BeatmapsStrings.GenreClassical; - - case SearchGenre.Folk: - return BeatmapsStrings.GenreFolk; - - case SearchGenre.Jazz: - return BeatmapsStrings.GenreJazz; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs index fc176c305a..7ffa0282b7 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs @@ -1,117 +1,73 @@ // 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.Localisation; using osu.Framework.Utils; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchLanguageEnumLocalisationMapper))] [HasOrderedElements] public enum SearchLanguage { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageAny))] [Order(0)] Any, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageUnspecified))] [Order(14)] Unspecified, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageEnglish))] [Order(1)] English, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageJapanese))] [Order(6)] Japanese, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageChinese))] [Order(2)] Chinese, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageInstrumental))] [Order(12)] Instrumental, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageKorean))] [Order(7)] Korean, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageFrench))] [Order(3)] French, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageGerman))] [Order(4)] German, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageSwedish))] [Order(9)] Swedish, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageSpanish))] [Order(8)] Spanish, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageItalian))] [Order(5)] Italian, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageRussian))] [Order(10)] Russian, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguagePolish))] [Order(11)] Polish, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageOther))] [Order(13)] Other } - - public class SearchLanguageEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchLanguage value) - { - switch (value) - { - case SearchLanguage.Any: - return BeatmapsStrings.LanguageAny; - - case SearchLanguage.Unspecified: - return BeatmapsStrings.LanguageUnspecified; - - case SearchLanguage.English: - return BeatmapsStrings.LanguageEnglish; - - case SearchLanguage.Japanese: - return BeatmapsStrings.LanguageJapanese; - - case SearchLanguage.Chinese: - return BeatmapsStrings.LanguageChinese; - - case SearchLanguage.Instrumental: - return BeatmapsStrings.LanguageInstrumental; - - case SearchLanguage.Korean: - return BeatmapsStrings.LanguageKorean; - - case SearchLanguage.French: - return BeatmapsStrings.LanguageFrench; - - case SearchLanguage.German: - return BeatmapsStrings.LanguageGerman; - - case SearchLanguage.Swedish: - return BeatmapsStrings.LanguageSwedish; - - case SearchLanguage.Spanish: - return BeatmapsStrings.LanguageSpanish; - - case SearchLanguage.Italian: - return BeatmapsStrings.LanguageItalian; - - case SearchLanguage.Russian: - return BeatmapsStrings.LanguageRussian; - - case SearchLanguage.Polish: - return BeatmapsStrings.LanguagePolish; - - case SearchLanguage.Other: - return BeatmapsStrings.LanguageOther; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs index f24cf46c2d..3b04ac01ca 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs @@ -1,38 +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 System; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SearchPlayedEnumLocalisationMapper))] public enum SearchPlayed { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.PlayedAny))] Any, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.PlayedPlayed))] Played, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.PlayedUnplayed))] Unplayed } - - public class SearchPlayedEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SearchPlayed value) - { - switch (value) - { - case SearchPlayed.Any: - return BeatmapsStrings.PlayedAny; - - case SearchPlayed.Played: - return BeatmapsStrings.PlayedPlayed; - - case SearchPlayed.Unplayed: - return BeatmapsStrings.PlayedUnplayed; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs index 5ea885eecc..871b3c162b 100644 --- a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs +++ b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs @@ -1,58 +1,35 @@ // 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.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { - [LocalisableEnum(typeof(SortCriteriaLocalisationMapper))] public enum SortCriteria { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingTitle))] Title, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingArtist))] Artist, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingDifficulty))] Difficulty, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingRanked))] Ranked, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingRating))] Rating, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingPlays))] Plays, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingFavourites))] Favourites, + + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingRelevance))] Relevance } - - public class SortCriteriaLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(SortCriteria value) - { - switch (value) - { - case SortCriteria.Title: - return BeatmapsStrings.ListingSearchSortingTitle; - - case SortCriteria.Artist: - return BeatmapsStrings.ListingSearchSortingArtist; - - case SortCriteria.Difficulty: - return BeatmapsStrings.ListingSearchSortingDifficulty; - - case SortCriteria.Ranked: - return BeatmapsStrings.ListingSearchSortingRanked; - - case SortCriteria.Rating: - return BeatmapsStrings.ListingSearchSortingRating; - - case SortCriteria.Plays: - return BeatmapsStrings.ListingSearchSortingPlays; - - case SortCriteria.Favourites: - return BeatmapsStrings.ListingSearchSortingFavourites; - - case SortCriteria.Relevance: - return BeatmapsStrings.ListingSearchSortingRelevance; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 056d4ad6f7..79dadf5e0d 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -23,30 +22,12 @@ namespace osu.Game.Overlays.Dashboard } } - [LocalisableEnum(typeof(DashboardOverlayTabsEnumLocalisationMapper))] public enum DashboardOverlayTabs { + [LocalisableDescription(typeof(FriendsStrings), nameof(FriendsStrings.TitleCompact))] Friends, [Description("Currently Playing")] CurrentlyPlaying } - - public class DashboardOverlayTabsEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(DashboardOverlayTabs value) - { - switch (value) - { - case DashboardOverlayTabs.Friends: - return FriendsStrings.TitleCompact; - - case DashboardOverlayTabs.CurrentlyPlaying: - return @"Currently Playing"; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs index 4b5a7ef066..853c94d8ae 100644 --- a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs +++ b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs @@ -1,38 +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 System; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Friends { - [LocalisableEnum(typeof(OnlineStatusEnumLocalisationMapper))] public enum OnlineStatus { + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusAll))] All, + + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusOnline))] Online, + + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusOffline))] Offline } - - public class OnlineStatusEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(OnlineStatus value) - { - switch (value) - { - case OnlineStatus.All: - return SortStrings.All; - - case OnlineStatus.Online: - return UsersStrings.StatusOnline; - - case OnlineStatus.Offline: - return UsersStrings.StatusOffline; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs index dc756e2957..7fee5f4668 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -12,33 +11,16 @@ namespace osu.Game.Overlays.Dashboard.Friends { } - [LocalisableEnum(typeof(UserSortCriteriaEnumLocalisationMappper))] public enum UserSortCriteria { + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.LastVisit))] [Description(@"Recently Active")] LastVisit, + + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Rank))] Rank, + + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Username))] Username } - - public class UserSortCriteriaEnumLocalisationMappper : EnumLocalisationMapper - { - public override LocalisableString Map(UserSortCriteria value) - { - switch (value) - { - case UserSortCriteria.LastVisit: - return SortStrings.LastVisit; - - case UserSortCriteria.Rank: - return SortStrings.Rank; - - case UserSortCriteria.Username: - return SortStrings.Username; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs index c2268ff43c..d7a3b052ae 100644 --- a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs +++ b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs @@ -12,7 +12,6 @@ using osu.Framework.Allocation; using osuTK.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; -using System; using osu.Game.Resources.Localisation.Web; using osu.Framework.Extensions; @@ -101,32 +100,15 @@ namespace osu.Game.Overlays } } - [LocalisableEnum(typeof(OverlayPanelDisplayStyleEnumLocalisationMapper))] public enum OverlayPanelDisplayStyle { + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ViewModeCard))] Card, + + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ViewModeList))] List, + + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ViewModeBrick))] Brick } - - public class OverlayPanelDisplayStyleEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(OverlayPanelDisplayStyle value) - { - switch (value) - { - case OverlayPanelDisplayStyle.Card: - return UsersStrings.ViewModeCard; - - case OverlayPanelDisplayStyle.List: - return UsersStrings.ViewModeList; - - case OverlayPanelDisplayStyle.Brick: - return UsersStrings.ViewModeBrick; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index f3b4551ff8..64f7da9ba3 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -1,74 +1,44 @@ // 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.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Scoring { - [LocalisableEnum(typeof(ScoreRankEnumLocalisationMapper))] public enum ScoreRank { + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankD))] [Description(@"D")] D, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankC))] [Description(@"C")] C, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankB))] [Description(@"B")] B, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankA))] [Description(@"A")] A, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankS))] [Description(@"S")] S, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankSH))] [Description(@"S+")] SH, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankX))] [Description(@"SS")] X, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankXH))] [Description(@"SS+")] XH, } - - public class ScoreRankEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(ScoreRank value) - { - switch (value) - { - case ScoreRank.XH: - return BeatmapsStrings.RankXH; - - case ScoreRank.X: - return BeatmapsStrings.RankX; - - case ScoreRank.SH: - return BeatmapsStrings.RankSH; - - case ScoreRank.S: - return BeatmapsStrings.RankS; - - case ScoreRank.A: - return BeatmapsStrings.RankA; - - case ScoreRank.B: - return BeatmapsStrings.RankB; - - case ScoreRank.C: - return BeatmapsStrings.RankC; - - case ScoreRank.D: - return BeatmapsStrings.RankD; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } From 397c73e786aa8c49ff233fc74bab2ec1bdd24657 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 31 Jul 2021 02:09:25 +0300 Subject: [PATCH 145/600] Add audio adjustment support to `Metronome` --- osu.Game/Rulesets/Mods/Metronome.cs | 62 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Metronome.cs b/osu.Game/Rulesets/Mods/Metronome.cs index ee0a42b4bc..8b6d86c45f 100644 --- a/osu.Game/Rulesets/Mods/Metronome.cs +++ b/osu.Game/Rulesets/Mods/Metronome.cs @@ -1,9 +1,9 @@ // 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.Allocation; +using osu.Framework.Audio; using osu.Framework.Audio.Track; -using osu.Framework.Graphics; +using osu.Framework.Bindables; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; @@ -11,11 +11,11 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mods { - public class Metronome : BeatSyncedContainer + public class Metronome : BeatSyncedContainer, IAdjustableAudioComponent { private readonly double firstHitTime; - private PausableSkinnableSound sample; + private readonly PausableSkinnableSound sample; /// Start time of the first hit object, used for providing a count down. public Metronome(double firstHitTime) @@ -23,15 +23,8 @@ namespace osu.Game.Rulesets.Mods this.firstHitTime = firstHitTime; AllowMistimedEventFiring = false; Divisor = 1; - } - [BackgroundDependencyLoader] - private void load() - { - InternalChildren = new Drawable[] - { - sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana")) - }; + InternalChild = sample = new PausableSkinnableSound(new SampleInfo("Gameplay/catch-banana")); } protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) @@ -49,5 +42,50 @@ namespace osu.Game.Rulesets.Mods sample.Frequency.Value = beatIndex % timeSignature == 0 ? 1 : 0.5f; sample.Play(); } + + #region IAdjustableAudioComponent + + public IBindable AggregateVolume => sample.AggregateVolume; + + public IBindable AggregateBalance => sample.AggregateBalance; + + public IBindable AggregateFrequency => sample.AggregateFrequency; + + public IBindable AggregateTempo => sample.AggregateTempo; + + public BindableNumber Volume => sample.Volume; + + public BindableNumber Balance => sample.Balance; + + public BindableNumber Frequency => sample.Frequency; + + public BindableNumber Tempo => sample.Tempo; + + public void BindAdjustments(IAggregateAudioAdjustment component) + { + sample.BindAdjustments(component); + } + + public void UnbindAdjustments(IAggregateAudioAdjustment component) + { + sample.UnbindAdjustments(component); + } + + public void AddAdjustment(AdjustableProperty type, IBindable adjustBindable) + { + sample.AddAdjustment(type, adjustBindable); + } + + public void RemoveAdjustment(AdjustableProperty type, IBindable adjustBindable) + { + sample.RemoveAdjustment(type, adjustBindable); + } + + public void RemoveAllAdjustments(AdjustableProperty type) + { + sample.RemoveAllAdjustments(type); + } + + #endregion } } From 4c68268d98186e445ce123ee57677a8bd577bcd7 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sat, 31 Jul 2021 08:31:08 +0900 Subject: [PATCH 146/600] Call `ApplyTransformsAt` on free --- osu.Game.Rulesets.Catch/UI/CatcherTrail.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs index a7a2941a7a..f3f996d2c5 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs @@ -31,9 +31,8 @@ namespace osu.Game.Rulesets.Catch.UI protected override void OnApply(CatcherTrailEntry entry) { - Scale = entry.Scale; Position = new Vector2(entry.Position, 0); - Alpha = 1; + Scale = entry.Scale; body.AnimationState.Value = entry.CatcherState; @@ -43,6 +42,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override void OnFree(CatcherTrailEntry entry) { + ApplyTransformsAt(double.MinValue); ClearTransforms(); } From e6f337a3c8c753681c8a22f91f84378db6e43e2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 14:27:20 +0900 Subject: [PATCH 147/600] User verbatim string for `ToLocalisableString` calls (and rename US spelling) --- .../Overlays/Rankings/SpotlightSelector.cs | 6 ++--- .../Rankings/Tables/CountriesTable.cs | 22 +++++++++---------- .../Rankings/Tables/PerformanceTable.cs | 2 +- .../Overlays/Rankings/Tables/RankingsTable.cs | 4 ++-- .../Overlays/Rankings/Tables/ScoresTable.cs | 2 +- .../Rankings/Tables/UserBasedTable.cs | 10 ++++----- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 89d40277fc..5309778a47 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -124,11 +124,11 @@ namespace osu.Game.Overlays.Rankings { startDateColumn.Value = dateToString(response.Spotlight.StartDate); endDateColumn.Value = dateToString(response.Spotlight.EndDate); - mapCountColumn.Value = response.BeatmapSets.Count.ToLocalisableString("N0"); - participantsColumn.Value = response.Spotlight.Participants?.ToLocalisableString("N0"); + mapCountColumn.Value = response.BeatmapSets.Count.ToLocalisableString(@"N0"); + participantsColumn.Value = response.Spotlight.Participants?.ToLocalisableString(@"N0"); } - private LocalisableString dateToString(DateTimeOffset date) => date.ToLocalisableString("yyyy-MM-dd"); + private LocalisableString dateToString(DateTimeOffset date) => date.ToLocalisableString(@"yyyy-MM-dd"); private class InfoColumn : FillFlowContainer { diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index a09629de57..85a317728f 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -37,29 +37,29 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new Drawable[] { - new ColoredRowText + new ColouredRowText { - Text = item.ActiveUsers.ToLocalisableString("N0") + Text = item.ActiveUsers.ToLocalisableString(@"N0") }, - new ColoredRowText + new ColouredRowText { - Text = item.PlayCount.ToLocalisableString("N0") + Text = item.PlayCount.ToLocalisableString(@"N0") }, - new ColoredRowText + new ColouredRowText { - Text = item.RankedScore.ToLocalisableString("N0") + Text = item.RankedScore.ToLocalisableString(@"N0") }, - new ColoredRowText + new ColouredRowText { - Text = (item.RankedScore / Math.Max(item.ActiveUsers, 1)).ToLocalisableString("N0") + Text = (item.RankedScore / Math.Max(item.ActiveUsers, 1)).ToLocalisableString(@"N0") }, new RowText { - Text = item.Performance.ToLocalisableString("N0") + Text = item.Performance.ToLocalisableString(@"N0") }, - new ColoredRowText + new ColouredRowText { - Text = (item.Performance / Math.Max(item.ActiveUsers, 1)).ToLocalisableString("N0") + Text = (item.Performance / Math.Max(item.ActiveUsers, 1)).ToLocalisableString(@"N0") } }; diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index ae49445702..6facf1e7a2 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { - new RowText { Text = item.PP.ToLocalisableString("N0"), } + new RowText { Text = item.PP.ToLocalisableString(@"N0"), } }; } } diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 59f38920d6..bc8eac16a9 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Rankings.Tables private OsuSpriteText createIndexDrawable(int index) => new RowText { - Text = (index + 1).ToLocalisableString("\\##"), + Text = (index + 1).ToLocalisableString(@"\##"), Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.SemiBold) }; @@ -144,7 +144,7 @@ namespace osu.Game.Overlays.Rankings.Tables } } - protected class ColoredRowText : RowText + protected class ColouredRowText : RowText { [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 4cf75eda81..312c894055 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { - new ColoredRowText + new ColouredRowText { Text = item.TotalScore.ToLocalisableString("N0"), }, diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 60c3c76a34..ce7a0e7e79 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -47,13 +47,13 @@ namespace osu.Game.Overlays.Rankings.Tables protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] { - new ColoredRowText { Text = item.DisplayAccuracy, }, - new ColoredRowText { Text = item.PlayCount.ToLocalisableString("N0") }, + new ColouredRowText { Text = item.DisplayAccuracy, }, + new ColouredRowText { Text = item.PlayCount.ToLocalisableString("N0") }, }.Concat(CreateUniqueContent(item)).Concat(new[] { - new ColoredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString("N0"), }, - new ColoredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString("N0"), }, - new ColoredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString("N0"), } + new ColouredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString("N0"), }, + new ColouredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString("N0"), }, + new ColouredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString("N0"), } }).ToArray(); protected abstract RankingsTableColumn[] CreateUniqueHeaders(); From c0824989558bc389b9bee043d5ded289f3e2f48d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 14:29:38 +0900 Subject: [PATCH 148/600] Fix some missed instances of verbatim string conversion --- osu.Game/Overlays/Rankings/Tables/ScoresTable.cs | 4 ++-- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 312c894055..b6bb66e2c8 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -27,11 +27,11 @@ namespace osu.Game.Overlays.Rankings.Tables { new ColouredRowText { - Text = item.TotalScore.ToLocalisableString("N0"), + Text = item.TotalScore.ToLocalisableString(@"N0"), }, new RowText { - Text = item.RankedScore.ToLocalisableString("N0") + Text = item.RankedScore.ToLocalisableString(@"N0") } }; } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index ce7a0e7e79..b96ab556df 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -48,12 +48,12 @@ namespace osu.Game.Overlays.Rankings.Tables protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] { new ColouredRowText { Text = item.DisplayAccuracy, }, - new ColouredRowText { Text = item.PlayCount.ToLocalisableString("N0") }, + new ColouredRowText { Text = item.PlayCount.ToLocalisableString(@"N0") }, }.Concat(CreateUniqueContent(item)).Concat(new[] { - new ColouredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString("N0"), }, - new ColouredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString("N0"), }, - new ColouredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString("N0"), } + new ColouredRowText { Text = (item.GradesCount[ScoreRank.XH] + item.GradesCount[ScoreRank.X]).ToLocalisableString(@"N0"), }, + new ColouredRowText { Text = (item.GradesCount[ScoreRank.SH] + item.GradesCount[ScoreRank.S]).ToLocalisableString(@"N0"), }, + new ColouredRowText { Text = item.GradesCount[ScoreRank.A].ToLocalisableString(@"N0"), } }).ToArray(); protected abstract RankingsTableColumn[] CreateUniqueHeaders(); From 29328bdf7f49a35f15e4bf87e9a2fd6151dd2567 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 15:03:26 +0900 Subject: [PATCH 149/600] Use metronome's audio adjustments directly --- osu.Game/Rulesets/Mods/ModMuted.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 5454483571..9eb218fd9b 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -35,8 +35,6 @@ namespace osu.Game.Rulesets.Mods private BindableNumber currentCombo; - private AudioContainer metronomeContainer; - [SettingSource("Enable metronome", "Add a metronome beat to help you keep track of the rhythm.")] public BindableBool EnableMetronome { get; } = new BindableBool { @@ -76,12 +74,11 @@ namespace osu.Game.Rulesets.Mods { if (EnableMetronome.Value) { - drawableRuleset.Overlays.Add(metronomeContainer = new AudioContainer - { - Child = new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime) - }); + Metronome metronome; - metronomeContainer.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust); + drawableRuleset.Overlays.Add(metronome = new Metronome(drawableRuleset.Beatmap.HitObjects.First().StartTime)); + + metronome.AddAdjustment(AdjustableProperty.Volume, metronomeVolumeAdjust); } if (AffectsHitSounds.Value) From 53c901bfa8051bab3ff96aee65ec8c16472764b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 15:05:54 +0900 Subject: [PATCH 150/600] Expose `DrawableRuleset` audio adjustments as non-container --- ...rDisplayExtensions.cs => TimeDisplayExtensions.cs} | 6 ++++++ osu.Game/Rulesets/Mods/ModMuted.cs | 3 +-- osu.Game/Rulesets/UI/DrawableRuleset.cs | 11 ++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) rename osu.Game/Extensions/{EditorDisplayExtensions.cs => TimeDisplayExtensions.cs} (77%) diff --git a/osu.Game/Extensions/EditorDisplayExtensions.cs b/osu.Game/Extensions/TimeDisplayExtensions.cs similarity index 77% rename from osu.Game/Extensions/EditorDisplayExtensions.cs rename to osu.Game/Extensions/TimeDisplayExtensions.cs index f749b88b46..dacde44ca1 100644 --- a/osu.Game/Extensions/EditorDisplayExtensions.cs +++ b/osu.Game/Extensions/TimeDisplayExtensions.cs @@ -22,5 +22,11 @@ namespace osu.Game.Extensions /// An editor formatted display string. public static string ToEditorFormattedString(this TimeSpan timeSpan) => $"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{timeSpan:mm\\:ss\\:fff}"; + + public static string ToFormattedDuration(this double milliseconds) => + ToFormattedDuration(TimeSpan.FromMilliseconds(milliseconds)); + + public static string ToFormattedDuration(this TimeSpan timeSpan) => + timeSpan.Hours == 0 ? $"{timeSpan:mm\\:ss}" : $"{timeSpan:HH\\:mm\\:ss}"; } } diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 9eb218fd9b..7fde14d6ca 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -7,7 +7,6 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Rulesets.Objects; @@ -82,7 +81,7 @@ namespace osu.Game.Rulesets.Mods } if (AffectsHitSounds.Value) - drawableRuleset.AudioContainer.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); + drawableRuleset.Audio.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); } public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index b3242a8b4b..29559f5036 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -99,12 +100,12 @@ namespace osu.Game.Rulesets.UI private DrawableRulesetDependencies dependencies; /// - /// An audio container which can be used to apply adjustments to playfield content. + /// Audio adjustments which are applied to the playfield. /// /// /// Does not affect . /// - public AudioContainer AudioContainer { get; private set; } + public IAdjustableAudioComponent Audio { get; private set; } /// /// Creates a ruleset visualisation for the provided ruleset and beatmap. @@ -163,13 +164,15 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load(CancellationToken? cancellationToken) { + AudioContainer audioContainer; + InternalChild = frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) { FrameStablePlayback = FrameStablePlayback, Children = new Drawable[] { FrameStableComponents, - AudioContainer = new AudioContainer + audioContainer = new AudioContainer { RelativeSizeAxes = Axes.Both, Child = KeyBindingInputManager @@ -181,6 +184,8 @@ namespace osu.Game.Rulesets.UI } }; + Audio = audioContainer; + if ((ResumeOverlay = CreateResumeOverlay()) != null) { AddInternal(CreateInputManager() From f3d4f47e62551fe313070879a11dcca10a98ba98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 15:52:36 +0900 Subject: [PATCH 151/600] Revert unrelated changes --- ...{TimeDisplayExtensions.cs => EditorDisplayExtensions.cs} | 6 ------ 1 file changed, 6 deletions(-) rename osu.Game/Extensions/{TimeDisplayExtensions.cs => EditorDisplayExtensions.cs} (77%) diff --git a/osu.Game/Extensions/TimeDisplayExtensions.cs b/osu.Game/Extensions/EditorDisplayExtensions.cs similarity index 77% rename from osu.Game/Extensions/TimeDisplayExtensions.cs rename to osu.Game/Extensions/EditorDisplayExtensions.cs index dacde44ca1..f749b88b46 100644 --- a/osu.Game/Extensions/TimeDisplayExtensions.cs +++ b/osu.Game/Extensions/EditorDisplayExtensions.cs @@ -22,11 +22,5 @@ namespace osu.Game.Extensions /// An editor formatted display string. public static string ToEditorFormattedString(this TimeSpan timeSpan) => $"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{timeSpan:mm\\:ss\\:fff}"; - - public static string ToFormattedDuration(this double milliseconds) => - ToFormattedDuration(TimeSpan.FromMilliseconds(milliseconds)); - - public static string ToFormattedDuration(this TimeSpan timeSpan) => - timeSpan.Hours == 0 ? $"{timeSpan:mm\\:ss}" : $"{timeSpan:HH\\:mm\\:ss}"; } } From 472c0137ec856381ff6f5802007d268aad662a8a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 16:45:53 +0900 Subject: [PATCH 152/600] Add new extension for formatting time durations --- .../NonVisual/TimeDisplayExtensionTest.cs | 41 +++++++++++++++ .../Extensions/EditorDisplayExtensions.cs | 26 ---------- osu.Game/Extensions/TimeDisplayExtensions.cs | 51 +++++++++++++++++++ 3 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs delete mode 100644 osu.Game/Extensions/EditorDisplayExtensions.cs create mode 100644 osu.Game/Extensions/TimeDisplayExtensions.cs diff --git a/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs b/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs new file mode 100644 index 0000000000..97d7880def --- /dev/null +++ b/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs @@ -0,0 +1,41 @@ +// 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 NUnit.Framework; +using osu.Game.Extensions; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class TimeDisplayExtensionTest + { + private static readonly object[][] editor_formatted_duration_tests = + { + new object[] { new TimeSpan(0, 0, 0, 0, 50), "00:00:050" }, + new object[] { new TimeSpan(0, 0, 0, 10, 50), "00:10:050" }, + new object[] { new TimeSpan(0, 0, 5, 10), "05:10:000" }, + new object[] { new TimeSpan(0, 1, 5, 10), "65:10:000" }, + }; + + [TestCaseSource(nameof(editor_formatted_duration_tests))] + public void TestEditorFormat(TimeSpan input, string expectedOutput) + { + Assert.AreEqual(expectedOutput, input.ToEditorFormattedString()); + } + + private static readonly object[][] formatted_duration_tests = + { + new object[] { new TimeSpan(0, 0, 10), "00:10" }, + new object[] { new TimeSpan(0, 5, 10), "05:10" }, + new object[] { new TimeSpan(1, 5, 10), "01:05:10" }, + new object[] { new TimeSpan(1, 1, 5, 10), "01:01:05:10" }, + }; + + [TestCaseSource(nameof(formatted_duration_tests))] + public void TestFormattedDuration(TimeSpan input, string expectedOutput) + { + Assert.AreEqual(expectedOutput, input.ToFormattedDuration().ToString()); + } + } +} diff --git a/osu.Game/Extensions/EditorDisplayExtensions.cs b/osu.Game/Extensions/EditorDisplayExtensions.cs deleted file mode 100644 index f749b88b46..0000000000 --- a/osu.Game/Extensions/EditorDisplayExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; - -namespace osu.Game.Extensions -{ - public static class EditorDisplayExtensions - { - /// - /// Get an editor formatted string (mm:ss:mss) - /// - /// A time value in milliseconds. - /// An editor formatted display string. - public static string ToEditorFormattedString(this double milliseconds) => - ToEditorFormattedString(TimeSpan.FromMilliseconds(milliseconds)); - - /// - /// Get an editor formatted string (mm:ss:mss) - /// - /// A time value. - /// An editor formatted display string. - public static string ToEditorFormattedString(this TimeSpan timeSpan) => - $"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{timeSpan:mm\\:ss\\:fff}"; - } -} diff --git a/osu.Game/Extensions/TimeDisplayExtensions.cs b/osu.Game/Extensions/TimeDisplayExtensions.cs new file mode 100644 index 0000000000..821686a349 --- /dev/null +++ b/osu.Game/Extensions/TimeDisplayExtensions.cs @@ -0,0 +1,51 @@ +// 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.Localisation; + +namespace osu.Game.Extensions +{ + public static class TimeDisplayExtensions + { + /// + /// Get an editor formatted string (mm:ss:mss) + /// + /// A time value in milliseconds. + /// An editor formatted display string. + public static string ToEditorFormattedString(this double milliseconds) => + ToEditorFormattedString(TimeSpan.FromMilliseconds(milliseconds)); + + /// + /// Get an editor formatted string (mm:ss:mss) + /// + /// A time value. + /// An editor formatted display string. + public static string ToEditorFormattedString(this TimeSpan timeSpan) => + $"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{(int)timeSpan.TotalMinutes:00}:{timeSpan:ss\\:fff}"; + + /// + /// Get a formatted duration (mm:ss or HH:mm:ss if more than an hour). + /// + /// A duration in milliseconds. + /// A formatted duration string. + public static LocalisableString ToFormattedDuration(this double milliseconds) => + ToFormattedDuration(TimeSpan.FromMilliseconds(milliseconds)); + + /// + /// Get a formatted duration (dd:hh:mm:ss with days/hours omitted if zero). + /// + /// A duration value. + /// A formatted duration string. + public static LocalisableString ToFormattedDuration(this TimeSpan timeSpan) + { + if (timeSpan.TotalDays >= 1) + return new LocalisableFormattableString(timeSpan, @"dd\:hh\:mm\:ss"); + + if (timeSpan.TotalHours >= 1) + return new LocalisableFormattableString(timeSpan, @"hh\:mm\:ss"); + + return new LocalisableFormattableString(timeSpan, @"mm\:ss"); + } + } +} From 081dafc4e4682b8595808696acdaace63f5ce060 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 16:46:02 +0900 Subject: [PATCH 153/600] Update existing inline usages to use new extension method --- osu.Game.Tournament/Components/SongBar.cs | 6 +++--- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 3 ++- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index cafec0a88b..6080f7b636 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Rulesets; using osu.Game.Screens.Menu; @@ -198,8 +198,8 @@ namespace osu.Game.Tournament.Components Direction = FillDirection.Vertical, Children = new Drawable[] { - new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))), - new DiffPiece(("BPM", $"{bpm:0.#}")) + new DiffPiece(("Length", length.ToFormattedDuration().ToString())), + new DiffPiece(("BPM", $"{bpm:0.#}")), } }, new Container diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index b81c60a5b9..3f1034759e 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; @@ -62,7 +63,7 @@ namespace osu.Game.Overlays.BeatmapSet } else { - length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToString(@"m\:ss"); + length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration(); circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString(); sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString(); } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 4a35202df2..763c27bcbb 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -24,6 +24,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -333,7 +334,7 @@ namespace osu.Game.Screens.Select { Name = "Length", CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length), - Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"), + Content = beatmap.BeatmapInfo.Length.ToFormattedDuration().ToString(), }), bpmLabelContainer = new Container { From 7a44ddb36baeafdab1fae0637571fab793ad145a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Jul 2021 16:48:43 +0900 Subject: [PATCH 154/600] Update incorrect xmldoc --- osu.Game/Extensions/TimeDisplayExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Extensions/TimeDisplayExtensions.cs b/osu.Game/Extensions/TimeDisplayExtensions.cs index 821686a349..dc05482a05 100644 --- a/osu.Game/Extensions/TimeDisplayExtensions.cs +++ b/osu.Game/Extensions/TimeDisplayExtensions.cs @@ -25,7 +25,7 @@ namespace osu.Game.Extensions $"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{(int)timeSpan.TotalMinutes:00}:{timeSpan:ss\\:fff}"; /// - /// Get a formatted duration (mm:ss or HH:mm:ss if more than an hour). + /// Get a formatted duration (dd:hh:mm:ss with days/hours omitted if zero). /// /// A duration in milliseconds. /// A formatted duration string. From 73393a5a0d102795f1f895e7f49b6ae2cda609e9 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 31 Jul 2021 15:56:25 +0200 Subject: [PATCH 155/600] Localise weighting percentage. --- .../Profile/Sections/Ranks/DrawableProfileWeightedScore.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs index 63305d004c..4e4a665a60 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; @@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks new OsuSpriteText { Font = OsuFont.GetFont(size: 12), - Text = UsersStrings.ShowExtraTopRanksPpWeight(weight.ToString("0%")) + Text = UsersStrings.ShowExtraTopRanksPpWeight(weight.ToLocalisableString("0%")) } } }; From 9a7537cd569c9401efbcda2eca04b4dcbca166a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 11 Jul 2021 19:48:21 +0200 Subject: [PATCH 156/600] Add support for adding new colours to palette --- .../Graphics/UserInterfaceV2/ColourPalette.cs | 131 ++++++++++++------ 1 file changed, 91 insertions(+), 40 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index d8edd00c16..1956eb045b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -1,12 +1,17 @@ // 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 System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; @@ -36,36 +41,24 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } - private FillFlowContainer palette; - private Container placeholder; + private FillFlowContainer palette; + + private IEnumerable colourDisplays => palette.OfType(); [BackgroundDependencyLoader] private void load() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + AutoSizeDuration = fade_duration; + AutoSizeEasing = Easing.OutQuint; - InternalChildren = new Drawable[] + InternalChild = palette = new FillFlowContainer { - palette = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(10), - Direction = FillDirection.Full - }, - placeholder = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = new OsuSpriteText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Text = "(none)", - Font = OsuFont.Default.With(weight: FontWeight.Bold) - } - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + Direction = FillDirection.Full }; } @@ -73,30 +66,20 @@ namespace osu.Game.Graphics.UserInterfaceV2 { base.LoadComplete(); - Colours.BindCollectionChanged((_, args) => updatePalette(args), true); + Colours.BindCollectionChanged((_, args) => + { + if (args.Action != NotifyCollectionChangedAction.Replace) + updatePalette(); + }, true); FinishTransforms(true); } private const int fade_duration = 200; - private void updatePalette(NotifyCollectionChangedEventArgs args) + private void updatePalette() { - if (args.Action == NotifyCollectionChangedAction.Replace) - return; - palette.Clear(); - if (Colours.Any()) - { - palette.FadeIn(fade_duration, Easing.OutQuint); - placeholder.FadeOut(fade_duration, Easing.OutQuint); - } - else - { - palette.FadeOut(fade_duration, Easing.OutQuint); - placeholder.FadeIn(fade_duration, Easing.OutQuint); - } - for (int i = 0; i < Colours.Count; ++i) { // copy to avoid accesses to modified closure. @@ -111,6 +94,11 @@ namespace osu.Game.Graphics.UserInterfaceV2 display.Current.BindValueChanged(colour => Colours[colourIndex] = colour.NewValue); } + palette.Add(new AddColourButton + { + Action = () => Colours.Add(Colour4.White) + }); + reindexItems(); } @@ -118,11 +106,74 @@ namespace osu.Game.Graphics.UserInterfaceV2 { int index = 1; - foreach (var colour in palette) + foreach (var colourDisplay in colourDisplays) { - colour.ColourName = $"{colourNamePrefix} {index}"; + colourDisplay.ColourName = $"{colourNamePrefix} {index}"; index += 1; } } + + private class AddColourButton : CompositeDrawable + { + public Action Action + { + set => circularButton.Action = value; + } + + private readonly OsuClickableContainer circularButton; + + public AddColourButton() + { + AutoSizeAxes = Axes.Y; + Width = 100; + + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + circularButton = new OsuClickableContainer + { + RelativeSizeAxes = Axes.X, + Height = 100, + CornerRadius = 50, + Masking = true, + BorderThickness = 5, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.Transparent, + AlwaysPresent = true + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20), + Icon = FontAwesome.Solid.Plus + } + } + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "New" + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + circularButton.BorderColour = colours.BlueDarker; + } + } } } From 3f005886d66e1c4c19e7fd60e5589861ec616cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 11 Jul 2021 20:02:39 +0200 Subject: [PATCH 157/600] Add support for removing colours from palette --- .../TestSceneLabelledColourPalette.cs | 19 ++-- .../Graphics/UserInterfaceV2/ColourDisplay.cs | 103 +++++++++++------- .../Graphics/UserInterfaceV2/ColourPalette.cs | 3 + 3 files changed, 81 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs index d7af47a835..bbb5ebd0d9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterfaceV2; using osuTK.Graphics; @@ -34,17 +35,21 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - Child = new Container + Child = new OsuContextMenuContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 500, - AutoSizeAxes = Axes.Y, - Child = component = new LabelledColourPalette + RelativeSizeAxes = Axes.Both, + Child = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, - ColourNamePrefix = "My colour #" + Width = 500, + AutoSizeAxes = Axes.Y, + Child = component = new LabelledColourPalette + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + ColourNamePrefix = "My colour #" + } } }; diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index 25f89fdcaa..85e18a6865 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -1,6 +1,7 @@ // 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.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -12,6 +13,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 @@ -19,12 +21,17 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// /// A component which displays a colour along with related description text. /// - public class ColourDisplay : CompositeDrawable, IHasCurrentValue, IHasPopover + public class ColourDisplay : CompositeDrawable, IHasCurrentValue { + /// + /// Invoked when the user has requested the colour corresponding to this + /// to be removed from its palette. + /// + public event Action DeleteRequested; + private readonly BindableWithCurrent current = new BindableWithCurrent(); - private Box fill; - private OsuSpriteText colourHexCode; + private OsuClickableContainer colourCircle; private OsuSpriteText colourName; public Bindable Current @@ -63,26 +70,10 @@ namespace osu.Game.Graphics.UserInterfaceV2 Spacing = new Vector2(0, 10), Children = new Drawable[] { - new OsuClickableContainer + colourCircle = new ColourCircle { - RelativeSizeAxes = Axes.X, - Height = 100, - CornerRadius = 50, - Masking = true, - Children = new Drawable[] - { - fill = new Box - { - RelativeSizeAxes = Axes.Both - }, - colourHexCode = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.Default.With(size: 12) - } - }, - Action = this.ShowPopover + Current = { BindTarget = Current }, + DeleteRequested = () => DeleteRequested?.Invoke(this) }, colourName = new OsuSpriteText { @@ -93,26 +84,64 @@ namespace osu.Game.Graphics.UserInterfaceV2 }; } - protected override void LoadComplete() + private class ColourCircle : OsuClickableContainer, IHasPopover, IHasContextMenu { - base.LoadComplete(); + public Bindable Current { get; } = new Bindable(); - current.BindValueChanged(_ => updateColour(), true); - } + public Action DeleteRequested { get; set; } - private void updateColour() - { - fill.Colour = current.Value; - colourHexCode.Text = current.Value.ToHex(); - colourHexCode.Colour = OsuColour.ForegroundTextColourFor(current.Value); - } + private readonly Box fill; + private readonly OsuSpriteText colourHexCode; - public Popover GetPopover() => new OsuPopover(false) - { - Child = new OsuColourPicker + public ColourCircle() { - Current = { BindTarget = Current } + RelativeSizeAxes = Axes.X; + Height = 100; + CornerRadius = 50; + Masking = true; + Action = this.ShowPopover; + + Children = new Drawable[] + { + fill = new Box + { + RelativeSizeAxes = Axes.Both + }, + colourHexCode = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(size: 12) + } + }; } - }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(_ => updateColour(), true); + } + + private void updateColour() + { + fill.Colour = Current.Value; + colourHexCode.Text = Current.Value.ToHex(); + colourHexCode.Colour = OsuColour.ForegroundTextColourFor(Current.Value); + } + + public Popover GetPopover() => new OsuPopover(false) + { + Child = new OsuColourPicker + { + Current = { BindTarget = Current } + } + }; + + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteRequested?.Invoke()) + }; + } } } diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index 1956eb045b..02d03bf07e 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -92,6 +92,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 }); display.Current.BindValueChanged(colour => Colours[colourIndex] = colour.NewValue); + display.DeleteRequested += colourDeletionRequested; } palette.Add(new AddColourButton @@ -102,6 +103,8 @@ namespace osu.Game.Graphics.UserInterfaceV2 reindexItems(); } + private void colourDeletionRequested(ColourDisplay display) => Colours.RemoveAt(palette.IndexOf(display)); + private void reindexItems() { int index = 1; From 4334121e8ecff738618e04006e89f6dcd61ae549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 11 Jul 2021 20:14:42 +0200 Subject: [PATCH 158/600] Add testing for colour palette behaviour --- .../TestSceneLabelledColourPalette.cs | 53 ++++++++++++++++++- .../Graphics/UserInterfaceV2/ColourPalette.cs | 2 +- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs index bbb5ebd0d9..6fafb8f87a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs @@ -1,17 +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.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledColourPalette : OsuTestScene + public class TestSceneLabelledColourPalette : OsuManualInputManagerTestScene { private LabelledColourPalette component; @@ -31,6 +35,22 @@ namespace osu.Game.Tests.Visual.UserInterface }, 8); } + [Test] + public void TestUserInteractions() + { + createColourPalette(); + assertColourCount(4); + + clickAddColour(); + assertColourCount(5); + + deleteFirstColour(); + assertColourCount(4); + + clickFirstColour(); + AddAssert("colour picker spawned", () => this.ChildrenOfType().Any()); + } + private void createColourPalette(bool hasDescription = false) { AddStep("create component", () => @@ -71,5 +91,36 @@ namespace osu.Game.Tests.Visual.UserInterface RNG.NextSingle(), RNG.NextSingle(), 1); + + private void assertColourCount(int count) => AddAssert($"colour count is {count}", () => component.Colours.Count == count); + + private void clickAddColour() => AddStep("click new colour button", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + private void clickFirstColour() => AddStep("click first colour", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + + private void deleteFirstColour() + { + AddStep("right-click first colour", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().First()); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for menu", () => this.ChildrenOfType().Any()); + + AddStep("click delete", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + } } } diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index 02d03bf07e..a966f61b74 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -116,7 +116,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } - private class AddColourButton : CompositeDrawable + internal class AddColourButton : CompositeDrawable { public Action Action { From 708b50fdba0016e950b1a4446e35534f50bf3720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 1 Aug 2021 00:11:56 +0200 Subject: [PATCH 159/600] Remove unused field --- osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index 85e18a6865..5240df74a2 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -31,7 +31,6 @@ namespace osu.Game.Graphics.UserInterfaceV2 private readonly BindableWithCurrent current = new BindableWithCurrent(); - private OsuClickableContainer colourCircle; private OsuSpriteText colourName; public Bindable Current @@ -70,7 +69,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 Spacing = new Vector2(0, 10), Children = new Drawable[] { - colourCircle = new ColourCircle + new ColourCircle { Current = { BindTarget = Current }, DeleteRequested = () => DeleteRequested?.Invoke(this) From f868a201f5347c607c65cf62e614faa8c268d9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 1 Aug 2021 15:03:51 +0200 Subject: [PATCH 160/600] Ensure proxied judgement content is correctly depth-ordered --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 6 +++++- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 8993a9b18a..c1c2ea2299 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.UI private void onJudgementLoaded(DrawableOsuJudgement judgement) { - judgementAboveHitObjectLayer.Add(judgement.GetProxyAboveHitObjectsContent()); + judgementAboveHitObjectLayer.Add(judgement.ProxiedAboveHitObjectsContent); } [BackgroundDependencyLoader(true)] @@ -150,6 +150,10 @@ namespace osu.Game.Rulesets.Osu.UI DrawableOsuJudgement explosion = poolDictionary[result.Type].Get(doj => doj.Apply(result, judgedObject)); judgementLayer.Add(explosion); + + // the proxied content is added to judgementAboveHitObjectLayer once, on first load, and never removed from it. + // ensure that ordering is consistent with expectations (latest judgement should be front-most). + judgementAboveHitObjectLayer.ChangeChildDepth(explosion.ProxiedAboveHitObjectsContent, (float)-result.TimeAbsolute); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos); diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 0f22d35bb5..d25d46c6e2 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -1,6 +1,7 @@ // 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.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -31,6 +32,9 @@ namespace osu.Game.Rulesets.Judgements private readonly Container aboveHitObjectsContent; + private readonly Lazy proxiedAboveHitObjectsContent; + public Drawable ProxiedAboveHitObjectsContent => proxiedAboveHitObjectsContent.Value; + /// /// Creates a drawable which visualises a . /// @@ -52,6 +56,8 @@ namespace osu.Game.Rulesets.Judgements Depth = float.MinValue, RelativeSizeAxes = Axes.Both }); + + proxiedAboveHitObjectsContent = new Lazy(() => aboveHitObjectsContent.CreateProxy()); } [BackgroundDependencyLoader] @@ -60,8 +66,6 @@ namespace osu.Game.Rulesets.Judgements prepareDrawables(); } - public Drawable GetProxyAboveHitObjectsContent() => aboveHitObjectsContent.CreateProxy(); - /// /// Apply top-level animations to the current judgement when successfully hit. /// If displaying components which require lifetime extensions, manually adjusting is required. From ac930b8918fcaa731965674cc6610fcb33f9a153 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 19:16:30 +0300 Subject: [PATCH 161/600] Fix judgement processors provided to mods while not completely loaded --- .../Rulesets/Mods/IApplicableToHealthProcessor.cs | 2 +- .../Rulesets/Mods/IApplicableToScoreProcessor.cs | 2 +- osu.Game/Screens/Play/Player.cs | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs index a181955653..c12b215d41 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods public interface IApplicableToHealthProcessor : IApplicableMod { /// - /// Provide a to a mod. Called once on initialisation of a play instance. + /// Provides a ready to a mod. Called once on initialisation of a play instance. /// void ApplyToHealthProcessor(HealthProcessor healthProcessor); } diff --git a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs index cb00770868..b93e50921f 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods public interface IApplicableToScoreProcessor : IApplicableMod { /// - /// Provide a to a mod. Called once on initialisation of a play instance. + /// Provides a loaded to a mod. Called once on initialisation of a play instance. /// void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d76d44767a..db6ec1f4a9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -297,11 +297,17 @@ namespace osu.Game.Screens.Play ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged); HealthProcessor.Failed += onFail; - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToScoreProcessor(ScoreProcessor); + ScoreProcessor.OnLoadComplete += _ => + { + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToScoreProcessor(ScoreProcessor); + }; - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToHealthProcessor(HealthProcessor); + HealthProcessor.OnLoadComplete += _ => + { + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToHealthProcessor(HealthProcessor); + }; IsBreakTime.BindTo(breakTracker.IsBreakTime); IsBreakTime.BindValueChanged(onBreakTimeChanged, true); From f12e66052c99581040e8d25822e9a979e041bf84 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 19:22:33 +0300 Subject: [PATCH 162/600] Reword outdated doc --- osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs index c12b215d41..2676060efa 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods public interface IApplicableToHealthProcessor : IApplicableMod { /// - /// Provides a ready to a mod. Called once on initialisation of a play instance. + /// Provides a loaded to a mod. Called once on initialisation of a play instance. /// void ApplyToHealthProcessor(HealthProcessor healthProcessor); } From c93533fa2e14407baec6c761bf2bf4ca06eb641b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:04:24 +0000 Subject: [PATCH 163/600] Bump Xamarin.Essentials from 1.6.1 to 1.7.0 Bumps [Xamarin.Essentials](https://github.com/xamarin/Essentials) from 1.6.1 to 1.7.0. - [Release notes](https://github.com/xamarin/Essentials/releases) - [Commits](https://github.com/xamarin/Essentials/compare/1.6.1...1.7.0) --- updated-dependencies: - dependency-name: Xamarin.Essentials dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Android/osu.Android.csproj | 2 +- osu.iOS/osu.iOS.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 582c856a47..b2599535ae 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -64,7 +64,7 @@ - + \ No newline at end of file diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 1cbe4422cc..1203c3659b 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -117,7 +117,7 @@ - + From 81f42da38678c1f3b6ebb8980f8d6ad4c759afb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:04:30 +0000 Subject: [PATCH 164/600] Bump MessagePack from 2.2.113 to 2.3.75 Bumps [MessagePack](https://github.com/neuecc/MessagePack-CSharp) from 2.2.113 to 2.3.75. - [Release notes](https://github.com/neuecc/MessagePack-CSharp/releases) - [Changelog](https://github.com/neuecc/MessagePack-CSharp/blob/master/prepare_release.ps1) - [Commits](https://github.com/neuecc/MessagePack-CSharp/compare/v2.2.113...v2.3.75) --- updated-dependencies: - dependency-name: MessagePack dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 936fe8db94..7ca52aaed5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,7 +22,7 @@ - + From aadd1c67816b5affa75b6df49b4a955db4ee2a40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:04:37 +0000 Subject: [PATCH 165/600] Bump Sentry from 3.8.2 to 3.8.3 Bumps [Sentry](https://github.com/getsentry/sentry-dotnet) from 3.8.2 to 3.8.3. - [Release notes](https://github.com/getsentry/sentry-dotnet/releases) - [Changelog](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-dotnet/compare/3.8.2...3.8.3) --- updated-dependencies: - dependency-name: Sentry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 936fe8db94..03ae29a384 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -38,7 +38,7 @@ - + From 1e3173bf446bc16eb42bae1b8cdc64cd19c22b33 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 20:12:35 +0300 Subject: [PATCH 166/600] Fix muted dim factor not considering "0 divided by 0" case --- osu.Game/Rulesets/Mods/ModMuted.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 7fde14d6ca..c6a3a1a603 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -89,7 +88,7 @@ namespace osu.Game.Rulesets.Mods currentCombo = scoreProcessor.Combo.GetBoundCopy(); currentCombo.BindValueChanged(combo => { - double dimFactor = Math.Min(1, (double)combo.NewValue / MuteComboCount.Value); + double dimFactor = MuteComboCount.Value == 0 ? 1 : (double)combo.NewValue / MuteComboCount.Value; if (InverseMuting.Value) dimFactor = 1 - dimFactor; From ce7987dac797f6721d9033aa503a0210cb7ccc55 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 20:09:37 +0300 Subject: [PATCH 167/600] Clarify `0` final combo indicates always muted audio --- osu.Game/Rulesets/Mods/ModMuted.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index c6a3a1a603..87a2e2446e 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -7,7 +7,10 @@ using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -40,7 +43,7 @@ namespace osu.Game.Rulesets.Mods Value = true }; - [SettingSource("Final volume at combo", "The combo count at which point the track reaches its final volume.")] + [SettingSource("Final volume at combo", "The combo count at which point the track reaches its final volume.", SettingControlType = typeof(SettingsSlider))] public BindableInt MuteComboCount { get; } = new BindableInt { Default = 100, @@ -100,4 +103,9 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } + + public class MuteComboSlider : OsuSliderBar + { + public override LocalisableString TooltipText => Current.Value == 0 ? "(always muted)" : base.TooltipText; + } } From 026c6325390fe7aa72a81b91b51a26ff836a4b7c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 20:12:43 +0300 Subject: [PATCH 168/600] Add test coverage --- .../Mods/TestSceneOsuModMuted.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs new file mode 100644 index 0000000000..30e234dd7a --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.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.Linq; +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; + +namespace osu.Game.Rulesets.Osu.Tests.Mods +{ + public class TestSceneOsuModMuted : OsuModTestScene + { + /// + /// Ensures that a final volume combo of 0 (i.e. "always muted" mode) constantly plays metronome and completely mutes track. + /// + [TestCase(0.0, 1.0)] + public void TestZeroFinalCombo(double expectedTrackVolume, double expectedMetronomeVolume) => CreateModTest(new ModTestData + { + Mod = new OsuModMuted + { + MuteComboCount = { Value = 0 }, + }, + PassCondition = () => Beatmap.Value.Track.AggregateVolume.Value == expectedTrackVolume && + Player.ChildrenOfType().SingleOrDefault()?.AggregateVolume.Value == expectedMetronomeVolume, + }); + } +} From a26e7b2680c7e2e53ad7fc0ba97f63ac6ea6791d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 20:59:29 +0300 Subject: [PATCH 169/600] Limit combo count to minimum 1 when using inversed Avoids making the mod of no effect. --- osu.Game/Rulesets/Mods/ModMuted.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 87a2e2446e..8991962349 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -66,6 +66,11 @@ namespace osu.Game.Rulesets.Mods Value = true }; + protected ModMuted() + { + InverseMuting.BindValueChanged(i => MuteComboCount.MinValue = i.NewValue ? 1 : 0, true); + } + public void ApplyToTrack(ITrack track) { track.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); From fb5ef7d2d28c0ce218bdc5a71bac8b542ce522c2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 20:59:51 +0300 Subject: [PATCH 170/600] Remove brackets --- osu.Game/Rulesets/Mods/ModMuted.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 8991962349..1d33b44812 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -111,6 +111,6 @@ namespace osu.Game.Rulesets.Mods public class MuteComboSlider : OsuSliderBar { - public override LocalisableString TooltipText => Current.Value == 0 ? "(always muted)" : base.TooltipText; + public override LocalisableString TooltipText => Current.Value == 0 ? "always muted" : base.TooltipText; } } From a75da8298686c180fe657a75899fc9838866251c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 1 Aug 2021 21:14:54 +0300 Subject: [PATCH 171/600] Add explaining comment --- osu.Game/Screens/Play/Player.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index db6ec1f4a9..09eaf1c543 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -297,6 +297,8 @@ namespace osu.Game.Screens.Play ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged); HealthProcessor.Failed += onFail; + // Provide judgement processors to mods after they're loaded so that they're on the gameplay clock, + // this is required for mods that apply transforms to these processors. ScoreProcessor.OnLoadComplete += _ => { foreach (var mod in Mods.Value.OfType()) From df9b6182560909c892ffd8ed7a324facb2504ec4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 11:44:05 +0900 Subject: [PATCH 172/600] Add localisation license header to editorconfig --- osu.Game/.editorconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/.editorconfig b/osu.Game/.editorconfig index 46a3dafd04..4107d1bb35 100644 --- a/osu.Game/.editorconfig +++ b/osu.Game/.editorconfig @@ -1,2 +1,3 @@ [*.cs] -dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation \ No newline at end of file +dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation +dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text. \ No newline at end of file From 356c157d1f860e621c5fdc594b4c95050facf158 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 11:49:21 +0900 Subject: [PATCH 173/600] Add localisation options to sln's .editorconfig --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 19bd89c52f..ceaaf4e8f1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -190,3 +190,6 @@ dotnet_diagnostic.CA2225.severity = none # Banned APIs dotnet_diagnostic.RS0030.severity = error + +dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation +dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text. From cd0fb2f4360cc4e3aae2003e9319989f88e27765 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 11:52:10 +0900 Subject: [PATCH 174/600] Remove namespace from sln's .editorconfig --- .editorconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index ceaaf4e8f1..3c4997c88d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -191,5 +191,4 @@ dotnet_diagnostic.CA2225.severity = none # Banned APIs dotnet_diagnostic.RS0030.severity = error -dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text. From 3e56388ba8ea4217f197cbb15ef78f216cbfb799 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 15:08:42 +0900 Subject: [PATCH 175/600] Match casing in enum value --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherTrail.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 9422d6d51b..b30c3d82a4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Catch.UI } if (!lastHyperDashState && Catcher.HyperDashing) - displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterimage); + displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterImage); if (Catcher.Dashing || Catcher.HyperDashing) { diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs index f3f996d2c5..6d2ac7e488 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI this.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); break; - case CatcherTrailAnimation.HyperDashAfterimage: + case CatcherTrailAnimation.HyperDashAfterImage: this.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); this.ScaleTo(Scale * 0.95f).ScaleTo(Scale * 1.2f, 1200, Easing.In); this.FadeOut(1200); diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs index 3ea99badc1..0a5281cd10 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs @@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Catch.UI { Dashing, HyperDashing, - HyperDashAfterimage + HyperDashAfterImage } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index f451f84c95..0f2530e56a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Catch.UI hyperDashTrails.Add(drawable); break; - case CatcherTrailAnimation.HyperDashAfterimage: + case CatcherTrailAnimation.HyperDashAfterImage: hyperDashAfterImages.Add(drawable); break; } @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Catch.UI hyperDashTrails.Remove(drawable); break; - case CatcherTrailAnimation.HyperDashAfterimage: + case CatcherTrailAnimation.HyperDashAfterImage: hyperDashAfterImages.Remove(drawable); break; } From e8338f2711ef20d3fc8ae16828d5f7b303583ad2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jul 2021 18:59:02 +0900 Subject: [PATCH 176/600] Add basic class structure for match rulesets and required state --- .../Online/Multiplayer/IMultiplayerClient.cs | 13 +++++++++++++ .../Multiplayer/MatchRulesetRoomState.cs | 18 ++++++++++++++++++ .../Online/Multiplayer/MatchRulesetType.cs | 11 +++++++++++ .../Multiplayer/MatchRulesetUserState.cs | 18 ++++++++++++++++++ .../MatchRulesets/TeamVs/MultiplayerTeam.cs | 19 +++++++++++++++++++ .../TeamVs/TeamVsMatchRoomState.cs | 14 ++++++++++++++ .../TeamVs/TeamVsMatchUserState.cs | 13 +++++++++++++ .../Online/Multiplayer/MultiplayerClient.cs | 10 ++++++++++ .../Online/Multiplayer/MultiplayerRoom.cs | 3 +++ .../Multiplayer/MultiplayerRoomSettings.cs | 7 ++++++- .../Online/Multiplayer/MultiplayerRoomUser.cs | 3 +++ 11 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs create mode 100644 osu.Game/Online/Multiplayer/MatchRulesetType.cs create mode 100644 osu.Game/Online/Multiplayer/MatchRulesetUserState.cs create mode 100644 osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs create mode 100644 osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs create mode 100644 osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 6d7b9d24d6..cfe5af3393 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -50,6 +50,19 @@ namespace osu.Game.Online.Multiplayer /// The new state of the user. Task UserStateChanged(int userId, MultiplayerUserState state); + /// + /// Signals that the match ruleset state has changed for a user in this room. + /// + /// The ID of the user performing a state change. + /// The new state of the user. + Task MatchRulesetUserStateChanged(int userId, MatchRulesetUserState state); + + /// + /// Signals that the match ruleset state has changed for this room. + /// + /// The new state of the room. + Task MatchRulesetRoomStateChanged(MatchRulesetRoomState state); + /// /// Signals that a user in this room changed their beatmap availability state. /// diff --git a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs new file mode 100644 index 0000000000..21bdec1b20 --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs @@ -0,0 +1,18 @@ +// 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 MessagePack; + +namespace osu.Game.Online.Multiplayer +{ + /// + /// Room-wide state for the current match ruleset. + /// Can be used to contain any state which should be used before or during match gameplay. + /// + [Serializable] + [MessagePackObject] + public abstract class MatchRulesetRoomState + { + } +} diff --git a/osu.Game/Online/Multiplayer/MatchRulesetType.cs b/osu.Game/Online/Multiplayer/MatchRulesetType.cs new file mode 100644 index 0000000000..b87a8eb174 --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesetType.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Online.Multiplayer +{ + public enum MatchRulesetType + { + HeadToHead, + TeamVs + } +} diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs new file mode 100644 index 0000000000..647574b54a --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs @@ -0,0 +1,18 @@ +// 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 MessagePack; + +namespace osu.Game.Online.Multiplayer +{ + /// + /// User specific state for the current match ruleset. + /// Can be used to contain any state which should be used before or during match gameplay. + /// + [Serializable] + [MessagePackObject] + public abstract class MatchRulesetUserState + { + } +} diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs new file mode 100644 index 0000000000..532111671e --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs @@ -0,0 +1,19 @@ +// 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 MessagePack; + +namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +{ + [Serializable] + [MessagePackObject] + public class MultiplayerTeam + { + [Key(0)] + public int ID { get; set; } + + [Key(1)] + public string Name { get; set; } + } +} diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs new file mode 100644 index 0000000000..6383617100 --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using MessagePack; + +namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +{ + public class TeamVsMatchRoomState : MatchRulesetRoomState + { + [Key(0)] + public List Teams { get; set; } + } +} diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs new file mode 100644 index 0000000000..b35cfd3cdd --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using MessagePack; + +namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +{ + public class TeamVsMatchUserState : MatchRulesetUserState + { + [Key(0)] + public int TeamID { get; set; } + } +} diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 9972d7e88d..fa0cbb1dff 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -420,6 +420,16 @@ namespace osu.Game.Online.Multiplayer return Task.CompletedTask; } + Task IMultiplayerClient.MatchRulesetUserStateChanged(int userId, MatchRulesetUserState state) + { + throw new NotImplementedException(); + } + + Task IMultiplayerClient.MatchRulesetRoomStateChanged(MatchRulesetRoomState state) + { + throw new NotImplementedException(); + } + Task IMultiplayerClient.UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability) { if (Room == null) diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs index c5fa6253ed..19c0d3cb24 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs @@ -47,6 +47,9 @@ namespace osu.Game.Online.Multiplayer [Key(4)] public MultiplayerRoomUser? Host { get; set; } + [Key(5)] + public MatchRulesetRoomState? MatchRulesetState { get; set; } + [JsonConstructor] [SerializationConstructor] public MultiplayerRoom(long roomId) diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index 4e94c5982f..2c49e3b251 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -39,6 +39,9 @@ namespace osu.Game.Online.Multiplayer [Key(7)] public string Password { get; set; } = string.Empty; + [Key(8)] + public MatchRulesetType MatchRulesetType { get; set; } + public bool Equals(MultiplayerRoomSettings other) => BeatmapID == other.BeatmapID && BeatmapChecksum == other.BeatmapChecksum @@ -47,7 +50,8 @@ namespace osu.Game.Online.Multiplayer && RulesetID == other.RulesetID && Password.Equals(other.Password, StringComparison.Ordinal) && Name.Equals(other.Name, StringComparison.Ordinal) - && PlaylistItemId == other.PlaylistItemId; + && PlaylistItemId == other.PlaylistItemId + && MatchRulesetType == other.MatchRulesetType; public override string ToString() => $"Name:{Name}" + $" Beatmap:{BeatmapID} ({BeatmapChecksum})" @@ -55,6 +59,7 @@ namespace osu.Game.Online.Multiplayer + $" AllowedMods:{string.Join(',', AllowedMods)}" + $" Password:{(string.IsNullOrEmpty(Password) ? "no" : "yes")}" + $" Ruleset:{RulesetID}" + + $" MatchRuleset:{MatchRulesetType}" + $" Item:{PlaylistItemId}"; } } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index a49a8f083c..d97d49aa8a 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -36,6 +36,9 @@ namespace osu.Game.Online.Multiplayer [Key(3)] public IEnumerable Mods { get; set; } = Enumerable.Empty(); + [Key(4)] + public MatchRulesetUserState? MatchRulesetState { get; set; } + [IgnoreMember] public User? User { get; set; } From 9d1e95caf01b548f80dfe59d11f5a2576fe40ca2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jul 2021 19:13:56 +0900 Subject: [PATCH 177/600] Add flow for sending match ruleset specific messages to the server --- .../Multiplayer/IMultiplayerRoomServer.cs | 6 ++++++ .../Multiplayer/MatchRulesetUserRequest.cs | 17 +++++++++++++++++ .../MatchRulesets/TeamVs/ChangeTeamRequest.cs | 13 +++++++++++++ .../Online/Multiplayer/MultiplayerClient.cs | 2 ++ .../Multiplayer/OnlineMultiplayerClient.cs | 8 ++++++++ .../Visual/Multiplayer/TestMultiplayerClient.cs | 2 ++ 6 files changed, 48 insertions(+) create mode 100644 osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs create mode 100644 osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index 3527ce6314..20c9f9e216 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -55,6 +55,12 @@ namespace osu.Game.Online.Multiplayer /// The proposed new mods, excluding any required by the room itself. Task ChangeUserMods(IEnumerable newMods); + /// + /// Send a match ruleset specific request. + /// + /// The request to send. + Task SendMatchRulesetRequest(MatchRulesetUserRequest request); + /// /// As the host of a room, start the match. /// diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs b/osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs new file mode 100644 index 0000000000..3cc430a2b7 --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs @@ -0,0 +1,17 @@ +// 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 MessagePack; + +namespace osu.Game.Online.Multiplayer +{ + /// + /// A request from a user to perform an action specific to the current match ruleset. + /// + [Serializable] + [MessagePackObject] + public abstract class MatchRulesetUserRequest + { + } +} diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs new file mode 100644 index 0000000000..9dd01ea87c --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using MessagePack; + +namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +{ + public class ChangeTeamRequest : MatchRulesetUserRequest + { + [Key(0)] + public int TeamID { get; set; } + } +} diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index fa0cbb1dff..299da2e06e 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -293,6 +293,8 @@ namespace osu.Game.Online.Multiplayer public abstract Task ChangeUserMods(IEnumerable newMods); + public abstract Task SendMatchRulesetRequest(MatchRulesetUserRequest request); + public abstract Task StartMatch(); Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 726e26ebe1..88d8c04c98 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -118,6 +118,14 @@ namespace osu.Game.Online.Multiplayer return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeUserMods), newMods); } + public override Task SendMatchRulesetRequest(MatchRulesetUserRequest request) + { + if (!IsConnected.Value) + return Task.CompletedTask; + + return connection.InvokeAsync(nameof(IMultiplayerServer.SendMatchRulesetRequest), request); + } + public override Task StartMatch() { if (!IsConnected.Value) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 3349d670c8..6a8bf87ff0 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -192,6 +192,8 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.CompletedTask; } + public override Task SendMatchRulesetRequest(MatchRulesetUserRequest request) => Task.CompletedTask; + public override Task StartMatch() { Debug.Assert(Room != null); From 1c125eef121ebfda79bf7069765092433e242eff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jul 2021 18:16:53 +0900 Subject: [PATCH 178/600] Make `Users` an `IList` for more flexibility server-side --- osu.Game/Online/Multiplayer/MultiplayerRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs index 19c0d3cb24..07d87fafc3 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs @@ -39,7 +39,7 @@ namespace osu.Game.Online.Multiplayer /// All users currently in this room. /// [Key(3)] - public List Users { get; set; } = new List(); + public IList Users { get; set; } = new List(); /// /// The host of this room, in control of changing room settings. From 1d645d4ca99b6c8787ab53a7ba9e2d7adc62a5c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jul 2021 19:48:52 +0900 Subject: [PATCH 179/600] Mark base classes non-abstract to fix messagepack serialisation --- osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs | 2 +- osu.Game/Online/Multiplayer/MatchRulesetUserState.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs index 21bdec1b20..d8072efa2a 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs @@ -12,7 +12,7 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - public abstract class MatchRulesetRoomState + public class MatchRulesetRoomState { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs index 647574b54a..e8d9961dbd 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs @@ -12,7 +12,7 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - public abstract class MatchRulesetUserState + public class MatchRulesetUserState { } } From d17b2b3268982af8801539dcdaf5bd6390a09c4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jul 2021 17:38:08 +0900 Subject: [PATCH 180/600] Add boilerplate for server events --- .../Online/Multiplayer/IMultiplayerClient.cs | 6 ++++++ .../Multiplayer/MatchRulesetServerEvent.cs | 17 +++++++++++++++++ .../Online/Multiplayer/MultiplayerClient.cs | 5 +++++ 3 files changed, 28 insertions(+) create mode 100644 osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index cfe5af3393..839ec9bd1f 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -63,6 +63,12 @@ namespace osu.Game.Online.Multiplayer /// The new state of the room. Task MatchRulesetRoomStateChanged(MatchRulesetRoomState state); + /// + /// Send a match ruleset specific request. + /// + /// The event to handle. + Task MatchRulesetEvent(MatchRulesetServerEvent e); + /// /// Signals that a user in this room changed their beatmap availability state. /// diff --git a/osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs b/osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs new file mode 100644 index 0000000000..c45615e914 --- /dev/null +++ b/osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs @@ -0,0 +1,17 @@ +// 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 MessagePack; + +namespace osu.Game.Online.Multiplayer +{ + /// + /// An event from the server to allow clients to update gameplay to an expected state. + /// + [Serializable] + [MessagePackObject] + public abstract class MatchRulesetServerEvent + { + } +} diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 299da2e06e..225d86ed9c 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -432,6 +432,11 @@ namespace osu.Game.Online.Multiplayer throw new NotImplementedException(); } + public Task MatchRulesetEvent(MatchRulesetServerEvent e) + { + throw new NotImplementedException(); + } + Task IMultiplayerClient.UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability) { if (Room == null) From 035dfd071fb720af2245e478ea1a7d2c8baef821 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Jul 2021 18:55:04 +0900 Subject: [PATCH 181/600] Add missing nullable specifications --- osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs | 2 ++ osu.Game/Online/Multiplayer/MatchRulesetUserState.cs | 2 ++ .../Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs | 2 ++ .../Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs | 4 +++- .../Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs | 4 +++- .../Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs | 2 ++ 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs index d8072efa2a..be8e54d341 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs @@ -4,6 +4,8 @@ using System; using MessagePack; +#nullable enable + namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs index e8d9961dbd..6fa0024c3d 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs @@ -4,6 +4,8 @@ using System; using MessagePack; +#nullable enable + namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs index 9dd01ea87c..5e1d489d39 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs @@ -3,6 +3,8 @@ using MessagePack; +#nullable enable + namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs { public class ChangeTeamRequest : MatchRulesetUserRequest diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs index 532111671e..f6bf893818 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs @@ -4,6 +4,8 @@ using System; using MessagePack; +#nullable enable + namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs { [Serializable] @@ -14,6 +16,6 @@ namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs public int ID { get; set; } [Key(1)] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs index 6383617100..57aae6e534 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs @@ -4,11 +4,13 @@ using System.Collections.Generic; using MessagePack; +#nullable enable + namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs { public class TeamVsMatchRoomState : MatchRulesetRoomState { [Key(0)] - public List Teams { get; set; } + public List Teams { get; set; } = new List(); } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs index b35cfd3cdd..0880787a5a 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs @@ -3,6 +3,8 @@ using MessagePack; +#nullable enable + namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs { public class TeamVsMatchUserState : MatchRulesetUserState From c023ce78d79a1dad4da6fc6138cdb02940237691 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 18:48:32 +0900 Subject: [PATCH 182/600] Match osu!stable taiko playfield size at 16:9 --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 46dafc3a30..0d9e08b8b7 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// Default height of a when inside a . /// - public const float DEFAULT_HEIGHT = 178; + public const float DEFAULT_HEIGHT = 212; private Container hitExplosionContainer; private Container kiaiExplosionContainer; From 867426441e98dbcd9a3af0cba8ec1545b1e00258 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 17:58:50 +0900 Subject: [PATCH 183/600] Fix weird access to room via `Client` --- .../OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs index baf9570209..2a40a61257 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs @@ -99,7 +99,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match break; } - bool enableButton = Client.Room?.State == MultiplayerRoomState.Open && !operationInProgress.Value; + bool enableButton = Room?.State == MultiplayerRoomState.Open && !operationInProgress.Value; // When the local user is the host and spectating the match, the "start match" state should be enabled if any users are ready. if (localUser?.State == MultiplayerUserState.Spectating) From 359eb9c4ec81d700d53ae156a81d02272acd0415 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 18:10:38 +0900 Subject: [PATCH 184/600] Add new event flow for match ruleset state handling I'm totally not happy with how this is done, but don't have the energy to rewrite everything just now. --- .../Online/Multiplayer/MultiplayerClient.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 225d86ed9c..deac736b80 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -424,17 +424,42 @@ namespace osu.Game.Online.Multiplayer Task IMultiplayerClient.MatchRulesetUserStateChanged(int userId, MatchRulesetUserState state) { - throw new NotImplementedException(); + if (Room == null) + return Task.CompletedTask; + + Scheduler.Add(() => + { + if (Room == null) + return; + + Room.Users.Single(u => u.UserID == userId).MatchRulesetState = state; + RoomUpdated?.Invoke(); + }, false); + + return Task.CompletedTask; } Task IMultiplayerClient.MatchRulesetRoomStateChanged(MatchRulesetRoomState state) { - throw new NotImplementedException(); + if (Room == null) + return Task.CompletedTask; + + Scheduler.Add(() => + { + if (Room == null) + return; + + Room.MatchRulesetState = state; + RoomUpdated?.Invoke(); + }); + + return Task.CompletedTask; } public Task MatchRulesetEvent(MatchRulesetServerEvent e) { - throw new NotImplementedException(); + // not used by any match rulesets just yet. + return Task.CompletedTask; } Task IMultiplayerClient.UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability) From ce92a47ec689da8765d8b8d383ab8b94aef7d06c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 18:19:46 +0900 Subject: [PATCH 185/600] Add silly event handling hookups --- osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 88d8c04c98..8137430d8e 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -56,6 +56,8 @@ namespace osu.Game.Online.Multiplayer connection.On(nameof(IMultiplayerClient.ResultsReady), ((IMultiplayerClient)this).ResultsReady); connection.On>(nameof(IMultiplayerClient.UserModsChanged), ((IMultiplayerClient)this).UserModsChanged); connection.On(nameof(IMultiplayerClient.UserBeatmapAvailabilityChanged), ((IMultiplayerClient)this).UserBeatmapAvailabilityChanged); + connection.On(nameof(IMultiplayerClient.MatchRulesetRoomStateChanged), ((IMultiplayerClient)this).MatchRulesetRoomStateChanged); + connection.On(nameof(IMultiplayerClient.MatchRulesetUserStateChanged), ((IMultiplayerClient)this).MatchRulesetUserStateChanged); }; IsConnected.BindTo(connector.IsConnected); From 4cf2c6188d3ecfd8b4e44a601941215cc78d9f82 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 19:37:47 +0900 Subject: [PATCH 186/600] Add union attributes for derived class deserialisation --- osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs | 4 +++- osu.Game/Online/Multiplayer/MatchRulesetUserState.cs | 4 +++- .../Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs index be8e54d341..773c9a55e8 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs @@ -3,6 +3,7 @@ using System; using MessagePack; +using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs; #nullable enable @@ -14,7 +15,8 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - public class MatchRulesetRoomState + [Union(0, typeof(TeamVsMatchRoomState))] + public abstract class MatchRulesetRoomState { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs index 6fa0024c3d..36eae2447e 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs @@ -3,6 +3,7 @@ using System; using MessagePack; +using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs; #nullable enable @@ -14,7 +15,8 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - public class MatchRulesetUserState + [Union(0, typeof(TeamVsMatchUserState))] + public abstract class MatchRulesetUserState { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs index 57aae6e534..338b9c965d 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs @@ -8,6 +8,7 @@ using MessagePack; namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs { + [MessagePackObject] public class TeamVsMatchRoomState : MatchRulesetRoomState { [Key(0)] From 1cd967b35129193c8adf37646118e854c375f8b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 14:37:47 +0900 Subject: [PATCH 187/600] Add signalr json type handling specification --- osu.Game/Online/HubClientConnector.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index 90049a6501..3876c8bbe6 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -150,7 +150,16 @@ namespace osu.Game.Online { // eventually we will precompile resolvers for messagepack, but this isn't working currently // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308. - builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); + builder.AddNewtonsoftJsonProtocol(options => + { + options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + options.PayloadSerializerSettings = new JsonSerializerSettings + { + // TODO: This should only be required to be `TypeNameHandling.Auto`. + // See usage in osu-server-spectator for further documentation as to why this is required. + TypeNameHandling = TypeNameHandling.All + }; + }); } var newConnection = builder.Build(); From 617ff40de763228ed652828d67a14cf462a7e000 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 14:44:51 +0900 Subject: [PATCH 188/600] Add the ability to not use MessagePack when creating a `HubConnector` --- osu.Game/Online/API/APIAccess.cs | 4 ++-- osu.Game/Online/API/DummyAPIAccess.cs | 2 +- osu.Game/Online/API/IAPIProvider.cs | 3 ++- osu.Game/Online/HubClientConnector.cs | 7 +++++-- osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 4 +++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index b35dfa11cb..f7a3f4602f 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -257,8 +257,8 @@ namespace osu.Game.Online.API this.password = password; } - public IHubClientConnector GetHubConnector(string clientName, string endpoint) => - new HubClientConnector(clientName, endpoint, this, versionHash); + public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => + new HubClientConnector(clientName, endpoint, this, versionHash, preferMessagePack); public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) { diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 52f2365165..1ba31db9fa 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -89,7 +89,7 @@ namespace osu.Game.Online.API state.Value = APIState.Offline; } - public IHubClientConnector GetHubConnector(string clientName, string endpoint) => null; + public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) { diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 3a77b9cfee..686df5c57c 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -102,7 +102,8 @@ namespace osu.Game.Online.API /// /// The name of the client this connector connects for, used for logging. /// The endpoint to the hub. - IHubClientConnector? GetHubConnector(string clientName, string endpoint); + /// + IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack = true); /// /// Create a new user account. This is a blocking operation. diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index 3876c8bbe6..6c6a217f54 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -26,6 +26,7 @@ namespace osu.Game.Online private readonly string clientName; private readonly string endpoint; private readonly string versionHash; + private readonly bool preferMessagePack; private readonly IAPIProvider api; /// @@ -51,12 +52,14 @@ namespace osu.Game.Online /// The endpoint to the hub. /// An API provider used to react to connection state changes. /// The hash representing the current game version, used for verification purposes. - public HubClientConnector(string clientName, string endpoint, IAPIProvider api, string versionHash) + /// Whether to use MessagePack for serialisation if available on this platform. + public HubClientConnector(string clientName, string endpoint, IAPIProvider api, string versionHash, bool preferMessagePack = true) { this.clientName = clientName; this.endpoint = endpoint; this.api = api; this.versionHash = versionHash; + this.preferMessagePack = preferMessagePack; apiState.BindTo(api.State); apiState.BindValueChanged(state => @@ -144,7 +147,7 @@ namespace osu.Game.Online options.Headers.Add("OsuVersionHash", versionHash); }); - if (RuntimeInfo.SupportsJIT) + if (RuntimeInfo.SupportsJIT && preferMessagePack) builder.AddMessagePackProtocol(); else { diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 8137430d8e..1dfc60312b 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -37,7 +37,9 @@ namespace osu.Game.Online.Multiplayer [BackgroundDependencyLoader] private void load(IAPIProvider api) { - connector = api.GetHubConnector(nameof(OnlineMultiplayerClient), endpoint); + // Importantly, we are intentionally not using MessagePack here to correctly support derived class serialization. + // More information on the limitations / reasoning can be found in osu-server-spectator's initialisation code. + connector = api.GetHubConnector(nameof(OnlineMultiplayerClient), endpoint, false); if (connector != null) { From c7274355a4ca9cfccbf2d2bd493efb5bc4bf4bbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 17:05:05 +0900 Subject: [PATCH 189/600] Remove `abstract` definitions from multiplayer states for now --- osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs | 2 +- osu.Game/Online/Multiplayer/MatchRulesetUserState.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs index 773c9a55e8..105bb1c281 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online.Multiplayer [Serializable] [MessagePackObject] [Union(0, typeof(TeamVsMatchRoomState))] - public abstract class MatchRulesetRoomState + public class MatchRulesetRoomState // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs index 36eae2447e..aa34cdab41 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online.Multiplayer [Serializable] [MessagePackObject] [Union(0, typeof(TeamVsMatchUserState))] - public abstract class MatchRulesetUserState + public class MatchRulesetUserState // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. { } } From d93421b9b895a138870bc50bd14cd33df175ebf4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 17:06:55 +0900 Subject: [PATCH 190/600] Expose a default `TeamVs` room state so it can be consumed by tests --- .../MatchRulesets/TeamVs/TeamVsMatchRoomState.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs index 338b9c965d..92f67e99bd 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs @@ -13,5 +13,15 @@ namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs { [Key(0)] public List Teams { get; set; } = new List(); + + public static TeamVsMatchRoomState CreateDefault() => + new TeamVsMatchRoomState + { + Teams = + { + new MultiplayerTeam { ID = 0, Name = "Team Red" }, + new MultiplayerTeam { ID = 1, Name = "Team Blue" }, + } + }; } } From 2af827f9133336fa39772758dff92d9349914b8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 19:37:45 +0900 Subject: [PATCH 191/600] Increase TimeRange max value --- osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 6ffdad211b..f8d5a6c5a9 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// The maximum span of time that may be visible by the length of the scrolling axes. /// - private const double time_span_max = 10000; + private const double time_span_max = 20000; /// /// The step increase/decrease of the span of time visible by the length of the scrolling axes. From 9327bc169b9449828373786f2a00afbc069a2c31 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 19:39:30 +0900 Subject: [PATCH 192/600] Make TaikoModClassic use classic-like scroll speed --- .../Mods/TaikoModClassic.cs | 22 ++++++++++++++++++- .../UI/DrawableTaikoRuleset.cs | 5 ++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index 5a4d18be98..6520517039 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -2,10 +2,30 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.UI; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModClassic : ModClassic + public class TaikoModClassic : ModClassic, IApplicableToDrawableRuleset, IUpdatableByPlayfield { + private DrawableTaikoRuleset drawableTaikoRuleset; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset; + } + + public void Update(Playfield playfield) + { + // Classic taiko scrolls at a constant 100px per 1000ms. More notes become visible as the playfield is lengthened. + const float scroll_rate = 10; + + // Since the time range will depend on a positional value, it is referenced to the x480 pixel space. + float ratio = drawableTaikoRuleset.DrawHeight / 480; + + drawableTaikoRuleset.TimeRange.Value = (playfield.HitObjectContainer.DrawWidth / ratio) * scroll_rate; + } } } diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index ed8e6859a2..650ce1f5a3 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; @@ -24,12 +25,14 @@ namespace osu.Game.Rulesets.Taiko.UI { public class DrawableTaikoRuleset : DrawableScrollingRuleset { - private SkinnableDrawable scroller; + public new BindableDouble TimeRange => base.TimeRange; protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; protected override bool UserScrollSpeedAdjustment => false; + private SkinnableDrawable scroller; + public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { From 455666ed94af154106caad62e3a5a5fe0316ace9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 20:18:01 +0900 Subject: [PATCH 193/600] Remove taiko HD mod 4:3 scaling --- .../Mods/TaikoModHidden.cs | 30 +------------------ 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs index 0fd3625a93..8406ab8505 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -17,18 +17,6 @@ namespace osu.Game.Rulesets.Taiko.Mods public override string Description => @"Beats fade out before you hit them!"; public override double ScoreMultiplier => 1.06; - /// - /// In osu-stable, the hit position is 160, so the active playfield is essentially 160 pixels shorter - /// than the actual screen width. The normalized playfield height is 480, so on a 4:3 screen the - /// playfield ratio of the active area up to the hit position will actually be (640 - 160) / 480 = 1. - /// For custom resolutions/aspect ratios (x:y), the screen width given the normalized height becomes 480 * x / y instead, - /// and the playfield ratio becomes (480 * x / y - 160) / 480 = x / y - 1/3. - /// This constant is equal to the playfield ratio on 4:3 screens divided by the playfield ratio on 16:9 screens. - /// - private const double hd_sv_scale = (4.0 / 3.0 - 1.0 / 3.0) / (16.0 / 9.0 - 1.0 / 3.0); - - private double originalSliderMultiplier; - private ControlPointInfo controlPointInfo; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) @@ -41,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Mods double beatLength = controlPointInfo.TimingPointAt(position).BeatLength; double speedMultiplier = controlPointInfo.DifficultyPointAt(position).SpeedMultiplier; - return originalSliderMultiplier * speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength; + return speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength; } protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) @@ -69,22 +57,6 @@ namespace osu.Game.Rulesets.Taiko.Mods } } - public void ReadFromDifficulty(BeatmapDifficulty difficulty) - { - } - - public void ApplyToDifficulty(BeatmapDifficulty difficulty) - { - // needs to be read after all processing has been run (TaikoBeatmapConverter applies an adjustment which would otherwise be omitted). - originalSliderMultiplier = difficulty.SliderMultiplier; - - // osu-stable has an added playfield cover that essentially forces a 4:3 playfield ratio, by cutting off all objects past that size. - // This is not yet implemented; instead a playfield adjustment container is present which maintains a 16:9 ratio. - // For now, increase the slider multiplier proportionally so that the notes stay on the screen for the same amount of time as on stable. - // Note that this means that the notes will scroll faster as they have a longer distance to travel on the screen in that same amount of time. - difficulty.SliderMultiplier /= hd_sv_scale; - } - public override void ApplyToBeatmap(IBeatmap beatmap) { controlPointInfo = beatmap.ControlPointInfo; From 8d999d30f6de986ac8758a9983a6c400606fb3b6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Aug 2021 20:38:46 +0900 Subject: [PATCH 194/600] Remove interface definition --- osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs index 8406ab8505..a6b3fe1cd9 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModHidden : ModHidden, IApplicableToDifficulty + public class TaikoModHidden : ModHidden { public override string Description => @"Beats fade out before you hit them!"; public override double ScoreMultiplier => 1.06; From 2564c0c3df5855beb76ca74b45b2501bd91202f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 14:46:31 +0900 Subject: [PATCH 195/600] Rename `GameType` to `MatchType` and make `enum` instead of `class` --- osu.Game/Online/Rooms/GameType.cs | 18 --- .../Rooms/GameTypes/GameTypePlaylists.cs | 25 --- .../Online/Rooms/GameTypes/GameTypeTag.cs | 28 ---- .../Online/Rooms/GameTypes/GameTypeTagTeam.cs | 45 ------ .../Rooms/GameTypes/GameTypeTeamVersus.cs | 32 ---- .../Online/Rooms/GameTypes/GameTypeVersus.cs | 22 --- osu.Game/Online/Rooms/GameTypes/VersusRow.cs | 55 ------- osu.Game/Online/Rooms/MatchType.cs | 18 +++ osu.Game/Online/Rooms/Room.cs | 3 +- .../OnlinePlay/Components/DrawableGameType.cs | 142 +++++++++++++++++- .../Match/Components/GameTypePicker.cs | 16 +- .../Match/MultiplayerMatchSettingsOverlay.cs | 3 +- .../Screens/OnlinePlay/OnlinePlayComposite.cs | 2 +- 13 files changed, 165 insertions(+), 244 deletions(-) delete mode 100644 osu.Game/Online/Rooms/GameType.cs delete mode 100644 osu.Game/Online/Rooms/GameTypes/GameTypePlaylists.cs delete mode 100644 osu.Game/Online/Rooms/GameTypes/GameTypeTag.cs delete mode 100644 osu.Game/Online/Rooms/GameTypes/GameTypeTagTeam.cs delete mode 100644 osu.Game/Online/Rooms/GameTypes/GameTypeTeamVersus.cs delete mode 100644 osu.Game/Online/Rooms/GameTypes/GameTypeVersus.cs delete mode 100644 osu.Game/Online/Rooms/GameTypes/VersusRow.cs create mode 100644 osu.Game/Online/Rooms/MatchType.cs diff --git a/osu.Game/Online/Rooms/GameType.cs b/osu.Game/Online/Rooms/GameType.cs deleted file mode 100644 index caa352d812..0000000000 --- a/osu.Game/Online/Rooms/GameType.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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.Graphics; -using osu.Game.Graphics; - -namespace osu.Game.Online.Rooms -{ - public abstract class GameType - { - public abstract string Name { get; } - - public abstract Drawable GetIcon(OsuColour colours, float size); - - public override int GetHashCode() => GetType().GetHashCode(); - public override bool Equals(object obj) => GetType() == obj?.GetType(); - } -} diff --git a/osu.Game/Online/Rooms/GameTypes/GameTypePlaylists.cs b/osu.Game/Online/Rooms/GameTypes/GameTypePlaylists.cs deleted file mode 100644 index 3425c6c5cd..0000000000 --- a/osu.Game/Online/Rooms/GameTypes/GameTypePlaylists.cs +++ /dev/null @@ -1,25 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osuTK; - -namespace osu.Game.Online.Rooms.GameTypes -{ - public class GameTypePlaylists : GameType - { - public override string Name => "Playlists"; - - public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = FontAwesome.Regular.Clock, - Size = new Vector2(size), - Colour = colours.Blue, - Shadow = false - }; - } -} diff --git a/osu.Game/Online/Rooms/GameTypes/GameTypeTag.cs b/osu.Game/Online/Rooms/GameTypes/GameTypeTag.cs deleted file mode 100644 index e468612738..0000000000 --- a/osu.Game/Online/Rooms/GameTypes/GameTypeTag.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osuTK; - -namespace osu.Game.Online.Rooms.GameTypes -{ - public class GameTypeTag : GameType - { - public override string Name => "Tag"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = FontAwesome.Solid.Sync, - Size = new Vector2(size), - Colour = colours.Blue, - Shadow = false, - }; - } - } -} diff --git a/osu.Game/Online/Rooms/GameTypes/GameTypeTagTeam.cs b/osu.Game/Online/Rooms/GameTypes/GameTypeTagTeam.cs deleted file mode 100644 index b82f203fac..0000000000 --- a/osu.Game/Online/Rooms/GameTypes/GameTypeTagTeam.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osuTK; - -namespace osu.Game.Online.Rooms.GameTypes -{ - public class GameTypeTagTeam : GameType - { - public override string Name => "Tag Team"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(2f), - Children = new[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.Sync, - Size = new Vector2(size * 0.75f), - Colour = colours.Blue, - Shadow = false, - }, - new SpriteIcon - { - Icon = FontAwesome.Solid.Sync, - Size = new Vector2(size * 0.75f), - Colour = colours.Pink, - Shadow = false, - }, - }, - }; - } - } -} diff --git a/osu.Game/Online/Rooms/GameTypes/GameTypeTeamVersus.cs b/osu.Game/Online/Rooms/GameTypes/GameTypeTeamVersus.cs deleted file mode 100644 index 5ad4033dc9..0000000000 --- a/osu.Game/Online/Rooms/GameTypes/GameTypeTeamVersus.cs +++ /dev/null @@ -1,32 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osuTK; - -namespace osu.Game.Online.Rooms.GameTypes -{ - public class GameTypeTeamVersus : GameType - { - public override string Name => "Team Versus"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(2f), - Children = new[] - { - new VersusRow(colours.Blue, colours.Pink, size * 0.5f), - new VersusRow(colours.Blue, colours.Pink, size * 0.5f), - }, - }; - } - } -} diff --git a/osu.Game/Online/Rooms/GameTypes/GameTypeVersus.cs b/osu.Game/Online/Rooms/GameTypes/GameTypeVersus.cs deleted file mode 100644 index 3783cc67b0..0000000000 --- a/osu.Game/Online/Rooms/GameTypes/GameTypeVersus.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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.Graphics; -using osu.Game.Graphics; - -namespace osu.Game.Online.Rooms.GameTypes -{ - public class GameTypeVersus : GameType - { - public override string Name => "Versus"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new VersusRow(colours.Blue, colours.Blue, size * 0.6f) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; - } - } -} diff --git a/osu.Game/Online/Rooms/GameTypes/VersusRow.cs b/osu.Game/Online/Rooms/GameTypes/VersusRow.cs deleted file mode 100644 index 0bd09a23ac..0000000000 --- a/osu.Game/Online/Rooms/GameTypes/VersusRow.cs +++ /dev/null @@ -1,55 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Online.Rooms.GameTypes -{ - public class VersusRow : FillFlowContainer - { - public VersusRow(Color4 first, Color4 second, float size) - { - var triangleSize = new Vector2(size); - AutoSizeAxes = Axes.Both; - Spacing = new Vector2(2f, 0f); - - Children = new[] - { - new Container - { - Size = triangleSize, - Colour = first, - Children = new[] - { - new EquilateralTriangle - { - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, - Rotation = 90, - EdgeSmoothness = new Vector2(1f), - }, - }, - }, - new Container - { - Size = triangleSize, - Colour = second, - Children = new[] - { - new EquilateralTriangle - { - Anchor = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, - Rotation = -90, - EdgeSmoothness = new Vector2(1f), - }, - }, - }, - }; - } - } -} diff --git a/osu.Game/Online/Rooms/MatchType.cs b/osu.Game/Online/Rooms/MatchType.cs new file mode 100644 index 0000000000..cafa147a61 --- /dev/null +++ b/osu.Game/Online/Rooms/MatchType.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.ComponentModel; + +namespace osu.Game.Online.Rooms +{ + public enum MatchType + { + Playlists, + + [Description("Head to head")] + HeadToHead, + + [Description("Team VS")] + TeamVersus, + } +} diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 4c506e26a8..fe7455d964 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -7,7 +7,6 @@ using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.IO.Serialization.Converters; -using osu.Game.Online.Rooms.GameTypes; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Users; using osu.Game.Utils; @@ -63,7 +62,7 @@ namespace osu.Game.Online.Rooms [Cached] [JsonIgnore] - public readonly Bindable Type = new Bindable(new GameTypePlaylists()); + public readonly Bindable Type = new Bindable(); [Cached] [JsonIgnore] diff --git a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs index ae1ca1b967..613f16563c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs @@ -2,24 +2,28 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Online.Rooms; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Components { public class DrawableGameType : CircularContainer, IHasTooltip { - private readonly GameType type; + private readonly MatchType type; - public LocalisableString TooltipText => type.Name; + public LocalisableString TooltipText => type.GetLocalisableDescription(); - public DrawableGameType(GameType type) + public DrawableGameType(MatchType type) { this.type = type; Masking = true; @@ -34,10 +38,138 @@ namespace osu.Game.Screens.OnlinePlay.Components }; } + [Resolved] + private OsuColour colours { get; set; } + [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - Add(type.GetIcon(colours, Height / 2)); + Add(getIconFor(type)); + } + + private Drawable getIconFor(MatchType matchType) + { + float size = Height / 2; + + switch (matchType) + { + default: + case MatchType.Playlists: + return new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(size), + Icon = FontAwesome.Regular.Clock, + Colour = colours.Blue, + Shadow = false + }; + + case MatchType.HeadToHead: + return new VersusRow(colours.Blue, colours.Blue, size * 0.6f) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + + case MatchType.TeamVersus: + return new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2f), + Children = new[] + { + new VersusRow(colours.Blue, colours.Pink, size * 0.5f), + new VersusRow(colours.Blue, colours.Pink, size * 0.5f), + }, + }; + + // case MatchType.TagCoop: + // return new SpriteIcon + // { + // Anchor = Anchor.Centre, + // Origin = Anchor.Centre, + // Size = new Vector2(size), + // Icon = FontAwesome.Solid.Sync, + // Colour = colours.Blue, + // + // Shadow = false + // }; + + // case MatchType.TagTeamCoop: + // return new FillFlowContainer + // { + // Anchor = Anchor.Centre, + // Origin = Anchor.Centre, + // AutoSizeAxes = Axes.Both, + // Direction = FillDirection.Horizontal, + // Spacing = new Vector2(2f), + // Children = new[] + // { + // new SpriteIcon + // { + // Icon = FontAwesome.Solid.Sync, + // Size = new Vector2(size * 0.75f), + // Colour = colours.Blue, + // Shadow = false, + // }, + // new SpriteIcon + // { + // Icon = FontAwesome.Solid.Sync, + // Size = new Vector2(size * 0.75f), + // Colour = colours.Pink, + // Shadow = false, + // }, + // }, + // }; + } + } + + private class VersusRow : FillFlowContainer + { + public VersusRow(Color4 first, Color4 second, float size) + { + var triangleSize = new Vector2(size); + AutoSizeAxes = Axes.Both; + Spacing = new Vector2(2f, 0f); + + Children = new[] + { + new Container + { + Size = triangleSize, + Colour = first, + Children = new[] + { + new EquilateralTriangle + { + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Rotation = 90, + EdgeSmoothness = new Vector2(1f), + }, + }, + }, + new Container + { + Size = triangleSize, + Colour = second, + Children = new[] + { + new EquilateralTriangle + { + Anchor = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Rotation = -90, + EdgeSmoothness = new Vector2(1f), + }, + }, + }, + }; + } } } } diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs index cca1f84bbb..864a9bc4d7 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs @@ -9,31 +9,27 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Rooms; -using osu.Game.Online.Rooms.GameTypes; using osu.Game.Screens.OnlinePlay.Components; using osuTK; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class GameTypePicker : DisableableTabControl + public class GameTypePicker : DisableableTabControl { private const float height = 40; private const float selection_width = 3; - protected override TabItem CreateTabItem(GameType value) => new GameTypePickerItem(value); + protected override TabItem CreateTabItem(MatchType value) => new GameTypePickerItem(value); - protected override Dropdown CreateDropdown() => null; + protected override Dropdown CreateDropdown() => null; public GameTypePicker() { Height = height + selection_width * 2; TabContainer.Spacing = new Vector2(10 - selection_width * 2); - AddItem(new GameTypeTag()); - AddItem(new GameTypeVersus()); - AddItem(new GameTypeTagTeam()); - AddItem(new GameTypeTeamVersus()); - AddItem(new GameTypePlaylists()); + AddItem(MatchType.HeadToHead); + AddItem(MatchType.TeamVersus); } private class GameTypePickerItem : DisableableTabItem @@ -42,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components private readonly CircularContainer hover, selection; - public GameTypePickerItem(GameType value) + public GameTypePickerItem(MatchType value) : base(value) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 338d2c9e84..3dfbeac411 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Graphics; @@ -265,7 +266,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match loadingLayer = new LoadingLayer(true) }; - TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true); + TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue.GetLocalisableDescription(), true); RoomName.BindValueChanged(name => NameField.Text = name.NewValue, true); Availability.BindValueChanged(availability => AvailabilityPicker.Current.Value = availability.NewValue, true); Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 0b28bc1a7e..49524660db 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay protected Bindable Status { get; private set; } [Resolved(typeof(Room))] - protected Bindable Type { get; private set; } + protected Bindable Type { get; private set; } [Resolved(typeof(Room))] protected BindableList Playlist { get; private set; } From 556962a3d881fe7a4f50ef8092432af19303521b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 14:50:56 +0900 Subject: [PATCH 196/600] Add missing xmldoc comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Online/API/IAPIProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 686df5c57c..5ad5367924 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -102,7 +102,7 @@ namespace osu.Game.Online.API /// /// The name of the client this connector connects for, used for logging. /// The endpoint to the hub. - /// + /// Whether to use MessagePack for serialisation if available on this platform. IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack = true); /// From 5ac3abac99befc092b6e92d5489b7b8dfc4e0759 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 14:53:04 +0900 Subject: [PATCH 197/600] Add missing `forceScheduled` parameter --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index deac736b80..5220db16b5 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -451,7 +451,7 @@ namespace osu.Game.Online.Multiplayer Room.MatchRulesetState = state; RoomUpdated?.Invoke(); - }); + }, false); return Task.CompletedTask; } From ee102e3755b0a15d7fd6af3be1e9de2b3beb09a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 14:55:20 +0900 Subject: [PATCH 198/600] Fix incorrectly overwritten `ReferenceLoopHandling` setting --- osu.Game/Online/HubClientConnector.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index 6c6a217f54..d2dba8a402 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -156,12 +156,9 @@ namespace osu.Game.Online builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - options.PayloadSerializerSettings = new JsonSerializerSettings - { - // TODO: This should only be required to be `TypeNameHandling.Auto`. - // See usage in osu-server-spectator for further documentation as to why this is required. - TypeNameHandling = TypeNameHandling.All - }; + // TODO: This should only be required to be `TypeNameHandling.Auto`. + // See usage in osu-server-spectator for further documentation as to why this is required. + options.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.All; }); } From 66427127f0f48bcbce56a4b8fb4eee40e2775128 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 15:09:03 +0900 Subject: [PATCH 199/600] Update naming in line with discussion --- osu.Game/Online/Multiplayer/MatchRulesetType.cs | 11 ----------- .../Online/Multiplayer/MultiplayerRoomSettings.cs | 3 ++- osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs | 6 +++--- 3 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 osu.Game/Online/Multiplayer/MatchRulesetType.cs diff --git a/osu.Game/Online/Multiplayer/MatchRulesetType.cs b/osu.Game/Online/Multiplayer/MatchRulesetType.cs deleted file mode 100644 index b87a8eb174..0000000000 --- a/osu.Game/Online/Multiplayer/MatchRulesetType.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Online.Multiplayer -{ - public enum MatchRulesetType - { - HeadToHead, - TeamVs - } -} diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index 2c49e3b251..f76ab5da89 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using MessagePack; using osu.Game.Online.API; +using osu.Game.Online.Rooms; namespace osu.Game.Online.Multiplayer { @@ -40,7 +41,7 @@ namespace osu.Game.Online.Multiplayer public string Password { get; set; } = string.Empty; [Key(8)] - public MatchRulesetType MatchRulesetType { get; set; } + public MatchType MatchRulesetType { get; set; } public bool Equals(MultiplayerRoomSettings other) => BeatmapID == other.BeatmapID diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index d97d49aa8a..96e9a7fd4a 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -24,6 +24,9 @@ namespace osu.Game.Online.Multiplayer [Key(1)] public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle; + [Key(4)] + public MatchRulesetUserState? MatchRulesetState { get; set; } + /// /// The availability state of the current beatmap. /// @@ -36,9 +39,6 @@ namespace osu.Game.Online.Multiplayer [Key(3)] public IEnumerable Mods { get; set; } = Enumerable.Empty(); - [Key(4)] - public MatchRulesetUserState? MatchRulesetState { get; set; } - [IgnoreMember] public User? User { get; set; } From 70da58323a3781cd83fb8f462351ce8026523d6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 15:43:04 +0900 Subject: [PATCH 200/600] Drop `MatchRuleset` terminology completely --- osu.Game/Online/Multiplayer/IMultiplayerClient.cs | 12 ++++++------ .../Online/Multiplayer/IMultiplayerRoomServer.cs | 4 ++-- ...{MatchRulesetRoomState.cs => MatchRoomState.cs} | 9 +++++---- ...chRulesetServerEvent.cs => MatchServerEvent.cs} | 2 +- .../TeamVersus}/ChangeTeamRequest.cs | 4 ++-- .../TeamVersus}/MultiplayerTeam.cs | 2 +- .../TeamVersus/TeamVersusRoomState.cs} | 8 ++++---- .../TeamVersus/TeamVersusUserState.cs} | 4 ++-- ...chRulesetUserRequest.cs => MatchUserRequest.cs} | 4 ++-- ...{MatchRulesetUserState.cs => MatchUserState.cs} | 9 +++++---- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 14 +++++++------- osu.Game/Online/Multiplayer/MultiplayerRoom.cs | 2 +- .../Online/Multiplayer/MultiplayerRoomSettings.cs | 6 +++--- osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs | 2 +- .../Online/Multiplayer/OnlineMultiplayerClient.cs | 8 ++++---- .../Visual/Multiplayer/TestMultiplayerClient.cs | 2 +- 16 files changed, 47 insertions(+), 45 deletions(-) rename osu.Game/Online/Multiplayer/{MatchRulesetRoomState.cs => MatchRoomState.cs} (56%) rename osu.Game/Online/Multiplayer/{MatchRulesetServerEvent.cs => MatchServerEvent.cs} (89%) rename osu.Game/Online/Multiplayer/{MatchRulesets/TeamVs => MatchTypes/TeamVersus}/ChangeTeamRequest.cs (68%) rename osu.Game/Online/Multiplayer/{MatchRulesets/TeamVs => MatchTypes/TeamVersus}/MultiplayerTeam.cs (87%) rename osu.Game/Online/Multiplayer/{MatchRulesets/TeamVs/TeamVsMatchRoomState.cs => MatchTypes/TeamVersus/TeamVersusRoomState.cs} (73%) rename osu.Game/Online/Multiplayer/{MatchRulesets/TeamVs/TeamVsMatchUserState.cs => MatchTypes/TeamVersus/TeamVersusUserState.cs} (68%) rename osu.Game/Online/Multiplayer/{MatchRulesetUserRequest.cs => MatchUserRequest.cs} (83%) rename osu.Game/Online/Multiplayer/{MatchRulesetUserState.cs => MatchUserState.cs} (56%) diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 839ec9bd1f..064065ab00 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -51,23 +51,23 @@ namespace osu.Game.Online.Multiplayer Task UserStateChanged(int userId, MultiplayerUserState state); /// - /// Signals that the match ruleset state has changed for a user in this room. + /// Signals that the match type state has changed for a user in this room. /// /// The ID of the user performing a state change. /// The new state of the user. - Task MatchRulesetUserStateChanged(int userId, MatchRulesetUserState state); + Task MatchUserStateChanged(int userId, MatchUserState state); /// - /// Signals that the match ruleset state has changed for this room. + /// Signals that the match type state has changed for this room. /// /// The new state of the room. - Task MatchRulesetRoomStateChanged(MatchRulesetRoomState state); + Task MatchRoomStateChanged(MatchRoomState state); /// - /// Send a match ruleset specific request. + /// Send a match type specific request. /// /// The event to handle. - Task MatchRulesetEvent(MatchRulesetServerEvent e); + Task MatchEvent(MatchServerEvent e); /// /// Signals that a user in this room changed their beatmap availability state. diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index 20c9f9e216..b26c4d8201 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -56,10 +56,10 @@ namespace osu.Game.Online.Multiplayer Task ChangeUserMods(IEnumerable newMods); /// - /// Send a match ruleset specific request. + /// Send a match type specific request. /// /// The request to send. - Task SendMatchRulesetRequest(MatchRulesetUserRequest request); + Task SendMatchRequest(MatchUserRequest request); /// /// As the host of a room, start the match. diff --git a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs b/osu.Game/Online/Multiplayer/MatchRoomState.cs similarity index 56% rename from osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs rename to osu.Game/Online/Multiplayer/MatchRoomState.cs index 105bb1c281..5b662af100 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRoomState.cs @@ -3,20 +3,21 @@ using System; using MessagePack; -using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; #nullable enable namespace osu.Game.Online.Multiplayer { /// - /// Room-wide state for the current match ruleset. + /// Room-wide state for the current match type. /// Can be used to contain any state which should be used before or during match gameplay. /// [Serializable] [MessagePackObject] - [Union(0, typeof(TeamVsMatchRoomState))] - public class MatchRulesetRoomState // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. + [Union(0, typeof(TeamVersusRoomState))] + // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. + public class MatchRoomState { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs b/osu.Game/Online/Multiplayer/MatchServerEvent.cs similarity index 89% rename from osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs rename to osu.Game/Online/Multiplayer/MatchServerEvent.cs index c45615e914..891fb2cc3b 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetServerEvent.cs +++ b/osu.Game/Online/Multiplayer/MatchServerEvent.cs @@ -11,7 +11,7 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - public abstract class MatchRulesetServerEvent + public abstract class MatchServerEvent { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs similarity index 68% rename from osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs rename to osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs index 5e1d489d39..9c3b07049c 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/ChangeTeamRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs @@ -5,9 +5,9 @@ using MessagePack; #nullable enable -namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { - public class ChangeTeamRequest : MatchRulesetUserRequest + public class ChangeTeamRequest : MatchUserRequest { [Key(0)] public int TeamID { get; set; } diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs similarity index 87% rename from osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs rename to osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs index f6bf893818..f952dbc1b5 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/MultiplayerTeam.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs @@ -6,7 +6,7 @@ using MessagePack; #nullable enable -namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { [Serializable] [MessagePackObject] diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs similarity index 73% rename from osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs rename to osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs index 92f67e99bd..91d1aa43d4 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs @@ -6,16 +6,16 @@ using MessagePack; #nullable enable -namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { [MessagePackObject] - public class TeamVsMatchRoomState : MatchRulesetRoomState + public class TeamVersusRoomState : MatchRoomState { [Key(0)] public List Teams { get; set; } = new List(); - public static TeamVsMatchRoomState CreateDefault() => - new TeamVsMatchRoomState + public static TeamVersusRoomState CreateDefault() => + new TeamVersusRoomState { Teams = { diff --git a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs similarity index 68% rename from osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs rename to osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs index 0880787a5a..96a4e2ea99 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesets/TeamVs/TeamVsMatchUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs @@ -5,9 +5,9 @@ using MessagePack; #nullable enable -namespace osu.Game.Online.Multiplayer.MatchRulesets.TeamVs +namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { - public class TeamVsMatchUserState : MatchRulesetUserState + public class TeamVersusUserState : MatchUserState { [Key(0)] public int TeamID { get; set; } diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs b/osu.Game/Online/Multiplayer/MatchUserRequest.cs similarity index 83% rename from osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs rename to osu.Game/Online/Multiplayer/MatchUserRequest.cs index 3cc430a2b7..15c3ad0776 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetUserRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchUserRequest.cs @@ -7,11 +7,11 @@ using MessagePack; namespace osu.Game.Online.Multiplayer { /// - /// A request from a user to perform an action specific to the current match ruleset. + /// A request from a user to perform an action specific to the current match type. /// [Serializable] [MessagePackObject] - public abstract class MatchRulesetUserRequest + public abstract class MatchUserRequest { } } diff --git a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs b/osu.Game/Online/Multiplayer/MatchUserState.cs similarity index 56% rename from osu.Game/Online/Multiplayer/MatchRulesetUserState.cs rename to osu.Game/Online/Multiplayer/MatchUserState.cs index aa34cdab41..f457191bb5 100644 --- a/osu.Game/Online/Multiplayer/MatchRulesetUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchUserState.cs @@ -3,20 +3,21 @@ using System; using MessagePack; -using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; #nullable enable namespace osu.Game.Online.Multiplayer { /// - /// User specific state for the current match ruleset. + /// User specific state for the current match type. /// Can be used to contain any state which should be used before or during match gameplay. /// [Serializable] [MessagePackObject] - [Union(0, typeof(TeamVsMatchUserState))] - public class MatchRulesetUserState // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. + [Union(0, typeof(TeamVersusUserState))] + // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. + public class MatchUserState { } } diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 5220db16b5..873be7f49c 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -293,7 +293,7 @@ namespace osu.Game.Online.Multiplayer public abstract Task ChangeUserMods(IEnumerable newMods); - public abstract Task SendMatchRulesetRequest(MatchRulesetUserRequest request); + public abstract Task SendMatchRequest(MatchUserRequest request); public abstract Task StartMatch(); @@ -422,7 +422,7 @@ namespace osu.Game.Online.Multiplayer return Task.CompletedTask; } - Task IMultiplayerClient.MatchRulesetUserStateChanged(int userId, MatchRulesetUserState state) + Task IMultiplayerClient.MatchUserStateChanged(int userId, MatchUserState state) { if (Room == null) return Task.CompletedTask; @@ -432,14 +432,14 @@ namespace osu.Game.Online.Multiplayer if (Room == null) return; - Room.Users.Single(u => u.UserID == userId).MatchRulesetState = state; + Room.Users.Single(u => u.UserID == userId).MatchState = state; RoomUpdated?.Invoke(); }, false); return Task.CompletedTask; } - Task IMultiplayerClient.MatchRulesetRoomStateChanged(MatchRulesetRoomState state) + Task IMultiplayerClient.MatchRoomStateChanged(MatchRoomState state) { if (Room == null) return Task.CompletedTask; @@ -449,16 +449,16 @@ namespace osu.Game.Online.Multiplayer if (Room == null) return; - Room.MatchRulesetState = state; + Room.MatchState = state; RoomUpdated?.Invoke(); }, false); return Task.CompletedTask; } - public Task MatchRulesetEvent(MatchRulesetServerEvent e) + public Task MatchEvent(MatchServerEvent e) { - // not used by any match rulesets just yet. + // not used by any match types just yet. return Task.CompletedTask; } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs index 07d87fafc3..175c0e0e27 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs @@ -48,7 +48,7 @@ namespace osu.Game.Online.Multiplayer public MultiplayerRoomUser? Host { get; set; } [Key(5)] - public MatchRulesetRoomState? MatchRulesetState { get; set; } + public MatchRoomState? MatchState { get; set; } [JsonConstructor] [SerializationConstructor] diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index f76ab5da89..706bc750d3 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -41,7 +41,7 @@ namespace osu.Game.Online.Multiplayer public string Password { get; set; } = string.Empty; [Key(8)] - public MatchType MatchRulesetType { get; set; } + public MatchType MatchType { get; set; } public bool Equals(MultiplayerRoomSettings other) => BeatmapID == other.BeatmapID @@ -52,7 +52,7 @@ namespace osu.Game.Online.Multiplayer && Password.Equals(other.Password, StringComparison.Ordinal) && Name.Equals(other.Name, StringComparison.Ordinal) && PlaylistItemId == other.PlaylistItemId - && MatchRulesetType == other.MatchRulesetType; + && MatchType == other.MatchType; public override string ToString() => $"Name:{Name}" + $" Beatmap:{BeatmapID} ({BeatmapChecksum})" @@ -60,7 +60,7 @@ namespace osu.Game.Online.Multiplayer + $" AllowedMods:{string.Join(',', AllowedMods)}" + $" Password:{(string.IsNullOrEmpty(Password) ? "no" : "yes")}" + $" Ruleset:{RulesetID}" - + $" MatchRuleset:{MatchRulesetType}" + + $" Type:{MatchType}" + $" Item:{PlaylistItemId}"; } } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index 96e9a7fd4a..5d11e2921a 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -25,7 +25,7 @@ namespace osu.Game.Online.Multiplayer public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle; [Key(4)] - public MatchRulesetUserState? MatchRulesetState { get; set; } + public MatchUserState? MatchState { get; set; } /// /// The availability state of the current beatmap. diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 1dfc60312b..00f30463a5 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -58,8 +58,8 @@ namespace osu.Game.Online.Multiplayer connection.On(nameof(IMultiplayerClient.ResultsReady), ((IMultiplayerClient)this).ResultsReady); connection.On>(nameof(IMultiplayerClient.UserModsChanged), ((IMultiplayerClient)this).UserModsChanged); connection.On(nameof(IMultiplayerClient.UserBeatmapAvailabilityChanged), ((IMultiplayerClient)this).UserBeatmapAvailabilityChanged); - connection.On(nameof(IMultiplayerClient.MatchRulesetRoomStateChanged), ((IMultiplayerClient)this).MatchRulesetRoomStateChanged); - connection.On(nameof(IMultiplayerClient.MatchRulesetUserStateChanged), ((IMultiplayerClient)this).MatchRulesetUserStateChanged); + connection.On(nameof(IMultiplayerClient.MatchRoomStateChanged), ((IMultiplayerClient)this).MatchRoomStateChanged); + connection.On(nameof(IMultiplayerClient.MatchUserStateChanged), ((IMultiplayerClient)this).MatchUserStateChanged); }; IsConnected.BindTo(connector.IsConnected); @@ -122,12 +122,12 @@ namespace osu.Game.Online.Multiplayer return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeUserMods), newMods); } - public override Task SendMatchRulesetRequest(MatchRulesetUserRequest request) + public override Task SendMatchRequest(MatchUserRequest request) { if (!IsConnected.Value) return Task.CompletedTask; - return connection.InvokeAsync(nameof(IMultiplayerServer.SendMatchRulesetRequest), request); + return connection.InvokeAsync(nameof(IMultiplayerServer.SendMatchRequest), request); } public override Task StartMatch() diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 6a8bf87ff0..7deecdfa28 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -192,7 +192,7 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.CompletedTask; } - public override Task SendMatchRulesetRequest(MatchRulesetUserRequest request) => Task.CompletedTask; + public override Task SendMatchRequest(MatchUserRequest request) => Task.CompletedTask; public override Task StartMatch() { From 8d1586261d47f3738e91adc37dc287746edf4887 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 15:59:13 +0900 Subject: [PATCH 201/600] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c1075cfb17..b01210a7b1 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7e32f1e9fd..b3eeaa4be7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7b7d5f80fe..7ad27b222c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 404faabbbc5d77f5497628fa5968ebb0081131e2 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Tue, 3 Aug 2021 15:34:21 +0800 Subject: [PATCH 202/600] Use direct reference instead --- .../NamedOverlayComponentStrings.cs | 22 ------------------- .../BeatmapListing/BeatmapListingHeader.cs | 3 ++- .../Overlays/BeatmapSet/BeatmapSetHeader.cs | 4 ++-- .../Overlays/Changelog/ChangelogHeader.cs | 2 +- .../Dashboard/DashboardOverlayHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 2 +- .../Rankings/RankingsOverlayHeader.cs | 3 ++- osu.Game/Overlays/Wiki/WikiHeader.cs | 2 +- 8 files changed, 10 insertions(+), 30 deletions(-) diff --git a/osu.Game/Localisation/NamedOverlayComponentStrings.cs b/osu.Game/Localisation/NamedOverlayComponentStrings.cs index f160ee57c7..475bea2a4a 100644 --- a/osu.Game/Localisation/NamedOverlayComponentStrings.cs +++ b/osu.Game/Localisation/NamedOverlayComponentStrings.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Localisation; -using osu.Game.Resources.Localisation.Web; namespace osu.Game.Localisation { @@ -10,52 +9,31 @@ namespace osu.Game.Localisation { private const string prefix = @"osu.Game.Resources.Localisation.NamedOverlayComponent"; - /// - public static LocalisableString BeatmapListingTitle => PageTitleStrings.MainBeatmapsetsControllerIndex; - /// /// "browse for new beatmaps" /// public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing_description"), @"browse for new beatmaps"); - /// - public static LocalisableString BeatmapSetTitle => PageTitleStrings.MainBeatmapsetsControllerShow; - - /// - public static LocalisableString ChangelogTitle => PageTitleStrings.MainChangelogControllerDefault; - /// /// "track recent dev updates in the osu! ecosystem" /// public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog_description"), @"track recent dev updates in the osu! ecosystem"); - /// - public static LocalisableString DashboardTitle => PageTitleStrings.MainHomeControllerIndex; - /// /// "view your friends and other information" /// public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard_description"), @"view your friends and other information"); - /// - public static LocalisableString RankingsTitle => PageTitleStrings.MainRankingControllerDefault; - /// /// "find out who's the best right now" /// public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings_description"), @"find out who's the best right now"); - /// - public static LocalisableString NewsTitle => PageTitleStrings.MainNewsControllerDefault; - /// /// "get up-to-date on community happenings" /// public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news_description"), @"get up-to-date on community happenings"); - /// - public static LocalisableString WikiTitle => PageTitleStrings.MainWikiControllerDefault; - /// /// "knowledge base" /// diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index fa2ee0d735..3568fe9e4f 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapListing { @@ -13,7 +14,7 @@ namespace osu.Game.Overlays.BeatmapListing { public BeatmapListingTitle() { - Title = NamedOverlayComponentStrings.BeatmapListingTitle; + Title = PageTitleStrings.MainBeatmapsetsControllerIndex; Description = NamedOverlayComponentStrings.BeatmapListingDescription; IconTexture = "Icons/Hexacons/beatmap"; } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs index 4fd24d9819..4a0c0e9f75 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs @@ -7,7 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; using osu.Game.Beatmaps; -using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet { public BeatmapHeaderTitle() { - Title = NamedOverlayComponentStrings.BeatmapSetTitle; + Title = PageTitleStrings.MainBeatmapsetsControllerShow; IconTexture = "Icons/Hexacons/beatmap"; } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 8707883ddd..52dea63ab7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -117,7 +117,7 @@ namespace osu.Game.Overlays.Changelog { public ChangelogHeaderTitle() { - Title = NamedOverlayComponentStrings.ChangelogTitle; + Title = PageTitleStrings.MainChangelogControllerDefault; Description = NamedOverlayComponentStrings.ChangelogDescription; IconTexture = "Icons/Hexacons/devtools"; } diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 05c9f30ff3..70991d47b7 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Dashboard { public DashboardTitle() { - Title = NamedOverlayComponentStrings.DashboardTitle; + Title = PageTitleStrings.MainHomeControllerIndex; Description = NamedOverlayComponentStrings.DashboardDescription; IconTexture = "Icons/Hexacons/social"; } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index bf739e1e8e..35e3c7755d 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.News { public NewsHeaderTitle() { - Title = NamedOverlayComponentStrings.NewsTitle; + Title = PageTitleStrings.MainNewsControllerDefault; Description = NamedOverlayComponentStrings.NewsDescription; IconTexture = "Icons/Hexacons/news"; } diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index c0f77049de..4916b8b327 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -4,6 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Users; @@ -30,7 +31,7 @@ namespace osu.Game.Overlays.Rankings { public RankingsTitle() { - Title = NamedOverlayComponentStrings.RankingsTitle; + Title = PageTitleStrings.MainRankingControllerDefault; Description = NamedOverlayComponentStrings.RankingsDescription; IconTexture = "Icons/Hexacons/rankings"; } diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index b57bffb3d8..3e81d2cffe 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Wiki { public WikiHeaderTitle() { - Title = NamedOverlayComponentStrings.WikiTitle; + Title = PageTitleStrings.MainWikiControllerDefault; Description = NamedOverlayComponentStrings.WikiDescription; IconTexture = "Icons/Hexacons/wiki"; } From 01f15bd6fc47df0bfc754d8cc3e100a7597a5d78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 17:47:53 +0900 Subject: [PATCH 203/600] Rename picker class to match new naming --- .../Components/{GameTypePicker.cs => MatchTypePicker.cs} | 4 ++-- .../Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Screens/OnlinePlay/Match/Components/{GameTypePicker.cs => MatchTypePicker.cs} (97%) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs similarity index 97% rename from osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs rename to osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs index 864a9bc4d7..c6f9b0f207 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/GameTypePicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public class GameTypePicker : DisableableTabControl + public class MatchTypePicker : DisableableTabControl { private const float height = 40; private const float selection_width = 3; @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override Dropdown CreateDropdown() => null; - public GameTypePicker() + public MatchTypePicker() { Height = height + selection_width * 2; TabContainer.Spacing = new Vector2(10 - selection_width * 2); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 3dfbeac411..425252f3cf 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match public OsuTextBox NameField, MaxParticipantsField; public RoomAvailabilityPicker AvailabilityPicker; - public GameTypePicker TypePicker; + public MatchTypePicker TypePicker; public OsuTextBox PasswordTextBox; public TriangleButton ApplyButton; @@ -158,7 +158,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match Spacing = new Vector2(7), Children = new Drawable[] { - TypePicker = new GameTypePicker + TypePicker = new MatchTypePicker { RelativeSizeAxes = Axes.X, Enabled = { Value = false } From feadfbcca765797fe62d278c725f696fa1b86595 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 17:48:20 +0900 Subject: [PATCH 204/600] Add playlist type to picker temporarily --- osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs index c6f9b0f207..c72fa24b67 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs @@ -30,6 +30,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components AddItem(MatchType.HeadToHead); AddItem(MatchType.TeamVersus); + // TODO: remove after osu-web is updated to set the correct default type. + AddItem(MatchType.Playlists); } private class GameTypePickerItem : DisableableTabItem From 062207fcd97a079fd88919758f12c5e45835657b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Aug 2021 18:16:58 +0900 Subject: [PATCH 205/600] Fix TestSceneCurrentlyPlayingDisplay reusing cached spectator client --- .../TestSceneCurrentlyPlayingDisplay.cs | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs index 30785fd163..2f11fec6d1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs @@ -1,13 +1,12 @@ // 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.Linq; using System.Threading; using System.Threading.Tasks; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Online.Spectator; @@ -21,51 +20,44 @@ namespace osu.Game.Tests.Visual.Online { private readonly User streamingUser = new User { Id = 2, Username = "Test user" }; - [Cached(typeof(SpectatorClient))] - private TestSpectatorClient testSpectatorClient = new TestSpectatorClient(); - + private TestSpectatorClient spectatorClient; private CurrentlyPlayingDisplay currentlyPlaying; - [Cached(typeof(UserLookupCache))] - private UserLookupCache lookupCache = new TestUserLookupCache(); - - private Container nestedContainer; - [SetUpSteps] public void SetUpSteps() { AddStep("add streaming client", () => { - nestedContainer?.Remove(testSpectatorClient); - Remove(lookupCache); + spectatorClient = new TestSpectatorClient(); + var lookupCache = new TestUserLookupCache(); Children = new Drawable[] { lookupCache, - nestedContainer = new Container + spectatorClient, + new DependencyProvidingContainer { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + CachedDependencies = new (Type, object)[] { - testSpectatorClient, - currentlyPlaying = new CurrentlyPlayingDisplay - { - RelativeSizeAxes = Axes.Both, - } + (typeof(SpectatorClient), spectatorClient), + (typeof(UserLookupCache), lookupCache) + }, + Child = currentlyPlaying = new CurrentlyPlayingDisplay + { + RelativeSizeAxes = Axes.Both, } }, }; }); - - AddStep("Reset players", () => testSpectatorClient.EndPlay(streamingUser.Id)); } [Test] public void TestBasicDisplay() { - AddStep("Add playing user", () => testSpectatorClient.StartPlay(streamingUser.Id, 0)); + AddStep("Add playing user", () => spectatorClient.StartPlay(streamingUser.Id, 0)); AddUntilStep("Panel loaded", () => currentlyPlaying.ChildrenOfType()?.FirstOrDefault()?.User.Id == 2); - AddStep("Remove playing user", () => testSpectatorClient.EndPlay(streamingUser.Id)); + AddStep("Remove playing user", () => spectatorClient.EndPlay(streamingUser.Id)); AddUntilStep("Panel no longer present", () => !currentlyPlaying.ChildrenOfType().Any()); } From 11b9ba86cbed430a2cb0c02dcb0087d168aa81e4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Aug 2021 18:28:08 +0900 Subject: [PATCH 206/600] Fix TestSceneSpectator reusing cached spectator client --- .../Visual/Gameplay/TestSceneSpectator.cs | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 7584d67afe..21c5d89aca 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -13,6 +13,7 @@ using osu.Game.Online.Spectator; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.UI; +using osu.Game.Screens; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; using osu.Game.Tests.Visual.Multiplayer; @@ -25,41 +26,43 @@ namespace osu.Game.Tests.Visual.Gameplay { private readonly User streamingUser = new User { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Test user" }; - [Cached(typeof(SpectatorClient))] - private TestSpectatorClient testSpectatorClient = new TestSpectatorClient(); - [Cached(typeof(UserLookupCache))] private UserLookupCache lookupCache = new TestUserLookupCache(); // used just to show beatmap card for the time being. protected override bool UseOnlineAPI => true; - private SoloSpectator spectatorScreen; - [Resolved] private OsuGameBase game { get; set; } - private BeatmapSetInfo importedBeatmap; + private TestSpectatorClient spectatorClient; + private SoloSpectator spectatorScreen; + private BeatmapSetInfo importedBeatmap; private int importedBeatmapId; - public override void SetUpSteps() + [SetUpSteps] + public void SetupSteps() { - base.SetUpSteps(); + DependenciesScreen dependenciesScreen = null; + + AddStep("load dependencies", () => + { + spectatorClient = new TestSpectatorClient(); + + // The screen gets suspended so it stops receiving updates. + Child = spectatorClient; + + LoadScreen(dependenciesScreen = new DependenciesScreen(spectatorClient)); + }); + + AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded); AddStep("import beatmap", () => { importedBeatmap = ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Result; importedBeatmapId = importedBeatmap.Beatmaps.First(b => b.RulesetID == 0).OnlineBeatmapID ?? -1; }); - - AddStep("add streaming client", () => - { - Remove(testSpectatorClient); - Add(testSpectatorClient); - }); - - finish(); } [Test] @@ -206,22 +209,36 @@ namespace osu.Game.Tests.Visual.Gameplay private void waitForPlayer() => AddUntilStep("wait for player", () => (Stack.CurrentScreen as Player)?.IsLoaded == true); - private void start(int? beatmapId = null) => AddStep("start play", () => testSpectatorClient.StartPlay(streamingUser.Id, beatmapId ?? importedBeatmapId)); + private void start(int? beatmapId = null) => AddStep("start play", () => spectatorClient.StartPlay(streamingUser.Id, beatmapId ?? importedBeatmapId)); - private void finish() => AddStep("end play", () => testSpectatorClient.EndPlay(streamingUser.Id)); + private void finish() => AddStep("end play", () => spectatorClient.EndPlay(streamingUser.Id)); private void checkPaused(bool state) => AddUntilStep($"game is {(state ? "paused" : "playing")}", () => player.ChildrenOfType().First().IsPaused.Value == state); private void sendFrames(int count = 10) { - AddStep("send frames", () => testSpectatorClient.SendFrames(streamingUser.Id, count)); + AddStep("send frames", () => spectatorClient.SendFrames(streamingUser.Id, count)); } private void loadSpectatingScreen() { - AddStep("load screen", () => LoadScreen(spectatorScreen = new SoloSpectator(streamingUser))); + AddStep("load spectator", () => LoadScreen(spectatorScreen = new SoloSpectator(streamingUser))); AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded); } + + /// + /// Used for the sole purpose of adding as a resolvable dependency. + /// + private class DependenciesScreen : OsuScreen + { + [Cached(typeof(SpectatorClient))] + public readonly TestSpectatorClient Client; + + public DependenciesScreen(TestSpectatorClient client) + { + Client = client; + } + } } } From 6b2ea1b08f638cc953956ee776e8fd3bcd69f60b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 18:30:04 +0900 Subject: [PATCH 207/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index b01210a7b1..1866acd248 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b3eeaa4be7..4b0edf990e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 7ad27b222c..e4992e1132 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 1152e15282b6497be0a6a904c61617f0f7e2efc1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 18:29:02 +0900 Subject: [PATCH 208/600] Update new usages of `LocalisableEnum` --- .../Rankings/RankingsOverlayHeader.cs | 2 +- osu.Game/Overlays/Rankings/RankingsScope.cs | 33 ++++--------------- .../Rankings/RankingsSortTabControl.cs | 23 ++----------- 3 files changed, 11 insertions(+), 47 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 4916b8b327..417b33ddf6 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -1,10 +1,10 @@ // 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.Graphics; using osu.Framework.Bindables; using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; +using osu.Framework.Graphics; using osu.Game.Rulesets; using osu.Game.Users; diff --git a/osu.Game/Overlays/Rankings/RankingsScope.cs b/osu.Game/Overlays/Rankings/RankingsScope.cs index 684408d3a2..e660c2898a 100644 --- a/osu.Game/Overlays/Rankings/RankingsScope.cs +++ b/osu.Game/Overlays/Rankings/RankingsScope.cs @@ -1,42 +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 System; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Rankings { - [LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))] public enum RankingsScope { + [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypePerformance))] Performance, + + [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCharts))] Spotlights, + + [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeScore))] Score, + + [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCountry))] Country } - - public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(RankingsScope value) - { - switch (value) - { - case RankingsScope.Performance: - return RankingsStrings.TypePerformance; - - case RankingsScope.Spotlights: - return RankingsStrings.TypeCharts; - - case RankingsScope.Score: - return RankingsStrings.TypeScore; - - case RankingsScope.Country: - return RankingsStrings.TypeCountry; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } diff --git a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs index c04eb5bdd1..f05795b2a2 100644 --- a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs +++ b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -16,28 +15,12 @@ namespace osu.Game.Overlays.Rankings } } - [LocalisableEnum(typeof(RankingsSortCriteriaEnumLocalisationMapper))] public enum RankingsSortCriteria { + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.All))] All, + + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Friends))] Friends } - - public class RankingsSortCriteriaEnumLocalisationMapper : EnumLocalisationMapper - { - public override LocalisableString Map(RankingsSortCriteria value) - { - switch (value) - { - case RankingsSortCriteria.All: - return SortStrings.All; - - case RankingsSortCriteria.Friends: - return SortStrings.Friends; - - default: - throw new ArgumentOutOfRangeException(nameof(value), value, null); - } - } - } } From ea02571da9e72b38f7b328434fece3a55af48c3f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 3 Aug 2021 12:49:37 +0300 Subject: [PATCH 209/600] Inline parameterised test case --- osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs index 30e234dd7a..acb5357c38 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs @@ -14,15 +14,15 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods /// /// Ensures that a final volume combo of 0 (i.e. "always muted" mode) constantly plays metronome and completely mutes track. /// - [TestCase(0.0, 1.0)] - public void TestZeroFinalCombo(double expectedTrackVolume, double expectedMetronomeVolume) => CreateModTest(new ModTestData + [Test] + public void TestZeroFinalCombo() => CreateModTest(new ModTestData { Mod = new OsuModMuted { MuteComboCount = { Value = 0 }, }, - PassCondition = () => Beatmap.Value.Track.AggregateVolume.Value == expectedTrackVolume && - Player.ChildrenOfType().SingleOrDefault()?.AggregateVolume.Value == expectedMetronomeVolume, + PassCondition = () => Beatmap.Value.Track.AggregateVolume.Value == 0.0 && + Player.ChildrenOfType().SingleOrDefault()?.AggregateVolume.Value == 1.0, }); } } From 0d22b9223b97131ed36f2469fd4f89aa6aabe267 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 3 Aug 2021 12:50:54 +0300 Subject: [PATCH 210/600] Add unit test for inverse muting transferal --- .../Mods/TestSceneOsuModMuted.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs index acb5357c38..c14dc78f38 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs @@ -24,5 +24,29 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods PassCondition = () => Beatmap.Value.Track.AggregateVolume.Value == 0.0 && Player.ChildrenOfType().SingleOrDefault()?.AggregateVolume.Value == 1.0, }); + + /// + /// Ensures that copying from a normal mod with 0 final combo while originally inversed does not yield incorrect results. + /// + [Test] + public void TestModCopy() + { + OsuModMuted muted = null; + + AddStep("create inversed mod", () => muted = new OsuModMuted + { + MuteComboCount = { Value = 100 }, + InverseMuting = { Value = true }, + }); + + AddStep("copy from normal", () => muted.CopyFrom(new OsuModMuted + { + MuteComboCount = { Value = 0 }, + InverseMuting = { Value = false }, + })); + + AddAssert("mute combo count = 0", () => muted.MuteComboCount.Value == 0); + AddAssert("inverse muting = false", () => muted.InverseMuting.Value == false); + } } } From 118e13227a9b979ee4e5c8822759eb0ca1c8fbd6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 18:37:01 +0900 Subject: [PATCH 211/600] Update existing test to make use of `ManualInputManager.Keys` --- .../Visual/Online/TestSceneChatOverlay.cs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 5e234bdacf..7cfca31167 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -330,22 +330,11 @@ namespace osu.Game.Tests.Visual.Online InputManager.ReleaseKey(Key.AltLeft); } - private void pressCloseDocumentKeys() => pressKeysFor(PlatformAction.DocumentClose); + private void pressCloseDocumentKeys() => InputManager.Keys(PlatformAction.DocumentClose); - private void pressNewTabKeys() => pressKeysFor(PlatformAction.TabNew); + private void pressNewTabKeys() => InputManager.Keys(PlatformAction.TabNew); - private void pressRestoreTabKeys() => pressKeysFor(PlatformAction.TabRestore); - - private void pressKeysFor(PlatformAction type) - { - var binding = host.PlatformKeyBindings.First(b => (PlatformAction)b.Action == type); - - foreach (var k in binding.KeyCombination.Keys) - InputManager.PressKey((Key)k); - - foreach (var k in binding.KeyCombination.Keys) - InputManager.ReleaseKey((Key)k); - } + private void pressRestoreTabKeys() => InputManager.Keys(PlatformAction.TabRestore); private void clickDrawable(Drawable d) { From 063868713e7d518b79eadac5750a3133a02a7f12 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 18:05:43 +0900 Subject: [PATCH 212/600] Add ability to create a room using only keyboard input --- .../Match/Components/CreateRoomButton.cs | 39 +++++++++++++++++++ .../CreateMultiplayerMatchButton.cs | 4 +- .../Match/BeatmapSelectionControl.cs | 24 +++++++++++- .../Match/MultiplayerMatchSettingsOverlay.cs | 23 ++++++++++- .../Playlists/CreatePlaylistsRoomButton.cs | 4 +- 5 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs new file mode 100644 index 0000000000..711eaa0ca1 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -0,0 +1,39 @@ +// 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.Allocation; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; + +namespace osu.Game.Screens.OnlinePlay.Match.Components +{ + public abstract class CreateRoomButton : PurpleTriangleButton, IKeyBindingHandler + { + [BackgroundDependencyLoader] + private void load() + { + Triangles.TriangleScale = 1.5f; + } + + public bool OnPressed(PlatformAction action) + { + if (!Enabled.Value) + return false; + + switch (action) + { + case PlatformAction.DocumentNew: + // might as well also handle new tab. it's a bit of an undefined flow on this screen. + case PlatformAction.TabNew: + Click(); + return true; + } + + return false; + } + + public void OnReleased(PlatformAction action) + { + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs index cc51b5b691..e80923ed47 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class CreateMultiplayerMatchButton : PurpleTriangleButton + public class CreateMultiplayerMatchButton : CreateRoomButton { private IBindable isConnected; private IBindable operationInProgress; @@ -22,8 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [BackgroundDependencyLoader] private void load() { - Triangles.TriangleScale = 1.5f; - Text = "Create room"; isConnected = multiplayerClient.IsConnected.GetBoundCopy(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs index ebe63e26d6..6293751ac0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs @@ -5,13 +5,15 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Bindings; using osu.Framework.Screens; +using osu.Game.Input.Bindings; using osu.Game.Online.API; using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class BeatmapSelectionControl : RoomSubScreenComposite + public class BeatmapSelectionControl : RoomSubScreenComposite, IKeyBindingHandler { [Resolved] private MultiplayerMatchSubScreen matchSubScreen { get; set; } @@ -75,5 +77,25 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match else beatmapPanelContainer.Child = new DrawableRoomPlaylistItem(SelectedItem.Value, false, false); } + + public bool OnPressed(GlobalAction action) + { + // only handle keyboard input if there is no current selection. + if (SelectedItem.Value != null) + return false; + + switch (action) + { + case GlobalAction.Select: + selectButton.Click(); + return true; + } + + return false; + } + + public void OnReleased(GlobalAction action) + { + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 338d2c9e84..b0e8e73732 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -11,11 +11,13 @@ using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays; @@ -352,7 +354,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match } } - public class CreateOrUpdateButton : TriangleButton + public class CreateOrUpdateButton : TriangleButton, IKeyBindingHandler { [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } @@ -370,6 +372,25 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match Triangles.ColourLight = colours.YellowLight; Triangles.ColourDark = colours.YellowDark; } + + public bool OnPressed(GlobalAction action) + { + if (!Enabled.Value) + return false; + + switch (action) + { + case GlobalAction.Select: + Click(); + return true; + } + + return false; + } + + public void OnReleased(GlobalAction action) + { + } } } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs index fcb773f8be..a9826a72eb 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs @@ -6,13 +6,11 @@ using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class CreatePlaylistsRoomButton : PurpleTriangleButton + public class CreatePlaylistsRoomButton : CreateRoomButton { [BackgroundDependencyLoader] private void load() { - Triangles.TriangleScale = 1.5f; - Text = "Create playlist"; } } From 3c7a49f4311f0fb2e7105d85436b0c3d371022c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 18:37:09 +0900 Subject: [PATCH 213/600] Add test coverage of keyboard room creation flow --- .../Multiplayer/TestSceneMultiplayer.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 7c151ffac3..1474e0f712 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; @@ -88,6 +89,28 @@ namespace osu.Game.Tests.Visual.Multiplayer // used to test the flow of multiplayer from visual tests. } + [Test] + public void TestCreateRoomViaKeyboard() + { + // create room dialog + AddStep("Press new document", () => InputManager.Keys(PlatformAction.DocumentNew)); + AddUntilStep("wait for settings", () => InputManager.ChildrenOfType().FirstOrDefault() != null); + + // edit playlist item + AddStep("Press select", () => InputManager.Key(Key.Enter)); + AddUntilStep("wait for song select", () => InputManager.ChildrenOfType().FirstOrDefault() != null); + + // select beatmap + AddStep("Press select", () => InputManager.Key(Key.Enter)); + AddUntilStep("wait for return to screen", () => InputManager.ChildrenOfType().FirstOrDefault() == null); + + // create room + AddStep("Press select", () => InputManager.Key(Key.Enter)); + + AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); + AddUntilStep("wait for join", () => client.Room != null); + } + [Test] public void TestCreateRoomWithoutPassword() { From 8b3feaabfcab105dc49ba0861e6f1ccbf528dd4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Aug 2021 20:07:42 +0900 Subject: [PATCH 214/600] Fix more compile errors --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 2 +- osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 6681703311..893d99fb9d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -401,7 +401,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createRoom(Func room) { AddUntilStep("wait for lounge", () => multiplayerScreen.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); - AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().OpenNewRoom(room())); + AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().Open(room())); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddWaitStep("wait for transition", 2); diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index fa2b2b363f..3c65f46c79 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -318,7 +318,7 @@ namespace osu.Game.Tests.Visual.Navigation PushAndConfirm(() => multiplayer = new TestMultiplayer()); AddUntilStep("wait for lounge", () => multiplayer.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); - AddStep("open room", () => multiplayer.ChildrenOfType().Single().OpenNewRoom()); + AddStep("open room", () => multiplayer.ChildrenOfType().Single().Open()); AddStep("press back button", () => Game.ChildrenOfType().First().Action()); AddWaitStep("wait two frames", 2); } From 56ded4fde640d5589af877e701f1b31bd2deb761 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Aug 2021 20:32:51 +0900 Subject: [PATCH 215/600] Fix DrawableRoom test scene --- .../Multiplayer/TestSceneDrawableRoom.cs | 131 ++++++++++-------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index c69890ba33..faabed0e17 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -4,6 +4,8 @@ using System; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; @@ -19,49 +21,78 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneDrawableRoom : OsuTestScene { - public TestSceneDrawableRoom() + [Cached] + private readonly Bindable selectedRoom = new Bindable(); + + [Test] + public void TestMultipleStatuses() { - Child = new FillFlowContainer + AddStep("create rooms", () => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.9f), - Spacing = new Vector2(10), - Children = new Drawable[] + Child = new FillFlowContainer { - createDrawableRoom(new Room + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.9f), + Spacing = new Vector2(10), + Children = new Drawable[] { - Name = { Value = "Room 1" }, - Status = { Value = new RoomStatusOpen() }, - EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, - }), - createDrawableRoom(new Room - { - Name = { Value = "Room 2" }, - Status = { Value = new RoomStatusPlaying() }, - EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, - }), - createDrawableRoom(new Room - { - Name = { Value = "Room 3" }, - Status = { Value = new RoomStatusEnded() }, - EndDate = { Value = DateTimeOffset.Now }, - }), - createDrawableRoom(new Room - { - Name = { Value = "Room 4 (realtime)" }, - Status = { Value = new RoomStatusOpen() }, - Category = { Value = RoomCategory.Realtime }, - }), - createDrawableRoom(new Room - { - Name = { Value = "Room 4 (spotlight)" }, - Status = { Value = new RoomStatusOpen() }, - Category = { Value = RoomCategory.Spotlight }, - }), - } - }; + createDrawableRoom(new Room + { + Name = { Value = "Room 1" }, + Status = { Value = new RoomStatusOpen() }, + EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, + }), + createDrawableRoom(new Room + { + Name = { Value = "Room 2" }, + Status = { Value = new RoomStatusPlaying() }, + EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, + }), + createDrawableRoom(new Room + { + Name = { Value = "Room 3" }, + Status = { Value = new RoomStatusEnded() }, + EndDate = { Value = DateTimeOffset.Now }, + }), + createDrawableRoom(new Room + { + Name = { Value = "Room 4 (realtime)" }, + Status = { Value = new RoomStatusOpen() }, + Category = { Value = RoomCategory.Realtime }, + }), + createDrawableRoom(new Room + { + Name = { Value = "Room 4 (spotlight)" }, + Status = { Value = new RoomStatusOpen() }, + Category = { Value = RoomCategory.Spotlight }, + }), + } + }; + }); + } + + [Test] + public void TestEnableAndDisablePassword() + { + DrawableRoom drawableRoom = null; + Room room = null; + + AddStep("create room", () => Child = drawableRoom = createDrawableRoom(room = new Room + { + Name = { Value = "Room with password" }, + Status = { Value = new RoomStatusOpen() }, + Category = { Value = RoomCategory.Realtime }, + })); + + AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha)); + + AddStep("set password", () => room.Password.Value = "password"); + AddAssert("password icon visible", () => Precision.AlmostEquals(1, drawableRoom.ChildrenOfType().Single().Alpha)); + + AddStep("unset password", () => room.Password.Value = string.Empty); + AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha)); } private DrawableRoom createDrawableRoom(Room room) @@ -82,27 +113,5 @@ namespace osu.Game.Tests.Visual.Multiplayer return drawableRoom; } - - [Test] - public void TestEnableAndDisablePassword() - { - DrawableRoom drawableRoom = null; - Room room = null; - - AddStep("create room", () => Child = drawableRoom = new DrawableRoom(room = new Room - { - Name = { Value = "Room with password" }, - Status = { Value = new RoomStatusOpen() }, - Category = { Value = RoomCategory.Realtime }, - }) { MatchingFilter = true }); - - AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha)); - - AddStep("set password", () => room.Password.Value = "password"); - AddAssert("password icon visible", () => Precision.AlmostEquals(1, drawableRoom.ChildrenOfType().Single().Alpha)); - - AddStep("unset password", () => room.Password.Value = string.Empty); - AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha)); - } } } From 8dd72a9dc6651eda4b536024442e5dc0ff4db96f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 12 Jul 2021 19:34:14 +0300 Subject: [PATCH 216/600] Add new difficulty rating colour method --- osu.Game/Graphics/OsuColour.cs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index c0bc8fdb76..7610f84eda 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -1,11 +1,13 @@ // 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.Extensions.Color4Extensions; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Utils; using osuTK.Graphics; namespace osu.Game.Graphics @@ -40,6 +42,33 @@ namespace osu.Game.Graphics } } + public Color4 ForDifficultyRatingNew(DifficultyRating difficulty) + { + switch (difficulty) + { + case DifficultyRating.Easy: + return Color4Extensions.FromHex("4ebfff"); + + case DifficultyRating.Normal: + return Color4Extensions.FromHex("66ff91"); + + case DifficultyRating.Hard: + return Color4Extensions.FromHex("f7e75d"); + + case DifficultyRating.Insane: + return Color4Extensions.FromHex("ff7e68"); + + case DifficultyRating.Expert: + return Color4Extensions.FromHex("fe3c71"); + + case DifficultyRating.ExpertPlus: + return Color4Extensions.FromHex("6662dd"); + + default: + throw new ArgumentOutOfRangeException(nameof(difficulty)); + } + } + /// /// Retrieves the colour for a . /// From d9686332a175c282dfe3633a7df8edb7c00b06b2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 12 Jul 2021 19:35:03 +0300 Subject: [PATCH 217/600] Implement new difficulty rating colour spectrum sampling --- osu.Game/Graphics/OsuColour.cs | 20 ++++++++++++++++++ osu.Game/Utils/ColourUtils.cs | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 osu.Game/Utils/ColourUtils.cs diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 7610f84eda..6aac78b765 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -69,6 +69,26 @@ namespace osu.Game.Graphics } } + public Color4 ForStarDifficulty(double starDifficulty) + { + var spectrumPoint = (float)(starDifficulty / 8.00); + + if (spectrumPoint > 1f) + return Color4.Black; + + return ColourUtils.SampleFromLinearGradient(new[] + { + (0.2159f, Color4Extensions.FromHex("4fc0ff")), + (0.2693f, Color4Extensions.FromHex("4fffd5")), + (0.3217f, Color4Extensions.FromHex("7cff4f")), + (0.4111f, Color4Extensions.FromHex("f6f05c")), + (0.5767f, Color4Extensions.FromHex("ff8068")), + (0.7307f, Color4Extensions.FromHex("ff3c71")), + (0.8667f, Color4Extensions.FromHex("6563de")), + (0.9996f, Color4Extensions.FromHex("18158e")), + }, spectrumPoint); + } + /// /// Retrieves the colour for a . /// diff --git a/osu.Game/Utils/ColourUtils.cs b/osu.Game/Utils/ColourUtils.cs new file mode 100644 index 0000000000..515963971d --- /dev/null +++ b/osu.Game/Utils/ColourUtils.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Utils; +using osuTK.Graphics; + +namespace osu.Game.Utils +{ + public static class ColourUtils + { + /// + /// Samples from a given linear gradient at a certain specified point. + /// + /// The gradient, defining the colour stops and their positions (in [0-1] range) in the gradient. + /// The point to sample the colour at. + /// A sampled from the linear gradient. + public static Color4 SampleFromLinearGradient(IReadOnlyList<(float position, Color4 colour)> gradient, float point) + { + if (point < gradient[0].position) + return gradient[0].colour; + + for (int i = 0; i < gradient.Count - 1; i++) + { + var startStop = gradient[i]; + var endStop = gradient[i + 1]; + + if (point >= endStop.position) + continue; + + return Interpolation.ValueAt(point, startStop.colour, endStop.colour, startStop.position, endStop.position); + } + + return gradient[^1].colour; + } + } +} From 50f6632051de4d0a0d609eb90e5c4ae9b93107dd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Aug 2021 20:38:50 +0900 Subject: [PATCH 218/600] Fix duplicate RoomManager --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 5ec9202759..fee612c0a5 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -140,7 +140,7 @@ namespace osu.Game.Screens.OnlinePlay } }, new Header(ScreenTitle, screenStack), - RoomManager = CreateRoomManager(), + RoomManager, ongoingOperationTracker } }; From 692e320ea57fc1cf52419448f3fce01aed5eecf7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Jul 2021 01:04:01 +0300 Subject: [PATCH 219/600] Add visual test scene --- .../Colours/TestSceneStarDifficultyColours.cs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs diff --git a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs new file mode 100644 index 0000000000..c345320e28 --- /dev/null +++ b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs @@ -0,0 +1,90 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Tests.Visual.Colours +{ + public class TestSceneStarDifficultyColours : OsuTestScene + { + [Resolved] + private OsuColour colours { get; set; } + + [Test] + public void TestColours() + { + AddStep("load colour displays", () => + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f), + ChildrenEnumerable = Enumerable.Range(0, 10).Select(i => new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10f), + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => + { + var colour = colours.ForStarDifficulty(1f * i + 0.1f * j); + + return new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, 10f), + Children = new Drawable[] + { + new CircularContainer + { + Masking = true, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Size = new Vector2(75f, 25f), + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = OsuColour.ForegroundTextColourFor(colour), + Text = colour.ToHex(), + }, + } + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = $"*{(1f * i + 0.1f * j):0.00}", + } + } + }; + }) + }) + }; + }); + } + } +} From 6fd97d67eb9297dbd75467009e511dded79903bd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 15 Jul 2021 23:57:48 +0300 Subject: [PATCH 220/600] Update colour spectrum inline with latest version From https://github.com/ppy/osu-web/pull/7855#issuecomment-880959644, less arbitrary. --- osu.Game/Graphics/OsuColour.cs | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 6aac78b765..4eb9aa7c94 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -69,25 +69,18 @@ namespace osu.Game.Graphics } } - public Color4 ForStarDifficulty(double starDifficulty) + public Color4 ForStarDifficulty(double starDifficulty) => ColourUtils.SampleFromLinearGradient(new[] { - var spectrumPoint = (float)(starDifficulty / 8.00); - - if (spectrumPoint > 1f) - return Color4.Black; - - return ColourUtils.SampleFromLinearGradient(new[] - { - (0.2159f, Color4Extensions.FromHex("4fc0ff")), - (0.2693f, Color4Extensions.FromHex("4fffd5")), - (0.3217f, Color4Extensions.FromHex("7cff4f")), - (0.4111f, Color4Extensions.FromHex("f6f05c")), - (0.5767f, Color4Extensions.FromHex("ff8068")), - (0.7307f, Color4Extensions.FromHex("ff3c71")), - (0.8667f, Color4Extensions.FromHex("6563de")), - (0.9996f, Color4Extensions.FromHex("18158e")), - }, spectrumPoint); - } + (1.5f, Color4Extensions.FromHex("4fc0ff")), + (2.0f, Color4Extensions.FromHex("4fffd5")), + (2.5f, Color4Extensions.FromHex("7cff4f")), + (3.25f, Color4Extensions.FromHex("f6f05c")), + (4.5f, Color4Extensions.FromHex("ff8068")), + (6.0f, Color4Extensions.FromHex("ff3c71")), + (7.0f, Color4Extensions.FromHex("6563de")), + (8.0f, Color4Extensions.FromHex("18158e")), + (8.0f, Color4.Black), + }, (float)starDifficulty); /// /// Retrieves the colour for a . From 9a5e052dc08c4eae30de3b2021f97cfdc19837b9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 3 Aug 2021 14:17:02 +0300 Subject: [PATCH 221/600] Use star difficulty colour spectrum game-wide --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 6 ++--- osu.Game/Graphics/OsuColour.cs | 25 ------------------- .../Components/StarRatingRangeDisplay.cs | 4 +-- .../Ranking/Expanded/StarRatingDisplay.cs | 4 +-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 5 files changed, 7 insertions(+), 34 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index c62b803d1a..9a3c75dcc6 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -106,7 +106,7 @@ namespace osu.Game.Beatmaps.Drawables Child = background = new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.ForDifficultyRating(beatmap.DifficultyRating) // Default value that will be re-populated once difficulty calculation completes + Colour = colours.ForStarDifficulty(beatmap.StarDifficulty) // Default value that will be re-populated once difficulty calculation completes }, }, new ConstrainedIconContainer @@ -124,7 +124,7 @@ namespace osu.Game.Beatmaps.Drawables else difficultyBindable.Value = new StarDifficulty(beatmap.StarDifficulty, 0); - difficultyBindable.BindValueChanged(difficulty => background.Colour = colours.ForDifficultyRating(difficulty.NewValue.DifficultyRating)); + difficultyBindable.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars)); } public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(); @@ -271,7 +271,7 @@ namespace osu.Game.Beatmaps.Drawables starDifficulty.BindValueChanged(difficulty => { starRating.Text = $"{difficulty.NewValue.Stars:0.##}"; - difficultyFlow.Colour = colours.ForDifficultyRating(difficulty.NewValue.DifficultyRating, true); + difficultyFlow.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars); }, true); return true; diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 4eb9aa7c94..222300d018 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -18,31 +18,6 @@ namespace osu.Game.Graphics public static Color4 Gray(byte amt) => new Color4(amt, amt, amt, 255); public Color4 ForDifficultyRating(DifficultyRating difficulty, bool useLighterColour = false) - { - switch (difficulty) - { - case DifficultyRating.Easy: - return Green; - - default: - case DifficultyRating.Normal: - return Blue; - - case DifficultyRating.Hard: - return Yellow; - - case DifficultyRating.Insane: - return Pink; - - case DifficultyRating.Expert: - return PurpleLight; - - case DifficultyRating.ExpertPlus: - return useLighterColour ? Gray9 : Color4Extensions.FromHex("#121415"); - } - } - - public Color4 ForDifficultyRatingNew(DifficultyRating difficulty) { switch (difficulty) { diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index b2e35d7020..8c1b10e3bd 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -86,8 +86,8 @@ namespace osu.Game.Screens.OnlinePlay.Components minDisplay.Current.Value = minDifficulty; maxDisplay.Current.Value = maxDifficulty; - minBackground.Colour = colours.ForDifficultyRating(minDifficulty.DifficultyRating, true); - maxBackground.Colour = colours.ForDifficultyRating(maxDifficulty.DifficultyRating, true); + minBackground.Colour = colours.ForStarDifficulty(minDifficulty.Stars); + maxBackground.Colour = colours.ForStarDifficulty(maxDifficulty.Stars); } } } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index e59a0de316..9d325768f3 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -107,9 +107,7 @@ namespace osu.Game.Screens.Ranking.Expanded string fractionPart = starRatingParts[1]; string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - var rating = Current.Value.DifficultyRating; - - background.Colour = colours.ForDifficultyRating(rating, true); + background.Colour = colours.ForStarDifficulty(Current.Value.Stars); textFlow.Clear(); textFlow.AddText($"{wholePart}", s => diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 763c27bcbb..3779523094 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -503,7 +503,7 @@ namespace osu.Game.Screens.Select { const float full_opacity_ratio = 0.7f; - var difficultyColour = colours.ForDifficultyRating(difficulty.DifficultyRating); + var difficultyColour = colours.ForStarDifficulty(difficulty.Stars); Children = new Drawable[] { From e11b815b82171be2eb98bdac91564154c7f0f13f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 23:08:11 +0900 Subject: [PATCH 222/600] Serialise `type` as snake_case --- osu.Game/Online/Rooms/MatchType.cs | 2 ++ osu.Game/Online/Rooms/Room.cs | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/osu.Game/Online/Rooms/MatchType.cs b/osu.Game/Online/Rooms/MatchType.cs index cafa147a61..36f0dc0c81 100644 --- a/osu.Game/Online/Rooms/MatchType.cs +++ b/osu.Game/Online/Rooms/MatchType.cs @@ -7,6 +7,8 @@ namespace osu.Game.Online.Rooms { public enum MatchType { + // used for osu-web deserialization so names shouldn't be changed. + Playlists, [Description("Head to head")] diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index fe7455d964..4bd5b1a788 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -64,6 +64,15 @@ namespace osu.Game.Online.Rooms [JsonIgnore] public readonly Bindable Type = new Bindable(); + // Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106) + [JsonConverter(typeof(SnakeCaseStringEnumConverter))] + [JsonProperty("type")] + private MatchType type + { + get => Type.Value; + set => Type.Value = value; + } + [Cached] [JsonIgnore] public readonly Bindable MaxParticipants = new Bindable(); From b956d325876226a49d508530d39c044c3c672505 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Jul 2021 15:30:57 +0900 Subject: [PATCH 223/600] Add the ability to change multiplayer game type --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 4 +++- osu.Game/Online/Rooms/Room.cs | 2 +- .../Screens/OnlinePlay/Components/DisableableTabControl.cs | 2 +- .../Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs | 4 +--- osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs | 3 ++- osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs | 6 +++++- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 873be7f49c..fed4564500 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -192,8 +192,9 @@ namespace osu.Game.Online.Multiplayer /// /// The new room name, if any. /// The new password, if any. + /// The type of the match, if any. /// The new room playlist item, if any. - public Task ChangeSettings(Optional name = default, Optional password = default, Optional item = default) + public Task ChangeSettings(Optional name = default, Optional password = default, Optional matchType = default, Optional item = default) { if (Room == null) throw new InvalidOperationException("Must be joined to a match to change settings."); @@ -219,6 +220,7 @@ namespace osu.Game.Online.Multiplayer BeatmapID = item.GetOr(existingPlaylistItem).BeatmapID, BeatmapChecksum = item.GetOr(existingPlaylistItem).Beatmap.Value.MD5Hash, RulesetID = item.GetOr(existingPlaylistItem).RulesetID, + MatchType = matchType.GetOr(Room.Settings.MatchType), RequiredMods = item.HasValue ? item.Value.AsNonNull().RequiredMods.Select(m => new APIMod(m)).ToList() : Room.Settings.RequiredMods, AllowedMods = item.HasValue ? item.Value.AsNonNull().AllowedMods.Select(m => new APIMod(m)).ToList() : Room.Settings.AllowedMods, }); diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 4bd5b1a788..de90907552 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -61,7 +61,7 @@ namespace osu.Game.Online.Rooms public readonly Bindable Availability = new Bindable(); [Cached] - [JsonIgnore] + [JsonProperty("type")] public readonly Bindable Type = new Bindable(); // Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106) diff --git a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs index bbc407e926..2b596da361 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs @@ -9,7 +9,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { public abstract class DisableableTabControl : TabControl { - public readonly BindableBool Enabled = new BindableBool(); + public readonly BindableBool Enabled = new BindableBool(true); protected override void AddTabItem(TabItem tab, bool addToDropdown = true) { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 425252f3cf..65ff02f2cc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -149,7 +149,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match }, new Section("Game type") { - Alpha = disabled_alpha, Child = new FillFlowContainer { AutoSizeAxes = Axes.Y, @@ -161,7 +160,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match TypePicker = new MatchTypePicker { RelativeSizeAxes = Axes.X, - Enabled = { Value = false } }, typeLabel = new OsuSpriteText { @@ -305,7 +303,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match // Otherwise, update the room directly in preparation for it to be submitted to the API on match creation. if (client.Room != null) { - client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text).ContinueWith(t => Schedule(() => + client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text, matchType: TypePicker.Current.Value).ContinueWith(t => Schedule(() => { if (t.IsCompletedSuccessfully) onSuccess(currentRoom.Value); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index dbac826954..d906cc8110 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -58,7 +58,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer new Room { Name = { Value = $"{API.LocalUser}'s awesome room" }, - Category = { Value = RoomCategory.Realtime } + Category = { Value = RoomCategory.Realtime }, + Type = { Value = MatchType.HeadToHead }, }; protected override string ScreenTitle => "Multiplayer"; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index 5b132c97fd..4f02651f02 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -48,7 +48,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override Room CreateNewRoom() { - return new Room { Name = { Value = $"{API.LocalUser}'s awesome playlist" } }; + return new Room + { + Name = { Value = $"{API.LocalUser}'s awesome playlist" }, + Type = { Value = MatchType.Playlists } + }; } protected override string ScreenTitle => "Playlists"; From 5e59b1325c8ecb10cbd063acaf0d4184f2d3cf7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Jul 2021 18:11:11 +0900 Subject: [PATCH 224/600] Add team display to participant list --- .../Participants/ParticipantPanel.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index f4a334e9d3..eca3ae0763 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs; using osu.Game.Rulesets; using osu.Game.Screens.Play.HUD; using osu.Game.Users; @@ -37,6 +38,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants private RulesetStore rulesets { get; set; } private SpriteIcon crown; + private Box teamDisplay; + private OsuSpriteText userRankText; private ModDisplay userModsDisplay; private StateDisplay userStateDisplay; @@ -67,6 +70,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Colour = Color4Extensions.FromHex("#F7E65D"), Alpha = 0 }, + teamDisplay = new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Y, + Width = 15, + Alpha = 0, + }, new Container { RelativeSizeAxes = Axes.Both, @@ -174,11 +184,36 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants else crown.FadeOut(fade_time); + if (User.MatchRulesetState is TeamVsMatchUserState teamState) + { + teamDisplay.Show(); + teamDisplay.FadeColour(getColourForTeam(teamState.TeamID), 100, Easing.OutQuint); + } + else + { + teamDisplay.Hide(); + } + // If the mods are updated at the end of the frame, the flow container will skip a reflow cycle: https://github.com/ppy/osu-framework/issues/4187 // This looks particularly jarring here, so re-schedule the update to that start of our frame as a fix. Schedule(() => userModsDisplay.Current.Value = User.Mods.Select(m => m.ToMod(ruleset)).ToList()); } + [Resolved] + private OsuColour colours { get; set; } + + private ColourInfo getColourForTeam(int id) + { + switch (id) + { + default: + return colours.Red; + + case 1: + return colours.Blue; + } + } + public MenuItem[] ContextMenuItems { get From 9bfb0f1294e3aa47f99e23e0db999dff570dc66a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 17:06:01 +0900 Subject: [PATCH 225/600] Add basic team vs handling to `TestMultiplayerClient` Not sure this is the best place to do so... I can foresee this class getting much larger than we want it to. --- .../Multiplayer/TestMultiplayerClient.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 7deecdfa28..9826d24d01 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -14,6 +14,7 @@ using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Mods; using osu.Game.Users; @@ -132,6 +133,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Settings = { Name = apiRoom.Name.Value, + MatchType = apiRoom.Type.Value, BeatmapID = apiRoom.Playlist.Last().BeatmapID, RulesetID = apiRoom.Playlist.Last().RulesetID, BeatmapChecksum = apiRoom.Playlist.Last().Beatmap.Value.MD5Hash, @@ -163,6 +165,23 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready)) ChangeUserState(user.UserID, MultiplayerUserState.Idle); + + switch (settings.MatchType) + { + case MatchType.HeadToHead: + await ((IMultiplayerClient)this).MatchRoomStateChanged(null).ConfigureAwait(false); + + foreach (var user in Room.Users) + await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, null).ConfigureAwait(false); + break; + + case MatchType.TeamVersus: + await ((IMultiplayerClient)this).MatchRoomStateChanged(TeamVersusRoomState.CreateDefault()).ConfigureAwait(false); + + foreach (var user in Room.Users) + await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, new TeamVersusUserState()).ConfigureAwait(false); + break; + } } public override Task ChangeState(MultiplayerUserState newState) @@ -192,7 +211,30 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.CompletedTask; } - public override Task SendMatchRequest(MatchUserRequest request) => Task.CompletedTask; + public override async Task SendMatchRequest(MatchUserRequest request) + { + Debug.Assert(Room != null); + Debug.Assert(LocalUser != null); + + switch (request) + { + case ChangeTeamRequest changeTeam: + + TeamVersusRoomState roomState = (TeamVersusRoomState)Room.MatchState!; + TeamVersusUserState userState = (TeamVersusUserState)LocalUser.MatchState!; + + var targetTeam = roomState.Teams.FirstOrDefault(t => t.ID == changeTeam.TeamID); + + if (targetTeam != null) + { + userState.TeamID = targetTeam.ID; + + await ((IMultiplayerClient)this).MatchUserStateChanged(LocalUser.UserID, userState).ConfigureAwait(false); + } + + break; + } + } public override Task StartMatch() { From b8e878ccc93d9c121e9dc501bda255f5886c718b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 17:07:08 +0900 Subject: [PATCH 226/600] Add the ability to change team by clicking current team colour Definitely not the final UX, but it's what people are used to and easy to implement, so it'll do for now. --- .../Participants/ParticipantPanel.cs | 201 ++++++++---------- .../Multiplayer/Participants/TeamDisplay.cs | 130 +++++++++++ 2 files changed, 218 insertions(+), 113 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index eca3ae0763..b2de9763ee 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -17,7 +17,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; -using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs; using osu.Game.Rulesets; using osu.Game.Screens.Play.HUD; using osu.Game.Users; @@ -38,7 +37,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants private RulesetStore rulesets { get; set; } private SpriteIcon crown; - private Box teamDisplay; private OsuSpriteText userRankText; private ModDisplay userModsDisplay; @@ -59,106 +57,108 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants var backgroundColour = Color4Extensions.FromHex("#33413C"); - InternalChildren = new Drawable[] + InternalChild = new GridContainer { - crown = new SpriteIcon + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.Crown, - Size = new Vector2(14), - Colour = Color4Extensions.FromHex("#F7E65D"), - Alpha = 0 + new Dimension(GridSizeMode.Absolute, 14), + new Dimension(GridSizeMode.AutoSize), + new Dimension() }, - teamDisplay = new Box + Content = new[] { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Y, - Width = 15, - Alpha = 0, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 24 }, - Child = new Container + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 5, - Children = new Drawable[] + crown = new SpriteIcon { - new Box + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.Crown, + Size = new Vector2(14), + Colour = Color4Extensions.FromHex("#F7E65D"), + Alpha = 0 + }, + new TeamDisplay(user), + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 5, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = backgroundColour - }, - new UserCoverBackground - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Both, - Width = 0.75f, - User = user, - Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f)) - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Spacing = new Vector2(10), - Direction = FillDirection.Horizontal, - Children = new Drawable[] + new Box { - new UpdateableAvatar + RelativeSizeAxes = Axes.Both, + Colour = backgroundColour + }, + new UserCoverBackground + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Both, + Width = 0.75f, + User = user, + Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f)) + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Spacing = new Vector2(10), + Direction = FillDirection.Horizontal, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - User = user - }, - new UpdateableFlag - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(30, 20), - Country = user?.Country - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), - Text = user?.Username - }, - userRankText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 14), + new UpdateableAvatar + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + User = user + }, + new UpdateableFlag + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(30, 20), + Country = user?.Country + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), + Text = user?.Username + }, + userRankText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 14), + } } - } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = 70 }, - Child = userModsDisplay = new ModDisplay + }, + new Container { - Scale = new Vector2(0.5f), - ExpansionMode = ExpansionMode.AlwaysContracted, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = 70 }, + Child = userModsDisplay = new ModDisplay + { + Scale = new Vector2(0.5f), + ExpansionMode = ExpansionMode.AlwaysContracted, + } + }, + userStateDisplay = new StateDisplay + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Margin = new MarginPadding { Right = 10 }, } - }, - userStateDisplay = new StateDisplay - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Margin = new MarginPadding { Right = 10 }, } } - } + }, } }; } @@ -184,36 +184,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants else crown.FadeOut(fade_time); - if (User.MatchRulesetState is TeamVsMatchUserState teamState) - { - teamDisplay.Show(); - teamDisplay.FadeColour(getColourForTeam(teamState.TeamID), 100, Easing.OutQuint); - } - else - { - teamDisplay.Hide(); - } - // If the mods are updated at the end of the frame, the flow container will skip a reflow cycle: https://github.com/ppy/osu-framework/issues/4187 // This looks particularly jarring here, so re-schedule the update to that start of our frame as a fix. Schedule(() => userModsDisplay.Current.Value = User.Mods.Select(m => m.ToMod(ruleset)).ToList()); } - [Resolved] - private OsuColour colours { get; set; } - - private ColourInfo getColourForTeam(int id) - { - switch (id) - { - default: - return colours.Red; - - case 1: - return colours.Blue; - } - } - public MenuItem[] ContextMenuItems { get diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs new file mode 100644 index 0000000000..fd4ce404f1 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs @@ -0,0 +1,130 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants +{ + internal class TeamDisplay : MultiplayerRoomComposite + { + private readonly User user; + private Drawable box; + + [Resolved] + private OsuColour colours { get; set; } + + [Resolved] + private MultiplayerClient client { get; set; } + + public TeamDisplay(User user) + { + this.user = user; + + RelativeSizeAxes = Axes.Y; + Width = 15; + + Margin = new MarginPadding { Horizontal = 3 }; + } + + [BackgroundDependencyLoader] + private void load() + { + box = new Container + { + RelativeSizeAxes = Axes.Both, + CornerRadius = 5, + Masking = true, + Alpha = 0, + Scale = new Vector2(0, 1), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Child = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + + if (user.Id == client.LocalUser?.UserID) + { + InternalChild = new OsuClickableContainer + { + RelativeSizeAxes = Axes.Both, + TooltipText = "Change team", + Action = changeTeam, + Child = box + }; + } + else + { + InternalChild = box; + } + } + + private void changeTeam() + { + client.SendMatchRequest(new ChangeTeamRequest + { + TeamID = ((client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0, + }); + } + + private int? displayedTeam; + + protected override void OnRoomUpdated() + { + base.OnRoomUpdated(); + + // we don't have a way of knowing when an individual user's state has updated, so just handle on RoomUpdated for now. + + var userRoomState = Room?.Users.FirstOrDefault(u => u.UserID == user.Id)?.MatchState; + + const double duration = 400; + + int? newTeam = (userRoomState as TeamVersusUserState)?.TeamID; + + if (newTeam == displayedTeam) + return; + + displayedTeam = newTeam; + + if (displayedTeam != null) + { + box.FadeIn(duration); + box.FadeColour(getColourForTeam(displayedTeam.Value), duration, Easing.OutQuint); + box.ScaleTo(new Vector2(box.Scale.X < 0 ? 1 : -1, 1), duration, Easing.OutQuint); + } + else + { + box.ScaleTo(new Vector2(0, 1), duration, Easing.OutQuint); + box.FadeOut(duration); + } + } + + private ColourInfo getColourForTeam(int id) + { + switch (id) + { + default: + return colours.Red; + + case 1: + return colours.Blue; + } + } + } +} From a0119f8cd6b8ca3ec2a67ed916cfa67cacd5162b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Aug 2021 18:31:56 +0900 Subject: [PATCH 227/600] Add basic test coverage --- .../Visual/Multiplayer/TestSceneTeamVersus.cs | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs new file mode 100644 index 0000000000..bbb1ea5fa0 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -0,0 +1,138 @@ +// 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.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Multiplayer; +using osu.Game.Screens.OnlinePlay.Multiplayer.Match; +using osu.Game.Tests.Resources; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneTeamVersus : ScreenTestScene + { + private BeatmapManager beatmaps; + private RulesetStore rulesets; + private BeatmapSetInfo importedSet; + + private DependenciesScreen dependenciesScreen; + private TestMultiplayer multiplayerScreen; + private TestMultiplayerClient client; + + [Cached(typeof(UserLookupCache))] + private UserLookupCache lookupCache = new TestUserLookupCache(); + + [BackgroundDependencyLoader] + private void load(GameHost host, AudioManager audio) + { + Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); + Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default)); + } + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("import beatmap", () => + { + beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait(); + importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First(); + }); + + AddStep("create multiplayer screen", () => multiplayerScreen = new TestMultiplayer()); + + AddStep("load dependencies", () => + { + client = new TestMultiplayerClient(multiplayerScreen.RoomManager); + + // The screen gets suspended so it stops receiving updates. + Child = client; + + LoadScreen(dependenciesScreen = new DependenciesScreen(client)); + }); + + AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded); + + AddStep("load multiplayer", () => LoadScreen(multiplayerScreen)); + AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded); + AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); + } + + [Test] + public void TestChangeTypeViaMatchSettings() + { + createRoom(() => new Room + { + Name = { Value = "Test Room" }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + } + } + }); + + AddAssert("room type is head to head", () => client.Room?.Settings.MatchType == MatchType.HeadToHead); + + AddStep("change to team vs", () => client.ChangeSettings(matchType: MatchType.TeamVersus)); + + AddAssert("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus); + } + + private void createRoom(Func room) + { + AddStep("open room", () => + { + multiplayerScreen.OpenNewRoom(room()); + }); + + AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); + AddWaitStep("wait for transition", 2); + + AddStep("create room", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + AddUntilStep("wait for join", () => client.Room != null); + } + + /// + /// Used for the sole purpose of adding as a resolvable dependency. + /// + private class DependenciesScreen : OsuScreen + { + [Cached(typeof(MultiplayerClient))] + public readonly TestMultiplayerClient Client; + + public DependenciesScreen(TestMultiplayerClient client) + { + Client = client; + } + } + + private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer + { + public new TestRequestHandlingMultiplayerRoomManager RoomManager { get; private set; } + + protected override RoomManager CreateRoomManager() => RoomManager = new TestRequestHandlingMultiplayerRoomManager(); + } + } +} From 75426f84f19ac34a6d52a0704957843d053f35a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 17:08:19 +0900 Subject: [PATCH 228/600] Fire initial match user states in `TestMultiplayerClient` --- .../Visual/Multiplayer/TestSceneTeamVersus.cs | 22 +++++++++ .../Online/Multiplayer/MultiplayerClient.cs | 9 ++++ .../Multiplayer/TestMultiplayerClient.cs | 47 ++++++++++++------- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index bbb1ea5fa0..7d9d35b896 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -11,6 +11,7 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; @@ -72,6 +73,27 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); } + [Test] + public void TestCreateWithType() + { + createRoom(() => new Room + { + Name = { Value = "Test Room" }, + Type = { Value = MatchType.TeamVersus }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + } + } + }); + + AddAssert("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus); + AddAssert("user state arrived", () => client.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState); + } + [Test] public void TestChangeTypeViaMatchSettings() { diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index fed4564500..bffb2d341a 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -142,6 +142,8 @@ namespace osu.Game.Online.Multiplayer APIRoom = room; foreach (var user in joinedRoom.Users) updateUserPlayingState(user.UserID, user.State); + + OnRoomJoined(); }, cancellationSource.Token).ConfigureAwait(false); // Update room settings. @@ -149,6 +151,13 @@ namespace osu.Game.Online.Multiplayer }, cancellationSource.Token).ConfigureAwait(false); } + /// + /// Fired when the room join sequence is complete + /// + protected virtual void OnRoomJoined() + { + } + /// /// Joins the with a given ID. /// diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 9826d24d01..43aadf5acb 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -153,6 +153,14 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.FromResult(room); } + protected override void OnRoomJoined() + { + Debug.Assert(Room != null); + + // emulate the server sending this after the join room. scheduler required to make sure the join room event is fired first (in Join). + changeMatchType(Room.Settings.MatchType).Wait(); + } + protected override Task LeaveRoomInternal() => Task.CompletedTask; public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId); @@ -166,22 +174,7 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready)) ChangeUserState(user.UserID, MultiplayerUserState.Idle); - switch (settings.MatchType) - { - case MatchType.HeadToHead: - await ((IMultiplayerClient)this).MatchRoomStateChanged(null).ConfigureAwait(false); - - foreach (var user in Room.Users) - await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, null).ConfigureAwait(false); - break; - - case MatchType.TeamVersus: - await ((IMultiplayerClient)this).MatchRoomStateChanged(TeamVersusRoomState.CreateDefault()).ConfigureAwait(false); - - foreach (var user in Room.Users) - await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, new TeamVersusUserState()).ConfigureAwait(false); - break; - } + await changeMatchType(settings.MatchType).ConfigureAwait(false); } public override Task ChangeState(MultiplayerUserState newState) @@ -260,5 +253,27 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.FromResult(set); } + + private async Task changeMatchType(MatchType type) + { + Debug.Assert(Room != null); + + switch (type) + { + case MatchType.HeadToHead: + await ((IMultiplayerClient)this).MatchRoomStateChanged(null).ConfigureAwait(false); + + foreach (var user in Room.Users) + await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, null).ConfigureAwait(false); + break; + + case MatchType.TeamVersus: + await ((IMultiplayerClient)this).MatchRoomStateChanged(TeamVersusRoomState.CreateDefault()).ConfigureAwait(false); + + foreach (var user in Room.Users) + await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, new TeamVersusUserState()).ConfigureAwait(false); + break; + } + } } } From 69e6c08cc26594947b039a5a4cfc05b489a808d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 17:26:10 +0900 Subject: [PATCH 229/600] Add test coverage of changing teams via clicking --- .../Visual/Multiplayer/TestSceneTeamVersus.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 7d9d35b896..e19665497d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -19,6 +19,7 @@ using osu.Game.Screens; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; +using osu.Game.Screens.OnlinePlay.Multiplayer.Participants; using osu.Game.Tests.Resources; using osuTK.Input; @@ -94,6 +95,36 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("user state arrived", () => client.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState); } + [Test] + public void TestChangeTeamsViaButton() + { + createRoom(() => new Room + { + Name = { Value = "Test Room" }, + Type = { Value = MatchType.TeamVersus }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + } + } + }); + + AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + + AddStep("press button", () => + { + InputManager.MoveMouseTo(multiplayerScreen.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1); + + AddStep("press button", () => InputManager.Click(MouseButton.Left)); + AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + } + [Test] public void TestChangeTypeViaMatchSettings() { From aa320c70a71254e00e267495467f6bc7687f08a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Aug 2021 23:13:12 +0900 Subject: [PATCH 230/600] Improve show/hide animation and add more padding around the crown --- .../Multiplayer/Participants/ParticipantPanel.cs | 2 +- .../Multiplayer/Participants/TeamDisplay.cs | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index b2de9763ee..89431445d3 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { - new Dimension(GridSizeMode.Absolute, 14), + new Dimension(GridSizeMode.Absolute, 18), new Dimension(GridSizeMode.AutoSize), new Dimension() }, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs index fd4ce404f1..5a7073f9de 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs @@ -36,6 +36,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Width = 15; Margin = new MarginPadding { Horizontal = 3 }; + + Alpha = 0; + Scale = new Vector2(0, 1); } [BackgroundDependencyLoader] @@ -46,7 +49,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants RelativeSizeAxes = Axes.Both, CornerRadius = 5, Masking = true, - Alpha = 0, Scale = new Vector2(0, 1), Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -104,14 +106,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants if (displayedTeam != null) { - box.FadeIn(duration); box.FadeColour(getColourForTeam(displayedTeam.Value), duration, Easing.OutQuint); box.ScaleTo(new Vector2(box.Scale.X < 0 ? 1 : -1, 1), duration, Easing.OutQuint); + + this.ScaleTo(Vector2.One, duration, Easing.OutQuint); + this.FadeIn(duration); } else { - box.ScaleTo(new Vector2(0, 1), duration, Easing.OutQuint); - box.FadeOut(duration); + this.ScaleTo(new Vector2(0, 1), duration, Easing.OutQuint); + this.FadeOut(duration); } } From cb72667aa844e19d053074686fed562b6f2a45c3 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 3 Aug 2021 22:10:33 +0700 Subject: [PATCH 231/600] add typeface inter in osu font --- osu.Game/Graphics/OsuFont.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 7c78141b4d..b6090d0e1a 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -21,6 +21,8 @@ namespace osu.Game.Graphics public static FontUsage Torus => GetFont(Typeface.Torus, weight: FontWeight.Regular); + public static FontUsage Inter => GetFont(Typeface.Inter, weight: FontWeight.Regular); + /// /// Retrieves a . /// @@ -54,6 +56,9 @@ namespace osu.Game.Graphics case Typeface.Torus: return "Torus"; + + case Typeface.Inter: + return "Inter"; } return null; @@ -107,7 +112,8 @@ namespace osu.Game.Graphics public enum Typeface { Venera, - Torus + Torus, + Inter, } public enum FontWeight From ed94266a5d9a8d8845592372c2b6037a1bd8e778 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 3 Aug 2021 22:14:44 +0700 Subject: [PATCH 232/600] change markdown container font --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 2 +- osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 81f30bd406..296c600771 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Graphics.Containers.Markdown public override SpriteText CreateSpriteText() => new OsuSpriteText { - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(Typeface.Inter, size: 14, weight: FontWeight.Regular), }; public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index a3a86df678..e4685a2935 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -70,7 +70,7 @@ namespace osu.Game.Graphics.Containers.Markdown public FontWeight FontWeight; protected override SpriteText CreateSpriteText() - => base.CreateSpriteText().With(t => t.Font = t.Font.With(size: FontSize, weight: FontWeight)); + => base.CreateSpriteText().With(t => t.Font = t.Font.With(Typeface.Torus, size: FontSize, weight: FontWeight)); } } } From d22f2ececbf007d27bc05dee4b8acb560d752460 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 3 Aug 2021 22:17:45 +0700 Subject: [PATCH 233/600] adjust wiki main page font --- osu.Game/Overlays/Wiki/WikiMainPage.cs | 2 +- osu.Game/Overlays/Wiki/WikiPanelContainer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Wiki/WikiMainPage.cs b/osu.Game/Overlays/Wiki/WikiMainPage.cs index c4c0b83ef4..3fb0aa450e 100644 --- a/osu.Game/Overlays/Wiki/WikiMainPage.cs +++ b/osu.Game/Overlays/Wiki/WikiMainPage.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Wiki Child = new OsuSpriteText { Text = blurbNode.InnerText, - Font = OsuFont.GetFont(size: 12), + Font = OsuFont.GetFont(Typeface.Inter, size: 12, weight: FontWeight.Light), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, } diff --git a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs index e1c00a955b..7e7e005586 100644 --- a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs +++ b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs @@ -89,7 +89,7 @@ namespace osu.Game.Overlays.Wiki DocumentMargin = new MarginPadding(0); } - public override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(weight: FontWeight.Bold)); + public override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(Typeface.Torus, weight: FontWeight.Bold)); public override MarkdownTextFlowContainer CreateTextFlow() => base.CreateTextFlow().With(f => f.TextAnchor = Anchor.TopCentre); From b5970d5cdcc18a35603b0f788cfe433ff2a8511c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 01:40:39 +0300 Subject: [PATCH 234/600] Handle pitch black background case --- .../Screens/Ranking/Expanded/StarRatingDisplay.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 9d325768f3..2b86100be8 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -23,6 +23,7 @@ namespace osu.Game.Screens.Ranking.Expanded public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { private Box background; + private FillFlowContainer content; private OsuTextFlowContainer textFlow; [Resolved] @@ -64,7 +65,7 @@ namespace osu.Game.Screens.Ranking.Expanded }, } }, - new FillFlowContainer + content = new FillFlowContainer { AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, @@ -78,7 +79,6 @@ namespace osu.Game.Screens.Ranking.Expanded Origin = Anchor.CentreLeft, Size = new Vector2(7), Icon = FontAwesome.Solid.Star, - Colour = Color4.Black }, textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { @@ -107,19 +107,20 @@ namespace osu.Game.Screens.Ranking.Expanded string fractionPart = starRatingParts[1]; string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - background.Colour = colours.ForStarDifficulty(Current.Value.Stars); + var stars = Current.Value.Stars; + + background.Colour = colours.ForStarDifficulty(stars); + content.Colour = stars >= 6.5 ? colours.Orange1 : Color4.Black; textFlow.Clear(); textFlow.AddText($"{wholePart}", s => { - s.Colour = Color4.Black; s.Font = s.Font.With(size: 14); s.UseFullGlyphHeight = false; }); textFlow.AddText($"{separator}{fractionPart}", s => { - s.Colour = Color4.Black; s.Font = s.Font.With(size: 7); s.UseFullGlyphHeight = false; }); From 4e303b2aa1b96fa20b2b97d1666393d129efb1f5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 01:52:26 +0300 Subject: [PATCH 235/600] Add xmldoc and source link --- osu.Game/Graphics/OsuColour.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 222300d018..98629a538e 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -17,6 +17,12 @@ namespace osu.Game.Graphics public static Color4 Gray(float amt) => new Color4(amt, amt, amt, 1f); public static Color4 Gray(byte amt) => new Color4(amt, amt, amt, 255); + /// + /// Retrieves the colour for a . + /// + /// + /// Sourced from the @diff-{rating} variables in https://github.com/ppy/osu-web/blob/71fbab8936d79a7929d13854f5e854b4f383b236/resources/assets/less/variables.less. + /// public Color4 ForDifficultyRating(DifficultyRating difficulty, bool useLighterColour = false) { switch (difficulty) From 65db9d664e19ecc115a11b1689ed6b146650b9f8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 01:52:34 +0300 Subject: [PATCH 236/600] Match osu-web colour for `DifficultyRating.Hard` --- osu.Game/Graphics/OsuColour.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 98629a538e..d6c5bc8754 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -34,7 +34,7 @@ namespace osu.Game.Graphics return Color4Extensions.FromHex("66ff91"); case DifficultyRating.Hard: - return Color4Extensions.FromHex("f7e75d"); + return Color4Extensions.FromHex("f7e85d"); case DifficultyRating.Insane: return Color4Extensions.FromHex("ff7e68"); From bec0f379a7cd050692d8f221160eeb345b6b5b5c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 02:13:19 +0300 Subject: [PATCH 237/600] Round star difficulty to two fractional digits during sampling --- osu.Game/Graphics/OsuColour.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index d6c5bc8754..1f87c06dd2 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -61,7 +61,7 @@ namespace osu.Game.Graphics (7.0f, Color4Extensions.FromHex("6563de")), (8.0f, Color4Extensions.FromHex("18158e")), (8.0f, Color4.Black), - }, (float)starDifficulty); + }, (float)Math.Round(starDifficulty, 2, MidpointRounding.AwayFromZero)); /// /// Retrieves the colour for a . From 401835a3d892ec1287183863ce42370a2afcda9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Aug 2021 13:13:47 +0900 Subject: [PATCH 238/600] Add missing event glue --- osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 00f30463a5..8b8d10ce4f 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -60,6 +60,7 @@ namespace osu.Game.Online.Multiplayer connection.On(nameof(IMultiplayerClient.UserBeatmapAvailabilityChanged), ((IMultiplayerClient)this).UserBeatmapAvailabilityChanged); connection.On(nameof(IMultiplayerClient.MatchRoomStateChanged), ((IMultiplayerClient)this).MatchRoomStateChanged); connection.On(nameof(IMultiplayerClient.MatchUserStateChanged), ((IMultiplayerClient)this).MatchUserStateChanged); + connection.On(nameof(IMultiplayerClient.MatchEvent), ((IMultiplayerClient)this).MatchEvent); }; IsConnected.BindTo(connector.IsConnected); From c06fffb56ac73219ba0f796fac0f5f39ac77ba93 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 4 Aug 2021 13:49:13 +0900 Subject: [PATCH 239/600] Increase background image resolution --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index c2955cec94..3112b2cc30 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -190,7 +190,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"#27302E"), }, - new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) + new OnlinePlayBackgroundSprite(BeatmapSetCoverType.Cover) { RelativeSizeAxes = Axes.Both }, From c76edd888716fbe6c0a33c00d97d4897258dffd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Aug 2021 17:24:13 +0900 Subject: [PATCH 240/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 1866acd248..591db6e2c2 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4b0edf990e..0c26bce8c9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index e4992e1132..b7f252820c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 9b9dacf3fe1d2cf5f8d89c9976140323449200b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Aug 2021 17:27:44 +0900 Subject: [PATCH 241/600] Update usages of `Drawable.Click()` --- .../Visual/Editing/TestSceneHitObjectComposer.cs | 2 +- .../Visual/Gameplay/TestSceneGameplayMenuOverlay.cs | 2 +- .../Multiplayer/TestSceneLoungeRoomsContainer.cs | 2 +- .../Visual/Multiplayer/TestSceneMultiplayer.cs | 6 +++--- .../Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs | 2 +- .../Visual/Online/TestSceneAccountCreationOverlay.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 2 +- .../Visual/Online/TestSceneShowMoreButton.cs | 6 +++--- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 6 +++--- .../Playlists/TestScenePlaylistsLoungeSubScreen.cs | 2 +- .../Playlists/TestScenePlaylistsRoomSubScreen.cs | 2 +- .../Visual/Settings/TestSceneKeyBindingPanel.cs | 4 ++-- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 4 ++-- .../Visual/UserInterface/TestSceneModSettings.cs | 2 +- .../Screens/TestSceneGameplayScreen.cs | 2 +- osu.Game/Graphics/UserInterface/BackButton.cs | 2 +- osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 2 +- osu.Game/Overlays/Comments/CommentEditor.cs | 2 +- osu.Game/Overlays/Dialog/PopupDialog.cs | 6 +++--- osu.Game/Overlays/DialogOverlay.cs | 2 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs | 2 +- osu.Game/Screens/Menu/ButtonSystem.cs | 10 +++++----- .../OnlinePlay/Lounge/Components/DrawableRoom.cs | 2 +- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 4 ++-- osu.Game/Screens/Play/PauseOverlay.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 2 +- osu.Game/Screens/Select/FooterButton.cs | 2 +- osu.Game/Screens/Select/FooterButtonRandom.cs | 2 +- .../Screens/Select/Options/BeatmapOptionsOverlay.cs | 2 +- 32 files changed, 48 insertions(+), 48 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index 550896270a..c758bd1707 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("Hitcircle button not clickable", () => !hitObjectComposer.ChildrenOfType().First(d => d.Button.Label == "HitCircle").Enabled.Value); AddStep("Add timing point", () => editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint())); AddAssert("Hitcircle button is clickable", () => hitObjectComposer.ChildrenOfType().First(d => d.Button.Label == "HitCircle").Enabled.Value); - AddStep("Change to hitcircle", () => hitObjectComposer.ChildrenOfType().First(d => d.Button.Label == "HitCircle").Click()); + AddStep("Change to hitcircle", () => hitObjectComposer.ChildrenOfType().First(d => d.Button.Label == "HitCircle").TriggerClick()); AddAssert("Tool changed", () => hitObjectComposer.ChildrenOfType().First().CurrentTool is HitCircleCompositionTool); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index ed40a83831..477ac70501 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -228,7 +228,7 @@ namespace osu.Game.Tests.Visual.Gameplay var lastAction = pauseOverlay.OnRetry; pauseOverlay.OnRetry = () => triggered = true; - getButton(1).Click(); + getButton(1).TriggerClick(); pauseOverlay.OnRetry = lastAction; }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 0a23550f5d..bcbdcd2a4f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("has 2 rooms", () => container.Rooms.Count == 2); AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0)); - AddStep("select first room", () => container.Rooms.First().Click()); + AddStep("select first room", () => container.Rooms.First().TriggerClick()); AddAssert("first room selected", () => checkRoomSelected(RoomManager.Rooms.First())); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 7c151ffac3..a535f8c3c3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -209,7 +209,7 @@ namespace osu.Game.Tests.Visual.Multiplayer DrawableRoom.PasswordEntryPopover passwordEntryPopover = null; AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "password"); - AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().Click()); + AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddUntilStep("wait for join", () => client.Room != null); @@ -373,7 +373,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddStep("open mod overlay", () => this.ChildrenOfType().ElementAt(2).Click()); + AddStep("open mod overlay", () => this.ChildrenOfType().ElementAt(2).TriggerClick()); AddStep("invoke on back button", () => multiplayerScreen.OnBackButton()); @@ -381,7 +381,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden); - testLeave("lounge tab item", () => this.ChildrenOfType.BreadcrumbTabItem>().First().Click()); + testLeave("lounge tab item", () => this.ChildrenOfType.BreadcrumbTabItem>().First().TriggerClick()); testLeave("back button", () => multiplayerScreen.OnBackButton()); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index 4ea635fd3e..c66d5429d6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("attempt join room", () => InputManager.Key(Key.Enter)); AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "password"); - AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().Click()); + AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); AddAssert("room join requested", () => lastJoinedRoom == RoomManager.Rooms.First()); AddAssert("room join password correct", () => lastJoinedPassword == "password"); diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 437c5b07c9..06cc613c17 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("show manually", () => accountCreation.Show()); AddUntilStep("overlay is visible", () => accountCreation.State.Value == Visibility.Visible); - AddStep("click button", () => accountCreation.ChildrenOfType().Single().Click()); + AddStep("click button", () => accountCreation.ChildrenOfType().Single().TriggerClick()); AddUntilStep("warning screen is present", () => accountCreation.ChildrenOfType().SingleOrDefault()?.IsPresent == true); AddStep("log back in", () => API.Login("dummy", "password")); diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 93a5b6fc59..f94c018b27 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show", () => overlay.Show()); AddUntilStep("Show More button is visible", () => showMoreButton?.Alpha == 1); setUpNewsResponse(responseWithNoCursor, "Set up no cursor response"); - AddStep("Click Show More", () => showMoreButton?.Click()); + AddStep("Click Show More", () => showMoreButton?.TriggerClick()); AddUntilStep("Show More button is hidden", () => showMoreButton?.Alpha == 0); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index 18ac415126..d7fa5a1f6d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -32,19 +32,19 @@ namespace osu.Game.Tests.Visual.Online } }); - AddStep("click button", () => button.Click()); + AddStep("click button", () => button.TriggerClick()); AddAssert("action fired once", () => fireCount == 1); AddAssert("is in loading state", () => button.IsLoading); - AddStep("click button", () => button.Click()); + AddStep("click button", () => button.TriggerClick()); AddAssert("action not fired", () => fireCount == 1); AddAssert("is in loading state", () => button.IsLoading); AddUntilStep("wait for loaded", () => !button.IsLoading); - AddStep("click button", () => button.Click()); + AddStep("click button", () => button.TriggerClick()); AddAssert("action fired twice", () => fireCount == 2); AddAssert("is in loading state", () => button.IsLoading); diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index e9e826e62f..a9fed7b302 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Log in", logIn); AddStep("User comment", () => addVotePill(getUserComment())); AddAssert("Background is transparent", () => votePill.Background.Alpha == 0); - AddStep("Click", () => votePill.Click()); + AddStep("Click", () => votePill.TriggerClick()); AddAssert("Not loading", () => !votePill.IsLoading); } @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Log in", logIn); AddStep("Random comment", () => addVotePill(getRandomComment())); AddAssert("Background is visible", () => votePill.Background.Alpha == 1); - AddStep("Click", () => votePill.Click()); + AddStep("Click", () => votePill.TriggerClick()); AddAssert("Loading", () => votePill.IsLoading); } @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Hide login overlay", () => login.Hide()); AddStep("Log out", API.Logout); AddStep("Random comment", () => addVotePill(getRandomComment())); - AddStep("Click", () => votePill.Click()); + AddStep("Click", () => votePill.TriggerClick()); AddAssert("Login overlay is visible", () => login.State.Value == Visibility.Visible); } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 79ba6d9660..ecdb046203 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Visual.Playlists AddUntilStep("first room is not masked", () => checkRoomVisible(roomsContainer.Rooms[0])); - AddStep("select last room", () => roomsContainer.Rooms[^1].Click()); + AddStep("select last room", () => roomsContainer.Rooms[^1].TriggerClick()); AddUntilStep("first room is masked", () => !checkRoomVisible(roomsContainer.Rooms[0])); AddUntilStep("last room is not masked", () => checkRoomVisible(roomsContainer.Rooms[^1])); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index f2bfb80beb..9fc29049ef 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Playlists }); }); - AddStep("start match", () => match.ChildrenOfType().First().Click()); + AddStep("start match", () => match.ChildrenOfType().First().TriggerClick()); AddUntilStep("player loader loaded", () => Stack.CurrentScreen is PlayerLoader); } diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index 54293485cb..fa2c9ecdea 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.Settings { var resetButton = settingsKeyBindingRow.ChildrenOfType>().First(); - resetButton.Click(); + resetButton.TriggerClick(); }); AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha == 0); @@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Settings { var resetButton = panel.ChildrenOfType().First(); - resetButton.Click(); + resetButton.TriggerClick(); }); AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha == 0); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 1e76c33fca..32c1d262d5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -94,10 +94,10 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("selected mod matches", () => (SelectedMods.Value.Single() as OsuModDoubleTime)?.SpeedChange.Value == 1.2); - AddStep("deselect", () => modSelect.DeselectAllButton.Click()); + AddStep("deselect", () => modSelect.DeselectAllButton.TriggerClick()); AddAssert("selected mods empty", () => SelectedMods.Value.Count == 0); - AddStep("reselect", () => modSelect.GetModButton(osuModDoubleTime).Click()); + AddStep("reselect", () => modSelect.GetModButton(osuModDoubleTime).TriggerClick()); AddAssert("selected mod has default value", () => (SelectedMods.Value.Single() as OsuModDoubleTime)?.SpeedChange.IsDefault == true); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 65db2e9644..84e2ebb6d8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait for button load", () => modSelect.ButtonsLoaded); AddStep("select mod", () => modSelect.SelectMod(testCustomisableMod)); AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); - AddStep("open Customisation", () => modSelect.CustomiseButton.Click()); + AddStep("open Customisation", () => modSelect.CustomiseButton.TriggerClick()); AddStep("deselect mod", () => modSelect.SelectMod(testCustomisableMod)); AddAssert("controls hidden", () => modSelect.ModSettingsContainer.State.Value == Visibility.Hidden); } diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index 522567584d..2e34c39370 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -40,6 +40,6 @@ namespace osu.Game.Tournament.Tests.Screens () => this.ChildrenOfType().All(score => score.Alpha == (visible ? 1 : 0))); private void toggleWarmup() - => AddStep("toggle warmup", () => this.ChildrenOfType().First().Click()); + => AddStep("toggle warmup", () => this.ChildrenOfType().First().TriggerClick()); } } diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index b8196c6360..1607762908 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -35,7 +35,7 @@ namespace osu.Game.Graphics.UserInterface Add(receptor = new Receptor()); } - receptor.OnBackPressed = () => button.Click(); + receptor.OnBackPressed = () => button.TriggerClick(); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index a5e5f664c9..5b3c142a66 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }; - Action = () => playButton.Click(); + Action = () => playButton.TriggerClick(); Playing.ValueChanged += playing => progress.FadeTo(playing.NewValue ? 1 : 0, 100); } diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 58b402c164..9d2cd8a21d 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -153,7 +153,7 @@ namespace osu.Game.Overlays.Chat.Tabs switch (e.Button) { case MouseButton.Middle: - CloseButton.Click(); + CloseButton.TriggerClick(); break; } } diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 7b4bf882dc..20a8ab64f7 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -120,7 +120,7 @@ namespace osu.Game.Overlays.Comments if (commitButton.IsBlocked.Value) return; - commitButton.Click(); + commitButton.TriggerClick(); }; } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index cd02900e88..78ef2ec795 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -218,7 +218,7 @@ namespace osu.Game.Overlays.Dialog /// /// Programmatically clicks the first . /// - public void PerformOkAction() => Buttons.OfType().First().Click(); + public void PerformOkAction() => Buttons.OfType().First().TriggerClick(); protected override bool OnKeyDown(KeyDownEvent e) { @@ -265,7 +265,7 @@ namespace osu.Game.Overlays.Dialog if (!actionInvoked && content.IsPresent) // In the case a user did not choose an action before a hide was triggered, press the last button. // This is presumed to always be a sane default "cancel" action. - buttonsContainer.Last().Click(); + buttonsContainer.Last().TriggerClick(); content.FadeOut(EXIT_DURATION, Easing.InSine); } @@ -273,7 +273,7 @@ namespace osu.Game.Overlays.Dialog private void pressButtonAtIndex(int index) { if (index < Buttons.Count()) - Buttons.Skip(index).First().Click(); + Buttons.Skip(index).First().TriggerClick(); } } } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index bc3b0e6c9a..43ef42a809 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -88,7 +88,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Select: - CurrentDialog?.Buttons.OfType().FirstOrDefault()?.Click(); + CurrentDialog?.Buttons.OfType().FirstOrDefault()?.TriggerClick(); return true; } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 793bb79318..96eba7808f 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -404,11 +404,11 @@ namespace osu.Game.Overlays.Mods switch (e.Key) { case Key.Number1: - DeselectAllButton.Click(); + DeselectAllButton.TriggerClick(); return true; case Key.Number2: - CloseButton.Click(); + CloseButton.TriggerClick(); return true; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 4a33f9e296..6da41b2b5f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -188,7 +188,7 @@ namespace osu.Game.Overlays.Toolbar { if (action == Hotkey) { - Click(); + TriggerClick(); return true; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs index 564fd65719..a70a0d8a71 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnClick(ClickEvent e) { - Parent.Click(); + Parent.TriggerClick(); return base.OnClick(e); } } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index bdb0157746..6c712e9d5b 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -210,7 +210,7 @@ namespace osu.Game.Screens.Menu { if (buttonsTopLevel.Any(b => e.Key == b.TriggerKey)) { - logo?.Click(); + logo?.TriggerClick(); return true; } } @@ -226,7 +226,7 @@ namespace osu.Game.Screens.Menu return goBack(); case GlobalAction.Select: - logo?.Click(); + logo?.TriggerClick(); return true; default: @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Menu return true; case ButtonSystemState.Play: - backButton.Click(); + backButton.TriggerClick(); return true; default: @@ -268,11 +268,11 @@ namespace osu.Game.Screens.Menu return true; case ButtonSystemState.TopLevel: - buttonsTopLevel.First().Click(); + buttonsTopLevel.First().TriggerClick(); return false; case ButtonSystemState.Play: - buttonsPlay.First().Click(); + buttonsPlay.First().TriggerClick(); return false; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index adff1cc33e..c455cb0c50 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -262,7 +262,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components switch (action) { case GlobalAction.Select: - Click(); + TriggerClick(); return true; } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 2608c93fa1..ce1f223403 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -42,12 +42,12 @@ namespace osu.Game.Screens.Play /// /// Action that is invoked when is triggered. /// - protected virtual Action BackAction => () => InternalButtons.Children.LastOrDefault()?.Click(); + protected virtual Action BackAction => () => InternalButtons.Children.LastOrDefault()?.TriggerClick(); /// /// Action that is invoked when is triggered. /// - protected virtual Action SelectAction => () => InternalButtons.Selected?.Click(); + protected virtual Action SelectAction => () => InternalButtons.Selected?.TriggerClick(); public abstract string Header { get; } diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 8778cff535..e0b7e5c941 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play private SkinnableSound pauseLoop; - protected override Action BackAction => () => InternalButtons.Children.First().Click(); + protected override Action BackAction => () => InternalButtons.Children.First().TriggerClick(); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index ed49fc40b2..4a74fa1d4f 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -148,7 +148,7 @@ namespace osu.Game.Screens.Play if (!button.Enabled.Value) return false; - button.Click(); + button.TriggerClick(); return true; } diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index c3fbd767ff..9c0a68133c 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Select { if (action == Hotkey) { - Click(); + TriggerClick(); return true; } diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index 2d14111137..1eaf2c591e 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Select return false; } - Click(); + TriggerClick(); return true; } diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 2676635764..b5fdbd225f 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -122,7 +122,7 @@ namespace osu.Game.Screens.Select.Options if (found != null) { - found.Click(); + found.TriggerClick(); return true; } } From 3b6771ca65514060935b5b34bab8da8d3b31e25e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 4 Aug 2021 22:09:03 +0900 Subject: [PATCH 242/600] Remove todo --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 0b19e2df1c..06c95dcb7d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -359,7 +359,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomCategory.BindTo(Room.Category); roomCategory.BindValueChanged(c => { - // Todo: Tournament category... if (c.NewValue == RoomCategory.Spotlight) specialCategoryPill.Show(); else From a01402664f341be9bc04ffbb9811ee6d40cbbdae Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 13 Jul 2021 05:22:11 +0300 Subject: [PATCH 243/600] Add redesigned star rating display Matching the same design as the one in the latest figma designs. --- .../Beatmaps/Drawables/StarRatingDisplayV2.cs | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs new file mode 100644 index 0000000000..aa411e74bd --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -0,0 +1,99 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Beatmaps.Drawables +{ + public class StarRatingDisplayV2 : CompositeDrawable, IHasCurrentValue + { + private readonly Box background; + private readonly SpriteIcon starIcon; + private readonly OsuSpriteText starsText; + + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + + [Resolved] + private OsuColour colours { get; set; } + + [Resolved(canBeNull: true)] + private OverlayColourProvider colourProvider { get; set; } + + /// + /// Creates a new using an already computed . + /// + /// The already computed to display the star difficulty of. + public StarRatingDisplayV2(StarDifficulty starDifficulty) + { + Size = new Vector2(52f, 20f); + + Current.Value = starDifficulty; + + InternalChild = new CircularContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + starIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Right = 30f }, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(8f), + }, + starsText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Left = 10f, Bottom = 1f }, + Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(c => + { + starsText.Text = c.NewValue.Stars.ToString("0.00"); + + background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); + + starIcon.Colour = c.NewValue.Stars >= 7.5 + ? colourProvider?.Content1 ?? Color4.White + : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + + starsText.Colour = c.NewValue.Stars >= 7.5 + ? colourProvider?.Content1 ?? Color4.White.Opacity(0.75f) + : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + }, true); + } + } +} From 6c9ed16b0caa5e29f436d58c388ada3ab34e31b1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 13 Jul 2021 05:29:16 +0300 Subject: [PATCH 244/600] Add visual test scene --- .../TestSceneStarRatingDisplayV2.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs new file mode 100644 index 0000000000..1b85e25e92 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneStarRatingDisplayV2 : OsuTestScene + { + [Test] + public void TestDisplay() + { + AddStep("load displays", () => + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2f), + Direction = FillDirection.Horizontal, + ChildrenEnumerable = Enumerable.Range(0, 10).Select(i => new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2f), + Direction = FillDirection.Vertical, + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplayV2(new StarDifficulty(i + j * 0.1f, 0)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }) + }) + }; + }); + } + + [Test] + public void TestChangingStarRatingDisplay() + { + StarRatingDisplayV2 starRating = null; + + AddStep("load display", () => Child = starRating = new StarRatingDisplayV2(new StarDifficulty(5.55, 1)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddRepeatStep("set random value", () => + { + starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), 1); + }, 10); + + AddSliderStep("set exact stars", 0.0, 11.0, 5.55, d => + { + if (starRating != null) + starRating.Current.Value = new StarDifficulty(d, 1); + }); + } + } +} From 19d54ee7510d0a4d594b0897e22fd39e45c3b9e5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Jul 2021 01:59:32 +0300 Subject: [PATCH 245/600] Update light background handling to `Color4.Yellow` instead Confirmed to be the way forward in https://github.com/ppy/osu-web/pull/7855#issuecomment-880959644. --- osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs index aa411e74bd..6154c8e811 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -86,13 +86,8 @@ namespace osu.Game.Beatmaps.Drawables background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); - starIcon.Colour = c.NewValue.Stars >= 7.5 - ? colourProvider?.Content1 ?? Color4.White - : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); - - starsText.Colour = c.NewValue.Stars >= 7.5 - ? colourProvider?.Content1 ?? Color4.White.Opacity(0.75f) - : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + starIcon.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + starsText.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); }, true); } } From 95b134f3d82ff42868c6726dcd0ad22220efe327 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 05:41:34 +0300 Subject: [PATCH 246/600] Use `OsuColour.Orange1` instead of pure yellow --- osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs index 6154c8e811..5a942cdeee 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -86,8 +86,8 @@ namespace osu.Game.Beatmaps.Drawables background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); - starIcon.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); - starsText.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); }, true); } } From 14da5ab813d1d7fe523827a59de535c2846d9298 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 05:43:04 +0300 Subject: [PATCH 247/600] Remove defined size from the star rating display --- osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs index 5a942cdeee..e8961ae414 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -43,8 +43,6 @@ namespace osu.Game.Beatmaps.Drawables /// The already computed to display the star difficulty of. public StarRatingDisplayV2(StarDifficulty starDifficulty) { - Size = new Vector2(52f, 20f); - Current.Value = starDifficulty; InternalChild = new CircularContainer From 0a8d37defa3a167ae725f62c9ab39799f03449bd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 05:48:38 +0300 Subject: [PATCH 248/600] Test star rating display with multiple sizes --- .../Visual/UserInterface/TestSceneStarRatingDisplayV2.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs index 1b85e25e92..43178bb280 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs @@ -14,8 +14,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStarRatingDisplayV2 : OsuTestScene { - [Test] - public void TestDisplay() + [TestCase(52f, 20f)] + [TestCase(52f, 16f)] + [TestCase(50f, 14f)] + public void TestDisplay(float width, float height) { AddStep("load displays", () => { @@ -37,6 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Size = new Vector2(width, height), }) }) }; @@ -52,6 +55,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Size = new Vector2(52f, 20f), }); AddRepeatStep("set random value", () => From d4399f10f9b65bb737da9785ceb44a1bf10ef6e7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 06:54:11 +0300 Subject: [PATCH 249/600] Merge both variants of the star rating display --- .../Ranking/TestSceneStarRatingDisplay.cs | 65 --------- ...layV2.cs => TestSceneStarRatingDisplay.cs} | 36 ++++- ...atingDisplayV2.cs => StarRatingDisplay.cs} | 21 ++- .../Components/StarRatingRangeDisplay.cs | 12 +- .../Screens/Play/BeatmapMetadataDisplay.cs | 2 +- .../Expanded/ExpandedPanelMiddleContent.cs | 1 + .../Ranking/Expanded/StarRatingDisplay.cs | 129 ------------------ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 - 8 files changed, 56 insertions(+), 211 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs rename osu.Game.Tests/Visual/UserInterface/{TestSceneStarRatingDisplayV2.cs => TestSceneStarRatingDisplay.cs} (66%) rename osu.Game/Beatmaps/Drawables/{StarRatingDisplayV2.cs => StarRatingDisplay.cs} (75%) delete mode 100644 osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs deleted file mode 100644 index 566452249f..0000000000 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Linq; -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Utils; -using osu.Game.Beatmaps; -using osu.Game.Screens.Ranking.Expanded; -using osuTK; - -namespace osu.Game.Tests.Visual.Ranking -{ - public class TestSceneStarRatingDisplay : OsuTestScene - { - [Test] - public void TestDisplay() - { - AddStep("load displays", () => Child = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ChildrenEnumerable = new[] - { - 1.23, - 2.34, - 3.45, - 4.56, - 5.67, - 6.78, - 10.11, - }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }) - }); - } - - [Test] - public void TestChangingStarRatingDisplay() - { - StarRatingDisplay starRating = null; - - AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(3f), - }); - - AddRepeatStep("set random value", () => - { - starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), 1); - }, 10); - - AddSliderStep("set exact stars", 0.0, 11.0, 5.55, d => - { - if (starRating != null) - starRating.Current.Value = new StarDifficulty(d, 1); - }); - } - } -} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs similarity index 66% rename from osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 43178bb280..4c65500fbe 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -12,12 +12,36 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneStarRatingDisplayV2 : OsuTestScene + public class TestSceneStarRatingDisplay : OsuTestScene { + [Test] + public void TestOldColoursDisplay() + { + AddStep("load displays", () => Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + ChildrenEnumerable = new[] + { + 1.23, + 2.34, + 3.45, + 4.56, + 5.67, + 6.78, + 10.11, + }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }) + }); + } + [TestCase(52f, 20f)] [TestCase(52f, 16f)] [TestCase(50f, 14f)] - public void TestDisplay(float width, float height) + public void TestNewColoursDisplay(float width, float height) { AddStep("load displays", () => { @@ -35,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplayV2(new StarDifficulty(i + j * 0.1f, 0)) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0), true) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -47,11 +71,11 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestChangingStarRatingDisplay() + public void TestChangingStarRatingDisplay([Values(false, true)] bool useNewColours) { - StarRatingDisplayV2 starRating = null; + StarRatingDisplay starRating = null; - AddStep("load display", () => Child = starRating = new StarRatingDisplayV2(new StarDifficulty(5.55, 1)) + AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1), useNewColours) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs similarity index 75% rename from osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs rename to osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index e8961ae414..ed751c66de 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -17,8 +17,12 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class StarRatingDisplayV2 : CompositeDrawable, IHasCurrentValue + /// + /// A pill that displays the star rating of a beatmap. + /// + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { + private readonly bool useNewDifficultyColours; private readonly Box background; private readonly SpriteIcon starIcon; private readonly OsuSpriteText starsText; @@ -38,13 +42,18 @@ namespace osu.Game.Beatmaps.Drawables private OverlayColourProvider colourProvider { get; set; } /// - /// Creates a new using an already computed . + /// Creates a new using an already computed . /// - /// The already computed to display the star difficulty of. - public StarRatingDisplayV2(StarDifficulty starDifficulty) + /// The already computed to display. + /// Use the new spectrum-based difficulty colours for the display, rather than the old. + public StarRatingDisplay(StarDifficulty starDifficulty, bool useNewDifficultyColours = false) { + this.useNewDifficultyColours = useNewDifficultyColours; + Current.Value = starDifficulty; + Size = new Vector2(52f, 20f); + InternalChild = new CircularContainer { Masking = true, @@ -82,7 +91,9 @@ namespace osu.Game.Beatmaps.Drawables { starsText.Text = c.NewValue.Stars.ToString("0.00"); - background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); + background.Colour = useNewDifficultyColours + ? colours.ForStarDifficulty(c.NewValue.Stars) + : colours.ForDifficultyRating(c.NewValue.DifficultyRating); starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 8c1b10e3bd..6f5e48f09c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -8,14 +8,16 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Screens.Ranking.Expanded; using osuTK; namespace osu.Game.Screens.OnlinePlay.Components { public class StarRatingRangeDisplay : OnlinePlayComposite { + private readonly bool useNewDifficultyColours; + [Resolved] private OsuColour colours { get; set; } @@ -24,8 +26,10 @@ namespace osu.Game.Screens.OnlinePlay.Components private StarRatingDisplay maxDisplay; private Drawable maxBackground; - public StarRatingRangeDisplay() + public StarRatingRangeDisplay(bool useNewDifficultyColours = false) { + this.useNewDifficultyColours = useNewDifficultyColours; + AutoSizeAxes = Axes.Both; } @@ -62,8 +66,8 @@ namespace osu.Game.Screens.OnlinePlay.Components AutoSizeAxes = Axes.Both, Children = new Drawable[] { - minDisplay = new StarRatingDisplay(default), - maxDisplay = new StarRatingDisplay(default) + minDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) }, + maxDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) } } } }; diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 4265a83ce1..d77673580a 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -10,12 +10,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; -using osu.Game.Screens.Ranking.Expanded; using osuTK; namespace osu.Game.Screens.Play diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index e10fe5726d..bcb5e7999f 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs deleted file mode 100644 index 2b86100be8..0000000000 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Globalization; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Screens.Ranking.Expanded -{ - /// - /// A pill that displays the star rating of a . - /// - public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue - { - private Box background; - private FillFlowContainer content; - private OsuTextFlowContainer textFlow; - - [Resolved] - private OsuColour colours { get; set; } - - private readonly BindableWithCurrent current = new BindableWithCurrent(); - - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } - - /// - /// Creates a new using an already computed . - /// - /// The already computed to display the star difficulty of. - public StarRatingDisplay(StarDifficulty starDifficulty) - { - Current.Value = starDifficulty; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) - { - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - } - }, - content = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(2, 0), - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(7), - Icon = FontAwesome.Solid.Star, - }, - textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - TextAnchor = Anchor.BottomLeft, - } - } - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Current.BindValueChanged(_ => updateDisplay(), true); - } - - private void updateDisplay() - { - var starRatingParts = Current.Value.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - - var stars = Current.Value.Stars; - - background.Colour = colours.ForStarDifficulty(stars); - content.Colour = stars >= 6.5 ? colours.Orange1 : Color4.Black; - - textFlow.Clear(); - textFlow.AddText($"{wholePart}", s => - { - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - - textFlow.AddText($"{separator}{fractionPart}", s => - { - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - } - } -} diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 3779523094..67eb8220f7 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -28,7 +28,6 @@ using osu.Game.Extensions; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Ranking.Expanded; using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select From 42370e48ec3b06e4861cb56175f521faece1f033 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Jul 2021 08:20:06 +0300 Subject: [PATCH 250/600] Disable shadow on star display text --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index ed751c66de..96e830ccc3 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -78,6 +78,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, Margin = new MarginPadding { Left = 10f, Bottom = 1f }, Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), + Shadow = false, } } }; From 284fa496463bc3c5d718b141bf1dd81293705845 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Jul 2021 08:20:22 +0300 Subject: [PATCH 251/600] Bring margins of components closer to existing designs --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 96e830ccc3..2b555cc096 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -68,7 +68,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Right = 30f }, + Margin = new MarginPadding { Right = 26.5f }, Icon = FontAwesome.Solid.Star, Size = new Vector2(8f), }, @@ -76,7 +76,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 10f, Bottom = 1f }, + Margin = new MarginPadding { Left = 10f, Bottom = 1.5f }, Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), Shadow = false, } From 7f9af0ae658331cc424b4572791ea5312bc63013 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Jul 2021 08:21:27 +0300 Subject: [PATCH 252/600] Scale up "changing display" test cases --- .../Visual/UserInterface/TestSceneStarRatingDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 4c65500fbe..88f43cd701 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(52f, 20f), + Scale = new Vector2(3f), }); AddRepeatStep("set random value", () => From b2332eb5b38091c6ea175cb27ead4b3d8d04c06f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 17:06:07 +0300 Subject: [PATCH 253/600] Use new difficulty colours permanently --- .../TestSceneStarRatingDisplay.cs | 32 +++---------------- .../Beatmaps/Drawables/StarRatingDisplay.cs | 10 ++---- .../Components/StarRatingRangeDisplay.cs | 6 +--- 3 files changed, 7 insertions(+), 41 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 88f43cd701..2f3593c062 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -14,34 +14,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStarRatingDisplay : OsuTestScene { - [Test] - public void TestOldColoursDisplay() - { - AddStep("load displays", () => Child = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ChildrenEnumerable = new[] - { - 1.23, - 2.34, - 3.45, - 4.56, - 5.67, - 6.78, - 10.11, - }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }) - }); - } - [TestCase(52f, 20f)] [TestCase(52f, 16f)] [TestCase(50f, 14f)] - public void TestNewColoursDisplay(float width, float height) + public void TestDisplay(float width, float height) { AddStep("load displays", () => { @@ -59,7 +35,7 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0), true) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -71,11 +47,11 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestChangingStarRatingDisplay([Values(false, true)] bool useNewColours) + public void TestChangingStarRatingDisplay() { StarRatingDisplay starRating = null; - AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1), useNewColours) + AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 2b555cc096..0520cea17a 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -22,7 +22,6 @@ namespace osu.Game.Beatmaps.Drawables /// public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { - private readonly bool useNewDifficultyColours; private readonly Box background; private readonly SpriteIcon starIcon; private readonly OsuSpriteText starsText; @@ -45,11 +44,8 @@ namespace osu.Game.Beatmaps.Drawables /// Creates a new using an already computed . /// /// The already computed to display. - /// Use the new spectrum-based difficulty colours for the display, rather than the old. - public StarRatingDisplay(StarDifficulty starDifficulty, bool useNewDifficultyColours = false) + public StarRatingDisplay(StarDifficulty starDifficulty) { - this.useNewDifficultyColours = useNewDifficultyColours; - Current.Value = starDifficulty; Size = new Vector2(52f, 20f); @@ -92,9 +88,7 @@ namespace osu.Game.Beatmaps.Drawables { starsText.Text = c.NewValue.Stars.ToString("0.00"); - background.Colour = useNewDifficultyColours - ? colours.ForStarDifficulty(c.NewValue.Stars) - : colours.ForDifficultyRating(c.NewValue.DifficultyRating); + background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 6f5e48f09c..867fa88352 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -16,8 +16,6 @@ namespace osu.Game.Screens.OnlinePlay.Components { public class StarRatingRangeDisplay : OnlinePlayComposite { - private readonly bool useNewDifficultyColours; - [Resolved] private OsuColour colours { get; set; } @@ -26,10 +24,8 @@ namespace osu.Game.Screens.OnlinePlay.Components private StarRatingDisplay maxDisplay; private Drawable maxBackground; - public StarRatingRangeDisplay(bool useNewDifficultyColours = false) + public StarRatingRangeDisplay() { - this.useNewDifficultyColours = useNewDifficultyColours; - AutoSizeAxes = Axes.Both; } From b63d47259480ddc46579b76cb8505102f249000c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 18:17:02 +0300 Subject: [PATCH 254/600] Adjust font size to match designs Looks silly when using `12f`, I've added a todo comment so that this specific case does not get forgotten when CSS-compatible font sizing gets supported. The todo comment may not be 100% required but very unsure about silently changing it and forgetting about it. --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 0520cea17a..2c40aebbe1 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Right = 26.5f }, + Margin = new MarginPadding { Right = 30f }, Icon = FontAwesome.Solid.Star, Size = new Vector2(8f), }, @@ -72,8 +72,10 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 10f, Bottom = 1.5f }, - Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), + Margin = new MarginPadding { Left = 10f, Bottom = 2f }, + // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f + // see https://github.com/ppy/osu-framework/issues/3271. + Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), Shadow = false, } } From c84bd2c74dd75193d7cc8c2b80af7ee29a8787ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 13:22:59 +0900 Subject: [PATCH 255/600] Update new obsolete usages --- .../Screens/OnlinePlay/Match/Components/CreateRoomButton.cs | 2 +- .../OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs | 2 +- .../Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs index 711eaa0ca1..cd4dee5e3a 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components case PlatformAction.DocumentNew: // might as well also handle new tab. it's a bit of an undefined flow on this screen. case PlatformAction.TabNew: - Click(); + TriggerClick(); return true; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs index 6293751ac0..d1e2f20755 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match switch (action) { case GlobalAction.Select: - selectButton.Click(); + selectButton.TriggerClick(); return true; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index c3257f8d94..b03a2e0677 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -382,7 +382,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match switch (action) { case GlobalAction.Select: - Click(); + TriggerClick(); return true; } From 2ccf7e75b08a18d7cbacd6cd165b8edb3685bb85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 13:24:59 +0900 Subject: [PATCH 256/600] Fix new possible nullref inspection due to delegate initialisation in constructor --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index ce1f223403..0efa66bac0 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -61,8 +61,6 @@ namespace osu.Game.Screens.Play protected GameplayMenuOverlay() { RelativeSizeAxes = Axes.Both; - - State.ValueChanged += s => InternalButtons.Deselect(); } [BackgroundDependencyLoader] @@ -142,6 +140,8 @@ namespace osu.Game.Screens.Play }, }; + State.ValueChanged += s => InternalButtons.Deselect(); + updateRetryCount(); } From fd54487186b6ad4cb1ee7c3a30d051becefb4680 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 14:00:16 +0900 Subject: [PATCH 257/600] Add safety against pushing to non-current screen --- .../OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs | 6 +++++- .../Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs index d1e2f20755..fb17291bec 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs @@ -49,7 +49,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match RelativeSizeAxes = Axes.X, Height = 40, Text = "Select beatmap", - Action = () => matchSubScreen.Push(new MultiplayerMatchSongSelect()), + Action = () => + { + if (matchSubScreen.IsCurrentScreen()) + matchSubScreen.Push(new MultiplayerMatchSongSelect()); + }, Alpha = 0 } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 092394446b..45aca24ab2 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -230,7 +230,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists settingsOverlay = new PlaylistsMatchSettingsOverlay { RelativeSizeAxes = Axes.Both, - EditPlaylist = () => this.Push(new PlaylistsSongSelect()), + EditPlaylist = () => + { + if (this.IsCurrentScreen()) + this.Push(new PlaylistsSongSelect()); + }, State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden } } }); From 22bd6c7556dbd872a87348d48470768fbad87c55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 14:00:35 +0900 Subject: [PATCH 258/600] Move keyboard progress flow handling to `MatchSettingsOverlay` --- .../Match/Components/MatchSettingsOverlay.cs | 32 +++++++++++++++++- .../Match/BeatmapSelectionControl.cs | 26 ++------------- .../Match/MultiplayerMatchSettingsOverlay.cs | 33 ++++++------------- .../PlaylistsMatchSettingsOverlay.cs | 8 ++++- 4 files changed, 51 insertions(+), 48 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs index 61bb39d0c5..5b89685c4c 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs @@ -4,15 +4,17 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public abstract class MatchSettingsOverlay : FocusedOverlayContainer + public abstract class MatchSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler { protected const float TRANSITION_DURATION = 350; protected const float FIELD_PADDING = 45; @@ -21,6 +23,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override bool BlockScrollInput => false; + protected abstract OsuButton SubmitButton { get; } + [BackgroundDependencyLoader] private void load() { @@ -29,6 +33,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components Add(Settings = CreateSettings()); } + protected abstract void SelectBeatmap(); + protected abstract OnlinePlayComposite CreateSettings(); protected override void PopIn() @@ -41,6 +47,30 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); } + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Select: + if (SubmitButton.Enabled.Value) + { + SubmitButton.TriggerClick(); + return true; + } + else + { + SelectBeatmap(); + return true; + } + } + + return false; + } + + public void OnReleased(GlobalAction action) + { + } + protected class SettingsTextBox : OsuTextBox { [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs index fb17291bec..56b87302c2 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs @@ -5,15 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Bindings; using osu.Framework.Screens; -using osu.Game.Input.Bindings; using osu.Game.Online.API; using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class BeatmapSelectionControl : RoomSubScreenComposite, IKeyBindingHandler + public class BeatmapSelectionControl : RoomSubScreenComposite { [Resolved] private MultiplayerMatchSubScreen matchSubScreen { get; set; } @@ -74,6 +72,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match }, true); } + public void BeginSelection() => selectButton.TriggerClick(); + private void updateBeatmap() { if (SelectedItem.Value == null) @@ -81,25 +81,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match else beatmapPanelContainer.Child = new DrawableRoomPlaylistItem(SelectedItem.Value, false, false); } - - public bool OnPressed(GlobalAction action) - { - // only handle keyboard input if there is no current selection. - if (SelectedItem.Value != null) - return false; - - switch (action) - { - case GlobalAction.Select: - selectButton.TriggerClick(); - return true; - } - - return false; - } - - public void OnReleased(GlobalAction action) - { - } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index b03a2e0677..1ddac94b33 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -12,13 +12,11 @@ using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Input.Bindings; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays; @@ -30,8 +28,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay { + private MatchSettings settings; + + protected override OsuButton SubmitButton => settings.ApplyButton; + + protected override void SelectBeatmap() => settings.SelectBeatmap(); + protected override OnlinePlayComposite CreateSettings() - => new MatchSettings + => settings = new MatchSettings { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Y, @@ -56,6 +60,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private LoadingLayer loadingLayer; private BeatmapSelectionControl initialBeatmapControl; + public void SelectBeatmap() => initialBeatmapControl.BeginSelection(); + [Resolved] private IRoomManager manager { get; set; } @@ -355,7 +361,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match } } - public class CreateOrUpdateButton : TriangleButton, IKeyBindingHandler + public class CreateOrUpdateButton : TriangleButton { [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } @@ -373,25 +379,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match Triangles.ColourLight = colours.YellowLight; Triangles.ColourDark = colours.YellowDark; } - - public bool OnPressed(GlobalAction action) - { - if (!Enabled.Value) - return false; - - switch (action) - { - case GlobalAction.Select: - TriggerClick(); - return true; - } - - return false; - } - - public void OnReleased(GlobalAction action) - { - } } } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs index 88ac5ef6e5..3b680a378c 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs @@ -26,8 +26,14 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { public Action EditPlaylist; + private MatchSettings settings; + + protected override OsuButton SubmitButton => settings.ApplyButton; + + protected override void SelectBeatmap() => EditPlaylist(); + protected override OnlinePlayComposite CreateSettings() - => new MatchSettings + => settings = new MatchSettings { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Y, From bf720f7e06edcbd2ee49350a9cb701f3b42f8b0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 14:14:07 +0900 Subject: [PATCH 259/600] Ensure operations are not performed during loading --- .../OnlinePlay/Match/Components/MatchSettingsOverlay.cs | 5 +++++ .../Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs | 5 +++++ .../OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs index 5b89685c4c..2676453a7e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs @@ -25,6 +25,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected abstract OsuButton SubmitButton { get; } + protected abstract bool IsLoading { get; } + [BackgroundDependencyLoader] private void load() { @@ -52,6 +54,9 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components switch (action) { case GlobalAction.Select: + if (IsLoading) + return true; + if (SubmitButton.Enabled.Value) { SubmitButton.TriggerClick(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 1ddac94b33..9d4d6ae079 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -32,6 +32,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match protected override OsuButton SubmitButton => settings.ApplyButton; + [Resolved] + private OngoingOperationTracker ongoingOperationTracker { get; set; } + + protected override bool IsLoading => ongoingOperationTracker.InProgress.Value; + protected override void SelectBeatmap() => settings.SelectBeatmap(); protected override OnlinePlayComposite CreateSettings() diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs index 3b680a378c..9847903c48 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs @@ -30,6 +30,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override OsuButton SubmitButton => settings.ApplyButton; + protected override bool IsLoading => settings.IsLoading; // should probably be replaced with an OngoingOperationTracker. + protected override void SelectBeatmap() => EditPlaylist(); protected override OnlinePlayComposite CreateSettings() @@ -51,6 +53,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists public RoomAvailabilityPicker AvailabilityPicker; public TriangleButton ApplyButton; + public bool IsLoading => loadingLayer.State.Value == Visibility.Visible; + public OsuSpriteText ErrorText; private LoadingLayer loadingLayer; From 2b973b9831daca95b12de46381fb4bb1b451f62e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 14:21:51 +0900 Subject: [PATCH 260/600] Redirect beatmap selection to intentionally click the button directly --- .../OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs index 9847903c48..2640f99ea5 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override bool IsLoading => settings.IsLoading; // should probably be replaced with an OngoingOperationTracker. - protected override void SelectBeatmap() => EditPlaylist(); + protected override void SelectBeatmap() => settings.SelectBeatmap(); protected override OnlinePlayComposite CreateSettings() => settings = new MatchSettings @@ -61,6 +61,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private DrawableRoomPlaylist playlist; private OsuSpriteText playlistLength; + private PurpleTriangleButton editPlaylistButton; + [Resolved(CanBeNull = true)] private IRoomManager manager { get; set; } @@ -209,7 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, new Drawable[] { - new PurpleTriangleButton + editPlaylistButton = new PurpleTriangleButton { RelativeSizeAxes = Axes.X, Height = 40, @@ -302,6 +304,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists ApplyButton.Enabled.Value = hasValidSettings; } + public void SelectBeatmap() => editPlaylistButton.TriggerClick(); + private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) => playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}"; From 94aa5fbca7ad9b4fd924dc35528e67dca6417f4f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 16:31:34 +0900 Subject: [PATCH 261/600] Fix doubled json property (runtime error) --- osu.Game/Online/Rooms/Room.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index de90907552..4bd5b1a788 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -61,7 +61,7 @@ namespace osu.Game.Online.Rooms public readonly Bindable Availability = new Bindable(); [Cached] - [JsonProperty("type")] + [JsonIgnore] public readonly Bindable Type = new Bindable(); // Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106) From 27ff428491cc31ea8af72b9e31f90c27251c4b06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 17:33:19 +0900 Subject: [PATCH 262/600] Revert "Temporary changes to compile with latest framework" This reverts commit 34c671f712d71c8a3e3821d7dc45e46f055e8f1b. --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 4 +--- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 3 +-- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 5 ++--- osu.Game/Screens/Edit/EditorTable.cs | 4 +--- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 4b44c34c6d..ddd1dfa6cd 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -8,8 +8,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.EnumExtensions; -using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -217,7 +215,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class HeaderText : OsuSpriteText { - public HeaderText(LocalisableString text) + public HeaderText(string text) { Text = text.ToUpper(); Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold); diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 3f8779b97b..585b5c22aa 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -10,7 +10,6 @@ using osu.Framework.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Localisation; using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; @@ -110,7 +109,7 @@ namespace osu.Game.Overlays.Rankings.Tables { private readonly bool isHighlighted; - public HeaderText(LocalisableString text, bool isHighlighted) + public HeaderText(string text, bool isHighlighted) { this.isHighlighted = isHighlighted; diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index a77ce81c23..a6969f483f 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Users; @@ -20,7 +19,7 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected virtual IEnumerable GradeColumns => new List { "SS", "S", "A" }; + protected virtual IEnumerable GradeColumns => new List { "SS", "S", "A" }; protected override TableColumn[] CreateAdditionalHeaders() => new[] { @@ -67,7 +66,7 @@ namespace osu.Game.Overlays.Rankings.Tables private class UserTableHeaderText : HeaderText { - public UserTableHeaderText(LocalisableString text, bool isHighlighted, bool isGrade) + public UserTableHeaderText(string text, bool isHighlighted, bool isGrade) : base(text, isHighlighted) { Margin = new MarginPadding diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index 77c3a2f26c..9578b96897 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -2,12 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -48,7 +46,7 @@ namespace osu.Game.Screens.Edit private class HeaderText : OsuSpriteText { - public HeaderText(LocalisableString text) + public HeaderText(string text) { Text = text.ToUpper(); Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold); From e6cd05ea938417c49bbffaf7e5d065c68affe3e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 19:06:05 +0900 Subject: [PATCH 263/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 591db6e2c2..f8cd4e41d4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0c26bce8c9..ec59b28ceb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index b7f252820c..bcc4b5f254 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From e13a82ed630639fb0f221ae795acf3a2ec0bbaff Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 5 Aug 2021 14:07:35 +0300 Subject: [PATCH 264/600] Fix colour picker antialiasing --- osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index 06056f239b..30e38e8938 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -89,8 +89,6 @@ namespace osu.Game.Graphics.UserInterfaceV2 { SelectionArea.CornerRadius = corner_radius; SelectionArea.Masking = true; - // purposefully use hard non-AA'd masking to avoid edge artifacts. - SelectionArea.MaskingSmoothness = 0; } protected override Marker CreateMarker() => new OsuMarker(); From c56b6a5379cb97e41da9caae4fa0b6f9b2176ed4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 20:52:40 +0900 Subject: [PATCH 265/600] Fix compilation failure --- osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index e19665497d..a8fda19c60 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Screens; using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Screens.OnlinePlay.Multiplayer.Participants; @@ -150,10 +151,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createRoom(Func room) { - AddStep("open room", () => - { - multiplayerScreen.OpenNewRoom(room()); - }); + AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().Open(room())); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddWaitStep("wait for transition", 2); From 5521f38cfbc240f222a79c949512a8d87cd56ead Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 20:56:09 +0900 Subject: [PATCH 266/600] Adjust spacing --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 06c95dcb7d..9d1f495ab9 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -235,7 +235,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), + Spacing = new Vector2(5), Children = new Drawable[] { new RoomStatusPill From bd394d937750f3b82aa12e15ee169e9ef5fa7db0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 20:56:14 +0900 Subject: [PATCH 267/600] Fix pluralisation --- .../Multiplayer/TestSceneDrawableRoom.cs | 47 +++++++++++++++++++ .../Lounge/Components/PlaylistCountPill.cs | 4 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index faabed0e17..adada5890e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -13,7 +13,9 @@ using osu.Framework.Utils; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Tests.Beatmaps; using osu.Game.Users; using osuTK; @@ -43,12 +45,57 @@ namespace osu.Game.Tests.Visual.Multiplayer Name = { Value = "Room 1" }, Status = { Value = new RoomStatusOpen() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, + Playlist = + { + new PlaylistItem + { + Beatmap = + { + Value = new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = + { + StarDifficulty = 2.5 + } + }.BeatmapInfo, + } + } + } }), createDrawableRoom(new Room { Name = { Value = "Room 2" }, Status = { Value = new RoomStatusPlaying() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, + Playlist = + { + new PlaylistItem + { + Beatmap = + { + Value = new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = + { + StarDifficulty = 2.5 + } + }.BeatmapInfo, + } + }, + new PlaylistItem + { + Beatmap = + { + Value = new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = + { + StarDifficulty = 4.5 + } + }.BeatmapInfo, + } + } + } }), createDrawableRoom(new Room { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 8d8309fcaa..2fe3c7b668 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Specialized; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; @@ -46,7 +47,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { count.Clear(); count.AddText(Playlist.Count.ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); - count.AddText(" Maps"); + count.AddText(" "); + count.AddText("Beatmap".ToQuantity(Playlist.Count, ShowQuantityAs.None)); } } } From b8ec1cb9847701aa88de554c35798281b0089b84 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 20:58:51 +0900 Subject: [PATCH 268/600] Hide star rating max display for equal difficulties --- .../Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index b2e35d7020..3b4ac69466 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Screens.Ranking.Expanded; @@ -85,6 +86,7 @@ namespace osu.Game.Screens.OnlinePlay.Components minDisplay.Current.Value = minDifficulty; maxDisplay.Current.Value = maxDifficulty; + maxDisplay.Alpha = Precision.AlmostEquals(minDifficulty.Stars, maxDifficulty.Stars) ? 0 : 1; minBackground.Colour = colours.ForDifficultyRating(minDifficulty.DifficultyRating, true); maxBackground.Colour = colours.ForDifficultyRating(maxDifficulty.DifficultyRating, true); From 2f2e3d736665c50675aff9ab0cd3b7c6cd6d731b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 21:01:21 +0900 Subject: [PATCH 269/600] Use higher res background image --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 9d1f495ab9..ae408f9f84 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -161,7 +161,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"#27302E"), }, - new OnlinePlayBackgroundSprite(BeatmapSetCoverType.List) + new OnlinePlayBackgroundSprite(BeatmapSetCoverType.Cover) { RelativeSizeAxes = Axes.Both }, From 438f0ce7027497816836431b0aaf4d470bd4faef Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 21:02:14 +0900 Subject: [PATCH 270/600] Increase default number of avatars --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index ae408f9f84..146add34b7 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -103,7 +103,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } - private int numberOfAvatars = 3; + private int numberOfAvatars = 7; public int NumberOfAvatars { From 87fd1eaf067919d49edf3513d8438b9e01743a8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 21:19:23 +0900 Subject: [PATCH 271/600] Explain negative padding --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 146add34b7..08137d1615 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -171,6 +171,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { Name = @"Room content", RelativeSizeAxes = Axes.Both, + // This negative padding resolves 1px gaps between this background and the background above. Padding = new MarginPadding { Left = 20, Vertical = -0.5f }, Child = new Container { From c74e620ce9bec562a1aed8af85a1990af291e817 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 21:20:55 +0900 Subject: [PATCH 272/600] Add constant for background colour --- .../OnlinePlay/Lounge/Components/DrawableRoom.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 08137d1615..ee0e1b5adc 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -40,6 +40,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private const float transition_duration = 60; private const float height = 100; + private static readonly Color4 background_colour = Color4Extensions.FromHex(@"#27302E"); + public event Action StateChanged; private Drawable selectionBox; @@ -159,7 +161,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), + Colour = background_colour, }, new OnlinePlayBackgroundSprite(BeatmapSetCoverType.Cover) { @@ -189,7 +191,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), + Colour = background_colour, }, new OnlinePlayBackgroundSprite(BeatmapSetCoverType.Cover) { @@ -209,12 +211,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#27302E"), + Colour = background_colour, }, new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4Extensions.FromHex(@"#27302E"), Color4Extensions.FromHex(@"#27302E").Opacity(0.3f)) + Colour = ColourInfo.GradientHorizontal(background_colour, background_colour.Opacity(0.3f)) }, } } From fd6d488657b55d14770aabe8436b456096fd0cf1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 21:40:09 +0900 Subject: [PATCH 273/600] Add thousands separator to rank range pill --- .../Multiplayer/TestSceneRankRangePill.cs | 28 +++++++++++++++++++ .../Lounge/Components/RankRangePill.cs | 7 +++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs index 5e28b3f8e5..9e03743e8d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -63,5 +63,33 @@ namespace osu.Game.Tests.Visual.Multiplayer Client.RemoveUser(API.LocalUser.Value); }); } + + [TestCase(1, 10)] + [TestCase(10, 100)] + [TestCase(100, 1000)] + [TestCase(1000, 10000)] + [TestCase(10000, 100000)] + [TestCase(100000, 1000000)] + [TestCase(1000000, 10000000)] + public void TestRange(int min, int max) + { + AddStep("add users", () => + { + Client.AddUser(new User + { + Id = 2, + Statistics = { GlobalRank = min } + }); + + Client.AddUser(new User + { + Id = 3, + Statistics = { GlobalRank = max } + }); + + // Remove the local user so only the ones above are displayed. + Client.RemoveUser(API.LocalUser.Value); + }); + } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs index 8f685ba033..42fe0bfecd 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs @@ -65,13 +65,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components return; } + int minRank = Room.Users.Select(u => u.User?.Statistics.GlobalRank ?? 0).DefaultIfEmpty(0).Min(); + int maxRank = Room.Users.Select(u => u.User?.Statistics.GlobalRank ?? 0).DefaultIfEmpty(0).Max(); + rankFlow.AddText("#"); - rankFlow.AddText(Room.Users.Select(u => u.User?.Statistics.GlobalRank ?? 0).DefaultIfEmpty(0).Min().ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + rankFlow.AddText(minRank.ToString("#,0"), s => s.Font = s.Font.With(weight: FontWeight.Bold)); rankFlow.AddText(" - "); rankFlow.AddText("#"); - rankFlow.AddText(Room.Users.Select(u => u.User?.Statistics.GlobalRank ?? 0).DefaultIfEmpty(0).Max().ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + rankFlow.AddText(maxRank.ToString("#,0"), s => s.Font = s.Font.With(weight: FontWeight.Bold)); } } } From 0ea982c036814109f43851716d3fc9124cdfb3ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Aug 2021 22:49:41 +0900 Subject: [PATCH 274/600] Update recent participants list to use participant_count --- .../TestSceneRecentParticipantsList.cs | 42 ++++++++++--------- .../Components/RecentParticipantsList.cs | 16 +++---- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs index c9959b3467..f05c092dfb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -36,13 +36,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add 50 users", () => { for (int i = 0; i < 50; i++) - { - SelectedRoom.Value.RecentParticipants.Add(new User - { - Id = i, - Username = $"User {i}" - }); - } + addUser(i); }); AddStep("set 3 avatars", () => list.NumberOfAvatars = 3); @@ -60,34 +54,44 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add 50 users", () => { for (int i = 0; i < 50; i++) - { - SelectedRoom.Value.RecentParticipants.Add(new User - { - Id = i, - Username = $"User {i}" - }); - } + addUser(i); }); - AddStep("remove from start", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0)); + AddStep("remove from start", () => removeUserAt(0)); AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("46 hidden users", () => list.ChildrenOfType().Single().Count == 46); - AddStep("remove from end", () => SelectedRoom.Value.RecentParticipants.RemoveAt(SelectedRoom.Value.RecentParticipants.Count - 1)); + AddStep("remove from end", () => removeUserAt(SelectedRoom.Value.RecentParticipants.Count - 1)); AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("45 hidden users", () => list.ChildrenOfType().Single().Count == 45); - AddRepeatStep("remove 45 users", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0), 45); + AddRepeatStep("remove 45 users", () => removeUserAt(0), 45); AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); AddAssert("hidden users bubble hidden", () => list.ChildrenOfType().Single().Alpha < 0.5f); - AddStep("remove another user", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0)); + AddStep("remove another user", () => removeUserAt(0)); AddAssert("2 avatars displayed", () => list.ChildrenOfType().Count() == 2); AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); - AddRepeatStep("remove the remaining two users", () => SelectedRoom.Value.RecentParticipants.RemoveAt(0), 2); + AddRepeatStep("remove the remaining two users", () => removeUserAt(0), 2); AddAssert("0 avatars displayed", () => !list.ChildrenOfType().Any()); } + + private void addUser(int id) + { + SelectedRoom.Value.ParticipantCount.Value++; + SelectedRoom.Value.RecentParticipants.Add(new User + { + Id = id, + Username = $"User {id}" + }); + } + + private void removeUserAt(int index) + { + SelectedRoom.Value.ParticipantCount.Value--; + SelectedRoom.Value.RecentParticipants.RemoveAt(index); + } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index bbea1ea1c3..da410716e4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -88,6 +88,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components base.LoadComplete(); RecentParticipants.BindCollectionChanged(onParticipantsChanged, true); + ParticipantCount.BindValueChanged(_ => updateHiddenUserCount(), true); } private int numberOfAvatars = 3; @@ -141,8 +142,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { if (avatarFlow.Count < NumberOfAvatars) avatarFlow.Add(new CircularAvatar { User = user }); - else - hiddenUsers.Count++; + + updateHiddenUserCount(); } private void removeUser(User user) @@ -150,21 +151,20 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components if (avatarFlow.RemoveAll(a => a.User == user) > 0) { if (RecentParticipants.Count >= NumberOfAvatars) - { avatarFlow.Add(new CircularAvatar { User = RecentParticipants.First(u => avatarFlow.All(a => a.User != u)) }); - hiddenUsers.Count--; - } } - else - hiddenUsers.Count--; + + updateHiddenUserCount(); } private void clearUsers() { avatarFlow.Clear(); - hiddenUsers.Count = 0; + updateHiddenUserCount(); } + private void updateHiddenUserCount() => hiddenUsers.Count = ParticipantCount.Value - avatarFlow.Count; + private class CircularAvatar : CompositeDrawable { public User User From 74bffeac5e0419bdc2d50164ed9420f0e723f167 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 17:03:44 +0900 Subject: [PATCH 275/600] Minor design adustments (paddings/sizing) --- .../Lounge/Components/DrawableRoom.cs | 2 +- .../Lounge/Components/PillContainer.cs | 25 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index ee0e1b5adc..e973dc75a7 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -288,7 +288,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Scale = new Vector2(0.85f) + Scale = new Vector2(0.8f) } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index ca153f7e9a..109851a16b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -17,12 +17,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public readonly Drawable Background; - protected override Container Content { get; } = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - }; + protected override Container Content => content; + private readonly Container content; public PillContainer() { @@ -59,7 +55,22 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Content = new[] { - new[] { Content } + new[] + { + new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding { Bottom = 2 }, + Child = content = new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + } } } } From 7d670c6d351467843c51f6d996083dfeccebef33 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Aug 2021 18:00:12 +0900 Subject: [PATCH 276/600] Fix gap in fill colour --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 9a3c75dcc6..3210ef0112 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -93,15 +93,15 @@ namespace osu.Game.Beatmaps.Drawables new CircularContainer { RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.84f), Anchor = Anchor.Centre, Origin = Anchor.Centre, Masking = true, EdgeEffect = new EdgeEffectParameters { - Colour = Color4.Black.Opacity(0.08f), + Colour = Color4.Black.Opacity(0.06f), + Type = EdgeEffectType.Shadow, - Radius = 5, + Radius = 3, }, Child = background = new Box { From bdfdd00afed0be62426123033f828de0be0ed590 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 18:52:01 +0900 Subject: [PATCH 277/600] Adjust spacings and sizings of left-side details --- .../Multiplayer/TestSceneDrawableRoom.cs | 2 +- .../Lounge/Components/DrawableRoom.cs | 71 ++++++++++--------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index adada5890e..e6a1bbeb92 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { createDrawableRoom(new Room { - Name = { Value = "Room 1" }, + Name = { Value = "Flyte's Trash Playlist" }, Status = { Value = new RoomStatusOpen() }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, Playlist = diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index e973dc75a7..179aef6a9b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -236,39 +236,46 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { new FillFlowContainer { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - Children = new Drawable[] - { - new RoomStatusPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - specialCategoryPill = new RoomSpecialCategoryPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - new EndDateInfo - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - } - }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Children = new Drawable[] { - new RoomNameText(), - new RoomHostText() - } + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Children = new Drawable[] + { + new RoomStatusPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + specialCategoryPill = new RoomSpecialCategoryPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new EndDateInfo + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 3 }, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new RoomNameText(), + new RoomHostText(), + } + } + }, }, new FillFlowContainer { @@ -276,7 +283,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Origin = Anchor.BottomLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(4), + Spacing = new Vector2(5), Children = new Drawable[] { new PlaylistCountPill @@ -429,7 +436,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public RoomNameText() { - Font = OsuFont.GetFont(size: 24); + Font = OsuFont.GetFont(size: 28); } [BackgroundDependencyLoader] @@ -451,7 +458,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [BackgroundDependencyLoader] private void load() { - InternalChild = hostText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + InternalChild = hostText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 16)) { AutoSizeAxes = Axes.Both }; From 798b16fc245b83ae8f1165ba442a3e948bbac31a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 18:52:46 +0900 Subject: [PATCH 278/600] Remove unused params --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 179aef6a9b..6ab46d5527 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -163,7 +163,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Colour = background_colour, }, - new OnlinePlayBackgroundSprite(BeatmapSetCoverType.Cover) + new OnlinePlayBackgroundSprite { RelativeSizeAxes = Axes.Both }, @@ -193,7 +193,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Colour = background_colour, }, - new OnlinePlayBackgroundSprite(BeatmapSetCoverType.Cover) + new OnlinePlayBackgroundSprite { RelativeSizeAxes = Axes.Both }, From 9019e0947a31c2fd3b0f28b81f68a2520343e2b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 18:54:02 +0900 Subject: [PATCH 279/600] Remove unused using --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 6ab46d5527..440c23b8fd 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -19,7 +19,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; From 8dc167ac9a5edfff25b818e10e0417e630205be0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Aug 2021 18:56:01 +0900 Subject: [PATCH 280/600] Set default `MultiplayerRoomSettings` type to something that isn't playlists --- osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index 706bc750d3..001cf2aa93 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -41,7 +41,7 @@ namespace osu.Game.Online.Multiplayer public string Password { get; set; } = string.Empty; [Key(8)] - public MatchType MatchType { get; set; } + public MatchType MatchType { get; set; } = MatchType.HeadToHead; public bool Equals(MultiplayerRoomSettings other) => BeatmapID == other.BeatmapID From b401dc0b2ea6609f7b7220fc480c0ae3578b73a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Aug 2021 18:58:50 +0900 Subject: [PATCH 281/600] Remove playlist button --- osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs index c72fa24b67..c6f9b0f207 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs @@ -30,8 +30,6 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components AddItem(MatchType.HeadToHead); AddItem(MatchType.TeamVersus); - // TODO: remove after osu-web is updated to set the correct default type. - AddItem(MatchType.Playlists); } private class GameTypePickerItem : DisableableTabItem From 19ed24a06f47a03e2443cea8291616a820068c1a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 18:59:19 +0900 Subject: [PATCH 282/600] Remove unnecessary duplicate background --- .../Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 440c23b8fd..53af2fe5c7 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -187,15 +187,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = background_colour, - }, - new OnlinePlayBackgroundSprite - { - RelativeSizeAxes = Axes.Both - }, new GridContainer { RelativeSizeAxes = Axes.Both, From c680012523ff9f4a1e8ab10f788401a9f3b68986 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 19:06:16 +0900 Subject: [PATCH 283/600] Buffer the entire star rating range to fix overlapping alpha --- .../Components/StarRatingRangeDisplay.cs | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 3b4ac69466..efc93ffeb0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -33,38 +33,41 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - InternalChildren = new Drawable[] + InternalChild = new BufferedContainer { - new Container + AutoSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 1, - Children = new[] + new Container { - minBackground = new Box + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Vertical = 1 }, + Children = new[] { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.5f), - }, - maxBackground = new Box - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.5f), - }, - } - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Children = new Drawable[] + minBackground = new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + maxBackground = new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + } + }, + new FillFlowContainer { - minDisplay = new StarRatingDisplay(default), - maxDisplay = new StarRatingDisplay(default) + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + minDisplay = new StarRatingDisplay(default), + maxDisplay = new StarRatingDisplay(default) + } } } }; From 724edcbecd764ff2b8e4473499763f5c82c984f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Aug 2021 19:22:48 +0900 Subject: [PATCH 284/600] Toggle the expanded state of the multiplayer leaderboard with the user's HUD Resolves https://github.com/ppy/osu/discussions/14140. --- Until now, the multiplayer leaderboard would expand during break time. Now, it respects the user's HUD visibility status (which can be toggled using Shift+Tab). --- osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 043cce4630..b54a4a7726 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -96,7 +96,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { base.LoadComplete(); - ((IBindable)leaderboard.Expanded).BindTo(IsBreakTime); + ((IBindable)leaderboard.Expanded).BindTo(HUDOverlay.ShowHud); } protected override void StartGameplay() From f262f288fceef2e066761367a0f25297ff411da9 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 6 Aug 2021 19:58:46 +0900 Subject: [PATCH 285/600] Fix DHO state is overwritten to `Idle` on `LoadComplete` The state may already be changed before `LoadComplete` is called because DHO is already added to the draw hierarchy. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 25f3b8931a..ff6168ee37 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -190,7 +190,9 @@ namespace osu.Game.Rulesets.Objects.Drawables comboIndexBindable.BindValueChanged(_ => UpdateComboColour()); comboIndexWithOffsetsBindable.BindValueChanged(_ => UpdateComboColour(), true); - updateState(ArmedState.Idle, true); + // If the state is changed, transforms are already initialized. + if (state.Value == ArmedState.Idle) + updateState(ArmedState.Idle, true); } /// From 53b98520340a9abf2d0b6415de8d78eb9c27ff12 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 6 Aug 2021 19:59:02 +0900 Subject: [PATCH 286/600] Add test case for DHO state change before load complete --- .../Gameplay/TestSceneDrawableHitObject.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 0ce71696bd..58f4c4c8db 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay @@ -121,6 +123,18 @@ namespace osu.Game.Tests.Gameplay AddAssert("Drawable lifetime is restored", () => dho.LifetimeStart == 666 && dho.LifetimeEnd == 999); } + [Test] + public void TestStateChangeBeforeLoadComplete() + { + TestDrawableHitObject dho = null; + AddStep("Add DHO and apply result", () => + { + Child = dho = new TestDrawableHitObject(new HitObject { StartTime = Time.Current }); + dho.MissForcefully(); + }); + AddAssert("DHO state is correct", () => dho.State.Value == ArmedState.Miss); + } + private class TestDrawableHitObject : DrawableHitObject { public const double INITIAL_LIFETIME_OFFSET = 100; @@ -141,6 +155,19 @@ namespace osu.Game.Tests.Gameplay if (SetLifetimeStartOnApply) LifetimeStart = LIFETIME_ON_APPLY; } + + public void MissForcefully() => ApplyResult(r => r.Type = HitResult.Miss); + + protected override void UpdateHitStateTransforms(ArmedState state) + { + if (state != ArmedState.Miss) + { + base.UpdateHitStateTransforms(state); + return; + } + + this.FadeOut(1000); + } } private class TestLifetimeEntry : HitObjectLifetimeEntry From f1ea8308284284134a74ad780f238d425c33b68e Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 6 Aug 2021 20:56:49 +0900 Subject: [PATCH 287/600] Re-add on-click feedback to MonthSection and OsuDropdown headers --- osu.Game/Graphics/UserInterface/OsuDropdown.cs | 2 +- osu.Game/Overlays/News/Sidebar/MonthSection.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index b97f12df02..61dd5fb2d9 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -288,7 +288,7 @@ namespace osu.Game.Graphics.UserInterface }, }; - AddInternal(new HoverSounds()); + AddInternal(new HoverClickSounds()); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index cd6ab224a9..948f312f15 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -79,8 +79,6 @@ namespace osu.Game.Overlays.News.Sidebar private readonly SpriteIcon icon; - protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(); - public DropdownHeader(int month, int year) { var date = new DateTime(year, month, 1); From 3f06ecdd4875027370f649b2e6784ef40a3922a2 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 6 Aug 2021 20:58:53 +0900 Subject: [PATCH 288/600] Add open/close sounds to menus --- osu.Game/Graphics/UserInterface/OsuMenu.cs | 35 ++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index e7bf4f66ee..b98a29aacb 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,6 +1,9 @@ // 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.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -13,6 +16,12 @@ namespace osu.Game.Graphics.UserInterface { public class OsuMenu : Menu { + private Sample sampleOpen; + private Sample sampleClose; + + // todo: this shouldn't be required after https://github.com/ppy/osu-framework/issues/4519 is fixed. + private bool wasOpened; + public OsuMenu(Direction direction, bool topLevelMenu = false) : base(direction, topLevelMenu) { @@ -22,8 +31,30 @@ namespace osu.Game.Graphics.UserInterface ItemsContainer.Padding = new MarginPadding(5); } - protected override void AnimateOpen() => this.FadeIn(300, Easing.OutQuint); - protected override void AnimateClose() => this.FadeOut(300, Easing.OutQuint); + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleOpen = audio.Samples.Get(@"UI/dropdown-open"); + sampleClose = audio.Samples.Get(@"UI/dropdown-close"); + } + + protected override void AnimateOpen() + { + if (!wasOpened) + sampleOpen?.Play(); + + this.FadeIn(300, Easing.OutQuint); + wasOpened = true; + } + + protected override void AnimateClose() + { + if (wasOpened) + sampleClose?.Play(); + + this.FadeOut(300, Easing.OutQuint); + wasOpened = false; + } protected override void UpdateSize(Vector2 newSize) { From 5031b19b422dea125aa49e963f3db14d3b75228b Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 6 Aug 2021 23:30:12 +0900 Subject: [PATCH 289/600] Add sounds to multiplayer games list --- .../Lounge/Components/DrawableRoom.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index c455cb0c50..7da964d84b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -5,6 +5,8 @@ using System; using System.Collections.Generic; using osu.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; @@ -44,6 +46,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public event Action StateChanged; + protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(); + private readonly Box selectionBox; [Resolved(canBeNull: true)] @@ -62,6 +66,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private SelectionState state; + private Sample sampleSelect; + private Sample sampleJoin; + public SelectionState State { get => state; @@ -125,7 +132,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, AudioManager audio) { float stripWidth = side_strip_width * (Room.Category.Value == RoomCategory.Spotlight ? 2 : 1); @@ -221,6 +228,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, }, }; + + sampleSelect = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select"); + sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Submit.GetDescription()}-select"); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -273,22 +283,25 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { } - protected override bool ShouldBeConsideredForInput(Drawable child) => state == SelectionState.Selected; + protected override bool ShouldBeConsideredForInput(Drawable child) => state == SelectionState.Selected || child is HoverSounds; protected override bool OnClick(ClickEvent e) { if (Room != selectedRoom.Value) { + sampleSelect?.Play(); selectedRoom.Value = Room; return true; } if (Room.HasPassword.Value) { + sampleJoin?.Play(); this.ShowPopover(); return true; } + sampleJoin?.Play(); lounge?.Join(Room, null); return base.OnClick(e); From 52400961f6ee5974c1bb0205005954a597ed2e99 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 6 Aug 2021 20:59:26 +0900 Subject: [PATCH 290/600] Add open/close sounds to context menus --- .../UserInterface/TestSceneContextMenu.cs | 61 ++++++++++++++++--- .../Cursor/OsuContextMenuContainer.cs | 2 +- .../Graphics/UserInterface/OsuContextMenu.cs | 53 ++++++++++++++-- 3 files changed, 100 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs index 53693d1b70..3b43f8485a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -68,13 +70,40 @@ namespace osu.Game.Tests.Visual.UserInterface ); } - private class MyContextMenuContainer : Container, IHasContextMenu + private static MenuItem[] makeMenu() { - public MenuItem[] ContextMenuItems => new MenuItem[] + return new MenuItem[] { new OsuMenuItem(@"Some option"), new OsuMenuItem(@"Highlighted option", MenuItemType.Highlighted), new OsuMenuItem(@"Another option"), + new OsuMenuItem(@"Nested option >") + { + Items = new MenuItem[] + { + new OsuMenuItem(@"Sub-One"), + new OsuMenuItem(@"Sub-Two"), + new OsuMenuItem(@"Sub-Three"), + new OsuMenuItem(@"Sub-Nested option >") + { + Items = new MenuItem[] + { + new OsuMenuItem(@"Double Sub-One"), + new OsuMenuItem(@"Double Sub-Two"), + new OsuMenuItem(@"Double Sub-Three"), + new OsuMenuItem(@"Sub-Sub-Nested option >") + { + Items = new MenuItem[] + { + new OsuMenuItem(@"Too Deep One"), + new OsuMenuItem(@"Too Deep Two"), + new OsuMenuItem(@"Too Deep Three"), + } + } + } + } + } + }, new OsuMenuItem(@"Choose me please"), new OsuMenuItem(@"And me too"), new OsuMenuItem(@"Trying to fill"), @@ -82,17 +111,29 @@ namespace osu.Game.Tests.Visual.UserInterface }; } + private class MyContextMenuContainer : Container, IHasContextMenu + { + public MenuItem[] ContextMenuItems => makeMenu(); + } + private class AnotherContextMenuContainer : Container, IHasContextMenu { - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem(@"Simple option"), - new OsuMenuItem(@"Simple very very long option"), - new OsuMenuItem(@"Change width", MenuItemType.Highlighted, () => this.ResizeWidthTo(Width * 2, 100, Easing.OutQuint)), - new OsuMenuItem(@"Change height", MenuItemType.Highlighted, () => this.ResizeHeightTo(Height * 2, 100, Easing.OutQuint)), - new OsuMenuItem(@"Change width back", MenuItemType.Destructive, () => this.ResizeWidthTo(Width / 2, 100, Easing.OutQuint)), - new OsuMenuItem(@"Change height back", MenuItemType.Destructive, () => this.ResizeHeightTo(Height / 2, 100, Easing.OutQuint)), - }; + get + { + List items = makeMenu().ToList(); + items.AddRange(new MenuItem[] + { + new OsuMenuItem(@"Change width", MenuItemType.Highlighted, () => this.ResizeWidthTo(Width * 2, 100, Easing.OutQuint)), + new OsuMenuItem(@"Change height", MenuItemType.Highlighted, () => this.ResizeHeightTo(Height * 2, 100, Easing.OutQuint)), + new OsuMenuItem(@"Change width back", MenuItemType.Destructive, () => this.ResizeWidthTo(Width / 2, 100, Easing.OutQuint)), + new OsuMenuItem(@"Change height back", MenuItemType.Destructive, () => this.ResizeHeightTo(Height / 2, 100, Easing.OutQuint)), + }); + + return items.ToArray(); + } + } } } } diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index fbb3fa0e6c..e64d2d98f4 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -9,6 +9,6 @@ namespace osu.Game.Graphics.Cursor { public class OsuContextMenuContainer : ContextMenuContainer { - protected override Menu CreateMenu() => new OsuContextMenu(); + protected override Menu CreateMenu() => new OsuContextMenu(true); } } diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index 8c7b44f952..7cf8b3eca8 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -3,6 +3,9 @@ using osuTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; @@ -13,8 +16,16 @@ namespace osu.Game.Graphics.UserInterface public class OsuContextMenu : OsuMenu { private const int fade_duration = 250; + private Sample sampleOpen; + private Sample sampleClose; + private Sample sampleClick; - public OsuContextMenu() + // todo: this shouldn't be required after https://github.com/ppy/osu-framework/issues/4519 is fixed. + private bool wasOpened; + private readonly bool playClickSample; + private readonly Menu parentMenu; + + public OsuContextMenu(bool playClickSample = false, Menu parentMenu = null) : base(Direction.Vertical) { MaskingContainer.CornerRadius = 5; @@ -28,17 +39,49 @@ namespace osu.Game.Graphics.UserInterface ItemsContainer.Padding = new MarginPadding { Vertical = DrawableOsuMenuItem.MARGIN_VERTICAL }; MaxHeight = 250; + + this.playClickSample = playClickSample; + this.parentMenu = parentMenu; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, AudioManager audio) { BackgroundColour = colours.ContextMenuGray; + sampleClick = audio.Samples.Get($"UI/{HoverSampleSet.Default.GetDescription()}-select"); + sampleOpen = audio.Samples.Get(@"UI/dropdown-open"); + sampleClose = audio.Samples.Get(@"UI/dropdown-close"); } - protected override void AnimateOpen() => this.FadeIn(fade_duration, Easing.OutQuint); - protected override void AnimateClose() => this.FadeOut(fade_duration, Easing.OutQuint); + protected override void AnimateOpen() + { + this.FadeIn(fade_duration, Easing.OutQuint); - protected override Menu CreateSubMenu() => new OsuContextMenu(); + if (playClickSample) + sampleClick?.Play(); + + if (!wasOpened) + sampleOpen?.Play(); + + wasOpened = true; + } + + protected override void AnimateClose() + { + this.FadeOut(fade_duration, Easing.OutQuint); + + if (parentMenu?.State == MenuState.Closed) + { + wasOpened = false; + return; + } + + if (wasOpened) + sampleClose?.Play(); + + wasOpened = false; + } + + protected override Menu CreateSubMenu() => new OsuContextMenu(false, this); } } From 067ff0e0ad4051ceaa7a8726d8f38d3ce884a8d6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 6 Aug 2021 18:38:14 +0300 Subject: [PATCH 291/600] Store last opened settings subpanel rather than relying on LINQ --- osu.Game/Overlays/SettingsOverlay.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 54b780615d..050502b3be 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -9,7 +9,6 @@ using osu.Game.Overlays.Settings.Sections; using osu.Game.Overlays.Settings.Sections.Input; using osuTK.Graphics; using System.Collections.Generic; -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Localisation; @@ -38,6 +37,8 @@ namespace osu.Game.Overlays private readonly List subPanels = new List(); + private SettingsSubPanel lastOpenedSubPanel; + protected override Drawable CreateHeader() => new SettingsHeader(Title, Description); protected override Drawable CreateFooter() => new SettingsFooter(); @@ -46,21 +47,21 @@ namespace osu.Game.Overlays { } - public override bool AcceptsFocus => subPanels.All(s => s.State.Value != Visibility.Visible); + public override bool AcceptsFocus => lastOpenedSubPanel == null || lastOpenedSubPanel.State.Value == Visibility.Hidden; private T createSubPanel(T subPanel) where T : SettingsSubPanel { subPanel.Depth = 1; subPanel.Anchor = Anchor.TopRight; - subPanel.State.ValueChanged += subPanelStateChanged; + subPanel.State.ValueChanged += e => subPanelStateChanged(subPanel, e); subPanels.Add(subPanel); return subPanel; } - private void subPanelStateChanged(ValueChangedEvent state) + private void subPanelStateChanged(SettingsSubPanel panel, ValueChangedEvent state) { switch (state.NewValue) { @@ -69,6 +70,8 @@ namespace osu.Game.Overlays SectionsContainer.FadeOut(300, Easing.OutQuint); ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint); + + lastOpenedSubPanel = panel; break; case Visibility.Hidden: @@ -80,7 +83,7 @@ namespace osu.Game.Overlays } } - protected override float ExpandedPosition => subPanels.Any(s => s.State.Value == Visibility.Visible) ? -WIDTH : base.ExpandedPosition; + protected override float ExpandedPosition => lastOpenedSubPanel?.State.Value == Visibility.Visible ? -WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() From 8e8e0fb8d8c9abce26fe64a0098507c8967d0739 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 6 Aug 2021 18:36:43 +0300 Subject: [PATCH 292/600] Add placement-dependent horizontal screen offset properties --- osu.Game/Overlays/NotificationOverlay.cs | 5 +++++ osu.Game/Overlays/SettingsOverlay.cs | 2 ++ osu.Game/Overlays/SettingsPanel.cs | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index b26e17b34c..af4f41901f 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -30,6 +30,11 @@ namespace osu.Game.Overlays private FlowContainer sections; + /// + /// A horizontal offset to apply to the game-wide screen. + /// + public float HorizontalScreenOffset => -width + X; + /// /// Provide a source for the toolbar height. /// diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 050502b3be..9ed1d950e3 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -21,6 +21,8 @@ namespace osu.Game.Overlays public LocalisableString Title => SettingsStrings.HeaderTitle; public LocalisableString Description => SettingsStrings.HeaderDescription; + public override float HorizontalScreenOffset => base.HorizontalScreenOffset + (lastOpenedSubPanel?.HorizontalScreenOffset ?? 0f); + protected override IEnumerable CreateSections() => new SettingsSection[] { new GeneralSection(), diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index eae828c142..2916ea013f 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -34,6 +34,11 @@ namespace osu.Game.Overlays protected override Container Content => ContentContainer; + /// + /// A horizontal offset to apply to the game-wide screen. + /// + public virtual float HorizontalScreenOffset => (WIDTH + Content?.X) ?? 0f; + protected Sidebar Sidebar; private SidebarButton selectedSidebarButton; @@ -64,6 +69,7 @@ namespace osu.Game.Overlays { InternalChild = ContentContainer = new NonMaskedContent { + X = -WIDTH + ExpandedPosition, Width = WIDTH, RelativeSizeAxes = Axes.Y, Children = new Drawable[] From f77037ef57d6df00845867ae436ceb77e3f525dd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 6 Aug 2021 18:38:48 +0300 Subject: [PATCH 293/600] Replace state-based screen offsetting logic with `HorizontalScreenOffset`s --- osu.Game/OsuGame.cs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3cfa2cc755..85428a12e3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -828,21 +828,6 @@ namespace osu.Game { if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); }; - - void updateScreenOffset() - { - float offset = 0; - - if (Settings.State.Value == Visibility.Visible) - offset += Toolbar.HEIGHT / 2; - if (notifications.State.Value == Visibility.Visible) - offset -= Toolbar.HEIGHT / 2; - - screenOffsetContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint); - } - - Settings.State.ValueChanged += _ => updateScreenOffset(); - notifications.State.ValueChanged += _ => updateScreenOffset(); } private void showOverlayAboveOthers(OverlayContainer overlay, OverlayContainer[] otherOverlays) @@ -1026,6 +1011,9 @@ namespace osu.Game screenOffsetContainer.Padding = new MarginPadding { Top = ToolbarOffset }; overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; + screenOffsetContainer.X = Settings.HorizontalScreenOffset * 0.125f + + notifications.HorizontalScreenOffset * 0.125f; + MenuCursorContainer.CanShowCursor = (ScreenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; } From 2f187cb90f0ecf3eb1cff9edcd95ea9703cfa856 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 7 Aug 2021 01:17:58 +0900 Subject: [PATCH 294/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f8cd4e41d4..03e01a24ca 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ec59b28ceb..227493c74a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index bcc4b5f254..ad5b26e968 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From ac157f6cef91f35252599059451fa315819180cf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 6 Aug 2021 22:10:03 +0300 Subject: [PATCH 295/600] Fix settings panel children not processing transforms while masked away --- osu.Game/Overlays/SettingsPanel.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 2916ea013f..79d78e6805 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -34,6 +34,12 @@ namespace osu.Game.Overlays protected override Container Content => ContentContainer; + /// + /// The always needs to be present for to process transforms while overlay is masked away. + /// todo: there may be a better solution for this and the existing , likely requires a refactor. + /// + public override bool IsPresent => true; + /// /// A horizontal offset to apply to the game-wide screen. /// From 8dc0650ca71d9143d0268268a6f21f826d658679 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 6 Aug 2021 22:36:40 +0300 Subject: [PATCH 296/600] Add test coverage --- .../Visual/Menus/TestSceneSideOverlays.cs | 62 +++++++++++++++++++ .../Visual/Navigation/OsuGameTestScene.cs | 7 ++- osu.Game/OsuGame.cs | 33 +++++----- osu.Game/Overlays/NotificationOverlay.cs | 8 +-- 4 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs new file mode 100644 index 0000000000..34259574f3 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -0,0 +1,62 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Overlays; +using osu.Game.Overlays.Settings.Sections.Input; +using osu.Game.Tests.Visual.Navigation; + +namespace osu.Game.Tests.Visual.Menus +{ + public class TestSceneSideOverlays : OsuGameTestScene + { + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddAssert("no screen offset applied", () => Game.ScreenOffsetContainer.X == 0f); + } + + [Test] + public void TestScreenOffsettingOnSettingsOverlay() + { + AddStep("open settings", () => Game.Settings.Show()); + AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + + AddStep("hide settings", () => Game.Settings.Hide()); + AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + } + + [Test] + public void TestScreenOffsettingAccountsForKeyBindingPanel() + { + AddStep("open settings", () => Game.Settings.Show()); + AddStep("open key binding panel", () => Game.Settings.ChildrenOfType().Single().Show()); + AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + + AddStep("hide key binding", () => Game.Settings.ChildrenOfType().Single().Show()); + AddUntilStep("right screen offset still applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + + AddStep("open key binding", () => Game.Settings.Show()); + AddUntilStep("right screen offset still applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + + AddStep("hide settings", () => Game.Settings.Hide()); + AddAssert("key binding panel still open", () => Game.Settings.ChildrenOfType().Single().State.Value == Visibility.Visible); + AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + } + + [Test] + public void TestScreenOffsettingOnNotificationOverlay() + { + AddStep("open notifications", () => Game.Notifications.Show()); + AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == -NotificationOverlay.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + + AddStep("hide notifications", () => Game.Notifications.Hide()); + AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + } + } +} diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs index f9a991f756..5cd55ed233 100644 --- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs +++ b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; using osu.Framework.Screens; @@ -103,7 +104,11 @@ namespace osu.Game.Tests.Visual.Navigation public new ScoreManager ScoreManager => base.ScoreManager; - public new SettingsPanel Settings => base.Settings; + public new Container ScreenOffsetContainer => base.ScreenOffsetContainer; + + public new SettingsOverlay Settings => base.Settings; + + public new NotificationOverlay Notifications => base.Notifications; public new MusicController MusicController => base.MusicController; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 85428a12e3..d2f86f812e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -64,6 +64,8 @@ namespace osu.Game /// public class OsuGame : OsuGameBase, IKeyBindingHandler { + public const float SCREEN_OFFSET_RATIO = 0.125f; + public Toolbar Toolbar; private ChatOverlay chatOverlay; @@ -71,7 +73,7 @@ namespace osu.Game private ChannelManager channelManager; [NotNull] - private readonly NotificationOverlay notifications = new NotificationOverlay(); + protected readonly NotificationOverlay Notifications = new NotificationOverlay(); private BeatmapListingOverlay beatmapListing; @@ -97,7 +99,7 @@ namespace osu.Game private ScalingContainer screenContainer; - private Container screenOffsetContainer; + protected Container ScreenOffsetContainer; [Resolved] private FrameworkConfigManager frameworkConfig { get; set; } @@ -312,7 +314,7 @@ namespace osu.Game case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - waitForReady(() => notifications, _ => notifications.Post(new SimpleNotification + waitForReady(() => Notifications, _ => Notifications.Post(new SimpleNotification { Text = @"This link type is not yet supported!", Icon = FontAwesome.Solid.LifeRing, @@ -611,12 +613,12 @@ namespace osu.Game MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false; // todo: all archive managers should be able to be looped here. - SkinManager.PostNotification = n => notifications.Post(n); + SkinManager.PostNotification = n => Notifications.Post(n); - BeatmapManager.PostNotification = n => notifications.Post(n); + BeatmapManager.PostNotification = n => Notifications.Post(n); BeatmapManager.PresentImport = items => PresentBeatmap(items.First()); - ScoreManager.PostNotification = n => notifications.Post(n); + ScoreManager.PostNotification = n => Notifications.Post(n); ScoreManager.PresentImport = items => PresentScore(items.First()); // make config aware of how to lookup skins for on-screen display purposes. @@ -655,7 +657,7 @@ namespace osu.Game ActionRequested = action => volume.Adjust(action), ScrollActionRequested = (action, amount, isPrecise) => volume.Adjust(action, amount, isPrecise), }, - screenOffsetContainer = new Container + ScreenOffsetContainer = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -724,7 +726,7 @@ namespace osu.Game loadComponentSingleFile(onScreenDisplay, Add, true); - loadComponentSingleFile(notifications.With(d => + loadComponentSingleFile(Notifications.With(d => { d.GetToolbarHeight = () => ToolbarOffset; d.Anchor = Anchor.TopRight; @@ -733,7 +735,7 @@ namespace osu.Game loadComponentSingleFile(new CollectionManager(Storage) { - PostNotification = n => notifications.Post(n), + PostNotification = n => Notifications.Post(n), }, Add, true); loadComponentSingleFile(stableImportManager, Add); @@ -785,7 +787,7 @@ namespace osu.Game Add(new MusicKeyBindingHandler()); // side overlays which cancel each other. - var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications }; + var singleDisplaySideOverlays = new OverlayContainer[] { Settings, Notifications }; foreach (var overlay in singleDisplaySideOverlays) { @@ -859,7 +861,7 @@ namespace osu.Game if (recentLogCount < short_term_display_limit) { - Schedule(() => notifications.Post(new SimpleErrorNotification + Schedule(() => Notifications.Post(new SimpleErrorNotification { Icon = entry.Level == LogLevel.Important ? FontAwesome.Solid.ExclamationCircle : FontAwesome.Solid.Bomb, Text = entry.Message.Truncate(256) + (entry.Exception != null && IsDeployedBuild ? "\n\nThis error has been automatically reported to the devs." : string.Empty), @@ -867,7 +869,7 @@ namespace osu.Game } else if (recentLogCount == short_term_display_limit) { - Schedule(() => notifications.Post(new SimpleNotification + Schedule(() => Notifications.Post(new SimpleNotification { Icon = FontAwesome.Solid.EllipsisH, Text = "Subsequent messages have been logged. Click to view log files.", @@ -1008,11 +1010,12 @@ namespace osu.Game { base.UpdateAfterChildren(); - screenOffsetContainer.Padding = new MarginPadding { Top = ToolbarOffset }; + ScreenOffsetContainer.Padding = new MarginPadding { Top = ToolbarOffset }; overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; - screenOffsetContainer.X = Settings.HorizontalScreenOffset * 0.125f + - notifications.HorizontalScreenOffset * 0.125f; + var settingsOffset = Settings.HorizontalScreenOffset * SCREEN_OFFSET_RATIO; + var notificationsOffset = Notifications.HorizontalScreenOffset * SCREEN_OFFSET_RATIO; + ScreenOffsetContainer.X = settingsOffset + notificationsOffset; MenuCursorContainer.CanShowCursor = (ScreenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; } diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index af4f41901f..9be3212159 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays public LocalisableString Title => NotificationsStrings.HeaderTitle; public LocalisableString Description => NotificationsStrings.HeaderDescription; - private const float width = 320; + public const float WIDTH = 320; public const float TRANSITION_LENGTH = 600; @@ -33,7 +33,7 @@ namespace osu.Game.Overlays /// /// A horizontal offset to apply to the game-wide screen. /// - public float HorizontalScreenOffset => -width + X; + public float HorizontalScreenOffset => -WIDTH + X; /// /// Provide a source for the toolbar height. @@ -43,7 +43,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { - Width = width; + Width = WIDTH; RelativeSizeAxes = Axes.Y; Children = new Drawable[] @@ -157,7 +157,7 @@ namespace osu.Game.Overlays markAllRead(); - this.MoveToX(width, TRANSITION_LENGTH, Easing.OutQuint); + this.MoveToX(WIDTH, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); } From ae733e202ff574b9a3065b9bc72fca71b8960580 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 7 Aug 2021 00:36:52 +0300 Subject: [PATCH 297/600] Fix tests executing before overlays load --- osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index 34259574f3..598998586d 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -19,6 +19,7 @@ namespace osu.Game.Tests.Visual.Menus base.SetUpSteps(); AddAssert("no screen offset applied", () => Game.ScreenOffsetContainer.X == 0f); + AddUntilStep("wait for overlays", () => Game.Settings.IsLoaded && Game.Notifications.IsLoaded); } [Test] From 9ac5c9aa2f8d426d1733140702ab3d3c518bce99 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 7 Aug 2021 01:27:54 +0300 Subject: [PATCH 298/600] Fix notification overlay having incorrect initial X --- osu.Game/Overlays/NotificationOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 9be3212159..cb5d4d57c6 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -43,6 +43,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { + X = WIDTH; Width = WIDTH; RelativeSizeAxes = Axes.Y; From ff1730f9f8edfe29ca2eae30a3ff0442a42fd282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 7 Aug 2021 14:38:54 +0200 Subject: [PATCH 299/600] Do not play open/close samples for top-level menus --- osu.Game/Graphics/UserInterface/OsuMenu.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index b98a29aacb..a16adcbd57 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -40,7 +40,7 @@ namespace osu.Game.Graphics.UserInterface protected override void AnimateOpen() { - if (!wasOpened) + if (!TopLevelMenu && !wasOpened) sampleOpen?.Play(); this.FadeIn(300, Easing.OutQuint); @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface protected override void AnimateClose() { - if (wasOpened) + if (!TopLevelMenu && wasOpened) sampleClose?.Play(); this.FadeOut(300, Easing.OutQuint); From e924ea8d934d043a446d92a0ffeea7885cee46ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 7 Aug 2021 18:52:27 +0300 Subject: [PATCH 300/600] Make `ScreenOffsetContainer` privatly settable only --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d2f86f812e..6fb884f80a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -99,7 +99,7 @@ namespace osu.Game private ScalingContainer screenContainer; - protected Container ScreenOffsetContainer; + protected Container ScreenOffsetContainer { get; private set; } [Resolved] private FrameworkConfigManager frameworkConfig { get; set; } From 9f3013e2c89a1ea018008cb6221d9165e72f13a2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 7 Aug 2021 19:30:12 +0300 Subject: [PATCH 301/600] Remove all `HorizontalScreenOffset` calculations from overlays --- osu.Game/Overlays/NotificationOverlay.cs | 5 ----- osu.Game/Overlays/SettingsOverlay.cs | 2 -- osu.Game/Overlays/SettingsPanel.cs | 5 ----- 3 files changed, 12 deletions(-) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index cb5d4d57c6..e3956089c2 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -30,11 +30,6 @@ namespace osu.Game.Overlays private FlowContainer sections; - /// - /// A horizontal offset to apply to the game-wide screen. - /// - public float HorizontalScreenOffset => -WIDTH + X; - /// /// Provide a source for the toolbar height. /// diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 9ed1d950e3..050502b3be 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -21,8 +21,6 @@ namespace osu.Game.Overlays public LocalisableString Title => SettingsStrings.HeaderTitle; public LocalisableString Description => SettingsStrings.HeaderDescription; - public override float HorizontalScreenOffset => base.HorizontalScreenOffset + (lastOpenedSubPanel?.HorizontalScreenOffset ?? 0f); - protected override IEnumerable CreateSections() => new SettingsSection[] { new GeneralSection(), diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 79d78e6805..64c3be4b9a 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -40,11 +40,6 @@ namespace osu.Game.Overlays /// public override bool IsPresent => true; - /// - /// A horizontal offset to apply to the game-wide screen. - /// - public virtual float HorizontalScreenOffset => (WIDTH + Content?.X) ?? 0f; - protected Sidebar Sidebar; private SidebarButton selectedSidebarButton; From 19a19f915cde29015df6e085406af348c487bba4 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 7 Aug 2021 19:56:51 +0300 Subject: [PATCH 302/600] Adjust settings panel to autosize to zero when hiding it Previously, when hiding the settings overlay, it remains to have a width of `56` (sidebar width), this is due to the panel content being placed next to the sidebar, so therefore the content has to move 400 (PANEL_WIDTH) + 56 (sidebar_width) backwards, for the overlay to have a width of 0 on hide. --- .../Visual/Settings/TestSceneTabletSettings.cs | 2 +- osu.Game/Overlays/SettingsOverlay.cs | 4 ++-- osu.Game/Overlays/SettingsPanel.cs | 12 ++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs index a62980addf..da474a64ba 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Settings new TabletSettings(tabletHandler) { RelativeSizeAxes = Axes.None, - Width = SettingsPanel.WIDTH, + Width = SettingsPanel.PANEL_WIDTH, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, } diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 050502b3be..55e8aee266 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -69,7 +69,7 @@ namespace osu.Game.Overlays Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint); SectionsContainer.FadeOut(300, Easing.OutQuint); - ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint); + ContentContainer.MoveToX(-PANEL_WIDTH, 500, Easing.OutQuint); lastOpenedSubPanel = panel; break; @@ -83,7 +83,7 @@ namespace osu.Game.Overlays } } - protected override float ExpandedPosition => lastOpenedSubPanel?.State.Value == Visibility.Visible ? -WIDTH : base.ExpandedPosition; + protected override float ExpandedPosition => lastOpenedSubPanel?.State.Value == Visibility.Visible ? -PANEL_WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 64c3be4b9a..8b953e8655 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -28,7 +28,15 @@ namespace osu.Game.Overlays private const float sidebar_width = Sidebar.DEFAULT_WIDTH; - public const float WIDTH = 400; + /// + /// The width of the settings panel content, excluding the sidebar. + /// + public const float PANEL_WIDTH = 400; + + /// + /// The full width of the settings panel, including the sidebar. + /// + public const float WIDTH = sidebar_width + PANEL_WIDTH; protected Container ContentContainer; @@ -71,7 +79,7 @@ namespace osu.Game.Overlays InternalChild = ContentContainer = new NonMaskedContent { X = -WIDTH + ExpandedPosition, - Width = WIDTH, + Width = PANEL_WIDTH, RelativeSizeAxes = Axes.Y, Children = new Drawable[] { From d099bb8ab631424f6a841d4f9947dc1ca3ba45bf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 7 Aug 2021 19:33:22 +0300 Subject: [PATCH 303/600] Calculate offsets from overlay `ScreenSpaceDrawQuad`s instead --- .../Visual/Menus/TestSceneSideOverlays.cs | 21 ------------------- osu.Game/OsuGame.cs | 7 ++++--- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index 598998586d..21db7e2802 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using NUnit.Framework; -using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Overlays; -using osu.Game.Overlays.Settings.Sections.Input; using osu.Game.Tests.Visual.Navigation; namespace osu.Game.Tests.Visual.Menus @@ -32,24 +29,6 @@ namespace osu.Game.Tests.Visual.Menus AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); } - [Test] - public void TestScreenOffsettingAccountsForKeyBindingPanel() - { - AddStep("open settings", () => Game.Settings.Show()); - AddStep("open key binding panel", () => Game.Settings.ChildrenOfType().Single().Show()); - AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); - - AddStep("hide key binding", () => Game.Settings.ChildrenOfType().Single().Show()); - AddUntilStep("right screen offset still applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); - - AddStep("open key binding", () => Game.Settings.Show()); - AddUntilStep("right screen offset still applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); - - AddStep("hide settings", () => Game.Settings.Hide()); - AddAssert("key binding panel still open", () => Game.Settings.ChildrenOfType().Single().State.Value == Visibility.Visible); - AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); - } - [Test] public void TestScreenOffsettingOnNotificationOverlay() { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6fb884f80a..1539d984ae 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1013,9 +1013,10 @@ namespace osu.Game ScreenOffsetContainer.Padding = new MarginPadding { Top = ToolbarOffset }; overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; - var settingsOffset = Settings.HorizontalScreenOffset * SCREEN_OFFSET_RATIO; - var notificationsOffset = Notifications.HorizontalScreenOffset * SCREEN_OFFSET_RATIO; - ScreenOffsetContainer.X = settingsOffset + notificationsOffset; + ScreenOffsetContainer.X = 0f; + + if (Settings.IsLoaded) ScreenOffsetContainer.X += (ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X) * SCREEN_OFFSET_RATIO; + if (Notifications.IsLoaded) ScreenOffsetContainer.X += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SCREEN_OFFSET_RATIO; MenuCursorContainer.CanShowCursor = (ScreenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; } From db270a79ab2ea0cc04a04dda75d5d7687741fc06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 8 Aug 2021 03:54:20 +0900 Subject: [PATCH 304/600] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 03e01a24ca..7a0a542ee9 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 227493c74a..0a6522f15e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ad5b26e968..00222877f1 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 3a0dd5b019e2401f917d2656ae73ef9ddd09847b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 8 Aug 2021 01:37:45 +0300 Subject: [PATCH 305/600] Add more insane star difficulties for visual testing --- .../Visual/UserInterface/TestSceneStarRatingDisplay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 2f3593c062..a8bc5664f3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics.Containers; using osuTK; namespace osu.Game.Tests.Visual.UserInterface @@ -28,19 +29,19 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Horizontal, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(i => new FillFlowContainer + ChildrenEnumerable = Enumerable.Range(0, 15).Select(i => new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0)) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i * (i >= 11 ? 25f : 1f) + j * 0.1f, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(width, height), - }) + }), }) }; }); From 9e805dcd44843ef04ea23ed26d311d3a39daebc0 Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Sun, 8 Aug 2021 21:27:32 +1000 Subject: [PATCH 306/600] Fix legacy slider body colour interpolation --- .../Skinning/Legacy/LegacySliderBody.cs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 744ded37c9..9e4b57ca10 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK.Graphics; @@ -40,7 +39,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Color4 outerColour = AccentColour.Darken(0.1f); Color4 innerColour = lighten(AccentColour, 0.5f); - return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); + // Stable doesn't use linear space / gamma-correct colour interpolation + // for slider bodies, so we can't use Interpolation.ValueAt(). + // Instead, we use a local method that interpolates between the colours directly in sRGB space. + return valueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); } /// @@ -55,6 +57,26 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Math.Min(1, color.B * (1 + 0.5f * amount) + 1 * amount), color.A); } + + private static Color4 valueAt(double time, Color4 startColour, Color4 endColour, double startTime, double endTime) + { + if (startColour == endColour) + return startColour; + + double current = time - startTime; + double duration = endTime - startTime; + + if (duration == 0 || current == 0) + return startColour; + + float t = (float)Math.Max(0, Math.Min(1, current / duration)); + + return new Color4( + startColour.R + t * (endColour.R - startColour.R), + startColour.G + t * (endColour.G - startColour.G), + startColour.B + t * (endColour.B - startColour.B), + startColour.A + t * (endColour.A - startColour.A)); + } } } } From 140d29d53762b1d0df5e44fdcd125410769ca50b Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Sun, 8 Aug 2021 23:54:35 +1000 Subject: [PATCH 307/600] Use helper methods instead of local valueAt() method --- .../Skinning/Legacy/LegacySliderBody.cs | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 9e4b57ca10..a8bb69c080 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK.Graphics; @@ -36,13 +37,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy position -= realBorderPortion; - Color4 outerColour = AccentColour.Darken(0.1f); - Color4 innerColour = lighten(AccentColour, 0.5f); + // Stable interpolates slider body colour directly in sRGB space, and because + // Interpolation.ValueAt() uses linear space, we have to counteract applying it + // by calling ToSRGB() on the input colours, and ToLinear() on the resulting colour. - // Stable doesn't use linear space / gamma-correct colour interpolation - // for slider bodies, so we can't use Interpolation.ValueAt(). - // Instead, we use a local method that interpolates between the colours directly in sRGB space. - return valueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); + Color4 outerColour = AccentColour.Darken(0.1f).ToSRGB(); + Color4 innerColour = lighten(AccentColour, 0.5f).ToSRGB(); + + return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1).ToLinear(); } /// @@ -57,26 +59,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Math.Min(1, color.B * (1 + 0.5f * amount) + 1 * amount), color.A); } - - private static Color4 valueAt(double time, Color4 startColour, Color4 endColour, double startTime, double endTime) - { - if (startColour == endColour) - return startColour; - - double current = time - startTime; - double duration = endTime - startTime; - - if (duration == 0 || current == 0) - return startColour; - - float t = (float)Math.Max(0, Math.Min(1, current / duration)); - - return new Color4( - startColour.R + t * (endColour.R - startColour.R), - startColour.G + t * (endColour.G - startColour.G), - startColour.B + t * (endColour.B - startColour.B), - startColour.A + t * (endColour.A - startColour.A)); - } } } } From c72224fa9412d72367a112e461029b864d5f782f Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Sun, 8 Aug 2021 13:45:13 -0400 Subject: [PATCH 308/600] Add "Mirror" mod to osu!catch --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 1 + .../Mods/CatchModMirror.cs | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index eafa1b9b9d..9fee6b2bc1 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -117,6 +117,7 @@ namespace osu.Game.Rulesets.Catch { new CatchModDifficultyAdjust(), new CatchModClassic(), + new CatchModMirror(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs new file mode 100644 index 0000000000..8eb092bfb3 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs @@ -0,0 +1,39 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModMirror : ModMirror, IApplicableToHitObject + { + public override string Description => "Fruits are flipped horizontally."; + + public void ApplyToHitObject(HitObject hitObject) + { + var catchObject = (CatchHitObject)hitObject; + + if (catchObject is BananaShower) + return; + + catchObject.OriginalX = CatchPlayfield.WIDTH - catchObject.OriginalX; + + foreach (var nested in catchObject.NestedHitObjects.Cast()) + nested.OriginalX = CatchPlayfield.WIDTH - nested.OriginalX; + + if (!(catchObject is JuiceStream juiceStream)) + return; + + var controlPoints = juiceStream.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); + foreach (var point in controlPoints) + point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); + + juiceStream.Path = new SliderPath(controlPoints, juiceStream.Path.ExpectedDistance.Value); + } + } +} From 3a741affa325fac471a06febff810827a76f44d5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 8 Aug 2021 21:27:48 +0300 Subject: [PATCH 309/600] Remove whitespaces --- osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs index 8eb092bfb3..ce5b78e12f 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Mods public class CatchModMirror : ModMirror, IApplicableToHitObject { public override string Description => "Fruits are flipped horizontally."; - + public void ApplyToHitObject(HitObject hitObject) { var catchObject = (CatchHitObject)hitObject; From a552b659d3f3fae9ac274686c240d83d1b761d51 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 8 Aug 2021 19:36:27 -0700 Subject: [PATCH 310/600] Update build status badge to github actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 016bd7d922..8f922f74a7 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # osu! -[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) +[![Build status](https://github.com/ppy/osu/actions/workflows/ci.yml/badge.svg?branch=master&event=push)](https://github.com/ppy/osu/actions/workflows/ci.yml) [![GitHub release](https://img.shields.io/github/release/ppy/osu.svg)](https://github.com/ppy/osu/releases/latest) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) From 30cda318f93fe5947cb44335b9ed163e2294d6fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 15:57:18 +0900 Subject: [PATCH 311/600] Reorganise code slightly --- .../Mods/CatchModMirror.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs index ce5b78e12f..7fe7e70fd0 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs @@ -16,24 +16,24 @@ namespace osu.Game.Rulesets.Catch.Mods public void ApplyToHitObject(HitObject hitObject) { - var catchObject = (CatchHitObject)hitObject; - - if (catchObject is BananaShower) + if (hitObject is BananaShower) return; + var catchObject = (CatchHitObject)hitObject; + catchObject.OriginalX = CatchPlayfield.WIDTH - catchObject.OriginalX; foreach (var nested in catchObject.NestedHitObjects.Cast()) nested.OriginalX = CatchPlayfield.WIDTH - nested.OriginalX; - if (!(catchObject is JuiceStream juiceStream)) - return; + if (catchObject is JuiceStream juiceStream) + { + var controlPoints = juiceStream.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); + foreach (var point in controlPoints) + point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); - var controlPoints = juiceStream.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); - foreach (var point in controlPoints) - point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); - - juiceStream.Path = new SliderPath(controlPoints, juiceStream.Path.ExpectedDistance.Value); + juiceStream.Path = new SliderPath(controlPoints, juiceStream.Path.ExpectedDistance.Value); + } } } } From 7cb743a734da2bae3b9349e573f25ff0a0a90907 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:17:51 +0900 Subject: [PATCH 312/600] Move font sizing to base class --- osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs | 1 + .../OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs | 1 - .../Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs index cd4dee5e3a..3801463095 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -12,6 +12,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components [BackgroundDependencyLoader] private void load() { + SpriteText.Font = SpriteText.Font.With(size: 14); Triangles.TriangleScale = 1.5f; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs index da141f96dd..e80923ed47 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs @@ -22,7 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [BackgroundDependencyLoader] private void load() { - SpriteText.Font = SpriteText.Font.With(size: 14); Text = "Create room"; isConnected = multiplayerClient.IsConnected.GetBoundCopy(); diff --git a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs index 3fdff8c4b2..a9826a72eb 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs @@ -11,7 +11,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [BackgroundDependencyLoader] private void load() { - SpriteText.Font = SpriteText.Font.With(size: 14); Text = "Create playlist"; } } From a12f6b78a4bbd265725f9981229c4dc2f7024c57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:21:12 +0900 Subject: [PATCH 313/600] Split status retrieval into its own method --- .../OnlinePlay/Lounge/Components/RoomStatusPill.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index ae17a80705..dfe7ff8cac 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void updateDisplay() { - RoomStatus status = EndDate.Value < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); + RoomStatus status = getDisplayStatus(); pill.Background.Alpha = 1; pill.Background.FadeColour(status.GetAppropriateColour(colours), firstDisplay ? 0 : 100); @@ -63,5 +63,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components firstDisplay = false; } + + private RoomStatus getDisplayStatus() + { + if (EndDate.Value < DateTimeOffset.Now) + return new RoomStatusEnded(); + + return Status.Value ?? new RoomStatusOpen(); + } } } From f4739d0118eb7340205176f1a96261cf7898e7d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:28:43 +0900 Subject: [PATCH 314/600] Remove `MaskingSmoothness` to avoid making sheered container blurry --- .../OnlinePlay/Lounge/Components/RecentParticipantsList.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index da410716e4..7f3fdf01d0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -39,7 +39,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { RelativeSizeAxes = Axes.Both, Masking = true, - MaskingSmoothness = 2, CornerRadius = 10, Shear = new Vector2(0.2f, 0), Child = new Box From e08b1223ab7ef6f4d12413ae520fc8f7ca58f260 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 18:23:39 +0900 Subject: [PATCH 315/600] Move team colours to `OsuColour` --- osu.Game.Tournament/TournamentGame.cs | 4 ++-- osu.Game/Graphics/OsuColour.cs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index cd0e601a2f..7a43fee013 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -26,8 +26,8 @@ namespace osu.Game.Tournament { public static ColourInfo GetTeamColour(TeamColour teamColour) => teamColour == TeamColour.Red ? COLOUR_RED : COLOUR_BLUE; - public static readonly Color4 COLOUR_RED = Color4Extensions.FromHex("#AA1414"); - public static readonly Color4 COLOUR_BLUE = Color4Extensions.FromHex("#1462AA"); + public static readonly Color4 COLOUR_RED = new OsuColour().TeamColourRed; + public static readonly Color4 COLOUR_BLUE = new OsuColour().TeamColourBlue; public static readonly Color4 ELEMENT_BACKGROUND_COLOUR = Color4Extensions.FromHex("#fff"); public static readonly Color4 ELEMENT_FOREGROUND_COLOUR = Color4Extensions.FromHex("#000"); diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 1f87c06dd2..d7cfc4094c 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -130,6 +130,9 @@ namespace osu.Game.Graphics return Gray(brightness > 0.5f ? 0.2f : 0.9f); } + public readonly Color4 TeamColourRed = Color4Extensions.FromHex("#AA1414"); + public readonly Color4 TeamColourBlue = Color4Extensions.FromHex("#1462AA"); + // See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less public readonly Color4 PurpleLighter = Color4Extensions.FromHex(@"eeeeff"); public readonly Color4 PurpleLight = Color4Extensions.FromHex(@"aa88ff"); From aa4c6b93412e3cacb557d7195bef8bbd8e3d7be3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 17:53:38 +0900 Subject: [PATCH 316/600] Bring across tournament score display for game usage --- .../Components/TestSceneMatchScoreDisplay.cs | 2 +- ...play.cs => TournamentMatchScoreDisplay.cs} | 5 +- .../Screens/Gameplay/GameplayScreen.cs | 4 +- .../Screens/Play/HUD/MatchScoreDisplay.cs | 153 ++++++++++++++++++ 4 files changed, 159 insertions(+), 5 deletions(-) rename osu.Game.Tournament/Screens/Gameplay/Components/{MatchScoreDisplay.cs => TournamentMatchScoreDisplay.cs} (97%) create mode 100644 osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs index acd5d53310..11b5cc7556 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tournament.Tests.Components public TestSceneMatchScoreDisplay() { - Add(new MatchScoreDisplay + Add(new TournamentMatchScoreDisplay { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs similarity index 97% rename from osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs rename to osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index 695c6d6f3e..994dee4da0 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -16,7 +16,8 @@ using osuTK; namespace osu.Game.Tournament.Screens.Gameplay.Components { - public class MatchScoreDisplay : CompositeDrawable + // TODO: Update to derive from osu-side class? + public class TournamentMatchScoreDisplay : CompositeDrawable { private const float bar_height = 18; @@ -29,7 +30,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private readonly Drawable score1Bar; private readonly Drawable score2Bar; - public MatchScoreDisplay() + public TournamentMatchScoreDisplay() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index f61506d7f2..540b45eb56 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -86,7 +86,7 @@ namespace osu.Game.Tournament.Screens.Gameplay }, } }, - scoreDisplay = new MatchScoreDisplay + scoreDisplay = new TournamentMatchScoreDisplay { Y = -147, Anchor = Anchor.BottomCentre, @@ -148,7 +148,7 @@ namespace osu.Game.Tournament.Screens.Gameplay } private ScheduledDelegate scheduledOperation; - private MatchScoreDisplay scoreDisplay; + private TournamentMatchScoreDisplay scoreDisplay; private TourneyState lastState; private MatchHeader header; diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs new file mode 100644 index 0000000000..3df4925972 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -0,0 +1,153 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + public class MatchScoreDisplay : CompositeDrawable + { + private const float bar_height = 18; + + public BindableInt Team1Score = new BindableInt(); + public BindableInt Team2Score = new BindableInt(); + + private MatchScoreCounter score1Text; + private MatchScoreCounter score2Text; + + private Drawable score1Bar; + private Drawable score2Bar; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChildren = new[] + { + new Box + { + Name = "top bar red (static)", + RelativeSizeAxes = Axes.X, + Height = bar_height / 4, + Width = 0.5f, + Colour = colours.TeamColourRed, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopRight + }, + new Box + { + Name = "top bar blue (static)", + RelativeSizeAxes = Axes.X, + Height = bar_height / 4, + Width = 0.5f, + Colour = colours.TeamColourBlue, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopLeft + }, + score1Bar = new Box + { + Name = "top bar red", + RelativeSizeAxes = Axes.X, + Height = bar_height, + Width = 0, + Colour = colours.TeamColourRed, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopRight + }, + score1Text = new MatchScoreCounter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + score2Bar = new Box + { + Name = "top bar blue", + RelativeSizeAxes = Axes.X, + Height = bar_height, + Width = 0, + Colour = colours.TeamColourBlue, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopLeft + }, + score2Text = new MatchScoreCounter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Team1Score.BindValueChanged(_ => updateScores()); + Team2Score.BindValueChanged(_ => updateScores()); + } + + private void updateScores() + { + score1Text.Current.Value = Team1Score.Value; + score2Text.Current.Value = Team2Score.Value; + + var winningText = Team1Score.Value > Team2Score.Value ? score1Text : score2Text; + var losingText = Team1Score.Value <= Team2Score.Value ? score1Text : score2Text; + + winningText.Winning = true; + losingText.Winning = false; + + var winningBar = Team1Score.Value > Team2Score.Value ? score1Bar : score2Bar; + var losingBar = Team1Score.Value <= Team2Score.Value ? score1Bar : score2Bar; + + var diff = Math.Max(Team1Score.Value, Team2Score.Value) - Math.Min(Team1Score.Value, Team2Score.Value); + + losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); + winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth); + score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth); + } + + private class MatchScoreCounter : ScoreCounter + { + private OsuSpriteText displayedSpriteText; + + public MatchScoreCounter() + { + Margin = new MarginPadding { Top = bar_height, Horizontal = 10 }; + } + + public bool Winning + { + set => updateFont(value); + } + + protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s => + { + displayedSpriteText = s; + displayedSpriteText.Spacing = new Vector2(-6); + updateFont(false); + }); + + private void updateFont(bool winning) + => displayedSpriteText.Font = winning + ? OsuFont.Torus.With(weight: FontWeight.Bold, size: 50, fixedWidth: true) + : OsuFont.Torus.With(weight: FontWeight.Regular, size: 40, fixedWidth: true); + } + } +} From fcec714b4f545ccc5fbddd4d21a61508f5b7bc62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 19:01:07 +0900 Subject: [PATCH 317/600] Add safeties to avoid `MultiplayerPlayer` crashing when beatmap can't be loaded --- .../OnlinePlay/Multiplayer/MultiplayerPlayer.cs | 13 +++++++++++++ osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index b54a4a7726..404fc21fc8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -57,6 +57,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [BackgroundDependencyLoader] private void load() { + if (!LoadedBeatmapSuccessfully) + return; + // todo: this should be implemented via a custom HUD implementation, and correctly masked to the main content area. LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(ScoreProcessor, userIds), HUDOverlay.Add); @@ -67,6 +70,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { base.LoadAsyncComplete(); + if (!LoadedBeatmapSuccessfully) + return; + if (!ValidForResume) return; // token retrieval may have failed. @@ -96,6 +102,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { base.LoadComplete(); + if (!LoadedBeatmapSuccessfully) + return; + ((IBindable)leaderboard.Expanded).BindTo(HUDOverlay.ShowHud); } @@ -118,6 +127,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override void Update() { base.Update(); + + if (!LoadedBeatmapSuccessfully) + return; + adjustLeaderboardPosition(); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 09eaf1c543..1692975210 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -962,7 +962,7 @@ namespace osu.Game.Screens.Play screenSuspension?.Expire(); // if arriving here and the results screen preparation task hasn't run, it's safe to say the user has not completed the beatmap. - if (prepareScoreForDisplayTask == null) + if (Score != null && prepareScoreForDisplayTask == null) { Score.ScoreInfo.Passed = false; // potentially should be ScoreRank.F instead? this is the best alternative for now. From 54ffb8dc4e61cce3e37cec371a7067e938074062 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Aug 2021 19:01:16 +0900 Subject: [PATCH 318/600] Add basic multiplayer gameplay test coverage --- .../Multiplayer/TestMultiplayerGameplay.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs new file mode 100644 index 0000000000..4b75121575 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Screens.OnlinePlay.Multiplayer; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestMultiplayerGameplay : MultiplayerTestScene + { + [Test] + public void TestBasic() + { + AddStep("load screen", () => + LoadScreen(new MultiplayerPlayer(Client.CurrentMatchPlayingItem.Value, Client.Room?.Users.Select(u => u.UserID).ToArray()))); + } + } +} From 0fa1f085df9720b6da39342da2ab6f2ae9337bb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Aug 2021 20:06:57 +0900 Subject: [PATCH 319/600] Store `MultiplayerRoomUser` as part of tracked data --- .../Multiplayer/Spectate/MultiSpectatorLeaderboard.cs | 7 ++++--- .../Play/HUD/MultiplayerGameplayLeaderboard.cs | 11 +++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs index 55c4270c70..95f9fa27f1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs @@ -4,6 +4,7 @@ using System; using JetBrains.Annotations; using osu.Framework.Timing; +using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate ((SpectatingTrackedUserData)data).Clock = null; } - protected override TrackedUserData CreateUserData(int userId, ScoreProcessor scoreProcessor) => new SpectatingTrackedUserData(userId, scoreProcessor); + protected override TrackedUserData CreateUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) => new SpectatingTrackedUserData(user, scoreProcessor); protected override void Update() { @@ -47,8 +48,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [CanBeNull] public IClock Clock; - public SpectatingTrackedUserData(int userId, ScoreProcessor scoreProcessor) - : base(userId, scoreProcessor) + public SpectatingTrackedUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) + : base(user, scoreProcessor) { } diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index a10c16fcd5..74e5710677 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -11,6 +11,7 @@ using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Rooms; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Scoring; @@ -55,7 +56,9 @@ namespace osu.Game.Screens.Play.HUD foreach (var userId in playingUsers) { - var trackedUser = CreateUserData(userId, scoreProcessor); + var user = multiplayerClient.Room?.Users.FirstOrDefault(u => u.UserID == userId); + + var trackedUser = CreateUserData(user, scoreProcessor); trackedUser.ScoringMode.BindTo(scoringMode); UserScores[userId] = trackedUser; } @@ -145,7 +148,7 @@ namespace osu.Game.Screens.Play.HUD protected class TrackedUserData { - public readonly int UserId; + public readonly MultiplayerRoomUser User; public readonly ScoreProcessor ScoreProcessor; public readonly BindableDouble Score = new BindableDouble(); @@ -157,9 +160,9 @@ namespace osu.Game.Screens.Play.HUD public readonly List Frames = new List(); - public TrackedUserData(int userId, ScoreProcessor scoreProcessor) + public TrackedUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) { - UserId = userId; + User = user; ScoreProcessor = scoreProcessor; ScoringMode.BindValueChanged(_ => UpdateScore()); From 1f69c61fd87a5a8b983bdcdbbca6be6d7811e198 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:38:21 +0900 Subject: [PATCH 320/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 7a0a542ee9..f757847c10 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0a6522f15e..3a840296ac 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 00222877f1..217ec6089a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 1e5d9003d389d3ef882c4aa9c3d63c2f0a63f887 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:44:50 +0900 Subject: [PATCH 321/600] Add the ability for tests to alter the room and user states which during testing --- ...TestSceneMultiplayerGameplayLeaderboard.cs | 4 +++ .../Multiplayer/MultiplayerTestScene.cs | 29 +++++++++++-------- .../Multiplayer/TestMultiplayerClient.cs | 7 ++++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 0e368b59dd..0aa47f0899 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -20,6 +20,7 @@ using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -53,7 +54,10 @@ namespace osu.Game.Tests.Visual.Multiplayer var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); foreach (var user in users) + { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); + OnlinePlayDependencies.Client.AddUser(new User { Id = user }); + } // Todo: This is REALLY bad. Client.CurrentMatchPlayingUserIds.AddRange(users); diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 42345b7266..f259784170 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -36,24 +36,29 @@ namespace osu.Game.Tests.Visual.Multiplayer { if (joinRoom) { - var room = new Room - { - Name = { Value = "test name" }, - Playlist = - { - new PlaylistItem - { - Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, - Ruleset = { Value = Ruleset.Value } - } - } - }; + var room = CreateRoom(); RoomManager.CreateRoom(room); SelectedRoom.Value = room; } }); + protected virtual Room CreateRoom() + { + return new Room + { + Name = { Value = "test name" }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, + Ruleset = { Value = Ruleset.Value } + } + } + }; + } + public override void SetUpSteps() { base.SetUpSteps(); diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 43aadf5acb..db491aac25 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -50,7 +50,12 @@ namespace osu.Game.Tests.Visual.Multiplayer public void Disconnect() => isConnected.Value = false; - public void AddUser(User user) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(user.Id) { User = user }); + public MultiplayerRoomUser AddUser(User user) + { + var roomUser = new MultiplayerRoomUser(user.Id) { User = user }; + ((IMultiplayerClient)this).UserJoined(roomUser); + return roomUser; + } public void AddNullUser(int userId) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(userId)); From ab522e1569e23000df98840a2f286f233a973284 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:50:25 +0900 Subject: [PATCH 322/600] Add test coverage of team display on leaderboard --- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs new file mode 100644 index 0000000000..0551f3b802 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -0,0 +1,99 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Framework.Utils; +using osu.Game.Configuration; +using osu.Game.Online.API; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Screens.Play.HUD; +using osu.Game.Tests.Visual.OnlinePlay; +using osu.Game.Tests.Visual.Spectator; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerTestScene + { + private static IEnumerable users => Enumerable.Range(0, 16); + + public new TestSceneMultiplayerGameplayLeaderboard.TestMultiplayerSpectatorClient SpectatorClient => + (TestSceneMultiplayerGameplayLeaderboard.TestMultiplayerSpectatorClient)OnlinePlayDependencies?.SpectatorClient; + + protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); + + protected class TestDependencies : MultiplayerTestSceneDependencies + { + protected override TestSpectatorClient CreateSpectatorClient() => new TestSceneMultiplayerGameplayLeaderboard.TestMultiplayerSpectatorClient(); + } + + private MultiplayerGameplayLeaderboard leaderboard; + + protected override Room CreateRoom() + { + var room = base.CreateRoom(); + room.Type.Value = MatchType.TeamVersus; + return room; + } + + [SetUpSteps] + public override void SetUpSteps() + { + AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).Result); + + AddStep("create leaderboard", () => + { + leaderboard?.Expire(); + + OsuScoreProcessor scoreProcessor; + Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); + + var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); + + foreach (var user in users) + { + SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); + var roomUser = OnlinePlayDependencies.Client.AddUser(new User { Id = user }); + + roomUser.MatchState = new TeamVersusUserState + { + TeamID = RNG.Next(0, 2) + }; + } + + // Todo: This is REALLY bad. + Client.CurrentMatchPlayingUserIds.AddRange(users); + + Children = new Drawable[] + { + scoreProcessor = new OsuScoreProcessor(), + }; + + scoreProcessor.ApplyBeatmap(playable); + + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, users.ToArray()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, Add); + }); + + AddUntilStep("wait for load", () => leaderboard.IsLoaded); + AddUntilStep("wait for user population", () => Client.CurrentMatchPlayingUserIds.Count > 0); + } + + [Test] + public void TestScoreUpdates() + { + AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 100); + AddToggleStep("switch compact mode", expanded => leaderboard.Expanded.Value = expanded); + } + } +} From e1d4eee1d2439167fa2362deaffe3dcb137956c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:59:24 +0900 Subject: [PATCH 323/600] Add the ability to set custom overriding colours on `GameplayLeaderboardScore`s --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 10 ++++++---- .../Screens/Play/HUD/GameplayLeaderboardScore.cs | 16 ++++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 34efeab54c..63cb4f89f5 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -48,10 +48,9 @@ namespace osu.Game.Screens.Play.HUD /// public ILeaderboardScore AddPlayer([CanBeNull] User user, bool isTracked) { - var drawable = new GameplayLeaderboardScore(user, isTracked) - { - Expanded = { BindTarget = Expanded }, - }; + var drawable = CreateLeaderboardScoreDrawable(user, isTracked); + + drawable.Expanded.BindTo(Expanded); base.Add(drawable); drawable.TotalScore.BindValueChanged(_ => sorting.Invalidate(), true); @@ -61,6 +60,9 @@ namespace osu.Game.Screens.Play.HUD return drawable; } + protected virtual GameplayLeaderboardScore CreateLeaderboardScoreDrawable(User user, bool isTracked) => + new GameplayLeaderboardScore(user, isTracked); + public sealed override void Add(GameplayLeaderboardScore drawable) { throw new NotSupportedException($"Use {nameof(AddPlayer)} instead."); diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 10476e5565..433bf78e9b 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -54,6 +54,10 @@ namespace osu.Game.Screens.Play.HUD public BindableInt Combo { get; } = new BindableInt(); public BindableBool HasQuit { get; } = new BindableBool(); + public Color4? BackgroundColour { get; set; } + + public Color4? TextColour { get; set; } + private int? scorePosition; public int? ScorePosition @@ -331,19 +335,19 @@ namespace osu.Game.Screens.Play.HUD if (scorePosition == 1) { widthExtension = true; - panelColour = Color4Extensions.FromHex("7fcc33"); - textColour = Color4.White; + panelColour = BackgroundColour ?? Color4Extensions.FromHex("7fcc33"); + textColour = TextColour ?? Color4.White; } else if (trackedPlayer) { widthExtension = true; - panelColour = Color4Extensions.FromHex("ffd966"); - textColour = Color4Extensions.FromHex("2e576b"); + panelColour = BackgroundColour ?? Color4Extensions.FromHex("ffd966"); + textColour = TextColour ?? Color4Extensions.FromHex("2e576b"); } else { - panelColour = Color4Extensions.FromHex("3399cc"); - textColour = Color4.White; + panelColour = BackgroundColour ?? Color4Extensions.FromHex("3399cc"); + textColour = TextColour ?? Color4.White; } this.TransformTo(nameof(SizeContainerLeftPadding), widthExtension ? -top_player_left_width_extension : 0, panel_transition_duration, Easing.OutElastic); From 77c9aadd05d3495a9f55bbf6d54c19305ca821ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 17:04:06 +0900 Subject: [PATCH 324/600] Add team colour support to multiplaye gameplay leaderboard panels --- .../HUD/MultiplayerGameplayLeaderboard.cs | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 74e5710677..36a0365775 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -7,13 +7,17 @@ using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Game.Configuration; using osu.Game.Database; +using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; -using osu.Game.Online.Rooms; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Scoring; +using osu.Game.Users; +using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { @@ -103,6 +107,34 @@ namespace osu.Game.Screens.Play.HUD spectatorClient.OnNewFrames += handleIncomingFrames; } + [Resolved] + private OsuColour colours { get; set; } + + protected override GameplayLeaderboardScore CreateLeaderboardScoreDrawable(User user, bool isTracked) + { + var leaderboardScore = base.CreateLeaderboardScoreDrawable(user, isTracked); + + if (UserScores[user.Id].Team is int team) + { + leaderboardScore.BackgroundColour = getTeamColour(team).Lighten(1.2f); + leaderboardScore.TextColour = Color4.White; + } + + return leaderboardScore; + } + + private Color4 getTeamColour(int team) + { + switch (team) + { + case 0: + return colours.TeamColourRed; + + default: + return colours.TeamColourBlue; + } + } + private void usersChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) @@ -129,7 +161,7 @@ namespace osu.Game.Screens.Play.HUD trackedData.UpdateScore(); }); - protected virtual TrackedUserData CreateUserData(int userId, ScoreProcessor scoreProcessor) => new TrackedUserData(userId, scoreProcessor); + protected virtual TrackedUserData CreateUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) => new TrackedUserData(user, scoreProcessor); protected override void Dispose(bool isDisposing) { @@ -160,6 +192,8 @@ namespace osu.Game.Screens.Play.HUD public readonly List Frames = new List(); + public int? Team => (User.MatchState as TeamVersusUserState)?.TeamID; + public TrackedUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) { User = user; From cdc173e86782026e7d6b11f3b9d0f3af26fbb672 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 17:07:50 +0900 Subject: [PATCH 325/600] Add tracking of team totals to leaderboard implementation --- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 6 ++++ .../HUD/MultiplayerGameplayLeaderboard.cs | 32 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 0551f3b802..6376d4e305 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -83,6 +83,12 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, }, Add); + + LoadComponentAsync(new MatchScoreDisplay + { + Team1Score = { BindTarget = leaderboard.Team1Score }, + Team2Score = { BindTarget = leaderboard.Team2Score } + }, Add); }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 36a0365775..19019e61f0 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -26,6 +26,12 @@ namespace osu.Game.Screens.Play.HUD { protected readonly Dictionary UserScores = new Dictionary(); + public readonly BindableInt Team1Score = new BindableInt(); + public readonly BindableInt Team2Score = new BindableInt(); + + [Resolved] + private OsuColour colours { get; set; } + [Resolved] private SpectatorClient spectatorClient { get; set; } @@ -39,6 +45,8 @@ namespace osu.Game.Screens.Play.HUD private readonly BindableList playingUsers; private Bindable scoringMode; + private bool hasTeams; + /// /// Construct a new leaderboard. /// @@ -65,6 +73,8 @@ namespace osu.Game.Screens.Play.HUD var trackedUser = CreateUserData(user, scoreProcessor); trackedUser.ScoringMode.BindTo(scoringMode); UserScores[userId] = trackedUser; + + hasTeams |= trackedUser.Team != null; } userLookupCache.GetUsersAsync(playingUsers.ToArray()).ContinueWith(users => Schedule(() => @@ -107,8 +117,7 @@ namespace osu.Game.Screens.Play.HUD spectatorClient.OnNewFrames += handleIncomingFrames; } - [Resolved] - private OsuColour colours { get; set; } + protected virtual TrackedUserData CreateUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) => new TrackedUserData(user, scoreProcessor); protected override GameplayLeaderboardScore CreateLeaderboardScoreDrawable(User user, bool isTracked) { @@ -159,9 +168,26 @@ namespace osu.Game.Screens.Play.HUD trackedData.Frames.Add(new TimedFrame(bundle.Frames.First().Time, bundle.Header)); trackedData.UpdateScore(); + + updateTotals(); }); - protected virtual TrackedUserData CreateUserData(MultiplayerRoomUser user, ScoreProcessor scoreProcessor) => new TrackedUserData(user, scoreProcessor); + private void updateTotals() + { + if (!hasTeams) + return; + + Team1Score.Value = 0; + Team2Score.Value = 0; + + foreach (var u in UserScores.Values) + { + if (u.Team == 0) + Team1Score.Value += (int)u.Score.Value; + else + Team2Score.Value += (int)u.Score.Value; + } + } protected override void Dispose(bool isDisposing) { From ebbf6467e815091149460b54b2ed6f5fec97e5b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 17:23:02 +0900 Subject: [PATCH 326/600] Support more than two teams --- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 17 ++++++++-------- .../HUD/MultiplayerGameplayLeaderboard.cs | 20 +++++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 6376d4e305..ce3add84c5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -4,11 +4,9 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Framework.Utils; -using osu.Game.Configuration; using osu.Game.Online.API; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; @@ -82,13 +80,16 @@ namespace osu.Game.Tests.Visual.Multiplayer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - }, Add); - - LoadComponentAsync(new MatchScoreDisplay + }, gameplayLeaderboard => { - Team1Score = { BindTarget = leaderboard.Team1Score }, - Team2Score = { BindTarget = leaderboard.Team2Score } - }, Add); + LoadComponentAsync(new MatchScoreDisplay + { + Team1Score = { BindTarget = leaderboard.TeamScores[0] }, + Team2Score = { BindTarget = leaderboard.TeamScores[1] } + }, Add); + + Add(gameplayLeaderboard); + }); }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 19019e61f0..2895d0cb5c 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -26,8 +26,7 @@ namespace osu.Game.Screens.Play.HUD { protected readonly Dictionary UserScores = new Dictionary(); - public readonly BindableInt Team1Score = new BindableInt(); - public readonly BindableInt Team2Score = new BindableInt(); + public readonly Dictionary TeamScores = new Dictionary(); [Resolved] private OsuColour colours { get; set; } @@ -45,7 +44,7 @@ namespace osu.Game.Screens.Play.HUD private readonly BindableList playingUsers; private Bindable scoringMode; - private bool hasTeams; + private bool hasTeams => TeamScores.Count > 0; /// /// Construct a new leaderboard. @@ -74,7 +73,8 @@ namespace osu.Game.Screens.Play.HUD trackedUser.ScoringMode.BindTo(scoringMode); UserScores[userId] = trackedUser; - hasTeams |= trackedUser.Team != null; + if (trackedUser.Team is int team && !TeamScores.ContainsKey(team)) + TeamScores.Add(team, new BindableInt()); } userLookupCache.GetUsersAsync(playingUsers.ToArray()).ContinueWith(users => Schedule(() => @@ -177,15 +177,15 @@ namespace osu.Game.Screens.Play.HUD if (!hasTeams) return; - Team1Score.Value = 0; - Team2Score.Value = 0; + foreach (var scores in TeamScores.Values) scores.Value = 0; foreach (var u in UserScores.Values) { - if (u.Team == 0) - Team1Score.Value += (int)u.Score.Value; - else - Team2Score.Value += (int)u.Score.Value; + if (u.Team == null) + continue; + + if (TeamScores.TryGetValue(u.Team.Value, out var team)) + team.Value += (int)u.Score.Value; } } From 24accdcab05b99e1b01a8f71d0f41609738d5d3c Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Mon, 9 Aug 2021 18:56:47 +1000 Subject: [PATCH 327/600] Add LegacyUtils class with non linear colour interpolation method --- .../Skinning/Legacy/LegacySliderBody.cs | 12 ++-- osu.Game/Utils/LegacyUtils.cs | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Utils/LegacyUtils.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index a8bb69c080..92941665e0 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -3,9 +3,9 @@ using System; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; +using osu.Game.Utils; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy @@ -37,14 +37,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy position -= realBorderPortion; - // Stable interpolates slider body colour directly in sRGB space, and because - // Interpolation.ValueAt() uses linear space, we have to counteract applying it - // by calling ToSRGB() on the input colours, and ToLinear() on the resulting colour. + Color4 outerColour = AccentColour.Darken(0.1f); + Color4 innerColour = lighten(AccentColour, 0.5f); - Color4 outerColour = AccentColour.Darken(0.1f).ToSRGB(); - Color4 innerColour = lighten(AccentColour, 0.5f).ToSRGB(); - - return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1).ToLinear(); + return LegacyUtils.InterpolateNonLinear(position / realGradientPortion, outerColour, innerColour, 0, 1); } /// diff --git a/osu.Game/Utils/LegacyUtils.cs b/osu.Game/Utils/LegacyUtils.cs new file mode 100644 index 0000000000..9351125acd --- /dev/null +++ b/osu.Game/Utils/LegacyUtils.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; +using osuTK.Graphics; + +namespace osu.Game.Utils +{ + public static class LegacyUtils + { + public static Color4 InterpolateNonLinear(double time, Color4 startColour, Color4 endColour, double startTime, double endTime, Easing easing = Easing.None) + => InterpolateNonLinear(time, startColour, endColour, startTime, endTime, new DefaultEasingFunction(easing)); + + public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, Easing easing = Easing.None) + => InterpolateNonLinear(time, startColour, endColour, startTime, endTime, new DefaultEasingFunction(easing)); + + /// + /// Interpolates between two sRGB s directly in sRGB space. + /// + public static Color4 InterpolateNonLinear(double time, Color4 startColour, Color4 endColour, double startTime, double endTime, TEasing easing) where TEasing : IEasingFunction + { + if (startColour == endColour) + return startColour; + + double current = time - startTime; + double duration = endTime - startTime; + + if (duration == 0 || current == 0) + return startColour; + + float t = Math.Max(0, Math.Min(1, (float)easing.ApplyEasing(current / duration))); + + return new Color4( + startColour.R + t * (endColour.R - startColour.R), + startColour.G + t * (endColour.G - startColour.G), + startColour.B + t * (endColour.B - startColour.B), + startColour.A + t * (endColour.A - startColour.A)); + } + + /// + /// Interpolates between two sRGB s directly in sRGB space. + /// + public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, in TEasing easing) where TEasing : IEasingFunction + { + if (startColour == endColour) + return startColour; + + double current = time - startTime; + double duration = endTime - startTime; + + if (duration == 0 || current == 0) + return startColour; + + float t = Math.Max(0, Math.Min(1, (float)easing.ApplyEasing(current / duration))); + + return new Colour4( + startColour.R + t * (endColour.R - startColour.R), + startColour.G + t * (endColour.G - startColour.G), + startColour.B + t * (endColour.B - startColour.B), + startColour.A + t * (endColour.A - startColour.A)); + } + } +} From 121648b5937f6370183bbb0a184973d3f8436f82 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 18:13:28 +0900 Subject: [PATCH 328/600] Add gameplay-specific team score display which can expand and contract --- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 16 ++++++- .../Multiplayer/GameplayMatchScoreDisplay.cs | 40 ++++++++++++++++++ .../Multiplayer/MultiplayerPlayer.cs | 42 +++++++++++++------ .../Screens/Play/HUD/MatchScoreDisplay.cs | 42 ++++++++++++------- 4 files changed, 111 insertions(+), 29 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index ce3add84c5..8eaa63a166 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -11,6 +11,7 @@ using osu.Game.Online.API; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; @@ -33,6 +34,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } private MultiplayerGameplayLeaderboard leaderboard; + private GameplayMatchScoreDisplay gameplayScoreDisplay; protected override Room CreateRoom() { @@ -88,6 +90,14 @@ namespace osu.Game.Tests.Visual.Multiplayer Team2Score = { BindTarget = leaderboard.TeamScores[1] } }, Add); + LoadComponentAsync(gameplayScoreDisplay = new GameplayMatchScoreDisplay + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Team1Score = { BindTarget = leaderboard.TeamScores[0] }, + Team2Score = { BindTarget = leaderboard.TeamScores[1] } + }, Add); + Add(gameplayLeaderboard); }); }); @@ -100,7 +110,11 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestScoreUpdates() { AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 100); - AddToggleStep("switch compact mode", expanded => leaderboard.Expanded.Value = expanded); + AddToggleStep("switch compact mode", expanded => + { + leaderboard.Expanded.Value = expanded; + gameplayScoreDisplay.Expanded.Value = expanded; + }); } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs new file mode 100644 index 0000000000..20a88545c5 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs @@ -0,0 +1,40 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Screens.Play.HUD; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Multiplayer +{ + public class GameplayMatchScoreDisplay : MatchScoreDisplay + { + public Bindable Expanded = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + Scale = new Vector2(0.5f); + + Expanded.BindValueChanged(expandedChanged, true); + } + + private void expandedChanged(ValueChangedEvent expanded) + { + if (expanded.NewValue) + { + Score1Text.FadeIn(500, Easing.OutQuint); + Score2Text.FadeIn(500, Easing.OutQuint); + this.ResizeWidthTo(2, 500, Easing.OutQuint); + } + else + { + Score1Text.FadeOut(500, Easing.OutQuint); + Score2Text.FadeOut(500, Easing.OutQuint); + this.ResizeWidthTo(1, 500, Easing.OutQuint); + } + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 404fc21fc8..0ff7d70c11 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -3,9 +3,12 @@ using System; using System.Diagnostics; +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Logging; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; @@ -37,6 +40,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private readonly int[] userIds; private LoadingLayer loadingDisplay; + private FillFlowContainer leaderboardFlow; /// /// Construct a multiplayer player. @@ -60,8 +64,32 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!LoadedBeatmapSuccessfully) return; + HUDOverlay.Add(leaderboardFlow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + }); + // todo: this should be implemented via a custom HUD implementation, and correctly masked to the main content area. - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(ScoreProcessor, userIds), HUDOverlay.Add); + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(ScoreProcessor, userIds), l => + { + if (!LoadedBeatmapSuccessfully) + return; + + ((IBindable)leaderboard.Expanded).BindTo(HUDOverlay.ShowHud); + + leaderboardFlow.Add(l); + + if (leaderboard.TeamScores.Count >= 2) + { + LoadComponentAsync(new GameplayMatchScoreDisplay + { + Team1Score = { BindTarget = leaderboard.TeamScores.First().Value }, + Team2Score = { BindTarget = leaderboard.TeamScores.Last().Value }, + Expanded = { BindTarget = HUDOverlay.ShowHud }, + }, leaderboardFlow.Add); + } + }); HUDOverlay.Add(loadingDisplay = new LoadingLayer(true) { Depth = float.MaxValue }); } @@ -98,16 +126,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Debug.Assert(client.Room != null); } - protected override void LoadComplete() - { - base.LoadComplete(); - - if (!LoadedBeatmapSuccessfully) - return; - - ((IBindable)leaderboard.Expanded).BindTo(HUDOverlay.ShowHud); - } - protected override void StartGameplay() { // block base call, but let the server know we are ready to start. @@ -138,7 +156,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { const float padding = 44; // enough margin to avoid the hit error display. - leaderboard.Position = new Vector2(padding, padding + HUDOverlay.TopScoringElementsHeight); + leaderboardFlow.Position = new Vector2(padding, padding + HUDOverlay.TopScoringElementsHeight); } private void onMatchStarted() => Scheduler.Add(() => diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 3df4925972..d25ceb948e 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -21,8 +21,8 @@ namespace osu.Game.Screens.Play.HUD public BindableInt Team1Score = new BindableInt(); public BindableInt Team2Score = new BindableInt(); - private MatchScoreCounter score1Text; - private MatchScoreCounter score2Text; + protected MatchScoreCounter Score1Text; + protected MatchScoreCounter Score2Text; private Drawable score1Bar; private Drawable score2Bar; @@ -65,11 +65,6 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.TopCentre, Origin = Anchor.TopRight }, - score1Text = new MatchScoreCounter - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, score2Bar = new Box { Name = "top bar blue", @@ -80,10 +75,25 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.TopCentre, Origin = Anchor.TopLeft }, - score2Text = new MatchScoreCounter + new Container { + RelativeSizeAxes = Axes.X, + Height = 50, Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre + Origin = Anchor.TopCentre, + Children = new Drawable[] + { + Score1Text = new MatchScoreCounter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + Score2Text = new MatchScoreCounter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + } }, }; } @@ -98,11 +108,11 @@ namespace osu.Game.Screens.Play.HUD private void updateScores() { - score1Text.Current.Value = Team1Score.Value; - score2Text.Current.Value = Team2Score.Value; + Score1Text.Current.Value = Team1Score.Value; + Score2Text.Current.Value = Team2Score.Value; - var winningText = Team1Score.Value > Team2Score.Value ? score1Text : score2Text; - var losingText = Team1Score.Value <= Team2Score.Value ? score1Text : score2Text; + var winningText = Team1Score.Value > Team2Score.Value ? Score1Text : Score2Text; + var losingText = Team1Score.Value <= Team2Score.Value ? Score1Text : Score2Text; winningText.Winning = true; losingText.Winning = false; @@ -119,11 +129,11 @@ namespace osu.Game.Screens.Play.HUD protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth); - score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth); + Score1Text.X = -Math.Max(5 + Score1Text.DrawWidth / 2, score1Bar.DrawWidth); + Score2Text.X = Math.Max(5 + Score2Text.DrawWidth / 2, score2Bar.DrawWidth); } - private class MatchScoreCounter : ScoreCounter + protected class MatchScoreCounter : ScoreCounter { private OsuSpriteText displayedSpriteText; From 5f3d0871012f88bf1bfba1d7cb309ad69b372384 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 19:05:23 +0900 Subject: [PATCH 329/600] Also add team score display to multiplayer spectator screen --- .../TestSceneMultiSpectatorLeaderboard.cs | 4 ++ .../TestSceneMultiSpectatorScreen.cs | 43 ++++++++++++++++++ .../Spectate/MultiSpectatorScreen.cs | 44 +++++++++++++++---- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index e14df62af1..22543b7b26 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -9,6 +9,7 @@ using osu.Framework.Timing; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play.HUD; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -31,7 +32,10 @@ namespace osu.Game.Tests.Visual.Multiplayer }; foreach (var (userId, _) in clocks) + { SpectatorClient.StartPlay(userId, 0); + OnlinePlayDependencies.Client.AddUser(new User { Id = userId }); + } }); AddStep("create leaderboard", () => diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 072e32370d..e8ee9fe012 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -8,10 +8,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -49,6 +51,10 @@ namespace osu.Game.Tests.Visual.Multiplayer { Client.CurrentMatchPlayingUserIds.Add(PLAYER_1_ID); Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); + + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }); + playingUserIds.Add(PLAYER_1_ID); playingUserIds.Add(PLAYER_2_ID); }); @@ -76,6 +82,41 @@ namespace osu.Game.Tests.Visual.Multiplayer AddWaitStep("wait a bit", 20); } + [Test] + public void TestTeamDisplay() + { + AddStep("start players", () => + { + Client.CurrentMatchPlayingUserIds.Add(PLAYER_1_ID); + Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); + + var player1 = OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }); + player1.MatchState = new TeamVersusUserState + { + TeamID = 0, + }; + + var player2 = OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }); + player2.MatchState = new TeamVersusUserState + { + TeamID = 1, + }; + + SpectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId); + SpectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId); + + playingUserIds.Add(PLAYER_1_ID); + playingUserIds.Add(PLAYER_2_ID); + }); + + loadSpectateScreen(); + + sendFrames(PLAYER_1_ID, 1000); + sendFrames(PLAYER_2_ID, 1000); + + AddWaitStep("wait a bit", 20); + } + [Test] public void TestTimeDoesNotProgressWhileAllPlayersPaused() { @@ -265,6 +306,8 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (int id in userIds) { Client.CurrentMatchPlayingUserIds.Add(id); + OnlinePlayDependencies.Client.AddUser(new User { Id = id }); + SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUserIds.Add(id); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 56ed7a9564..9923c42583 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Online.Spectator; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Spectate; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate @@ -59,6 +60,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private void load() { Container leaderboardContainer; + Container scoreDisplayContainer; + masterClockContainer = new MasterGameplayClockContainer(Beatmap.Value, 0); InternalChildren = new[] @@ -67,20 +70,36 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate masterClockContainer.WithChild(new GridContainer { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, Content = new[] { new Drawable[] { - leaderboardContainer = new Container + scoreDisplayContainer = new Container { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y }, - grid = new PlayerGrid { RelativeSizeAxes = Axes.Both } + }, + new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + Content = new[] + { + new Drawable[] + { + leaderboardContainer = new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X + }, + grid = new PlayerGrid { RelativeSizeAxes = Axes.Both } + } + } + } } } }) @@ -108,6 +127,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate leaderboard.AddClock(instance.UserId, instance.GameplayClock); leaderboardContainer.Add(leaderboard); + + if (leaderboard.TeamScores.Count >= 2) + { + LoadComponentAsync(new MatchScoreDisplay + { + Team1Score = { BindTarget = leaderboard.TeamScores.First().Value }, + Team2Score = { BindTarget = leaderboard.TeamScores.Last().Value }, + }, scoreDisplayContainer.Add); + } }); } From 551929cf5ad214fce24e99f6d76d185ae6ff8987 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 19:18:13 +0900 Subject: [PATCH 330/600] Simplify method of marking players as playing in test scenes --- .../TestSceneMultiSpectatorScreen.cs | 17 +++++------------ .../TestSceneMultiplayerGameplayLeaderboard.cs | 5 +---- ...tSceneMultiplayerGameplayLeaderboardTeams.cs | 5 +---- .../Online/Multiplayer/MultiplayerClient.cs | 14 ++++++++------ .../Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- .../Visual/Multiplayer/TestMultiplayerClient.cs | 6 +++++- 6 files changed, 21 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index e8ee9fe012..116349c71e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -49,11 +49,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start players silently", () => { - Client.CurrentMatchPlayingUserIds.Add(PLAYER_1_ID); - Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); - - OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }); - OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }, true); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }, true); playingUserIds.Add(PLAYER_1_ID); playingUserIds.Add(PLAYER_2_ID); @@ -87,16 +84,13 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start players", () => { - Client.CurrentMatchPlayingUserIds.Add(PLAYER_1_ID); - Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); - - var player1 = OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }); + var player1 = OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }, true); player1.MatchState = new TeamVersusUserState { TeamID = 0, }; - var player2 = OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }); + var player2 = OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }, true); player2.MatchState = new TeamVersusUserState { TeamID = 1, @@ -305,8 +299,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { foreach (int id in userIds) { - Client.CurrentMatchPlayingUserIds.Add(id); - OnlinePlayDependencies.Client.AddUser(new User { Id = id }); + OnlinePlayDependencies.Client.AddUser(new User { Id = id }, true); SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUserIds.Add(id); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 0aa47f0899..8121492a0b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -56,12 +56,9 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (var user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - OnlinePlayDependencies.Client.AddUser(new User { Id = user }); + OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); } - // Todo: This is REALLY bad. - Client.CurrentMatchPlayingUserIds.AddRange(users); - Children = new Drawable[] { scoreProcessor = new OsuScoreProcessor(), diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 8eaa63a166..d363c6eed4 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (var user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - var roomUser = OnlinePlayDependencies.Client.AddUser(new User { Id = user }); + var roomUser = OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); roomUser.MatchState = new TeamVersusUserState { @@ -68,9 +68,6 @@ namespace osu.Game.Tests.Visual.Multiplayer }; } - // Todo: This is REALLY bad. - Client.CurrentMatchPlayingUserIds.AddRange(users); - Children = new Drawable[] { scoreProcessor = new OsuScoreProcessor(), diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index bffb2d341a..14beb38cde 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -62,7 +62,9 @@ namespace osu.Game.Online.Multiplayer /// /// The users in the joined which are participating in the current gameplay loop. /// - public readonly BindableList CurrentMatchPlayingUserIds = new BindableList(); + public IBindableList CurrentMatchPlayingUserIds => PlayingUserIds; + + protected readonly BindableList PlayingUserIds = new BindableList(); public readonly Bindable CurrentMatchPlayingItem = new Bindable(); @@ -179,7 +181,7 @@ namespace osu.Game.Online.Multiplayer { APIRoom = null; Room = null; - CurrentMatchPlayingUserIds.Clear(); + PlayingUserIds.Clear(); RoomUpdated?.Invoke(); }); @@ -376,7 +378,7 @@ namespace osu.Game.Online.Multiplayer return; Room.Users.Remove(user); - CurrentMatchPlayingUserIds.Remove(user.UserID); + PlayingUserIds.Remove(user.UserID); RoomUpdated?.Invoke(); }, false); @@ -659,16 +661,16 @@ namespace osu.Game.Online.Multiplayer /// The new state of the user. private void updateUserPlayingState(int userId, MultiplayerUserState state) { - bool wasPlaying = CurrentMatchPlayingUserIds.Contains(userId); + bool wasPlaying = PlayingUserIds.Contains(userId); bool isPlaying = state >= MultiplayerUserState.WaitingForLoad && state <= MultiplayerUserState.FinishedPlay; if (isPlaying == wasPlaying) return; if (isPlaying) - CurrentMatchPlayingUserIds.Add(userId); + PlayingUserIds.Add(userId); else - CurrentMatchPlayingUserIds.Remove(userId); + PlayingUserIds.Remove(userId); } private Task scheduleAsync(Action action, CancellationToken cancellationToken = default) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 2895d0cb5c..4968dc0706 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Play.HUD private UserLookupCache userLookupCache { get; set; } private readonly ScoreProcessor scoreProcessor; - private readonly BindableList playingUsers; + private readonly IBindableList playingUsers; private Bindable scoringMode; private bool hasTeams => TeamScores.Count > 0; diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index db491aac25..cffaea5c94 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -50,10 +50,14 @@ namespace osu.Game.Tests.Visual.Multiplayer public void Disconnect() => isConnected.Value = false; - public MultiplayerRoomUser AddUser(User user) + public MultiplayerRoomUser AddUser(User user, bool markAsPlaying = false) { var roomUser = new MultiplayerRoomUser(user.Id) { User = user }; ((IMultiplayerClient)this).UserJoined(roomUser); + + if (markAsPlaying) + PlayingUserIds.Add(user.Id); + return roomUser; } From ea6e441dec4201f10fe21bd71aea833f1cf5c9a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 19:18:13 +0900 Subject: [PATCH 331/600] Simplify method of marking players as playing in test scenes --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 9 ++++++--- .../TestSceneMultiplayerGameplayLeaderboard.cs | 7 ++++--- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 14 ++++++++------ .../Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- .../Visual/Multiplayer/TestMultiplayerClient.cs | 11 ++++++++++- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 072e32370d..e9fae32335 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -47,8 +48,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start players silently", () => { - Client.CurrentMatchPlayingUserIds.Add(PLAYER_1_ID); - Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }, true); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }, true); + playingUserIds.Add(PLAYER_1_ID); playingUserIds.Add(PLAYER_2_ID); }); @@ -264,7 +266,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { foreach (int id in userIds) { - Client.CurrentMatchPlayingUserIds.Add(id); + OnlinePlayDependencies.Client.AddUser(new User { Id = id }, true); + SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUserIds.Add(id); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 0e368b59dd..8121492a0b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -20,6 +20,7 @@ using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -53,10 +54,10 @@ namespace osu.Game.Tests.Visual.Multiplayer var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); foreach (var user in users) + { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - - // Todo: This is REALLY bad. - Client.CurrentMatchPlayingUserIds.AddRange(users); + OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); + } Children = new Drawable[] { diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index bffb2d341a..14beb38cde 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -62,7 +62,9 @@ namespace osu.Game.Online.Multiplayer /// /// The users in the joined which are participating in the current gameplay loop. /// - public readonly BindableList CurrentMatchPlayingUserIds = new BindableList(); + public IBindableList CurrentMatchPlayingUserIds => PlayingUserIds; + + protected readonly BindableList PlayingUserIds = new BindableList(); public readonly Bindable CurrentMatchPlayingItem = new Bindable(); @@ -179,7 +181,7 @@ namespace osu.Game.Online.Multiplayer { APIRoom = null; Room = null; - CurrentMatchPlayingUserIds.Clear(); + PlayingUserIds.Clear(); RoomUpdated?.Invoke(); }); @@ -376,7 +378,7 @@ namespace osu.Game.Online.Multiplayer return; Room.Users.Remove(user); - CurrentMatchPlayingUserIds.Remove(user.UserID); + PlayingUserIds.Remove(user.UserID); RoomUpdated?.Invoke(); }, false); @@ -659,16 +661,16 @@ namespace osu.Game.Online.Multiplayer /// The new state of the user. private void updateUserPlayingState(int userId, MultiplayerUserState state) { - bool wasPlaying = CurrentMatchPlayingUserIds.Contains(userId); + bool wasPlaying = PlayingUserIds.Contains(userId); bool isPlaying = state >= MultiplayerUserState.WaitingForLoad && state <= MultiplayerUserState.FinishedPlay; if (isPlaying == wasPlaying) return; if (isPlaying) - CurrentMatchPlayingUserIds.Add(userId); + PlayingUserIds.Add(userId); else - CurrentMatchPlayingUserIds.Remove(userId); + PlayingUserIds.Remove(userId); } private Task scheduleAsync(Action action, CancellationToken cancellationToken = default) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index a10c16fcd5..7ee77759b0 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Play.HUD private UserLookupCache userLookupCache { get; set; } private readonly ScoreProcessor scoreProcessor; - private readonly BindableList playingUsers; + private readonly IBindableList playingUsers; private Bindable scoringMode; /// diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 43aadf5acb..cffaea5c94 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -50,7 +50,16 @@ namespace osu.Game.Tests.Visual.Multiplayer public void Disconnect() => isConnected.Value = false; - public void AddUser(User user) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(user.Id) { User = user }); + public MultiplayerRoomUser AddUser(User user, bool markAsPlaying = false) + { + var roomUser = new MultiplayerRoomUser(user.Id) { User = user }; + ((IMultiplayerClient)this).UserJoined(roomUser); + + if (markAsPlaying) + PlayingUserIds.Add(user.Id); + + return roomUser; + } public void AddNullUser(int userId) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(userId)); From 490f9e18486ba5abd03c2300b802f0c193b14df4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 19:45:16 +0900 Subject: [PATCH 332/600] Fix overlap in spectator view --- osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index d25ceb948e..837d8bfde7 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -17,6 +17,7 @@ namespace osu.Game.Screens.Play.HUD public class MatchScoreDisplay : CompositeDrawable { private const float bar_height = 18; + private const float font_size = 50; public BindableInt Team1Score = new BindableInt(); public BindableInt Team2Score = new BindableInt(); @@ -78,7 +79,7 @@ namespace osu.Game.Screens.Play.HUD new Container { RelativeSizeAxes = Axes.X, - Height = 50, + Height = font_size + bar_height, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Children = new Drawable[] @@ -156,8 +157,8 @@ namespace osu.Game.Screens.Play.HUD private void updateFont(bool winning) => displayedSpriteText.Font = winning - ? OsuFont.Torus.With(weight: FontWeight.Bold, size: 50, fixedWidth: true) - : OsuFont.Torus.With(weight: FontWeight.Regular, size: 40, fixedWidth: true); + ? OsuFont.Torus.With(weight: FontWeight.Bold, size: font_size, fixedWidth: true) + : OsuFont.Torus.With(weight: FontWeight.Regular, size: font_size * 0.8f, fixedWidth: true); } } } From 58714dbe719ee3b5544166e3791d962046fa21b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 19:48:53 +0900 Subject: [PATCH 333/600] Fix ordering of teams to match colours --- osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 4968dc0706..013d266ac2 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD { protected readonly Dictionary UserScores = new Dictionary(); - public readonly Dictionary TeamScores = new Dictionary(); + public readonly SortedDictionary TeamScores = new SortedDictionary(); [Resolved] private OsuColour colours { get; set; } From 76e5a40b8ed15dfba6bf5812743a5bbf1f15a542 Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Mon, 9 Aug 2021 20:53:02 +1000 Subject: [PATCH 334/600] Remove unnecessary "in" keyword --- osu.Game/Utils/LegacyUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Utils/LegacyUtils.cs b/osu.Game/Utils/LegacyUtils.cs index 9351125acd..64306adf50 100644 --- a/osu.Game/Utils/LegacyUtils.cs +++ b/osu.Game/Utils/LegacyUtils.cs @@ -42,7 +42,7 @@ namespace osu.Game.Utils /// /// Interpolates between two sRGB s directly in sRGB space. /// - public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, in TEasing easing) where TEasing : IEasingFunction + public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, TEasing easing) where TEasing : IEasingFunction { if (startColour == endColour) return startColour; From c5b490c4414d64a9dc80353850cad62d707aa85d Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Tue, 10 Aug 2021 11:29:31 +1000 Subject: [PATCH 335/600] Use non linear colour interpolation for legacy health display --- osu.Game/Skinning/LegacyHealthDisplay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacyHealthDisplay.cs b/osu.Game/Skinning/LegacyHealthDisplay.cs index 67280e4acd..b1cd1f86c0 100644 --- a/osu.Game/Skinning/LegacyHealthDisplay.cs +++ b/osu.Game/Skinning/LegacyHealthDisplay.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Utils; using osu.Game.Rulesets.Judgements; using osu.Game.Screens.Play.HUD; +using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -83,10 +84,10 @@ namespace osu.Game.Skinning private static Color4 getFillColour(double hp) { if (hp < 0.2) - return Interpolation.ValueAt(0.2 - hp, Color4.Black, Color4.Red, 0, 0.2); + return LegacyUtils.InterpolateNonLinear(0.2 - hp, Color4.Black, Color4.Red, 0, 0.2); if (hp < epic_cutoff) - return Interpolation.ValueAt(0.5 - hp, Color4.White, Color4.Black, 0, 0.5); + return LegacyUtils.InterpolateNonLinear(0.5 - hp, Color4.White, Color4.Black, 0, 0.5); return Color4.White; } From 0b41731d0bb5ffef7219d3d7e64011e3fd26dc62 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 11:43:11 +0700 Subject: [PATCH 336/600] initial changelog supporter promo section --- .../Changelog/ChangelogSingleBuild.cs | 1 + .../Changelog/ChangelogSupporterPromo.cs | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 8b89d63aab..25d8eaf0db 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -71,6 +71,7 @@ namespace osu.Game.Overlays.Changelog Colour = colourProvider.Background6, Margin = new MarginPadding { Top = 30 }, }, + new ChangelogSupporterPromo(), comments = new CommentsContainer() }; diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs new file mode 100644 index 0000000000..98b3cc2002 --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -0,0 +1,46 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogSupporterPromo : CompositeDrawable + { + public ChangelogSupporterPromo() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Padding = new MarginPadding + { + Vertical = 20, + Horizontal = 50, + }; + InternalChildren = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.3f), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + Height = 200, + }, + } + }, + }; + } + } +} From bdf6c2a5edf61d89dcb095acd86672c1367e07e2 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 12:00:26 +0700 Subject: [PATCH 337/600] add changelog supporter promo test scene --- .../TestSceneChangelogSupporterPromo.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs new file mode 100644 index 0000000000..22220a7d9c --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs @@ -0,0 +1,35 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; +using osu.Game.Overlays.Changelog; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneChangelogSupporterPromo : OsuTestScene + { + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + + public TestSceneChangelogSupporterPromo() + { + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background4, + }, + new ChangelogSupporterPromo(), + } + }; + } + } +} From a2b4f05ebe311527ec77351c293f5a111e5535a7 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 12:11:21 +0700 Subject: [PATCH 338/600] add border radius and shadow --- .../Overlays/Changelog/ChangelogSupporterPromo.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 98b3cc2002..0775ba4494 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -4,7 +4,9 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog @@ -26,6 +28,15 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Masking = true, + CornerRadius = 6, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Offset = new Vector2(0, 1), + Radius = 3, + }, Children = new Drawable[] { new Box From 3aa72163f234ab22dff7a350b1aeba9cafdb76c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 15:14:43 +0900 Subject: [PATCH 339/600] Add simple download progress display to download buttons on playlist items --- osu.Game/Graphics/UserInterface/GrayButton.cs | 4 ++-- .../BeatmapListing/Panels/BeatmapPanelDownloadButton.cs | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GrayButton.cs b/osu.Game/Graphics/UserInterface/GrayButton.cs index 88c46f29e0..0a2c83d5a8 100644 --- a/osu.Game/Graphics/UserInterface/GrayButton.cs +++ b/osu.Game/Graphics/UserInterface/GrayButton.cs @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load() { - Children = new Drawable[] + AddRange(new Drawable[] { Background = new Box { @@ -42,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface Size = new Vector2(13), Icon = icon, }, - }; + }); } } } diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs index cec1a5ac12..47b477ef9a 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs @@ -37,6 +37,13 @@ namespace osu.Game.Overlays.BeatmapListing.Panels RelativeSizeAxes = Axes.Both, }, }; + + button.Add(new DownloadProgressBar(beatmapSet) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Depth = -1, + }); } protected override void LoadComplete() From 7c8df571090813a641c86b0ca215b234a6b9acf6 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 13:21:23 +0700 Subject: [PATCH 340/600] add description text --- .../Changelog/ChangelogSupporterPromo.cs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 0775ba4494..ba5cac731b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -1,11 +1,17 @@ // 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.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -13,6 +19,9 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogSupporterPromo : CompositeDrawable { + private readonly LinkFlowContainer supportLinkText; + private readonly TextFlowContainer supportNoteText; + public ChangelogSupporterPromo() { RelativeSizeAxes = Axes.X; @@ -22,6 +31,7 @@ namespace osu.Game.Overlays.Changelog Vertical = 20, Horizontal = 50, }; + InternalChildren = new Drawable[] { new Container @@ -48,10 +58,67 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X, Height = 200, + Padding = new MarginPadding { Horizontal = 75 }, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = ChangelogStrings.SupportHeading, + Font = OsuFont.GetFont(size: 22, weight: FontWeight.Light), + Margin = new MarginPadding { Bottom = 20 }, + }, + supportLinkText = new LinkFlowContainer(t => + { + t.Font = t.Font.With(size: 17.5f); + }) + { + AutoSizeAxes = Axes.Both, + }, + supportNoteText = new TextFlowContainer(t => + { + t.Font = t.Font.With(size: 15); + }) + { + Margin = new MarginPadding { Top = 10 }, + AutoSizeAxes = Axes.Both, + } + }, + }, + } }, } }, }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + void fontPinkColour(SpriteText t) => t.Colour = colour.PinkLighter; + + supportLinkText.AddText("Support further development of osu! and ", fontPinkColour); + supportLinkText.AddLink("become an osu!supporter", "https://osu.ppy.sh/home/support", t => + { + t.Colour = colour.PinkDark; + t.Font = t.Font.With(weight: FontWeight.Bold); + }); + supportLinkText.AddText(" today!", fontPinkColour); + + supportNoteText.AddText(new OsuSpriteText + { + Text = ChangelogStrings.SupportText2, + Colour = colour.PinkLighter, + }); + } } } From 49de8ce1df4254c30d8d0de05c2298c10523f56a Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 13:53:06 +0700 Subject: [PATCH 341/600] fix up some layouting --- .../Changelog/ChangelogSupporterPromo.cs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index ba5cac731b..b90e158f58 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -19,6 +19,8 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogSupporterPromo : CompositeDrawable { + private const float image_width = 164; + private readonly LinkFlowContainer supportLinkText; private readonly TextFlowContainer supportNoteText; @@ -54,12 +56,11 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.Both, Colour = Color4.Black.Opacity(0.3f), }, - new FillFlowContainer + new Container { RelativeSizeAxes = Axes.X, Height = 200, Padding = new MarginPadding { Horizontal = 75 }, - Direction = FillDirection.Horizontal, Children = new Drawable[] { new FillFlowContainer @@ -69,6 +70,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + Padding = new MarginPadding { Right = 50 + image_width }, Children = new Drawable[] { new OsuSpriteText @@ -82,7 +84,8 @@ namespace osu.Game.Overlays.Changelog t.Font = t.Font.With(size: 17.5f); }) { - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, }, supportNoteText = new TextFlowContainer(t => { @@ -90,10 +93,18 @@ namespace osu.Game.Overlays.Changelog }) { Margin = new MarginPadding { Top = 10 }, - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, } }, }, + new Container + { + RelativeSizeAxes = Axes.Y, + Width = image_width, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } } }, } @@ -114,11 +125,7 @@ namespace osu.Game.Overlays.Changelog }); supportLinkText.AddText(" today!", fontPinkColour); - supportNoteText.AddText(new OsuSpriteText - { - Text = ChangelogStrings.SupportText2, - Colour = colour.PinkLighter, - }); + supportNoteText.AddText("Not only will you help speed development, but you will also get some extra features and customisations!", fontPinkColour); } } } From b3fbf52571a0ded416210174d901d61bdeb0a218 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 14:07:20 +0700 Subject: [PATCH 342/600] add pippi and heart texture --- .../Changelog/ChangelogSupporterPromo.cs | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index b90e158f58..03373c4810 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -19,10 +20,11 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogSupporterPromo : CompositeDrawable { - private const float image_width = 164; + private const float image_container_width = 164; private readonly LinkFlowContainer supportLinkText; private readonly TextFlowContainer supportNoteText; + private readonly Container imageContainer; public ChangelogSupporterPromo() { @@ -70,7 +72,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Padding = new MarginPadding { Right = 50 + image_width }, + Padding = new MarginPadding { Right = 50 + image_container_width }, Children = new Drawable[] { new OsuSpriteText @@ -98,10 +100,10 @@ namespace osu.Game.Overlays.Changelog } }, }, - new Container + imageContainer = new Container { RelativeSizeAxes = Axes.Y, - Width = image_width, + Width = image_container_width, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, } @@ -113,7 +115,7 @@ namespace osu.Game.Overlays.Changelog } [BackgroundDependencyLoader] - private void load(OsuColour colour) + private void load(OsuColour colour, TextureStore textures) { void fontPinkColour(SpriteText t) => t.Colour = colour.PinkLighter; @@ -126,6 +128,27 @@ namespace osu.Game.Overlays.Changelog supportLinkText.AddText(" today!", fontPinkColour); supportNoteText.AddText("Not only will you help speed development, but you will also get some extra features and customisations!", fontPinkColour); + + imageContainer.Children = new Drawable[] + { + new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + Texture = textures.Get(@"Online/supporter-pippi"), + }, + new Sprite + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 75, + Height = 75, + Margin = new MarginPadding { Top = 70 }, + Texture = textures.Get(@"Online/supporter-heart"), + }, + }; } } } From f7a02219b80e528c90ca49283d6647599a74f81b Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 14:23:15 +0700 Subject: [PATCH 343/600] fix font size description --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 03373c4810..f5638293bb 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -78,12 +78,12 @@ namespace osu.Game.Overlays.Changelog new OsuSpriteText { Text = ChangelogStrings.SupportHeading, - Font = OsuFont.GetFont(size: 22, weight: FontWeight.Light), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Light), Margin = new MarginPadding { Bottom = 20 }, }, supportLinkText = new LinkFlowContainer(t => { - t.Font = t.Font.With(size: 17.5f); + t.Font = t.Font.With(size: 14); }) { RelativeSizeAxes = Axes.X, @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Changelog }, supportNoteText = new TextFlowContainer(t => { - t.Font = t.Font.With(size: 15); + t.Font = t.Font.With(size: 12); }) { Margin = new MarginPadding { Top = 10 }, From 5ea7909eeae16e20c265c95889f459cd0b7e64ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 16:18:57 +0900 Subject: [PATCH 344/600] Fix incorrectly failing test --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index dfb78a235b..5e30cb86cc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Online.Rooms; using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; @@ -215,7 +216,7 @@ namespace osu.Game.Tests.Visual.Multiplayer assertDownloadButtonVisible(false); void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}", - () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0)); + () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0)); } [Test] @@ -229,7 +230,7 @@ namespace osu.Game.Tests.Visual.Multiplayer createPlaylist(byOnlineId, byChecksum); - AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent)); + AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent)); } [Test] From c63dfa21e130ebf85bf6f860a5fbb427f0eb2f26 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 10 Aug 2021 16:34:38 +0900 Subject: [PATCH 345/600] Always initialize DHO transforms on LoadComplete With the previous commit, the transform application is skipped when the state is already changed. But it turns out the previous commit breaks slider animation in the standard editor. This is probably due to the transforms are applied before nested hit objects are added. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ff6168ee37..29d8a475ef 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -190,9 +190,8 @@ namespace osu.Game.Rulesets.Objects.Drawables comboIndexBindable.BindValueChanged(_ => UpdateComboColour()); comboIndexWithOffsetsBindable.BindValueChanged(_ => UpdateComboColour(), true); - // If the state is changed, transforms are already initialized. - if (state.Value == ArmedState.Idle) - updateState(ArmedState.Idle, true); + // Apply transforms + updateState(State.Value, true); } /// From 2b9168157db3e99b2ee759cd71d5114c9642faa2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 16:50:39 +0900 Subject: [PATCH 346/600] Fix `CurrentMatchPlayingItem` not being reset on leaving a multiplayer room --- .../NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs | 4 ++++ osu.Game/Online/Multiplayer/MultiplayerClient.cs | 1 + 2 files changed, 5 insertions(+) diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index 0983b806e2..07ec86b0e7 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -24,6 +24,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer AddRepeatStep("add some users", () => Client.AddUser(new User { Id = id++ }), 5); checkPlayingUserCount(0); + AddAssert("playlist item is available", () => Client.CurrentMatchPlayingItem.Value != null); + changeState(3, MultiplayerUserState.WaitingForLoad); checkPlayingUserCount(3); @@ -41,6 +43,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer AddStep("leave room", () => Client.LeaveRoom()); checkPlayingUserCount(0); + + AddAssert("playlist item is null", () => Client.CurrentMatchPlayingItem.Value == null); } [Test] diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 14beb38cde..dafc737ba2 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -181,6 +181,7 @@ namespace osu.Game.Online.Multiplayer { APIRoom = null; Room = null; + CurrentMatchPlayingItem.Value = null; PlayingUserIds.Clear(); RoomUpdated?.Invoke(); From 3fb2ca4f4a96acea47b9c17b2713afbec0d576fa Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 14:55:57 +0700 Subject: [PATCH 347/600] add border bottom --- osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 25d8eaf0db..1f1a4a43de 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -72,6 +72,12 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 30 }, }, new ChangelogSupporterPromo(), + new Box + { + RelativeSizeAxes = Axes.X, + Height = 2, + Colour = colourProvider.Background6, + }, comments = new CommentsContainer() }; From 93408c636bbdd7b8bb5c92b3731c919d0687d620 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 14:56:54 +0700 Subject: [PATCH 348/600] hide supporter promo section for supporter --- osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 1f1a4a43de..93486274fc 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -71,12 +71,16 @@ namespace osu.Game.Overlays.Changelog Colour = colourProvider.Background6, Margin = new MarginPadding { Top = 30 }, }, - new ChangelogSupporterPromo(), + new ChangelogSupporterPromo + { + Alpha = api.LocalUser.Value.IsSupporter ? 0 : 1, + }, new Box { RelativeSizeAxes = Axes.X, Height = 2, Colour = colourProvider.Background6, + Alpha = api.LocalUser.Value.IsSupporter ? 0 : 1, }, comments = new CommentsContainer() }; From 595763ae3453d1fbb979a299798809cf672e801c Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 10 Aug 2021 14:58:11 +0700 Subject: [PATCH 349/600] add test case for supporter and non supporter --- osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 8818ac75b1..159eb9912c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using Humanizer; using NUnit.Framework; +using osu.Framework.Testing; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -95,9 +96,11 @@ namespace osu.Game.Tests.Visual.Online AddAssert(@"no stream selected", () => changelog.Header.Streams.Current.Value == null); } - [Test] - public void ShowWithBuild() + [TestCase(false)] + [TestCase(true)] + public void ShowWithBuild(bool isSupporter) { + AddStep(@"set supporter", () => dummyAPI.LocalUser.Value.IsSupporter = isSupporter); showBuild(() => new APIChangelogBuild { Version = "2018.712.0", @@ -155,6 +158,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep(@"wait for streams", () => changelog.Streams?.Count > 0); AddAssert(@"correct build displayed", () => changelog.Current.Value.Version == "2018.712.0"); AddAssert(@"correct stream selected", () => changelog.Header.Streams.Current.Value.Id == 5); + AddAssert(@"supporter promo showed", () => changelog.ChildrenOfType().First().Alpha == (isSupporter ? 0 : 1)); } [Test] From e0e0d5deb0f7debb5ffce87075a847304bdf759c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Aug 2021 17:25:10 +0900 Subject: [PATCH 350/600] Remove unused using --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 5e30cb86cc..93bdbb79f4 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -14,7 +14,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Online.Rooms; -using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; From d9b5f235d88a28ba1577a94f479016b1ef81d397 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 17:36:58 +0900 Subject: [PATCH 351/600] Add xmldoc explaining thread safety limitations of `IModelManager` "events" --- osu.Game/Database/IModelManager.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 7f7e5565f1..8c314f1617 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -13,8 +13,16 @@ namespace osu.Game.Database public interface IModelManager where TModel : class { + /// + /// A bindable which contains a weak reference to the last item that was updated. + /// This is not thread-safe and should be scheduled locally if consumed from a drawable component. + /// IBindable> ItemUpdated { get; } + /// + /// A bindable which contains a weak reference to the last item that was removed. + /// This is not thread-safe and should be scheduled locally if consumed from a drawable component. + /// IBindable> ItemRemoved { get; } } } From b121d95400727bedb1c6d929d8ed5a741e904399 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 17:37:24 +0900 Subject: [PATCH 352/600] Avoid potential null reference exception in `OnlinePlayBeatmapAvailabilityTracker` --- osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index 72ea84d4a8..86879ba245 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -59,8 +59,8 @@ namespace osu.Game.Online.Rooms protected override bool VerifyDatabasedModel(BeatmapSetInfo databasedSet) { - int? beatmapId = SelectedItem.Value.Beatmap.Value.OnlineBeatmapID; - string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash; + int? beatmapId = SelectedItem.Value?.Beatmap.Value.OnlineBeatmapID; + string checksum = SelectedItem.Value?.Beatmap.Value.MD5Hash; var matchingBeatmap = databasedSet.Beatmaps.FirstOrDefault(b => b.OnlineBeatmapID == beatmapId && b.MD5Hash == checksum); From f86ef54e93dc1ea0e346554bfc5ddbec8f2312f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Aug 2021 17:36:40 +0900 Subject: [PATCH 353/600] Fix incorrect legacy slider body alpha --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 92941665e0..1c8dfeac52 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy // Roughly matches osu!stable's slider border portions. => base.CalculatedBorderPortion * 0.77f; - public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f); + public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, 0.7f); protected override Color4 ColourAt(float position) { From 53d03745e046327870484b4ea38122aef357c68e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 17:48:47 +0900 Subject: [PATCH 354/600] Remove unused test scene --- .../Multiplayer/TestMultiplayerGameplay.cs | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs deleted file mode 100644 index 4b75121575..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestMultiplayerGameplay.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Linq; -using NUnit.Framework; -using osu.Game.Screens.OnlinePlay.Multiplayer; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestMultiplayerGameplay : MultiplayerTestScene - { - [Test] - public void TestBasic() - { - AddStep("load screen", () => - LoadScreen(new MultiplayerPlayer(Client.CurrentMatchPlayingItem.Value, Client.Room?.Users.Select(u => u.UserID).ToArray()))); - } - } -} From a503274e1d79e40bea8a85e9c4e8f45529822b61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 18:39:20 +0900 Subject: [PATCH 355/600] Pass through `MultiplayerRoomUser`s instead of `int`s to avoid re-retrieval --- .../TestSceneMultiSpectatorLeaderboard.cs | 3 +- .../TestSceneMultiSpectatorScreen.cs | 17 +++++----- ...TestSceneMultiplayerGameplayLeaderboard.cs | 2 +- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 2 +- .../Multiplayer/MultiplayerMatchSubScreen.cs | 6 ++-- .../Multiplayer/MultiplayerPlayer.cs | 10 +++--- .../Spectate/MultiSpectatorLeaderboard.cs | 4 +-- .../Spectate/MultiSpectatorScreen.cs | 19 +++++++---- .../HUD/MultiplayerGameplayLeaderboard.cs | 33 +++++++++---------- osu.Game/Screens/Spectate/SpectatorScreen.cs | 14 ++++---- 10 files changed, 59 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 22543b7b26..ade24b8740 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Testing; using osu.Framework.Timing; +using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play.HUD; @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var scoreProcessor = new OsuScoreProcessor(); scoreProcessor.ApplyBeatmap(playable); - LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, clocks.Keys.ToArray()) { Expanded = { Value = true } }, Add); + LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, clocks.Keys.Select(id => new MultiplayerRoomUser(id)).ToArray()) { Expanded = { Value = true } }, Add); }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 116349c71e..3118a23fd5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; @@ -27,7 +28,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private MultiSpectatorScreen spectatorScreen; - private readonly List playingUserIds = new List(); + private readonly List playingUsers = new List(); private BeatmapSetInfo importedSet; private BeatmapInfo importedBeatmap; @@ -42,7 +43,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [SetUp] - public new void Setup() => Schedule(() => playingUserIds.Clear()); + public new void Setup() => Schedule(() => playingUsers.Clear()); [Test] public void TestDelayedStart() @@ -52,8 +53,8 @@ namespace osu.Game.Tests.Visual.Multiplayer OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }, true); OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }, true); - playingUserIds.Add(PLAYER_1_ID); - playingUserIds.Add(PLAYER_2_ID); + playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID)); + playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID)); }); loadSpectateScreen(false); @@ -99,8 +100,8 @@ namespace osu.Game.Tests.Visual.Multiplayer SpectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId); SpectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId); - playingUserIds.Add(PLAYER_1_ID); - playingUserIds.Add(PLAYER_2_ID); + playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID)); + playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID)); }); loadSpectateScreen(); @@ -287,7 +288,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Beatmap.Value = beatmapManager.GetWorkingBeatmap(importedBeatmap); Ruleset.Value = importedBeatmap.Ruleset; - LoadScreen(spectatorScreen = new MultiSpectatorScreen(playingUserIds.ToArray())); + LoadScreen(spectatorScreen = new MultiSpectatorScreen(playingUsers.ToArray())); }); AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded && (!waitForPlayerLoad || spectatorScreen.AllPlayersLoaded)); @@ -302,7 +303,7 @@ namespace osu.Game.Tests.Visual.Multiplayer OnlinePlayDependencies.Client.AddUser(new User { Id = id }, true); SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); - playingUserIds.Add(id); + playingUsers.Add(new MultiplayerRoomUser(id)); } }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 8121492a0b..0997de478b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer scoreProcessor.ApplyBeatmap(playable); - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, users.ToArray()) + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, Client.Room?.Users.ToArray()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index d363c6eed4..274c9ea4b2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Multiplayer scoreProcessor.ApplyBeatmap(playable); - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, users.ToArray()) + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, Client.Room?.Users.ToArray()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 561fa220c8..9fa19aaf21 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -475,16 +475,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override Screen CreateGameplayScreen() { Debug.Assert(client.LocalUser != null); + Debug.Assert(client.Room != null); int[] userIds = client.CurrentMatchPlayingUserIds.ToArray(); + MultiplayerRoomUser[] users = userIds.Select(id => client.Room.Users.First(u => u.UserID == id)).ToArray(); switch (client.LocalUser.State) { case MultiplayerUserState.Spectating: - return new MultiSpectatorScreen(userIds); + return new MultiSpectatorScreen(users.Take(PlayerGrid.MAX_PLAYERS).ToArray()); default: - return new PlayerLoader(() => new MultiplayerPlayer(SelectedItem.Value, userIds)); + return new PlayerLoader(() => new MultiplayerPlayer(SelectedItem.Value, users)); } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 0ff7d70c11..3ba7b8b982 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerGameplayLeaderboard leaderboard; - private readonly int[] userIds; + private readonly MultiplayerRoomUser[] users; private LoadingLayer loadingDisplay; private FillFlowContainer leaderboardFlow; @@ -46,8 +46,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer /// Construct a multiplayer player. /// /// The playlist item to be played. - /// The users which are participating in this game. - public MultiplayerPlayer(PlaylistItem playlistItem, int[] userIds) + /// The users which are participating in this game. + public MultiplayerPlayer(PlaylistItem playlistItem, MultiplayerRoomUser[] users) : base(playlistItem, new PlayerConfiguration { AllowPause = false, @@ -55,7 +55,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer AllowSkipping = false, }) { - this.userIds = userIds; + this.users = users; } [BackgroundDependencyLoader] @@ -71,7 +71,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer }); // todo: this should be implemented via a custom HUD implementation, and correctly masked to the main content area. - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(ScoreProcessor, userIds), l => + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(ScoreProcessor, users), l => { if (!LoadedBeatmapSuccessfully) return; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs index 95f9fa27f1..1614828a78 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs @@ -12,8 +12,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { public class MultiSpectatorLeaderboard : MultiplayerGameplayLeaderboard { - public MultiSpectatorLeaderboard([NotNull] ScoreProcessor scoreProcessor, int[] userIds) - : base(scoreProcessor, userIds) + public MultiSpectatorLeaderboard([NotNull] ScoreProcessor scoreProcessor, MultiplayerRoomUser[] users) + : base(scoreProcessor, users) { } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 9923c42583..f77303eec7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -46,14 +46,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private PlayerArea currentAudioSource; private bool canStartMasterClock; + private readonly MultiplayerRoomUser[] users; + /// /// Creates a new . /// - /// The players to spectate. - public MultiSpectatorScreen(int[] userIds) - : base(userIds.Take(PlayerGrid.MAX_PLAYERS).ToArray()) + /// The players to spectate. + public MultiSpectatorScreen(MultiplayerRoomUser[] users) + : base(users.Select(u => u.UserID).ToArray()) { - instances = new PlayerArea[UserIds.Count]; + // todo: this is a bit ugly, but not sure on a better way to handle. + this.users = users; + + instances = new PlayerArea[Users.Count]; } [BackgroundDependencyLoader] @@ -105,9 +110,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate }) }; - for (int i = 0; i < UserIds.Count; i++) + for (int i = 0; i < Users.Count; i++) { - grid.Add(instances[i] = new PlayerArea(UserIds[i], masterClockContainer.GameplayClock)); + grid.Add(instances[i] = new PlayerArea(Users[i], masterClockContainer.GameplayClock)); syncManager.AddPlayerClock(instances[i].GameplayClock); } @@ -116,7 +121,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate var scoreProcessor = Ruleset.Value.CreateInstance().CreateScoreProcessor(); scoreProcessor.ApplyBeatmap(playableBeatmap); - LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, UserIds.ToArray()) + LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, users) { Expanded = { Value = true }, Anchor = Anchor.CentreLeft, diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 013d266ac2..3f9258930e 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -41,23 +41,24 @@ namespace osu.Game.Screens.Play.HUD private UserLookupCache userLookupCache { get; set; } private readonly ScoreProcessor scoreProcessor; - private readonly IBindableList playingUsers; + private readonly MultiplayerRoomUser[] playingUsers; private Bindable scoringMode; + private readonly IBindableList playingUserIds = new BindableList(); + private bool hasTeams => TeamScores.Count > 0; /// /// Construct a new leaderboard. /// /// A score processor instance to handle score calculation for scores of users in the match. - /// IDs of all users in this match. - public MultiplayerGameplayLeaderboard(ScoreProcessor scoreProcessor, int[] userIds) + /// IDs of all users in this match. + public MultiplayerGameplayLeaderboard(ScoreProcessor scoreProcessor, MultiplayerRoomUser[] users) { // todo: this will eventually need to be created per user to support different mod combinations. this.scoreProcessor = scoreProcessor; - // todo: this will likely be passed in as User instances. - playingUsers = new BindableList(userIds); + playingUsers = users; } [BackgroundDependencyLoader] @@ -65,19 +66,17 @@ namespace osu.Game.Screens.Play.HUD { scoringMode = config.GetBindable(OsuSetting.ScoreDisplayMode); - foreach (var userId in playingUsers) + foreach (var user in playingUsers) { - var user = multiplayerClient.Room?.Users.FirstOrDefault(u => u.UserID == userId); - var trackedUser = CreateUserData(user, scoreProcessor); trackedUser.ScoringMode.BindTo(scoringMode); - UserScores[userId] = trackedUser; + UserScores[user.UserID] = trackedUser; if (trackedUser.Team is int team && !TeamScores.ContainsKey(team)) TeamScores.Add(team, new BindableInt()); } - userLookupCache.GetUsersAsync(playingUsers.ToArray()).ContinueWith(users => Schedule(() => + userLookupCache.GetUsersAsync(playingUsers.Select(u => u.UserID).ToArray()).ContinueWith(users => Schedule(() => { foreach (var user in users.Result) { @@ -100,18 +99,18 @@ namespace osu.Game.Screens.Play.HUD base.LoadComplete(); // BindableList handles binding in a really bad way (Clear then AddRange) so we need to do this manually.. - foreach (int userId in playingUsers) + foreach (var user in playingUsers) { - spectatorClient.WatchUser(userId); + spectatorClient.WatchUser(user.UserID); - if (!multiplayerClient.CurrentMatchPlayingUserIds.Contains(userId)) - usersChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new[] { userId })); + if (!multiplayerClient.CurrentMatchPlayingUserIds.Contains(user.UserID)) + usersChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new[] { user.UserID })); } // bind here is to support players leaving the match. // new players are not supported. - playingUsers.BindTo(multiplayerClient.CurrentMatchPlayingUserIds); - playingUsers.BindCollectionChanged(usersChanged); + playingUserIds.BindTo(multiplayerClient.CurrentMatchPlayingUserIds); + playingUserIds.BindCollectionChanged(usersChanged); // this leaderboard should be guaranteed to be completely loaded before the gameplay starts (is a prerequisite in MultiplayerPlayer). spectatorClient.OnNewFrames += handleIncomingFrames; @@ -197,7 +196,7 @@ namespace osu.Game.Screens.Play.HUD { foreach (var user in playingUsers) { - spectatorClient.StopWatchingUser(user); + spectatorClient.StopWatchingUser(user.UserID); } spectatorClient.OnNewFrames -= handleIncomingFrames; diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index b6eafe496f..f0a68ea078 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -24,9 +24,9 @@ namespace osu.Game.Screens.Spectate /// public abstract class SpectatorScreen : OsuScreen { - protected IReadOnlyList UserIds => userIds; + protected IReadOnlyList Users => users; - private readonly List userIds = new List(); + private readonly List users = new List(); [Resolved] private BeatmapManager beatmaps { get; set; } @@ -50,17 +50,17 @@ namespace osu.Game.Screens.Spectate /// /// Creates a new . /// - /// The users to spectate. - protected SpectatorScreen(params int[] userIds) + /// The users to spectate. + protected SpectatorScreen(params int[] users) { - this.userIds.AddRange(userIds); + this.users.AddRange(users); } protected override void LoadComplete() { base.LoadComplete(); - userLookupCache.GetUsersAsync(userIds.ToArray()).ContinueWith(users => Schedule(() => + userLookupCache.GetUsersAsync(users.ToArray()).ContinueWith(users => Schedule(() => { foreach (var u in users.Result) { @@ -207,7 +207,7 @@ namespace osu.Game.Screens.Spectate { onUserStateRemoved(userId); - userIds.Remove(userId); + users.Remove(userId); userMap.Remove(userId); spectatorClient.StopWatchingUser(userId); From 60302e3daae38014ed9577ffd0c7d172482a05a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 18:46:20 +0900 Subject: [PATCH 356/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f757847c10..c1eddfd428 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3a840296ac..55bac93f30 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 217ec6089a..5a0b21f51d 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 58db6b758d07150acbd2b58a92e3b7bea9120c17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 18:47:39 +0900 Subject: [PATCH 357/600] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c1eddfd428..8de516240f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55bac93f30..59283084db 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5a0b21f51d..c8d3d150db 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 4268e4d75028d5ca43cf9786bb0a5efdcfb950a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 7 Aug 2021 14:19:05 +0200 Subject: [PATCH 358/600] Fix nested menus layering close samples if multiple menu levels are closed --- .../Cursor/OsuContextMenuContainer.cs | 9 +++++ .../Graphics/UserInterface/OsuContextMenu.cs | 29 +++++---------- .../UserInterface/OsuContextMenuSamples.cs | 35 +++++++++++++++++++ 3 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index e64d2d98f4..171ad4ee65 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -1,6 +1,7 @@ // 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.Allocation; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; @@ -9,6 +10,14 @@ namespace osu.Game.Graphics.Cursor { public class OsuContextMenuContainer : ContextMenuContainer { + [Cached] + private OsuContextMenuSamples samples = new OsuContextMenuSamples(); + + public OsuContextMenuContainer() + { + AddInternal(samples); + } + protected override Menu CreateMenu() => new OsuContextMenu(true); } } diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index 7cf8b3eca8..cf201b18b4 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -4,8 +4,6 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; @@ -16,16 +14,15 @@ namespace osu.Game.Graphics.UserInterface public class OsuContextMenu : OsuMenu { private const int fade_duration = 250; - private Sample sampleOpen; - private Sample sampleClose; - private Sample sampleClick; + + [Resolved] + private OsuContextMenuSamples samples { get; set; } // todo: this shouldn't be required after https://github.com/ppy/osu-framework/issues/4519 is fixed. private bool wasOpened; private readonly bool playClickSample; - private readonly Menu parentMenu; - public OsuContextMenu(bool playClickSample = false, Menu parentMenu = null) + public OsuContextMenu(bool playClickSample = false) : base(Direction.Vertical) { MaskingContainer.CornerRadius = 5; @@ -41,16 +38,12 @@ namespace osu.Game.Graphics.UserInterface MaxHeight = 250; this.playClickSample = playClickSample; - this.parentMenu = parentMenu; } [BackgroundDependencyLoader] private void load(OsuColour colours, AudioManager audio) { BackgroundColour = colours.ContextMenuGray; - sampleClick = audio.Samples.Get($"UI/{HoverSampleSet.Default.GetDescription()}-select"); - sampleOpen = audio.Samples.Get(@"UI/dropdown-open"); - sampleClose = audio.Samples.Get(@"UI/dropdown-close"); } protected override void AnimateOpen() @@ -58,10 +51,10 @@ namespace osu.Game.Graphics.UserInterface this.FadeIn(fade_duration, Easing.OutQuint); if (playClickSample) - sampleClick?.Play(); + samples.PlayClickSample(); if (!wasOpened) - sampleOpen?.Play(); + samples.PlayOpenSample(); wasOpened = true; } @@ -70,18 +63,12 @@ namespace osu.Game.Graphics.UserInterface { this.FadeOut(fade_duration, Easing.OutQuint); - if (parentMenu?.State == MenuState.Closed) - { - wasOpened = false; - return; - } - if (wasOpened) - sampleClose?.Play(); + samples.PlayCloseSample(); wasOpened = false; } - protected override Menu CreateSubMenu() => new OsuContextMenu(false, this); + protected override Menu CreateSubMenu() => new OsuContextMenu(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs b/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs new file mode 100644 index 0000000000..d67ea499e5 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs @@ -0,0 +1,35 @@ +// 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.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Extensions; +using osu.Framework.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public class OsuContextMenuSamples : Component + { + private Sample sampleClick; + private Sample sampleOpen; + private Sample sampleClose; + + [BackgroundDependencyLoader] + private void load(OsuColour colours, AudioManager audio) + { + sampleClick = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select"); + sampleOpen = audio.Samples.Get(@"UI/dropdown-open"); + sampleClose = audio.Samples.Get(@"UI/dropdown-close"); + } + + public void PlayClickSample() => Scheduler.AddOnce(playClickSample); + private void playClickSample() => sampleClick.Play(); + + public void PlayOpenSample() => Scheduler.AddOnce(playOpenSample); + private void playOpenSample() => sampleOpen.Play(); + + public void PlayCloseSample() => Scheduler.AddOnce(playCloseSample); + private void playCloseSample() => sampleClose.Play(); + } +} From 30cb4280a450664dd04fc13b31c80ec8f96798c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Aug 2021 22:21:54 +0200 Subject: [PATCH 359/600] Add test for catch beatmap mirroring --- .../Mods/CatchModMirrorTest.cs | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs new file mode 100644 index 0000000000..8e66284a23 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs @@ -0,0 +1,122 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Tests.Mods +{ + [TestFixture] + public class CatchModMirrorTest + { + [Test] + public void TestModMirror() + { + IBeatmap original = createBeatmap(false); + IBeatmap mirrored = createBeatmap(true); + + assertEffectivePositionsMirrored(original, mirrored); + } + + private static IBeatmap createBeatmap(bool withMirrorMod) + { + var beatmap = createRawBeatmap(); + var mirrorMod = new CatchModMirror(); + + var beatmapProcessor = new CatchBeatmapProcessor(beatmap); + beatmapProcessor.PreProcess(); + + foreach (var hitObject in beatmap.HitObjects) + { + hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + if (withMirrorMod) + mirrorMod.ApplyToHitObject(hitObject); + } + + beatmapProcessor.PostProcess(); + + return beatmap; + } + + private static IBeatmap createRawBeatmap() => new Beatmap + { + HitObjects = new List + { + new Fruit + { + OriginalX = 150, + StartTime = 0 + }, + new Fruit + { + OriginalX = 450, + StartTime = 500 + }, + new JuiceStream + { + OriginalX = 250, + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(new Vector2(-100, 1)), + new PathControlPoint(new Vector2(0, 2)), + new PathControlPoint(new Vector2(100, 3)), + new PathControlPoint(new Vector2(0, 4)) + } + }, + StartTime = 1000, + }, + new BananaShower + { + StartTime = 5000, + Duration = 5000 + } + } + }; + + private static void assertEffectivePositionsMirrored(IBeatmap original, IBeatmap mirrored) + { + if (original.HitObjects.Count != mirrored.HitObjects.Count) + Assert.Fail($"Top-level object count mismatch (original: {original.HitObjects.Count}, mirrored: {mirrored.HitObjects.Count})"); + + for (int i = 0; i < original.HitObjects.Count; ++i) + { + var originalObject = (CatchHitObject)original.HitObjects[i]; + var mirroredObject = (CatchHitObject)mirrored.HitObjects[i]; + + // banana showers themselves are exempt, as we only really care about their nested bananas' positions. + if (!effectivePositionMirrored(originalObject, mirroredObject) && !(originalObject is BananaShower)) + Assert.Fail($"{originalObject.GetType().Name} at time {originalObject.StartTime} is not mirrored ({printEffectivePositions(originalObject, mirroredObject)})"); + + if (originalObject.NestedHitObjects.Count != mirroredObject.NestedHitObjects.Count) + Assert.Fail($"{originalObject.GetType().Name} nested object count mismatch (original: {originalObject.NestedHitObjects.Count}, mirrored: {mirroredObject.NestedHitObjects.Count})"); + + for (int j = 0; j < originalObject.NestedHitObjects.Count; ++j) + { + var originalNested = (CatchHitObject)originalObject.NestedHitObjects[j]; + var mirroredNested = (CatchHitObject)mirroredObject.NestedHitObjects[j]; + + if (!effectivePositionMirrored(originalNested, mirroredNested)) + Assert.Fail($"{originalObject.GetType().Name}'s nested {originalNested.GetType().Name} at time {originalObject.StartTime} is not mirrored ({printEffectivePositions(originalNested, mirroredNested)})"); + } + } + } + + private static string printEffectivePositions(CatchHitObject original, CatchHitObject mirrored) + => $"original X: {original.EffectiveX}, mirrored X is: {mirrored.EffectiveX}, mirrored X should be: {CatchPlayfield.WIDTH - original.EffectiveX}"; + + private static bool effectivePositionMirrored(CatchHitObject original, CatchHitObject mirrored) + => Precision.AlmostEquals(original.EffectiveX, CatchPlayfield.WIDTH - mirrored.EffectiveX); + } +} From 637e5cb6b713bd942c6dd58d6f1a56c0ead646b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Aug 2021 21:42:41 +0200 Subject: [PATCH 360/600] Fix offsets not being mirrored --- .../Mods/CatchModMirrorTest.cs | 8 +++---- .../Mods/CatchModMirror.cs | 21 +++++++++++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs index 8e66284a23..fbbfee6b60 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs @@ -36,15 +36,13 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods beatmapProcessor.PreProcess(); foreach (var hitObject in beatmap.HitObjects) - { hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - if (withMirrorMod) - mirrorMod.ApplyToHitObject(hitObject); - } - beatmapProcessor.PostProcess(); + if (withMirrorMod) + mirrorMod.ApplyToBeatmap(beatmap); + return beatmap; } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs index 7fe7e70fd0..3aa8862a0a 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Catch.UI; @@ -10,11 +12,22 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModMirror : ModMirror, IApplicableToHitObject + public class CatchModMirror : ModMirror, IApplicableToBeatmap { public override string Description => "Fruits are flipped horizontally."; - public void ApplyToHitObject(HitObject hitObject) + /// + /// is used instead of , + /// as applies offsets in . + /// runs after post-processing, while runs before it. + /// + public void ApplyToBeatmap(IBeatmap beatmap) + { + foreach (var hitObject in beatmap.HitObjects) + applyToHitObject(hitObject); + } + + private void applyToHitObject(HitObject hitObject) { if (hitObject is BananaShower) return; @@ -22,9 +35,13 @@ namespace osu.Game.Rulesets.Catch.Mods var catchObject = (CatchHitObject)hitObject; catchObject.OriginalX = CatchPlayfield.WIDTH - catchObject.OriginalX; + catchObject.XOffset = -catchObject.XOffset; foreach (var nested in catchObject.NestedHitObjects.Cast()) + { nested.OriginalX = CatchPlayfield.WIDTH - nested.OriginalX; + nested.XOffset = -nested.XOffset; + } if (catchObject is JuiceStream juiceStream) { From a9e53107d146ac1fad598136b439f9296a1c51a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Aug 2021 21:51:46 +0200 Subject: [PATCH 361/600] Also mirror banana showers --- .../Mods/CatchModMirror.cs | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs index 3aa8862a0a..932c8cad85 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs @@ -29,11 +29,30 @@ namespace osu.Game.Rulesets.Catch.Mods private void applyToHitObject(HitObject hitObject) { - if (hitObject is BananaShower) - return; - var catchObject = (CatchHitObject)hitObject; + switch (catchObject) + { + case Fruit fruit: + mirrorEffectiveX(fruit); + break; + + case JuiceStream juiceStream: + mirrorEffectiveX(juiceStream); + mirrorJuiceStreamPath(juiceStream); + break; + + case BananaShower bananaShower: + mirrorBananaShower(bananaShower); + break; + } + } + + /// + /// Mirrors the effective X position of and its nested hit objects. + /// + private static void mirrorEffectiveX(CatchHitObject catchObject) + { catchObject.OriginalX = CatchPlayfield.WIDTH - catchObject.OriginalX; catchObject.XOffset = -catchObject.XOffset; @@ -42,15 +61,27 @@ namespace osu.Game.Rulesets.Catch.Mods nested.OriginalX = CatchPlayfield.WIDTH - nested.OriginalX; nested.XOffset = -nested.XOffset; } + } - if (catchObject is JuiceStream juiceStream) - { - var controlPoints = juiceStream.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); - foreach (var point in controlPoints) - point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); + /// + /// Mirrors the path of the . + /// + private static void mirrorJuiceStreamPath(JuiceStream juiceStream) + { + var controlPoints = juiceStream.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray(); + foreach (var point in controlPoints) + point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y); - juiceStream.Path = new SliderPath(controlPoints, juiceStream.Path.ExpectedDistance.Value); - } + juiceStream.Path = new SliderPath(controlPoints, juiceStream.Path.ExpectedDistance.Value); + } + + /// + /// Mirrors X positions of all bananas in the . + /// + private static void mirrorBananaShower(BananaShower bananaShower) + { + foreach (var banana in bananaShower.NestedHitObjects.OfType()) + banana.XOffset = CatchPlayfield.WIDTH - banana.XOffset; } } } From a3a9d0579f13166a975d75dec3cdf8cc40d9c511 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 12:33:14 +0900 Subject: [PATCH 362/600] Adjust checkbox / sliderbar animation speeds to match sound effects better --- osu.Game/Graphics/UserInterface/Nub.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 18d8b880ea..8d686e8c2f 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -21,6 +21,9 @@ namespace osu.Game.Graphics.UserInterface private const float border_width = 3; + private const double animate_in_duration = 150; + private const double animate_out_duration = 500; + public Nub() { Box fill; @@ -77,20 +80,26 @@ namespace osu.Game.Graphics.UserInterface if (value) { - this.FadeColour(GlowingAccentColour, 500, Easing.OutQuint); - FadeEdgeEffectTo(1, 500, Easing.OutQuint); + this.FadeColour(GlowingAccentColour, animate_in_duration, Easing.OutQuint); + FadeEdgeEffectTo(1, animate_in_duration, Easing.OutQuint); } else { - FadeEdgeEffectTo(0, 500); - this.FadeColour(AccentColour, 500); + FadeEdgeEffectTo(0, animate_out_duration); + this.FadeColour(AccentColour, animate_out_duration); } } } public bool Expanded { - set => this.ResizeTo(new Vector2(value ? EXPANDED_SIZE : COLLAPSED_SIZE, 12), 500, Easing.OutQuint); + set + { + if (value) + this.ResizeTo(new Vector2(EXPANDED_SIZE, 12), animate_in_duration, Easing.OutQuint); + else + this.ResizeTo(new Vector2(COLLAPSED_SIZE, 12), animate_out_duration, Easing.OutQuint); + } } private readonly Bindable current = new Bindable(); From f2f84a2e239ca8f03a899a81c6ec551c403170ba Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 11 Aug 2021 12:11:39 +0700 Subject: [PATCH 363/600] wait for content to load in test --- osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 159eb9912c..8f000afb91 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -158,6 +158,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep(@"wait for streams", () => changelog.Streams?.Count > 0); AddAssert(@"correct build displayed", () => changelog.Current.Value.Version == "2018.712.0"); AddAssert(@"correct stream selected", () => changelog.Header.Streams.Current.Value.Id == 5); + AddUntilStep(@"wait for content load", () => changelog.ChildrenOfType().Any()); AddAssert(@"supporter promo showed", () => changelog.ChildrenOfType().First().Alpha == (isSupporter ? 0 : 1)); } From cf82bca09c56eed50dd4dc7b8e97e80af76825d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 14:44:13 +0900 Subject: [PATCH 364/600] Change logic to only handle the case of exactly two teams --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index f77303eec7..2846fbec29 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -133,7 +133,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate leaderboardContainer.Add(leaderboard); - if (leaderboard.TeamScores.Count >= 2) + if (leaderboard.TeamScores.Count == 2) { LoadComponentAsync(new MatchScoreDisplay { From ee3b373e8a0db22c0119d1822ca2db468ba586fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 14:48:37 +0900 Subject: [PATCH 365/600] Correctly handle tied scores --- .../Screens/Play/HUD/MatchScoreDisplay.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 837d8bfde7..c77b872786 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -112,11 +112,23 @@ namespace osu.Game.Screens.Play.HUD Score1Text.Current.Value = Team1Score.Value; Score2Text.Current.Value = Team2Score.Value; - var winningText = Team1Score.Value > Team2Score.Value ? Score1Text : Score2Text; - var losingText = Team1Score.Value <= Team2Score.Value ? Score1Text : Score2Text; + int comparison = Team1Score.Value.CompareTo(Team2Score.Value); - winningText.Winning = true; - losingText.Winning = false; + if (comparison > 0) + { + Score1Text.Winning = true; + Score2Text.Winning = false; + } + else if (comparison < 0) + { + Score1Text.Winning = false; + Score2Text.Winning = true; + } + else + { + Score1Text.Winning = false; + Score2Text.Winning = false; + } var winningBar = Team1Score.Value > Team2Score.Value ? score1Bar : score2Bar; var losingBar = Team1Score.Value <= Team2Score.Value ? score1Bar : score2Bar; From fb7ed08bab60c42b68bb3d3816259cd8bbeb8c70 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 11 Aug 2021 12:49:22 +0700 Subject: [PATCH 366/600] move text creation to load method --- .../Changelog/ChangelogSupporterPromo.cs | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index f5638293bb..c0d78cc887 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -22,8 +22,7 @@ namespace osu.Game.Overlays.Changelog { private const float image_container_width = 164; - private readonly LinkFlowContainer supportLinkText; - private readonly TextFlowContainer supportNoteText; + private readonly FillFlowContainer textContainer; private readonly Container imageContainer; public ChangelogSupporterPromo() @@ -65,7 +64,7 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding { Horizontal = 75 }, Children = new Drawable[] { - new FillFlowContainer + textContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -73,32 +72,6 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Padding = new MarginPadding { Right = 50 + image_container_width }, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = ChangelogStrings.SupportHeading, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Light), - Margin = new MarginPadding { Bottom = 20 }, - }, - supportLinkText = new LinkFlowContainer(t => - { - t.Font = t.Font.With(size: 14); - }) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - supportNoteText = new TextFlowContainer(t => - { - t.Font = t.Font.With(size: 12); - }) - { - Margin = new MarginPadding { Top = 10 }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } - }, }, imageContainer = new Container { @@ -117,17 +90,44 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load(OsuColour colour, TextureStore textures) { - void fontPinkColour(SpriteText t) => t.Colour = colour.PinkLighter; + LinkFlowContainer supportLinkText; + textContainer.Children = new Drawable[] + { + new OsuSpriteText + { + Text = ChangelogStrings.SupportHeading, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Light), + Margin = new MarginPadding { Bottom = 20 }, + }, + supportLinkText = new LinkFlowContainer(t => + { + t.Font = t.Font.With(size: 14); + t.Colour = colour.PinkLighter; + }) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + new TextFlowContainer(t => + { + t.Font = t.Font.With(size: 12); + t.Colour = colour.PinkLighter; + }) + { + Text = "Not only will you help speed development, but you will also get some extra features and customisations!", + Margin = new MarginPadding { Top = 10 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + }; - supportLinkText.AddText("Support further development of osu! and ", fontPinkColour); + supportLinkText.AddText("Support further development of osu! and "); supportLinkText.AddLink("become an osu!supporter", "https://osu.ppy.sh/home/support", t => { t.Colour = colour.PinkDark; t.Font = t.Font.With(weight: FontWeight.Bold); }); - supportLinkText.AddText(" today!", fontPinkColour); - - supportNoteText.AddText("Not only will you help speed development, but you will also get some extra features and customisations!", fontPinkColour); + supportLinkText.AddText(" today!"); imageContainer.Children = new Drawable[] { From 735c5085ddd29088ba5ae1a9fd817b1f335995d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 14:43:01 +0900 Subject: [PATCH 367/600] Fix match score display not doing an initial value update --- osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index c77b872786..607d08b8ed 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Play.HUD base.LoadComplete(); Team1Score.BindValueChanged(_ => updateScores()); - Team2Score.BindValueChanged(_ => updateScores()); + Team2Score.BindValueChanged(_ => updateScores(), true); } private void updateScores() From c376e652a4abdd44cc2e22ea06a45cd356e22b45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 14:43:16 +0900 Subject: [PATCH 368/600] Convey and show team scores at the multiplayer results screen --- .../TestSceneMultiplayerTeamResults.cs | 88 +++++++++++++++++++ .../Multiplayer/MultiplayerPlayer.cs | 2 +- .../Multiplayer/MultiplayerResultsScreen.cs | 23 ++++- 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs new file mode 100644 index 0000000000..2b04955d5e --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -0,0 +1,88 @@ +// 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.Bindables; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Osu; +using osu.Game.Scoring; +using osu.Game.Screens.OnlinePlay.Multiplayer; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMultiplayerTeamResults : ScreenTestScene + { + [Test] + public void TestDisplayWithTeams() + { + AddStep("show results screen", () => + { + var rulesetInfo = new OsuRuleset().RulesetInfo; + var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo; + + var score = new ScoreInfo + { + Rank = ScoreRank.B, + TotalScore = 987654, + Accuracy = 0.8, + MaxCombo = 500, + Combo = 250, + Beatmap = beatmapInfo, + User = new User { Username = "Test user" }, + Date = DateTimeOffset.Now, + OnlineScoreID = 12345, + Ruleset = rulesetInfo, + }; + + PlaylistItem playlistItem = new PlaylistItem + { + BeatmapID = beatmapInfo.ID, + }; + + SortedDictionary teamScores = new SortedDictionary + { + { 0, new BindableInt(7483253) }, + { 1, new BindableInt(1048576) } + }; + + Stack.Push(new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); + }); + } + + [Test] + public void TestDisplayWithoutTeams() + { + AddStep("show results screen", () => + { + var rulesetInfo = new OsuRuleset().RulesetInfo; + var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo; + + var score = new ScoreInfo + { + Rank = ScoreRank.B, + TotalScore = 987654, + Accuracy = 0.8, + MaxCombo = 500, + Combo = 250, + Beatmap = beatmapInfo, + User = new User { Username = "Test user" }, + Date = DateTimeOffset.Now, + OnlineScoreID = 12345, + Ruleset = rulesetInfo, + }; + + PlaylistItem playlistItem = new PlaylistItem + { + BeatmapID = beatmapInfo.ID, + }; + + SortedDictionary teamScores = new SortedDictionary(); + + Stack.Push(new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); + }); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 3ba7b8b982..3c892d03df 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -181,7 +181,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override ResultsScreen CreateResults(ScoreInfo score) { Debug.Assert(RoomId.Value != null); - return new MultiplayerResultsScreen(score, RoomId.Value.Value, PlaylistItem); + return new MultiplayerResultsScreen(score, RoomId.Value.Value, PlaylistItem, leaderboard.TeamScores); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 140b3c45d8..66de572b77 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -1,17 +1,38 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; +using osu.Game.Screens.Play.HUD; namespace osu.Game.Screens.OnlinePlay.Multiplayer { public class MultiplayerResultsScreen : PlaylistsResultsScreen { - public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem) + private readonly SortedDictionary teamScores; + + public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) : base(score, roomId, playlistItem, false, false) { + this.teamScores = teamScores; + } + + [BackgroundDependencyLoader] + private void load() + { + if (teamScores.Count == 2) + { + LoadComponentAsync(new MatchScoreDisplay + { + Team1Score = { BindTarget = teamScores.First().Value }, + Team2Score = { BindTarget = teamScores.Last().Value }, + }, AddInternal); + } } } } From 430a0e496caf02df211f55fcb0fee7fdb0bf5759 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 15:32:10 +0900 Subject: [PATCH 369/600] Add winner text --- .../MultiplayerResultsScreenStrings.cs | 19 +++++ .../Multiplayer/MultiplayerResultsScreen.cs | 72 +++++++++++++++++-- 2 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Localisation/MultiplayerResultsScreenStrings.cs diff --git a/osu.Game/Localisation/MultiplayerResultsScreenStrings.cs b/osu.Game/Localisation/MultiplayerResultsScreenStrings.cs new file mode 100644 index 0000000000..e586faba66 --- /dev/null +++ b/osu.Game/Localisation/MultiplayerResultsScreenStrings.cs @@ -0,0 +1,19 @@ +// 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 MultiplayerResultsScreenStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.MultiplayerResultsScreen"; + + /// + /// "Team {0} wins!" + /// + public static LocalisableString TeamWins(string winner) => new TranslatableString(getKey(@"team_wins"), @"Team {0} wins!", winner); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} \ No newline at end of file diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 66de572b77..61bc66de45 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -5,10 +5,18 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play.HUD; +using osu.Game.Localisation; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer { @@ -16,22 +24,78 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { private readonly SortedDictionary teamScores; + private Drawable winnerText; + public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) : base(score, roomId, playlistItem, false, false) { this.teamScores = teamScores; } + [Resolved] + private OsuColour colours { get; set; } + [BackgroundDependencyLoader] private void load() { if (teamScores.Count == 2) { - LoadComponentAsync(new MatchScoreDisplay + var redScore = teamScores.First().Value; + var blueScore = teamScores.Last().Value; + + // eventually this will be replaced by team names coming from the multiplayer match state. + string winner = redScore.Value > blueScore.Value ? @"Red" : @"Blue"; + + var winnerColour = redScore.Value > blueScore.Value ? colours.TeamColourRed : colours.TeamColourBlue; + + AddRangeInternal(new Drawable[] { - Team1Score = { BindTarget = teamScores.First().Value }, - Team2Score = { BindTarget = teamScores.Last().Value }, - }, AddInternal); + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new MatchScoreDisplay + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Team1Score = { BindTarget = redScore }, + Team2Score = { BindTarget = blueScore }, + }, + (winnerText = new OsuSpriteText + { + Alpha = 0, + Font = OsuFont.Torus.With(size: 40, weight: FontWeight.Bold), + Text = MultiplayerResultsScreenStrings.TeamWins(winner) + }).WithEffect(new GlowEffect + { + Colour = winnerColour, + }).With(e => + { + e.Anchor = Anchor.TopCentre; + e.Origin = Anchor.TopCentre; + }) + } + }, + }); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + using (BeginDelayedSequence(300)) + { + winnerText.FadeInFromZero(600, Easing.InQuint); + + winnerText + .ScaleTo(10) + .ScaleTo(1, 600, Easing.InQuad) + .Then() + .ScaleTo(1.02f, 1600, Easing.OutQuint); } } } From a223f111cb43633f53be512e16215c13b4f90721 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 15:50:01 +0900 Subject: [PATCH 370/600] Move text to avoid overlapping the results panel --- .../Multiplayer/MultiplayerResultsScreen.cs | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 61bc66de45..0e4655e336 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -5,18 +5,16 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Localisation; using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play.HUD; -using osu.Game.Localisation; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer { @@ -50,35 +48,27 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer AddRangeInternal(new Drawable[] { - new FillFlowContainer + new MatchScoreDisplay { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new MatchScoreDisplay - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Team1Score = { BindTarget = redScore }, - Team2Score = { BindTarget = blueScore }, - }, - (winnerText = new OsuSpriteText - { - Alpha = 0, - Font = OsuFont.Torus.With(size: 40, weight: FontWeight.Bold), - Text = MultiplayerResultsScreenStrings.TeamWins(winner) - }).WithEffect(new GlowEffect - { - Colour = winnerColour, - }).With(e => - { - e.Anchor = Anchor.TopCentre; - e.Origin = Anchor.TopCentre; - }) - } + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Team1Score = { BindTarget = redScore }, + Team2Score = { BindTarget = blueScore }, }, + (winnerText = new OsuSpriteText + { + Alpha = 0, + Font = OsuFont.Torus.With(size: 80, weight: FontWeight.Bold), + Text = MultiplayerResultsScreenStrings.TeamWins(winner), + Blending = BlendingParameters.Additive + }).WithEffect(new GlowEffect + { + Colour = winnerColour, + }).With(e => + { + e.Anchor = Anchor.Centre; + e.Origin = Anchor.Centre; + }) }); } } @@ -95,7 +85,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer .ScaleTo(10) .ScaleTo(1, 600, Easing.InQuad) .Then() - .ScaleTo(1.02f, 1600, Easing.OutQuint); + .ScaleTo(1.02f, 1600, Easing.OutQuint) + .FadeOut(5000, Easing.InQuad); } } } From f8683e2256d8e452da31d6429cdada61e92833b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 16:17:21 +0900 Subject: [PATCH 371/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 8de516240f..454bb46059 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 59283084db..e6219fcb85 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index c8d3d150db..9904946363 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 0ffe740ca1dcce1e2c7fa276f96f523b004b0fed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 16:24:47 +0900 Subject: [PATCH 372/600] Bring back `TestSceneOsuGame` I marked this as headless to avoid it being "ungrouped", but it turns out this is quite useful to have around and I have searched for it on multiple occasions. --- osu.Game.Tests/Visual/{ => Navigation}/TestSceneOsuGame.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) rename osu.Game.Tests/Visual/{ => Navigation}/TestSceneOsuGame.cs (98%) diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs similarity index 98% rename from osu.Game.Tests/Visual/TestSceneOsuGame.cs rename to osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index c52d846a68..26641214b1 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -30,10 +29,9 @@ using osu.Game.Skinning; using osu.Game.Utils; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Navigation { [TestFixture] - [HeadlessTest] public class TestSceneOsuGame : OsuTestScene { private IReadOnlyList requiredGameDependencies => new[] From 3f067e3a8d20ed33d8ab8f7f9434b3da6377fcc0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 16:59:42 +0900 Subject: [PATCH 373/600] Remove likely unnecessary score null check --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1692975210..09eaf1c543 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -962,7 +962,7 @@ namespace osu.Game.Screens.Play screenSuspension?.Expire(); // if arriving here and the results screen preparation task hasn't run, it's safe to say the user has not completed the beatmap. - if (Score != null && prepareScoreForDisplayTask == null) + if (prepareScoreForDisplayTask == null) { Score.ScoreInfo.Passed = false; // potentially should be ScoreRank.F instead? this is the best alternative for now. From e8ad0fba75f8bf6482a1a60e8ec18019c7adc30f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 17:20:41 +0900 Subject: [PATCH 374/600] Add required server methods for kicking users --- osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs | 8 ++++++++ osu.Game/Online/Multiplayer/MultiplayerClient.cs | 2 ++ osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 8 ++++++++ .../Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 7 +++++++ 4 files changed, 25 insertions(+) diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index b26c4d8201..da637c229f 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -27,6 +27,14 @@ namespace osu.Game.Online.Multiplayer /// If the user is not in a room. Task TransferHost(int userId); + /// + /// As the host, kick another user from the room. + /// + /// The user to kick.. + /// A user other than the current host is attempting to kick a user. + /// If the user is not in a room. + Task KickUser(int userId); + /// /// As the host, update the settings of the currently joined room. /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index dafc737ba2..4607211cdf 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -293,6 +293,8 @@ namespace osu.Game.Online.Multiplayer public abstract Task TransferHost(int userId); + public abstract Task KickUser(int userId); + public abstract Task ChangeSettings(MultiplayerRoomSettings settings); public abstract Task ChangeState(MultiplayerUserState newState); diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 8b8d10ce4f..55477a9fc7 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -91,6 +91,14 @@ namespace osu.Game.Online.Multiplayer return connection.InvokeAsync(nameof(IMultiplayerServer.TransferHost), userId); } + public override Task KickUser(int userId) + { + if (!IsConnected.Value) + return Task.CompletedTask; + + return connection.InvokeAsync(nameof(IMultiplayerServer.KickUser), userId); + } + public override Task ChangeSettings(MultiplayerRoomSettings settings) { if (!IsConnected.Value) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index cffaea5c94..a28b4140ca 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -174,6 +174,13 @@ namespace osu.Game.Tests.Visual.Multiplayer public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId); + public override Task KickUser(int userId) + { + Debug.Assert(Room != null); + + return ((IMultiplayerClient)this).UserLeft(Room.Users.Single(u => u.UserID == userId)); + } + public override async Task ChangeSettings(MultiplayerRoomSettings settings) { Debug.Assert(Room != null); From 7aab8c32ecec37fe1c34e1f344bfd90eca3aa1ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 17:20:47 +0900 Subject: [PATCH 375/600] Add kick button and hook up logic --- .../Participants/ParticipantPanel.cs | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index 89431445d3..bfe99911b6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -42,6 +43,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants private ModDisplay userModsDisplay; private StateDisplay userStateDisplay; + private IconButton kickButton; + public ParticipantPanel(MultiplayerRoomUser user) { User = user; @@ -64,7 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { new Dimension(GridSizeMode.Absolute, 18), new Dimension(GridSizeMode.AutoSize), - new Dimension() + new Dimension(), + new Dimension(GridSizeMode.AutoSize), }, Content = new[] { @@ -157,7 +161,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Margin = new MarginPadding { Right = 10 }, } } - } + }, + kickButton = new KickButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0, + Margin = new MarginPadding(4), + Action = () => + { + Debug.Assert(user != null); + + Client.KickUser(user.Id); + } + }, }, } }; @@ -179,6 +196,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants userStateDisplay.UpdateStatus(User.State, User.BeatmapAvailability); + if (Client.LocalUser != null && Room.Host?.Equals(Client.LocalUser) == true) + kickButton.FadeIn(fade_time); + else + kickButton.FadeOut(fade_time); + if (Room.Host?.Equals(User) == true) crown.FadeIn(fade_time); else @@ -219,5 +241,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants }; } } + + public class KickButton : IconButton + { + public KickButton() + { + Icon = FontAwesome.Solid.UserTimes; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IconHoverColour = colours.Red; + } + } } } From 50bda6023cf995258991598f8b02bc3ed9761767 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 17:31:37 +0900 Subject: [PATCH 376/600] Add test coverage --- .../TestSceneMultiplayerParticipantsList.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index 6526f7eea7..b2fca61530 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -155,6 +155,42 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("second user crown visible", () => this.ChildrenOfType().ElementAt(1).ChildrenOfType().First().Alpha == 1); } + [Test] + public void TestKickButtonOnlyPresentWhenHost() + { + AddStep("add user", () => Client.AddUser(new User + { + Id = 3, + Username = "Second", + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", + })); + + AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 2); + + AddStep("make second user host", () => Client.TransferHost(3)); + + AddUntilStep("kick buttons not visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 0); + + AddStep("make local user host again", () => Client.TransferHost(API.LocalUser.Value.Id)); + + AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 2); + } + + [Test] + public void TestKickButtonKicks() + { + AddStep("add user", () => Client.AddUser(new User + { + Id = 3, + Username = "Second", + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", + })); + + AddStep("kick second user", () => this.ChildrenOfType().Last().TriggerClick()); + + AddAssert("second user kicked", () => Client.Room?.Users.Single().UserID == API.LocalUser.Value.Id); + } + [Test] public void TestManyUsers() { From bb51ebd0ef2c67dbe1978ac5edad128adc98c8e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 17:39:23 +0900 Subject: [PATCH 377/600] Don't show button on self --- .../Multiplayer/TestSceneMultiplayerParticipantsList.cs | 6 +++--- .../OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index b2fca61530..a3e6c8de3b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -165,7 +165,7 @@ namespace osu.Game.Tests.Visual.Multiplayer CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", })); - AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 2); + AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 1); AddStep("make second user host", () => Client.TransferHost(3)); @@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("make local user host again", () => Client.TransferHost(API.LocalUser.Value.Id)); - AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 2); + AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 1); } [Test] @@ -186,7 +186,7 @@ namespace osu.Game.Tests.Visual.Multiplayer CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", })); - AddStep("kick second user", () => this.ChildrenOfType().Last().TriggerClick()); + AddStep("kick second user", () => this.ChildrenOfType().Single(d => d.IsPresent).TriggerClick()); AddAssert("second user kicked", () => Client.Room?.Users.Single().UserID == API.LocalUser.Value.Id); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index bfe99911b6..54baaceb36 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { base.OnRoomUpdated(); - if (Room == null) + if (Room == null || Client.LocalUser == null) return; const double fade_time = 50; @@ -196,7 +196,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants userStateDisplay.UpdateStatus(User.State, User.BeatmapAvailability); - if (Client.LocalUser != null && Room.Host?.Equals(Client.LocalUser) == true) + if (Client.IsHost && !User.Equals(Client.LocalUser)) kickButton.FadeIn(fade_time); else kickButton.FadeOut(fade_time); From d6352637d6e7ea99dbe02cbe1c920b7d14aa9a54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 17:45:34 +0900 Subject: [PATCH 378/600] Also add tooltip and context menu item --- .../Multiplayer/Participants/ParticipantPanel.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index 54baaceb36..1787480e1f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -233,10 +233,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants new OsuMenuItem("Give host", MenuItemType.Standard, () => { // Ensure the local user is still host. - if (Room.Host?.UserID != api.LocalUser.Value.Id) + if (!Client.IsHost) return; Client.TransferHost(targetUser); + }), + new OsuMenuItem("Kick", MenuItemType.Destructive, () => + { + // Ensure the local user is still host. + if (!Client.IsHost) + return; + + Client.KickUser(targetUser); }) }; } @@ -247,6 +255,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants public KickButton() { Icon = FontAwesome.Solid.UserTimes; + TooltipText = "Kick"; } [BackgroundDependencyLoader] From eb59f3c59188d7ca86e42143a9d9f45802fdda53 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Aug 2021 18:15:53 +0900 Subject: [PATCH 379/600] Revert "Buffer the entire star rating range to fix overlapping alpha" This reverts commit c680012523ff9f4a1e8ab10f788401a9f3b68986. --- .../Components/StarRatingRangeDisplay.cs | 57 +++++++++---------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 622643f5ea..01a21227df 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -33,41 +33,38 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - InternalChild = new BufferedContainer + InternalChildren = new Drawable[] { - AutoSizeAxes = Axes.Both, - Children = new Drawable[] + new Container { - new Container + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 1, + Children = new[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Vertical = 1 }, - Children = new[] + minBackground = new Box { - minBackground = new Box - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.5f), - }, - maxBackground = new Box - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.5f), - }, - } - }, - new FillFlowContainer + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + maxBackground = new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - minDisplay = new StarRatingDisplay(default), - maxDisplay = new StarRatingDisplay(default) - } + minDisplay = new StarRatingDisplay(default), + maxDisplay = new StarRatingDisplay(default) } } }; From 4002a1606eaf8db60d40370d63f2caf3ee3880a6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Aug 2021 18:20:39 +0900 Subject: [PATCH 380/600] Round star ratings before comparing --- .../Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 01a21227df..a27b27b8ad 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -1,6 +1,7 @@ // 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.Specialized; using System.Linq; using osu.Framework.Allocation; @@ -86,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Components minDisplay.Current.Value = minDifficulty; maxDisplay.Current.Value = maxDifficulty; - maxDisplay.Alpha = Precision.AlmostEquals(minDifficulty.Stars, maxDifficulty.Stars) ? 0 : 1; + maxDisplay.Alpha = Precision.AlmostEquals(Math.Round(minDifficulty.Stars, 2), Math.Round(maxDifficulty.Stars, 2)) ? 0 : 1; minBackground.Colour = colours.ForStarDifficulty(minDifficulty.Stars); maxBackground.Colour = colours.ForStarDifficulty(maxDifficulty.Stars); From d9a4f018e65ce669a1fd329a3aa6880b5c94bdbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 18:26:36 +0900 Subject: [PATCH 381/600] Add event flow for receiving kick commands --- osu.Game/Online/Multiplayer/IMultiplayerClient.cs | 9 +++++++++ osu.Game/Online/Multiplayer/MultiplayerClient.cs | 6 ++++++ osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 1 + 3 files changed, 16 insertions(+) diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 064065ab00..8f16d22c4c 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -31,6 +31,15 @@ namespace osu.Game.Online.Multiplayer /// The user. Task UserLeft(MultiplayerRoomUser user); + /// + /// Signals that a user has been kicked from the room. + /// + /// + /// This will also be sent to the user that was kicked. + /// + /// The user. + Task UserKicked(MultiplayerRoomUser user); + /// /// Signal that the host of the room has changed. /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 4607211cdf..7e964ed5fa 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -389,6 +389,12 @@ namespace osu.Game.Online.Multiplayer return Task.CompletedTask; } + Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) + { + // TODO: also inform users of the kick operation. + return ((IMultiplayerClient)this).UserLeft(user); + } + Task IMultiplayerClient.HostChanged(int userId) { if (Room == null) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 55477a9fc7..c38a648a6a 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -50,6 +50,7 @@ namespace osu.Game.Online.Multiplayer connection.On(nameof(IMultiplayerClient.RoomStateChanged), ((IMultiplayerClient)this).RoomStateChanged); connection.On(nameof(IMultiplayerClient.UserJoined), ((IMultiplayerClient)this).UserJoined); connection.On(nameof(IMultiplayerClient.UserLeft), ((IMultiplayerClient)this).UserLeft); + connection.On(nameof(IMultiplayerClient.UserKicked), ((IMultiplayerClient)this).UserKicked); connection.On(nameof(IMultiplayerClient.HostChanged), ((IMultiplayerClient)this).HostChanged); connection.On(nameof(IMultiplayerClient.SettingsChanged), ((IMultiplayerClient)this).SettingsChanged); connection.On(nameof(IMultiplayerClient.UserStateChanged), ((IMultiplayerClient)this).UserStateChanged); From 9b21ebd6d04410d2e5fcd363cf26b4ee88a0bfec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 18:31:04 +0900 Subject: [PATCH 382/600] Add client side handling on incoming kick --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 7e964ed5fa..57dbfbb507 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -190,7 +190,8 @@ namespace osu.Game.Online.Multiplayer return joinOrLeaveTaskChain.Add(async () => { await scheduledReset.ConfigureAwait(false); - await LeaveRoomInternal().ConfigureAwait(false); + if (Room != null) + await LeaveRoomInternal().ConfigureAwait(false); }); } @@ -391,6 +392,12 @@ namespace osu.Game.Online.Multiplayer Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) { + if (LocalUser == null) + return Task.CompletedTask; + + if (user.Equals(LocalUser)) + LeaveRoom(); + // TODO: also inform users of the kick operation. return ((IMultiplayerClient)this).UserLeft(user); } From 31608a1bc6c4a691571967dd1e893a7ac4338ee9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 19:56:25 +0900 Subject: [PATCH 383/600] Leave the match screen when kicked --- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 561fa220c8..57dde31b68 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -448,6 +448,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private void onRoomUpdated() { + // may happen if the client is kicked or otherwise removed from the room. + if (client.Room == null) + { + Schedule(this.Exit); + return; + } + Scheduler.AddOnce(UpdateMods); } From a1f50e39aa12d86456af684804c0894ec1ccf871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jul 2021 16:50:52 +0200 Subject: [PATCH 384/600] Add basic structure for skinning catch explosions --- .../TestSceneCatcherArea.cs | 1 + .../CatchSkinComponents.cs | 3 +- .../Skinning/Default/DefaultHitExplosion.cs | 145 ++++++++++++++++++ osu.Game.Rulesets.Catch/UI/HitExplosion.cs | 121 ++------------- .../UI/HitExplosionContainer.cs | 3 + 5 files changed, 168 insertions(+), 105 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index a3307c9224..6abfbdbe21 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -40,6 +40,7 @@ namespace osu.Game.Rulesets.Catch.Tests { AddSliderStep("circle size", 0, 8, 5, createCatcher); AddToggleStep("hyper dash", t => this.ChildrenOfType().ForEach(area => area.ToggleHyperDash(t))); + AddToggleStep("toggle hit lighting", lighting => config.SetValue(OsuSetting.HitLighting, lighting)); AddStep("catch centered fruit", () => attemptCatch(new Fruit())); AddStep("catch many random fruit", () => diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs index e736d68740..371e901c69 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs @@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Catch Banana, Droplet, Catcher, - CatchComboCounter + CatchComboCounter, + HitExplosion } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs new file mode 100644 index 0000000000..41ba81d34c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -0,0 +1,145 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Utils; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Utils; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Skinning.Default +{ + public class DefaultHitExplosion : CompositeDrawable + { + [Resolved] + private Bindable entryBindable { get; set; } + + private CircularContainer largeFaint; + private CircularContainer smallFaint; + private CircularContainer directionalGlow1; + private CircularContainer directionalGlow2; + + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(20); + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + + // scale roughly in-line with visual appearance of notes + const float initial_height = 10; + + InternalChildren = new Drawable[] + { + largeFaint = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Blending = BlendingParameters.Additive, + }, + smallFaint = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Blending = BlendingParameters.Additive, + }, + directionalGlow1 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.01f, initial_height), + Blending = BlendingParameters.Additive, + }, + directionalGlow2 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.01f, initial_height), + Blending = BlendingParameters.Additive, + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + entryBindable.BindValueChanged(entry => apply(entry.NewValue), true); + } + + private void apply(HitExplosionEntry entry) + { + if (entry == null) + return; + + X = entry.Position; + Scale = new Vector2(entry.Scale); + setColour(entry.ObjectColour); + + using (BeginAbsoluteSequence(entry.LifetimeStart)) + applyTransforms(entry.RNGSeed); + } + + private void applyTransforms(int randomSeed) + { + ClearTransforms(true); + + const double duration = 400; + + // we want our size to be very small so the glow dominates it. + largeFaint.Size = new Vector2(0.8f); + largeFaint + .ResizeTo(largeFaint.Size * new Vector2(5, 1), duration, Easing.OutQuint) + .FadeOut(duration * 2); + + const float angle_variangle = 15; // should be less than 45 + directionalGlow1.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 4); + directionalGlow2.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 5); + + this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out).Expire(); + } + + private void setColour(Color4 objectColour) + { + const float roundness = 100; + + largeFaint.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f), + Roundness = 160, + Radius = 200, + }; + + smallFaint.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1), + Roundness = 20, + Radius = 50, + }; + + directionalGlow1.EdgeEffect = directionalGlow2.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1), + Roundness = roundness, + Radius = 40, + }; + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index d9ab428231..7f3b1619ce 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -1,129 +1,42 @@ // 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.Extensions.Color4Extensions; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Utils; +using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Rulesets.Objects.Pooling; -using osu.Game.Utils; -using osuTK; -using osuTK.Graphics; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.UI { public class HitExplosion : PoolableDrawableWithLifetime { - private readonly CircularContainer largeFaint; - private readonly CircularContainer smallFaint; - private readonly CircularContainer directionalGlow1; - private readonly CircularContainer directionalGlow2; + [Cached] + private Bindable bindableEntry { get; set; } = new Bindable(); public HitExplosion() { - Size = new Vector2(20); - Anchor = Anchor.TopCentre; + RelativeSizeAxes = Axes.Both; + Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; + } - // scale roughly in-line with visual appearance of notes - const float initial_height = 10; - - InternalChildren = new Drawable[] + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.HitExplosion), _ => new DefaultHitExplosion()) { - largeFaint = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - Blending = BlendingParameters.Additive, - }, - smallFaint = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - Blending = BlendingParameters.Additive, - }, - directionalGlow1 = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - Size = new Vector2(0.01f, initial_height), - Blending = BlendingParameters.Additive, - }, - directionalGlow2 = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - Size = new Vector2(0.01f, initial_height), - Blending = BlendingParameters.Additive, - } + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre }; } protected override void OnApply(HitExplosionEntry entry) { - X = entry.Position; - Scale = new Vector2(entry.Scale); - setColour(entry.ObjectColour); + base.OnApply(entry); - using (BeginAbsoluteSequence(entry.LifetimeStart)) - applyTransforms(entry.RNGSeed); - } - - private void applyTransforms(int randomSeed) - { - ClearTransforms(true); - - const double duration = 400; - - // we want our size to be very small so the glow dominates it. - largeFaint.Size = new Vector2(0.8f); - largeFaint - .ResizeTo(largeFaint.Size * new Vector2(5, 1), duration, Easing.OutQuint) - .FadeOut(duration * 2); - - const float angle_variangle = 15; // should be less than 45 - directionalGlow1.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 4); - directionalGlow2.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 5); - - this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out).Expire(); - } - - private void setColour(Color4 objectColour) - { - const float roundness = 100; - - largeFaint.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f), - Roundness = 160, - Radius = 200, - }; - - smallFaint.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1), - Roundness = 20, - Radius = 50, - }; - - directionalGlow1.EdgeEffect = directionalGlow2.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1), - Roundness = roundness, - Radius = 40, - }; + bindableEntry.Value = entry; } } } diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs index 094d88243a..6df13e52ef 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs @@ -1,6 +1,7 @@ // 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.Graphics; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Objects.Pooling; @@ -14,6 +15,8 @@ namespace osu.Game.Rulesets.Catch.UI public HitExplosionContainer() { + RelativeSizeAxes = Axes.Both; + AddInternal(pool = new DrawablePool(10)); } From 95a58ca3666dfe785034741caa6d4f5ac39b9170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jul 2021 17:19:51 +0200 Subject: [PATCH 385/600] Store judgement directly in hit explosion entry --- .../Skinning/Default/DefaultHitExplosion.cs | 4 +-- osu.Game.Rulesets.Catch/UI/Catcher.cs | 6 ++-- .../UI/HitExplosionEntry.cs | 30 ++++++++++++++----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs index 41ba81d34c..f4b952c559 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -87,11 +87,11 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default return; X = entry.Position; - Scale = new Vector2(entry.Scale); + Scale = new Vector2(entry.HitObject.Scale); setColour(entry.ObjectColour); using (BeginAbsoluteSequence(entry.LifetimeStart)) - applyTransforms(entry.RNGSeed); + applyTransforms(entry.HitObject.RandomSeed); } private void applyTransforms(int randomSeed) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 9fd4610e6e..a1aa58f163 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Catch.UI placeCaughtObject(palpableObject, positionInStack); if (hitLighting.Value) - addLighting(hitObject, positionInStack.X, drawableObject.AccentColour.Value); + addLighting(result, drawableObject.AccentColour.Value, positionInStack.X); } // droplet doesn't affect the catcher state @@ -365,8 +365,8 @@ namespace osu.Game.Rulesets.Catch.UI return position; } - private void addLighting(CatchHitObject hitObject, float x, Color4 colour) => - hitExplosionContainer.Add(new HitExplosionEntry(Time.Current, x, hitObject.Scale, colour, hitObject.RandomSeed)); + private void addLighting(JudgementResult judgementResult, Color4 colour, float x) => + hitExplosionContainer.Add(new HitExplosionEntry(judgementResult, colour, x, Time.Current)); private CaughtObject getCaughtObject(PalpableCatchHitObject source) { diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs index b142962a8a..749a448314 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs @@ -2,24 +2,40 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Performance; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Judgements; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.UI { public class HitExplosionEntry : LifetimeEntry { - public readonly float Position; - public readonly float Scale; - public readonly Color4 ObjectColour; - public readonly int RNGSeed; + /// + /// The judgement result that triggered this explosion. + /// + public JudgementResult JudgementResult { get; } - public HitExplosionEntry(double startTime, float position, float scale, Color4 objectColour, int rngSeed) + /// + /// The hitobject which triggered this explosion. + /// + public CatchHitObject HitObject => (CatchHitObject)JudgementResult.HitObject; + + /// + /// The accent colour of the object caught. + /// + public Color4 ObjectColour { get; } + + /// + /// The position at which the object was caught. + /// + public float Position { get; } + + public HitExplosionEntry(JudgementResult judgementResult, Color4 objectColour, float position, double startTime) { LifetimeStart = startTime; Position = position; - Scale = scale; + JudgementResult = judgementResult; ObjectColour = objectColour; - RNGSeed = rngSeed; } } } From 8c8a64fe6eafc5452c2f63c3b0c464bc025389bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jul 2021 19:00:37 +0200 Subject: [PATCH 386/600] Add legacy hit lighting implementation --- .../Legacy/CatchLegacySkinTransformer.cs | 20 +++- .../Skinning/Legacy/LegacyHitExplosion.cs | 103 ++++++++++++++++++ osu.Game.Rulesets.Catch/UI/Catcher.cs | 7 +- osu.Game.Rulesets.Catch/UI/HitExplosion.cs | 1 + 4 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index 5e744ec001..10fc4e78b2 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -70,13 +70,11 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy if (version < 2.3m) { - if (GetTexture(@"fruit-ryuuta") != null || - GetTexture(@"fruit-ryuuta-0") != null) + if (hasOldStyleCatcherSprite()) return new LegacyCatcherOld(); } - if (GetTexture(@"fruit-catcher-idle") != null || - GetTexture(@"fruit-catcher-idle-0") != null) + if (hasNewStyleCatcherSprite()) return new LegacyCatcherNew(); return null; @@ -86,12 +84,26 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy return new LegacyCatchComboCounter(Skin); return null; + + case CatchSkinComponents.HitExplosion: + if (hasOldStyleCatcherSprite() || hasNewStyleCatcherSprite()) + return new LegacyHitExplosion(); + + return null; } } return base.GetDrawableComponent(component); } + private bool hasOldStyleCatcherSprite() => + GetTexture(@"fruit-ryuuta") != null + || GetTexture(@"fruit-ryuuta-0") != null; + + private bool hasNewStyleCatcherSprite() => + GetTexture(@"fruit-catcher-idle") != null + || GetTexture(@"fruit-catcher-idle-0") != null; + public override IBindable GetConfig(TLookup lookup) { switch (lookup) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs new file mode 100644 index 0000000000..339055c91d --- /dev/null +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -0,0 +1,103 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Skinning.Legacy +{ + public class LegacyHitExplosion : CompositeDrawable + { + [Resolved] + private Catcher catcher { get; set; } + + [Resolved] + private Bindable entryBindable { get; set; } + + private const float catch_margin = (1 - Catcher.ALLOWED_CATCH_RANGE) / 2; + + private readonly Sprite explosion1; + private readonly Sprite explosion2; + + public LegacyHitExplosion() + { + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + RelativeSizeAxes = Axes.Both; + Scale = new Vector2(0.4f); + + InternalChildren = new[] + { + explosion1 = new Sprite + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.CentreLeft, + Blending = BlendingParameters.Additive, + Rotation = -90 + }, + explosion2 = new Sprite + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.CentreLeft, + Blending = BlendingParameters.Additive, + Rotation = -90 + } + }; + } + + [BackgroundDependencyLoader] + private void load(SkinManager skins) + { + var defaultLegacySkin = skins.DefaultLegacySkin; + + explosion1.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-2"); + explosion2.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-1"); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + entryBindable.BindValueChanged(entry => apply(entry.NewValue), true); + } + + private void apply(HitExplosionEntry entry) + { + if (entry == null) + return; + + Colour = entry.ObjectColour; + + using (BeginAbsoluteSequence(entry.LifetimeStart)) + { + float halfCatchWidth = catcher.CatchWidth / 2; + float explosionOffset = Math.Clamp(entry.Position, -halfCatchWidth + catch_margin * 3, halfCatchWidth - catch_margin * 3); + + if (!(entry.HitObject is Droplet)) + { + float scale = Math.Clamp(entry.JudgementResult.ComboAtJudgement / 200f, 0.35f, 1.125f); + + explosion1.Scale = new Vector2(1, 0.9f); + explosion1.Position = new Vector2(explosionOffset, 0); + + explosion1.FadeOut(300); + explosion1.ScaleTo(new Vector2(20 * scale, 1.1f), 160, Easing.Out); + } + + explosion2.Scale = new Vector2(0.9f, 1); + explosion2.Position = new Vector2(explosionOffset, 0); + + explosion2.FadeOut(700); + explosion2.ScaleTo(new Vector2(0.9f, 1.3f), 500, Easing.Out); + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index a1aa58f163..aec8e752a7 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -23,6 +23,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.UI { + [Cached] public class Catcher : SkinReloadableDrawable { /// @@ -106,7 +107,7 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Width of the area that can be used to attempt catches during gameplay. /// - private readonly float catchWidth; + public readonly float CatchWidth; private readonly SkinnableCatcher body; @@ -133,7 +134,7 @@ namespace osu.Game.Rulesets.Catch.UI if (difficulty != null) Scale = calculateScale(difficulty); - catchWidth = CalculateCatchWidth(Scale); + CatchWidth = CalculateCatchWidth(Scale); InternalChildren = new Drawable[] { @@ -193,7 +194,7 @@ namespace osu.Game.Rulesets.Catch.UI if (!(hitObject is PalpableCatchHitObject fruit)) return false; - float halfCatchWidth = catchWidth * 0.5f; + float halfCatchWidth = CatchWidth * 0.5f; return fruit.EffectiveX >= X - halfCatchWidth && fruit.EffectiveX <= X + halfCatchWidth; } diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 7f3b1619ce..671b14640d 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -27,6 +27,7 @@ namespace osu.Game.Rulesets.Catch.UI { InternalChild = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.HitExplosion), _ => new DefaultHitExplosion()) { + CentreComponent = false, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre }; From 4bcbe6ac90def30bda7da29052b748bc5a2b1359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 7 Aug 2021 18:19:29 +0200 Subject: [PATCH 387/600] Restructure explosion to ensure proper lifetime bounds --- .../Skinning/Default/DefaultHitExplosion.cs | 17 +++------------ .../Skinning/Legacy/LegacyHitExplosion.cs | 21 ++++++------------- osu.Game.Rulesets.Catch/UI/HitExplosion.cs | 12 ++++++----- osu.Game.Rulesets.Catch/UI/IHitExplosion.cs | 16 ++++++++++++++ 4 files changed, 32 insertions(+), 34 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/UI/IHitExplosion.cs diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs index f4b952c559..2660e0730d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,11 +14,8 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default { - public class DefaultHitExplosion : CompositeDrawable + public class DefaultHitExplosion : CompositeDrawable, IHitExplosion { - [Resolved] - private Bindable entryBindable { get; set; } - private CircularContainer largeFaint; private CircularContainer smallFaint; private CircularContainer directionalGlow1; @@ -74,14 +70,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default }; } - protected override void LoadComplete() - { - base.LoadComplete(); - - entryBindable.BindValueChanged(entry => apply(entry.NewValue), true); - } - - private void apply(HitExplosionEntry entry) + public void Animate(HitExplosionEntry entry) { if (entry == null) return; @@ -110,7 +99,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default directionalGlow1.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 4); directionalGlow2.Rotation = StatelessRNG.NextSingle(-angle_variangle, angle_variangle, randomSeed, 5); - this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out).Expire(); + this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out); } private void setColour(Color4 objectColour) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index 339055c91d..6708989b89 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -14,14 +13,11 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Legacy { - public class LegacyHitExplosion : CompositeDrawable + public class LegacyHitExplosion : CompositeDrawable, IHitExplosion { [Resolved] private Catcher catcher { get; set; } - [Resolved] - private Bindable entryBindable { get; set; } - private const float catch_margin = (1 - Catcher.ALLOWED_CATCH_RANGE) / 2; private readonly Sprite explosion1; @@ -62,14 +58,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy explosion2.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-1"); } - protected override void LoadComplete() - { - base.LoadComplete(); - - entryBindable.BindValueChanged(entry => apply(entry.NewValue), true); - } - - private void apply(HitExplosionEntry entry) + public void Animate(HitExplosionEntry entry) { if (entry == null) return; @@ -88,15 +77,17 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy explosion1.Scale = new Vector2(1, 0.9f); explosion1.Position = new Vector2(explosionOffset, 0); - explosion1.FadeOut(300); + explosion1.FadeOutFromOne(300); explosion1.ScaleTo(new Vector2(20 * scale, 1.1f), 160, Easing.Out); } explosion2.Scale = new Vector2(0.9f, 1); explosion2.Position = new Vector2(explosionOffset, 0); - explosion2.FadeOut(700); + explosion2.FadeOutFromOne(700); explosion2.ScaleTo(new Vector2(0.9f, 1.3f), 500, Easing.Out); + + this.Delay(700).FadeOutFromOne(); } } } diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 671b14640d..0a5341cb67 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Rulesets.Objects.Pooling; @@ -12,8 +11,7 @@ namespace osu.Game.Rulesets.Catch.UI { public class HitExplosion : PoolableDrawableWithLifetime { - [Cached] - private Bindable bindableEntry { get; set; } = new Bindable(); + private SkinnableDrawable skinnableExplosion; public HitExplosion() { @@ -25,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - InternalChild = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.HitExplosion), _ => new DefaultHitExplosion()) + InternalChild = skinnableExplosion = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.HitExplosion), _ => new DefaultHitExplosion()) { CentreComponent = false, Anchor = Anchor.BottomCentre, @@ -37,7 +35,11 @@ namespace osu.Game.Rulesets.Catch.UI { base.OnApply(entry); - bindableEntry.Value = entry; + ApplyTransformsAt(double.MinValue, true); + ClearTransforms(true); + + (skinnableExplosion.Drawable as IHitExplosion)?.Animate(entry); + LifetimeEnd = skinnableExplosion.Drawable.LatestTransformEndTime; } } } diff --git a/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs b/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs new file mode 100644 index 0000000000..4a9d7e8ac0 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Catch.UI +{ + /// + /// Common interface for all hit explosion skinnables. + /// + public interface IHitExplosion + { + /// + /// Begins animating this . + /// + void Animate(HitExplosionEntry entry); + } +} From 2fb19210af31d7aba85348c4b8bc3f023f0e61da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 11 Aug 2021 22:36:27 +0200 Subject: [PATCH 388/600] Fix legacy explosion sprites incorrectly showing after skin change --- osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index 6708989b89..78b0e1e327 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -36,6 +36,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy { Anchor = Anchor.BottomCentre, Origin = Anchor.CentreLeft, + Alpha = 0, Blending = BlendingParameters.Additive, Rotation = -90 }, @@ -43,6 +44,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy { Anchor = Anchor.BottomCentre, Origin = Anchor.CentreLeft, + Alpha = 0, Blending = BlendingParameters.Additive, Rotation = -90 } From 427a88940c56988484a17c0e0020613243be9083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 11 Aug 2021 23:18:42 +0200 Subject: [PATCH 389/600] Remove duplicated `ClearTransforms()` call --- osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs index 2660e0730d..680fbc7b15 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -85,8 +85,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default private void applyTransforms(int randomSeed) { - ClearTransforms(true); - const double duration = 400; // we want our size to be very small so the glow dominates it. From 98ce69d1d32b65abd9983dbd1124cad8f6bc938b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 11 Aug 2021 23:32:58 +0200 Subject: [PATCH 390/600] Fix explosion reading out time values from wrong clock --- osu.Game.Rulesets.Catch/UI/HitExplosion.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 0a5341cb67..35af39348d 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -34,7 +34,18 @@ namespace osu.Game.Rulesets.Catch.UI protected override void OnApply(HitExplosionEntry entry) { base.OnApply(entry); + if (IsLoaded) + apply(entry); + } + protected override void LoadComplete() + { + base.LoadComplete(); + apply(Entry); + } + + private void apply(HitExplosionEntry entry) + { ApplyTransformsAt(double.MinValue, true); ClearTransforms(true); From 58d76e903618e640fe97d9b341959cca33804940 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 09:13:10 +0900 Subject: [PATCH 391/600] Use FinishTransforms() --- .../Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index dfe7ff8cac..052ad35dd7 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -21,7 +21,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [Resolved] private OsuColour colours { get; set; } - private bool firstDisplay = true; private PillContainer pill; private SpriteText statusText; @@ -51,6 +50,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components EndDate.BindValueChanged(_ => updateDisplay()); Status.BindValueChanged(_ => updateDisplay(), true); + + FinishTransforms(true); } private void updateDisplay() @@ -58,10 +59,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RoomStatus status = getDisplayStatus(); pill.Background.Alpha = 1; - pill.Background.FadeColour(status.GetAppropriateColour(colours), firstDisplay ? 0 : 100); + pill.Background.FadeColour(status.GetAppropriateColour(colours), 100); statusText.Text = status.Message; - - firstDisplay = false; } private RoomStatus getDisplayStatus() From bbb28d1b2984c2478414e068830aa54c9b4beb03 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 09:14:46 +0900 Subject: [PATCH 392/600] Don't use null-propagation for status --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index 052ad35dd7..1d43f2dc65 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components if (EndDate.Value < DateTimeOffset.Now) return new RoomStatusEnded(); - return Status.Value ?? new RoomStatusOpen(); + return Status.Value; } } } From fbaa480b3e21808f15e6e3cbef7262e440f2ca66 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 10:08:54 +0900 Subject: [PATCH 393/600] Fix out-of-order hits in editor causing exceptions --- .../Edit/DrawableOsuEditorRuleset.cs | 5 +++++ osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs index 0e61c02e2d..d4f1602a46 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs @@ -41,6 +41,11 @@ namespace osu.Game.Rulesets.Osu.Edit protected override GameplayCursorContainer CreateCursor() => null; + public OsuEditorPlayfield() + { + HitPolicy = new AnyOrderHitPolicy(); + } + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { diff --git a/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs new file mode 100644 index 0000000000..b4de91562b --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Osu.UI +{ + /// + /// An which allows hitobjects to be hit in any order. + /// + public class AnyOrderHitPolicy : IHitPolicy + { + public IHitObjectContainer HitObjectContainer { get; set; } + + public bool IsHittable(DrawableHitObject hitObject, double time) => true; + + public void HandleHit(DrawableHitObject hitObject) + { + } + } +} From 5d0b92e28cdff72e8185827d34f7cff5ddb3d191 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 10:38:20 +0900 Subject: [PATCH 394/600] Fix multi spectator test not showing teams --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 3118a23fd5..65b1d6d53a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -97,11 +97,11 @@ namespace osu.Game.Tests.Visual.Multiplayer TeamID = 1, }; - SpectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId); - SpectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId); + SpectatorClient.StartPlay(player1.UserID, importedBeatmapId); + SpectatorClient.StartPlay(player2.UserID, importedBeatmapId); - playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID)); - playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID)); + playingUsers.Add(player1); + playingUsers.Add(player2); }); loadSpectateScreen(); From 543482111b470d63cf74c4ed6dab294282fa7af8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 10:40:14 +0900 Subject: [PATCH 395/600] Remove outdated todo --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 2846fbec29..d10917259d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -55,7 +55,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public MultiSpectatorScreen(MultiplayerRoomUser[] users) : base(users.Select(u => u.UserID).ToArray()) { - // todo: this is a bit ugly, but not sure on a better way to handle. this.users = users; instances = new PlayerArea[Users.Count]; From 531fba8f39949265ef61cd17a3c66d881695c9e4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 11:05:31 +0900 Subject: [PATCH 396/600] Fix potential test case failure --- .../TestSceneMultiplayerGameplayLeaderboard.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 0997de478b..3317ddc767 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -12,6 +12,7 @@ using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; using osu.Game.Online.Spectator; using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Osu.Scoring; @@ -51,12 +52,13 @@ namespace osu.Game.Tests.Visual.Multiplayer OsuScoreProcessor scoreProcessor; Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); - var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); + var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); + var multiplayerUsers = new List(); foreach (var user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); + multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true)); } Children = new Drawable[] @@ -64,9 +66,9 @@ namespace osu.Game.Tests.Visual.Multiplayer scoreProcessor = new OsuScoreProcessor(), }; - scoreProcessor.ApplyBeatmap(playable); + scoreProcessor.ApplyBeatmap(playableBeatmap); - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, Client.Room?.Users.ToArray()) + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, multiplayerUsers.ToArray()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 9393c6351d41a7affb43988a1d6932476d31c99a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 11:08:52 +0900 Subject: [PATCH 397/600] Fix another potential test case failure --- .../TestSceneMultiplayerGameplayLeaderboardTeams.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 274c9ea4b2..dfaf2f1dc3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Osu.Scoring; @@ -55,7 +56,8 @@ namespace osu.Game.Tests.Visual.Multiplayer OsuScoreProcessor scoreProcessor; Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); - var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); + var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); + var multiplayerUsers = new List(); foreach (var user in users) { @@ -66,6 +68,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { TeamID = RNG.Next(0, 2) }; + + multiplayerUsers.Add(roomUser); } Children = new Drawable[] @@ -73,9 +77,9 @@ namespace osu.Game.Tests.Visual.Multiplayer scoreProcessor = new OsuScoreProcessor(), }; - scoreProcessor.ApplyBeatmap(playable); + scoreProcessor.ApplyBeatmap(playableBeatmap); - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, Client.Room?.Users.ToArray()) + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, multiplayerUsers.ToArray()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 18ecd8758ba0646e5c54621eb77d23d152eea397 Mon Sep 17 00:00:00 2001 From: PercyDan <50285552+PercyDan54@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:12:35 +0800 Subject: [PATCH 398/600] Make Perfect auto restart toggleable --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 5 +++++ osu.Game/Rulesets/Mods/ModPerfect.cs | 5 +++++ osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index c0d7bae2b2..c6855a3d38 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; +using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -11,6 +13,9 @@ namespace osu.Game.Rulesets.Mods { public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + [SettingSource("Restart on fail", "Automatically restarts when failed.")] + public BindableBool Restart { get; } = new BindableBool(); + public virtual bool PerformFail() => true; public virtual bool RestartOnFail => true; diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 187a4d8e23..9016a24f8d 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -21,6 +21,11 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModSuddenDeath)).ToArray(); + protected ModPerfect() + { + Restart.Value = Restart.Default = true; + } + protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type.AffectsAccuracy() && result.Type != result.Judgement.MaxResult; diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 7df561b199..68ed112078 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,9 +3,7 @@ using System; using System.Linq; -using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -23,9 +21,6 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray(); - [SettingSource("Restart on fail", "Automatically restarts when failed.")] - public BindableBool Restart { get; } = new BindableBool(); - public override bool PerformFail() => true; public override bool RestartOnFail => Restart.Value; From d80a2dcca72da28a9fac4a6ec3c5abff2d5ddf30 Mon Sep 17 00:00:00 2001 From: PercyDan <50285552+PercyDan54@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:14:01 +0800 Subject: [PATCH 399/600] Missed one --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 2 +- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index c6855a3d38..4425ece513 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods public virtual bool PerformFail() => true; - public virtual bool RestartOnFail => true; + public virtual bool RestartOnFail => Restart.Value; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 68ed112078..031eb716c3 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -23,8 +23,6 @@ namespace osu.Game.Rulesets.Mods public override bool PerformFail() => true; - public override bool RestartOnFail => Restart.Value; - protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type.AffectsCombo() && !result.IsHit; From 6ecc728c0121e4821cf83346e2cf8a5401a6210e Mon Sep 17 00:00:00 2001 From: PercyDan <50285552+PercyDan54@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:27:36 +0800 Subject: [PATCH 400/600] Remove override --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 031eb716c3..1abd353d20 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -21,8 +21,6 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray(); - public override bool PerformFail() => true; - protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type.AffectsCombo() && !result.IsHit; From 97041de09f5230e2fe1d5d9004e74b920be8b42b Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 11:23:12 +0800 Subject: [PATCH 401/600] Preparation for localisation. --- osu.Game/Overlays/Settings/SettingsSection.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 4143605c28..f993a46dc6 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; @@ -19,10 +20,10 @@ namespace osu.Game.Overlays.Settings protected override Container Content => FlowContent; public abstract Drawable CreateIcon(); - public abstract string Header { get; } + public abstract LocalisableString Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public virtual IEnumerable FilterTerms => new[] { Header }; + public virtual IEnumerable FilterTerms => new[] { Header.ToString() }; private const int header_size = 26; private const int margin = 20; From 9a5d4ffd43e1fc2fed39cf03992ff7e503cd5473 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 15:25:08 +0800 Subject: [PATCH 402/600] Add GeneralSettingsStrings --- .../Localisation/GeneralSettingsStrings.cs | 59 +++++++++++++++++++ .../Sections/General/LanguageSettings.cs | 6 +- .../Sections/General/UpdateSettings.cs | 11 ++-- .../Settings/Sections/GeneralSection.cs | 4 +- 4 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 osu.Game/Localisation/GeneralSettingsStrings.cs diff --git a/osu.Game/Localisation/GeneralSettingsStrings.cs b/osu.Game/Localisation/GeneralSettingsStrings.cs new file mode 100644 index 0000000000..19fb8de972 --- /dev/null +++ b/osu.Game/Localisation/GeneralSettingsStrings.cs @@ -0,0 +1,59 @@ +// 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 GeneralSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GeneralSettings"; + + /// + /// "General" + /// + public static LocalisableString GeneralSectionHeader => new TranslatableString(getKey(@"general_section_header"), @"General"); + + /// + /// "Language" + /// + public static LocalisableString LanguageHeader => new TranslatableString(getKey(@"language_header"), @"Language"); + + /// + /// "Language" + /// + public static LocalisableString LanguageDropdown => new TranslatableString(getKey(@"language_dropdown"), @"Language"); + + /// + /// "Prefer metadata in original language" + /// + public static LocalisableString PreferOriginal => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); + + /// + /// "Updates" + /// + public static LocalisableString UpdateHeader => new TranslatableString(getKey(@"update_header"), @"Updates"); + + /// + /// "Release stream" + /// + public static LocalisableString ReleaseStream => new TranslatableString(getKey(@"release_stream"), @"Release stream"); + + /// + /// "Check for updates" + /// + public static LocalisableString CheckUpdate => new TranslatableString(getKey(@"check_update"), @"Check for updates"); + + /// + /// "Open osu! folder" + /// + public static LocalisableString OpenOsuFolder => new TranslatableString(getKey(@"open_osu_folder"), @"Open osu! folder"); + + /// + /// "Change folder location..." + /// + public static LocalisableString ChangeFolderLocation => new TranslatableString(getKey(@"change_folder_location"), @"Change folder location..."); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index c6c752e2fd..ac95a713bf 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.General private SettingsDropdown languageSelection; private Bindable frameworkLocale; - protected override LocalisableString Header => "Language"; + protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader; [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) @@ -27,11 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.General { languageSelection = new SettingsEnumDropdown { - LabelText = "Language", + LabelText = GeneralSettingsStrings.LanguageDropdown, }, new SettingsCheckbox { - LabelText = "Prefer metadata in original language", + LabelText = GeneralSettingsStrings.PreferOriginal, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowUnicode) }, }; diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index dd20e1d7ef..aa37748653 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -9,6 +9,7 @@ using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Updater; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.General [Resolved(CanBeNull = true)] private UpdateManager updateManager { get; set; } - protected override LocalisableString Header => "Updates"; + protected override LocalisableString Header => GeneralSettingsStrings.UpdateHeader; private SettingsButton checkForUpdatesButton; @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Add(new SettingsEnumDropdown { - LabelText = "Release stream", + LabelText = GeneralSettingsStrings.ReleaseStream, Current = config.GetBindable(OsuSetting.ReleaseStream), }); @@ -40,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Add(checkForUpdatesButton = new SettingsButton { - Text = "Check for updates", + Text = GeneralSettingsStrings.CheckUpdate, Action = () => { checkForUpdatesButton.Enabled.Value = false; @@ -65,13 +66,13 @@ namespace osu.Game.Overlays.Settings.Sections.General { Add(new SettingsButton { - Text = "Open osu! folder", + Text = GeneralSettingsStrings.OpenOsuFolder, Action = storage.OpenInNativeExplorer, }); Add(new SettingsButton { - Text = "Change folder location...", + Text = GeneralSettingsStrings.ChangeFolderLocation, Action = () => game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())) }); } diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index fefc3fe6a7..87e9f34833 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.General; namespace osu.Game.Overlays.Settings.Sections { public class GeneralSection : SettingsSection { - public override string Header => "General"; + public override LocalisableString Header => GeneralSettingsStrings.GeneralSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 078953980e65c4639899833556b6cd3969e6fd1c Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 16:48:37 +0800 Subject: [PATCH 403/600] Add GraphicsSettingsStrings --- osu.Game/Localisation/CommonStrings.cs | 7 +- .../Localisation/GraphicsSettingsStrings.cs | 119 ++++++++++++++++++ .../Sections/Graphics/DetailSettings.cs | 11 +- .../Sections/Graphics/LayoutSettings.cs | 25 ++-- .../Sections/Graphics/RendererSettings.cs | 13 +- .../Settings/Sections/GraphicsSection.cs | 4 +- 6 files changed, 152 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Localisation/GraphicsSettingsStrings.cs diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index bf488d2590..5e4ce235b4 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -19,6 +19,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Enabled => new TranslatableString(getKey(@"enabled"), @"Enabled"); + /// + /// "Default" + /// + public static LocalisableString Default => new TranslatableString(getKey(@"default"), @"Default"); + /// /// "Width" /// @@ -31,4 +36,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs new file mode 100644 index 0000000000..841635649e --- /dev/null +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -0,0 +1,119 @@ +// 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 GraphicsSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GraphicsSettings"; + + /// + /// "Graphics" + /// + public static LocalisableString GraphicsSectionHeader => new TranslatableString(getKey(@"graphics_section_header"), @"Graphics"); + + /// + /// "Renderer" + /// + public static LocalisableString RendererHeader => new TranslatableString(getKey(@"renderer_header"), @"Renderer"); + + /// + /// "Frame limiter" + /// + public static LocalisableString FrameLimiter => new TranslatableString(getKey(@"frame_limiter"), @"Frame limiter"); + + /// + /// "Threading mode" + /// + public static LocalisableString ThreadingMode => new TranslatableString(getKey(@"threading_mode"), @"Threading mode"); + + /// + /// "Show FPS" + /// + public static LocalisableString ShowFPS => new TranslatableString(getKey(@"show_fps"), @"Show FPS"); + + /// + /// "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. "2x refresh rate" is recommended." + /// + public static LocalisableString UnlimitedFramesNote => new TranslatableString(getKey(@"unlimited_frames_note"), @"Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. ""2x refresh rate"" is recommended."); + + /// + /// "Layout" + /// + public static LocalisableString LayoutHeader => new TranslatableString(getKey(@"layout_header"), @"Layout"); + + /// + /// "Screen mode" + /// + public static LocalisableString ScreenMode => new TranslatableString(getKey(@"screen_mode"), @"Screen mode"); + + /// + /// "Resolution" + /// + public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution"); + + /// + /// "UI Scaling" + /// + public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI Scaling"); + + /// + /// "Screen Scaling" + /// + public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen Scaling"); + + /// + /// "Horizontal position" + /// + public static LocalisableString HorizontalPosition => new TranslatableString(getKey(@"horizontal_position"), @"Horizontal position"); + + /// + /// "Vertical position" + /// + public static LocalisableString VerticalPosition => new TranslatableString(getKey(@"vertical_position"), @"Vertical position"); + + /// + /// "Horizontal scale" + /// + public static LocalisableString HorizontalScale => new TranslatableString(getKey(@"horizontal_scale"), @"Horizontal scale"); + + /// + /// "Vertical scale" + /// + public static LocalisableString VerticalScale => new TranslatableString(getKey(@"vertical_scale"), @"Vertical scale"); + + /// + /// "Running without fullscreen mode will increase your input latency!" + /// + public static LocalisableString NotFullscreenNote => new TranslatableString(getKey(@"not_fullscreen_note"), @"Running without fullscreen mode will increase your input latency!"); + + /// + /// "Detail Settings" + /// + public static LocalisableString DetailSettingsHeader => new TranslatableString(getKey(@"detail_settings_header"), @"Detail Settings"); + + /// + /// "Storyboard / Video" + /// + public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / Video"); + + /// + /// "Hit Lighting" + /// + public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit Lighting"); + + /// + /// "Screenshot format" + /// + public static LocalisableString ScreenshotFormat => new TranslatableString(getKey(@"screenshot_format"), @"Screenshot format"); + + /// + /// "Show menu cursor in screenshots" + /// + public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@""), @"Show menu cursor in screenshots"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index f889cfca0f..20b1d8d801 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { public class DetailSettings : SettingsSubsection { - protected override LocalisableString Header => "Detail Settings"; + protected override LocalisableString Header => GraphicsSettingsStrings.DetailSettingsHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,22 +20,22 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { new SettingsCheckbox { - LabelText = "Storyboard / Video", + LabelText = GraphicsSettingsStrings.StoryboardVideo, Current = config.GetBindable(OsuSetting.ShowStoryboard) }, new SettingsCheckbox { - LabelText = "Hit Lighting", + LabelText = GraphicsSettingsStrings.HitLighting, Current = config.GetBindable(OsuSetting.HitLighting) }, new SettingsEnumDropdown { - LabelText = "Screenshot format", + LabelText = GraphicsSettingsStrings.ScreenshotFormat, Current = config.GetBindable(OsuSetting.ScreenshotFormat) }, new SettingsCheckbox { - LabelText = "Show menu cursor in screenshots", + LabelText = GraphicsSettingsStrings.ShowCursorInScreenshots, Current = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor) } }; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 91208cb78a..50bd8184ee 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -16,13 +16,14 @@ using osu.Framework.Platform; using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osuTK.Graphics; namespace osu.Game.Overlays.Settings.Sections.Graphics { public class LayoutSettings : SettingsSubsection { - protected override LocalisableString Header => "Layout"; + protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader; private FillFlowContainer> scalingSettings; @@ -67,20 +68,20 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { windowModeDropdown = new SettingsDropdown { - LabelText = "Screen mode", + LabelText = GraphicsSettingsStrings.ScreenMode, ItemSource = windowModes, Current = config.GetBindable(FrameworkSetting.WindowMode), }, resolutionDropdown = new ResolutionSettingsDropdown { - LabelText = "Resolution", + LabelText = GraphicsSettingsStrings.Resolution, ShowsDefaultIndicator = false, ItemSource = resolutions, Current = sizeFullscreen }, new SettingsSlider { - LabelText = "UI Scaling", + LabelText = GraphicsSettingsStrings.UIScaling, TransferValueOnCommit = true, Current = osuConfig.GetBindable(OsuSetting.UIScale), KeyboardStep = 0.01f, @@ -88,7 +89,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, new SettingsEnumDropdown { - LabelText = "Screen Scaling", + LabelText = GraphicsSettingsStrings.ScreenScaling, Current = osuConfig.GetBindable(OsuSetting.Scaling), Keywords = new[] { "scale", "letterbox" }, }, @@ -104,28 +105,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { new SettingsSlider { - LabelText = "Horizontal position", + LabelText = GraphicsSettingsStrings.HorizontalPosition, Current = scalingPositionX, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Vertical position", + LabelText = GraphicsSettingsStrings.VerticalPosition, Current = scalingPositionY, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Horizontal scale", + LabelText = GraphicsSettingsStrings.HorizontalScale, Current = scalingSizeX, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Vertical scale", + LabelText = GraphicsSettingsStrings.VerticalScale, Current = scalingSizeY, KeyboardStep = 0.01f, DisplayAsPercentage = true @@ -145,9 +146,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { updateResolutionDropdown(); - const string not_fullscreen_note = "Running without fullscreen mode will increase your input latency!"; - - windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty; + windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : string.Empty; }, true); windowModes.BindCollectionChanged((sender, args) => @@ -245,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics protected override LocalisableString GenerateItemText(Size item) { if (item == new Size(9999, 9999)) - return "Default"; + return CommonStrings.Default; return $"{item.Width}x{item.Height}"; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 2210c7911e..9747f6b373 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -7,12 +7,13 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { public class RendererSettings : SettingsSubsection { - protected override LocalisableString Header => "Renderer"; + protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader; private SettingsEnumDropdown frameLimiterDropdown; @@ -25,17 +26,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics // TODO: this needs to be a custom dropdown at some point frameLimiterDropdown = new SettingsEnumDropdown { - LabelText = "Frame limiter", + LabelText = GraphicsSettingsStrings.FrameLimiter, Current = config.GetBindable(FrameworkSetting.FrameSync) }, new SettingsEnumDropdown { - LabelText = "Threading mode", + LabelText = GraphicsSettingsStrings.ThreadingMode, Current = config.GetBindable(FrameworkSetting.ExecutionMode) }, new SettingsCheckbox { - LabelText = "Show FPS", + LabelText = GraphicsSettingsStrings.ShowFPS, Current = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; @@ -47,9 +48,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics frameLimiterDropdown.Current.BindValueChanged(limit => { - const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. \"2x refresh rate\" is recommended."; - - frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty; + frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 4ade48031f..fd0718f9f2 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Graphics; namespace osu.Game.Overlays.Settings.Sections { public class GraphicsSection : SettingsSection { - public override string Header => "Graphics"; + public override LocalisableString Header => GraphicsSettingsStrings.GraphicsSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From b2986e99d30a8e638e53047dd3b594343a18e073 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 17:10:08 +0800 Subject: [PATCH 404/600] Add AudioSettingsStrings --- osu.Game/Localisation/AudioSettingsStrings.cs | 64 +++++++++++++++++++ .../Sections/Audio/AudioDevicesSettings.cs | 5 +- .../Settings/Sections/Audio/OffsetSettings.cs | 7 +- .../Settings/Sections/Audio/VolumeSettings.cs | 11 ++-- .../Settings/Sections/AudioSection.cs | 4 +- 5 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Localisation/AudioSettingsStrings.cs diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs new file mode 100644 index 0000000000..aa6eabd7d1 --- /dev/null +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -0,0 +1,64 @@ +// 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 AudioSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.AudioSettings"; + + /// + /// "Audio" + /// + public static LocalisableString AudioSectionHeader => new TranslatableString(getKey(@"audio_section_header"), @"Audio"); + + /// + /// "Devices" + /// + public static LocalisableString AudioDevicesHeader => new TranslatableString(getKey(@"audio_devices_header"), @"Devices"); + + /// + /// "Volume" + /// + public static LocalisableString VolumeHeader => new TranslatableString(getKey(@"volume_header"), @"Volume"); + + /// + /// "Master" + /// + public static LocalisableString MasterVolume => new TranslatableString(getKey(@"master_volume"), @"Master"); + + /// + /// "Master (window inactive)" + /// + public static LocalisableString MasterVolumeInactive => new TranslatableString(getKey(@"master_volume_inactive"), @"Master (window inactive)"); + + /// + /// "Effect" + /// + public static LocalisableString EffectVolume => new TranslatableString(getKey(@"effect_volume"), @"Effect"); + + /// + /// "Music" + /// + public static LocalisableString MusicVolume => new TranslatableString(getKey(@"music_volume"), @"Music"); + + /// + /// "Offset Adjustment" + /// + public static LocalisableString OffsetHeader => new TranslatableString(getKey(@"offset_header"), @"Offset Adjustment"); + + /// + /// "Audio offset" + /// + public static LocalisableString AudioOffset => new TranslatableString(getKey(@"audio_offset"), @"Audio offset"); + + /// + /// "Offset wizard" + /// + public static LocalisableString OffsetWizard => new TranslatableString(getKey(@"offset_wizard"), @"Offset wizard"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index d64f176468..501f1b86b8 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -8,12 +8,13 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { public class AudioDevicesSettings : SettingsSubsection { - protected override LocalisableString Header => "Devices"; + protected override LocalisableString Header => AudioSettingsStrings.AudioDevicesHeader; [Resolved] private AudioManager audio { get; set; } @@ -78,7 +79,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio private class AudioDeviceDropdownControl : DropdownControl { protected override LocalisableString GenerateItemText(string item) - => string.IsNullOrEmpty(item) ? "Default" : base.GenerateItemText(item); + => string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index 7f2e377c83..85973c81c9 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { public class OffsetSettings : SettingsSubsection { - protected override LocalisableString Header => "Offset Adjustment"; + protected override LocalisableString Header => AudioSettingsStrings.OffsetHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -20,13 +21,13 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { new SettingsSlider { - LabelText = "Audio offset", + LabelText = AudioSettingsStrings.AudioOffset, Current = config.GetBindable(OsuSetting.AudioOffset), KeyboardStep = 1f }, new SettingsButton { - Text = "Offset wizard" + Text = AudioSettingsStrings.OffsetWizard } }; } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 8f88b03471..00c1cb8f43 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { public class VolumeSettings : SettingsSubsection { - protected override LocalisableString Header => "Volume"; + protected override LocalisableString Header => AudioSettingsStrings.VolumeHeader; [BackgroundDependencyLoader] private void load(AudioManager audio, OsuConfigManager config) @@ -20,28 +21,28 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { new SettingsSlider { - LabelText = "Master", + LabelText = AudioSettingsStrings.MasterVolume, Current = audio.Volume, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Master (window inactive)", + LabelText = AudioSettingsStrings.MasterVolumeInactive, Current = config.GetBindable(OsuSetting.VolumeInactive), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Effect", + LabelText = AudioSettingsStrings.EffectVolume, Current = audio.VolumeSample, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Music", + LabelText = AudioSettingsStrings.MusicVolume, Current = audio.VolumeTrack, KeyboardStep = 0.01f, DisplayAsPercentage = true diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 7072d8e63d..694da0529a 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -3,15 +3,17 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Localisation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Audio; namespace osu.Game.Overlays.Settings.Sections { public class AudioSection : SettingsSection { - public override string Header => "Audio"; + public override LocalisableString Header => AudioSettingsStrings.AudioSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 2cc89f50cce503ed8ecd3a86206b8cd6a50660ea Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 09:14:49 +0800 Subject: [PATCH 405/600] Add missing key --- osu.Game/Localisation/GraphicsSettingsStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 841635649e..989eaf19b9 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -112,7 +112,7 @@ namespace osu.Game.Localisation /// /// "Show menu cursor in screenshots" /// - public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@""), @"Show menu cursor in screenshots"); + public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@"show_cursor_in_screenshots"), @"Show menu cursor in screenshots"); private static string getKey(string key) => $"{prefix}:{key}"; } From 03013d0d307480f3589714dd4b6043555fb4943d Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 09:53:31 +0800 Subject: [PATCH 406/600] Add InputSettingsStrings Existed strings files keep no change --- osu.Game/Localisation/CommonStrings.cs | 5 ++ osu.Game/Localisation/InputSettingsStrings.cs | 59 +++++++++++++++++++ .../Input/GlobalKeyBindingsSection.cs | 11 ++-- .../Sections/Input/KeyBindingPanel.cs | 3 +- .../Settings/Sections/Input/KeyBindingRow.cs | 5 +- .../Sections/Input/KeyBindingsSubsection.cs | 3 +- .../Sections/Input/RulesetBindingsSection.cs | 3 +- .../Settings/Sections/InputSection.cs | 5 +- 8 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 osu.Game/Localisation/InputSettingsStrings.cs diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 5e4ce235b4..432c1c6255 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -14,6 +14,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Cancel => new TranslatableString(getKey(@"cancel"), @"Cancel"); + /// + /// "Clear" + /// + public static LocalisableString Clear => new TranslatableString(getKey(@"clear"), @"Clear"); + /// /// "Enabled" /// diff --git a/osu.Game/Localisation/InputSettingsStrings.cs b/osu.Game/Localisation/InputSettingsStrings.cs new file mode 100644 index 0000000000..e46b4cecf3 --- /dev/null +++ b/osu.Game/Localisation/InputSettingsStrings.cs @@ -0,0 +1,59 @@ +// 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 InputSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.InputSettings"; + + /// + /// "Input" + /// + public static LocalisableString InputSectionHeader => new TranslatableString(getKey(@"input_section_header"), @"Input"); + + /// + /// "Global" + /// + public static LocalisableString GlobalKeyBindingHeader => new TranslatableString(getKey(@"global_key_binding_header"), @"Global"); + + /// + /// "Song Select" + /// + public static LocalisableString SongSelectSection => new TranslatableString(getKey(@"song_select_section"), @"Song Select"); + + /// + /// "In Game" + /// + public static LocalisableString InGameSection => new TranslatableString(getKey(@"in_game_section"), @"In Game"); + + /// + /// "Audio" + /// + public static LocalisableString AudioSection => new TranslatableString(getKey(@"audio_section"), @"Audio"); + + /// + /// "Editor" + /// + public static LocalisableString EditorSection => new TranslatableString(getKey(@"editor_section"), @"Editor"); + + /// + /// "Reset all bindings in section" + /// + public static LocalisableString ResetSectionButton => new TranslatableString(getKey(@"reset_section_button"), @"Reset all bindings in section"); + + /// + /// "key configuration" + /// + public static LocalisableString KeyBindingPanelHeader => new TranslatableString(getKey(@"key_binding_panel_header"), @"key configuration"); + + /// + /// "Customise your keys!" + /// + public static LocalisableString KeyBindingPanelDescription => new TranslatableString(getKey(@"key_binding_panel_description"), @"Customise your keys!"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs index 9898a50320..3350ff4eaa 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Input.Bindings; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { @@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Icon = FontAwesome.Solid.Globe }; - public override string Header => "Global"; + public override LocalisableString Header => InputSettingsStrings.GlobalKeyBindingHeader; public GlobalKeyBindingsSection(GlobalActionContainer manager) { @@ -39,7 +40,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class SongSelectKeyBindingSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "Song Select"; + protected override LocalisableString Header => InputSettingsStrings.SongSelectSection; public SongSelectKeyBindingSubsection(GlobalActionContainer manager) : base(null) @@ -50,7 +51,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class InGameKeyBindingsSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "In Game"; + protected override LocalisableString Header => InputSettingsStrings.InGameSection; public InGameKeyBindingsSubsection(GlobalActionContainer manager) : base(null) @@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "Audio"; + protected override LocalisableString Header => InputSettingsStrings.AudioSection; public AudioControlKeyBindingsSubsection(GlobalActionContainer manager) : base(null) @@ -72,7 +73,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class EditorKeyBindingsSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "Editor"; + protected override LocalisableString Header => InputSettingsStrings.EditorSection; public EditorKeyBindingsSubsection(GlobalActionContainer manager) : base(null) diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs index 7cdc739b7c..67f1bb8d3e 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs @@ -4,13 +4,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections.Input { public class KeyBindingPanel : SettingsSubPanel { - protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); + protected override Drawable CreateHeader() => new SettingsHeader(InputSettingsStrings.KeyBindingPanelHeader, InputSettingsStrings.KeyBindingPanelDescription); [BackgroundDependencyLoader(permitNulls: true)] private void load(RulesetStore rulesets, GlobalActionContainer global) diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 6e018597be..c38c516f21 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -20,6 +20,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -385,7 +386,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public CancelButton() { - Text = "Cancel"; + Text = CommonStrings.Cancel; Size = new Vector2(80, 20); } } @@ -394,7 +395,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public ClearButton() { - Text = "Clear"; + Text = CommonStrings.Clear; Size = new Vector2(80, 20); } } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index d65684fd37..ef5ccae1a0 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -10,6 +10,7 @@ using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Rulesets; +using osu.Game.Localisation; using osuTK; namespace osu.Game.Overlays.Settings.Sections.Input @@ -64,7 +65,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input [BackgroundDependencyLoader] private void load() { - Text = "Reset all bindings in section"; + Text = InputSettingsStrings.ResetSectionButton; RelativeSizeAxes = Axes.X; Width = 0.5f; Anchor = Anchor.TopCentre; diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 81a4d7eccd..5246051a4a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Rulesets; @@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Icon = OsuIcon.Hot }; - public override string Header => ruleset.Name; + public override LocalisableString Header => ruleset.Name; private readonly RulesetInfo ruleset; diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 366f39388a..d282ba5318 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Platform; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Input; namespace osu.Game.Overlays.Settings.Sections @@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections { private readonly KeyBindingPanel keyConfig; - public override string Header => "Input"; + public override LocalisableString Header => InputSettingsStrings.InputSectionHeader; [Resolved] private GameHost host { get; set; } @@ -95,7 +96,7 @@ namespace osu.Game.Overlays.Settings.Sections { new SettingsCheckbox { - LabelText = "Enabled", + LabelText = CommonStrings.Enabled, Current = handler.Enabled }, }; From 7adf2bb64c3be39f920cb074781fe032af3d0e9b Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 10:48:29 +0800 Subject: [PATCH 407/600] Add UserInterfaceStrings --- osu.Game/Localisation/UserInterfaceStrings.cs | 114 ++++++++++++++++++ .../Sections/UserInterface/GeneralSettings.cs | 11 +- .../UserInterface/MainMenuSettings.cs | 17 ++- .../UserInterface/SongSelectSettings.cs | 15 +-- .../Settings/Sections/UserInterfaceSection.cs | 4 +- 5 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 osu.Game/Localisation/UserInterfaceStrings.cs diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs new file mode 100644 index 0000000000..18a9257732 --- /dev/null +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -0,0 +1,114 @@ +// 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 UserInterfaceStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.UserInterface"; + + /// + /// "User Interface" + /// + public static LocalisableString UserInterfaceSectionHeader => new TranslatableString(getKey(@"user_interface_section_header"), @"User Interface"); + + /// + /// "General" + /// + public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General"); + + /// + /// "Rotate cursor when dragging" + /// + public static LocalisableString CursorRotation => new TranslatableString(getKey(@"cursor_rotation"), @"Rotate cursor when dragging"); + + /// + /// "Menu cursor size" + /// + public static LocalisableString MenuCursorSize => new TranslatableString(getKey(@"menu_cursor_size"), @"Menu cursor size"); + + /// + /// "Parallax" + /// + public static LocalisableString Parallax => new TranslatableString(getKey(@"parallax"), @"Parallax"); + + /// + /// "Hold-to-confirm activation time" + /// + public static LocalisableString HoldActivationDelay => new TranslatableString(getKey(@"hold_activation_delay"), @"Hold-to-confirm activation time"); + + /// + /// "Main Menu" + /// + public static LocalisableString MainMenuHeader => new TranslatableString(getKey(@"main_menu_header"), @"Main Menu"); + + /// + /// "Interface voices" + /// + public static LocalisableString InterfaceVoices => new TranslatableString(getKey(@"interface_voices"), @"Interface voices"); + + /// + /// "osu! music theme" + /// + public static LocalisableString OsuMusicTheme => new TranslatableString(getKey(@"osu_music_theme"), @"osu! music theme"); + + /// + /// "Intro sequence" + /// + public static LocalisableString IntroSequence => new TranslatableString(getKey(@"intro_sequence"), @"Intro sequence"); + + /// + /// "Background source" + /// + public static LocalisableString BackgroundSource => new TranslatableString(getKey(@"background_source"), @"Background source"); + + /// + /// "Seasonal backgrounds" + /// + public static LocalisableString SeasonalBackgrounds => new TranslatableString(getKey(@"seasonal_backgrounds"), @"Seasonal backgrounds"); + + /// + /// "Changes to this setting will only apply with an active osu!supporter tag." + /// + public static LocalisableString NotSupporterNote => new TranslatableString(getKey(@"not_supporter_note"), @"Changes to this setting will only apply with an active osu!supporter tag."); + + /// + /// "Song Select" + /// + public static LocalisableString SoneSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select"); + + /// + /// "Right mouse drag to absolute scroll" + /// + public static LocalisableString RightMouseScroll => new TranslatableString(getKey(@"right_mouse_scroll"), @"Right mouse drag to absolute scroll"); + + /// + /// "Show converted beatmaps" + /// + public static LocalisableString ShowConvertedBeatmaps => new TranslatableString(getKey(@"show_converted_beatmaps"), @"Show converted beatmaps"); + + /// + /// "Display beatmaps from" + /// + public static LocalisableString StarsMinimum => new TranslatableString(getKey(@"stars_minimum"), @"Display beatmaps from"); + + /// + /// "up to" + /// + public static LocalisableString StarsMaximum => new TranslatableString(getKey(@"stars_maximum"), @"up to"); + + /// + /// "Random selection algorithm" + /// + public static LocalisableString RandomSelectionAlgorithm => new TranslatableString(getKey(@"random_selection_algorithm"), @"Random selection algorithm"); + + /// + /// "no limit" + /// + public static LocalisableString NoLimit => new TranslatableString(getKey(@"no_limit"), @"no limit"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 4b26645ef3..b26363a9da 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.UserInterface { public class GeneralSettings : SettingsSubsection { - protected override LocalisableString Header => "General"; + protected override LocalisableString Header => UserInterfaceStrings.GeneralHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -20,23 +21,23 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - LabelText = "Rotate cursor when dragging", + LabelText = UserInterfaceStrings.CursorRotation, Current = config.GetBindable(OsuSetting.CursorRotation) }, new SettingsSlider { - LabelText = "Menu cursor size", + LabelText = UserInterfaceStrings.MenuCursorSize, Current = config.GetBindable(OsuSetting.MenuCursorSize), KeyboardStep = 0.01f }, new SettingsCheckbox { - LabelText = "Parallax", + LabelText = UserInterfaceStrings.Parallax, Current = config.GetBindable(OsuSetting.MenuParallax) }, new SettingsSlider { - LabelText = "Hold-to-confirm activation time", + LabelText = UserInterfaceStrings.HoldActivationDelay, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), KeyboardStep = 50 }, diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 81bbcbb54a..976893bf0a 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Users; @@ -13,7 +14,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { public class MainMenuSettings : SettingsSubsection { - protected override LocalisableString Header => "Main Menu"; + protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader; private IBindable user; @@ -28,27 +29,27 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - LabelText = "Interface voices", + LabelText = UserInterfaceStrings.InterfaceVoices, Current = config.GetBindable(OsuSetting.MenuVoice) }, new SettingsCheckbox { - LabelText = "osu! music theme", + LabelText = UserInterfaceStrings.OsuMusicTheme, Current = config.GetBindable(OsuSetting.MenuMusic) }, new SettingsEnumDropdown { - LabelText = "Intro sequence", + LabelText = UserInterfaceStrings.IntroSequence, Current = config.GetBindable(OsuSetting.IntroSequence), }, backgroundSourceDropdown = new SettingsEnumDropdown { - LabelText = "Background source", + LabelText = UserInterfaceStrings.BackgroundSource, Current = config.GetBindable(OsuSetting.MenuBackgroundSource), }, new SettingsEnumDropdown { - LabelText = "Seasonal backgrounds", + LabelText = UserInterfaceStrings.SeasonalBackgrounds, Current = config.GetBindable(OsuSetting.SeasonalBackgroundMode), } }; @@ -60,9 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface user.BindValueChanged(u => { - const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; - - backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? not_supporter_note : string.Empty; + backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 587155eb0d..8596cecbb8 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.UserInterface { @@ -16,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface private Bindable minStars; private Bindable maxStars; - protected override LocalisableString Header => "Song Select"; + protected override LocalisableString Header => UserInterfaceStrings.SoneSelectHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -31,31 +32,31 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - LabelText = "Right mouse drag to absolute scroll", + LabelText = UserInterfaceStrings.RightMouseScroll, Current = config.GetBindable(OsuSetting.SongSelectRightMouseScroll), }, new SettingsCheckbox { - LabelText = "Show converted beatmaps", + LabelText = UserInterfaceStrings.ShowConvertedBeatmaps, Current = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), }, new SettingsSlider { - LabelText = "Display beatmaps from", + LabelText = UserInterfaceStrings.StarsMinimum, Current = config.GetBindable(OsuSetting.DisplayStarsMinimum), KeyboardStep = 0.1f, Keywords = new[] { "minimum", "maximum", "star", "difficulty" } }, new SettingsSlider { - LabelText = "up to", + LabelText = UserInterfaceStrings.StarsMaximum, Current = config.GetBindable(OsuSetting.DisplayStarsMaximum), KeyboardStep = 0.1f, Keywords = new[] { "minimum", "maximum", "star", "difficulty" } }, new SettingsEnumDropdown { - LabelText = "Random selection algorithm", + LabelText = UserInterfaceStrings.RandomSelectionAlgorithm, Current = config.GetBindable(OsuSetting.RandomSelectAlgorithm), } }; @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface private class MaximumStarsSlider : StarsSlider { - public override LocalisableString TooltipText => Current.IsDefault ? "no limit" : base.TooltipText; + public override LocalisableString TooltipText => Current.IsDefault ? UserInterfaceStrings.NoLimit : base.TooltipText; } private class StarsSlider : OsuSliderBar diff --git a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs index 718fea5f2b..6228c4c99a 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.UserInterface; namespace osu.Game.Overlays.Settings.Sections { public class UserInterfaceSection : SettingsSection { - public override string Header => "User Interface"; + public override LocalisableString Header => UserInterfaceStrings.UserInterfaceSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 31ffaf15d4866275f1c86c0dbecd67af5eba59ff Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 11:11:22 +0800 Subject: [PATCH 408/600] Add GameplaySettingsStrings --- .../Localisation/GameplaySettingsStrings.cs | 95 +++++++++++++++++++ .../Sections/Gameplay/GeneralSettings.cs | 27 +++--- .../Sections/Gameplay/ModsSettings.cs | 5 +- .../Settings/Sections/GameplaySection.cs | 4 +- 4 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Localisation/GameplaySettingsStrings.cs diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs new file mode 100644 index 0000000000..172387bbb8 --- /dev/null +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -0,0 +1,95 @@ +// 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 GameplaySettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GameplaySettings"; + + /// + /// "Gameplay" + /// + public static LocalisableString GameplaySectionHeader => new TranslatableString(getKey(@"gameplay_section_header"), @"Gameplay"); + + /// + /// "General" + /// + public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General"); + + /// + /// "Background dim" + /// + public static LocalisableString Dim => new TranslatableString(getKey(@"dim"), @"Background dim"); + + /// + /// "Background blur" + /// + public static LocalisableString Blur => new TranslatableString(getKey(@"blur"), @"Background blur"); + + /// + /// "Lighten playfield during breaks" + /// + public static LocalisableString LightenDuringBreaks => new TranslatableString(getKey(@"lighten_during_breaks"), @"Lighten playfield during breaks"); + + /// + /// "HUD overlay visibility mode" + /// + public static LocalisableString HUDVisibilityMode => new TranslatableString(getKey(@"hud_visibility_mode"), @"HUD overlay visibility mode"); + + /// + /// "Show difficulty graph on progress bar" + /// + public static LocalisableString ShowProgressGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); + + /// + /// "Show health display even when you can't fail" + /// + public static LocalisableString ShowHealthDisplayWhenCantFail => new TranslatableString(getKey(@"show_health_display_when_cant_fail"), @"Show health display even when you can't fail"); + + /// + /// "Fade playfield to red when health is low" + /// + public static LocalisableString FadePlayfieldWhenHealthLow => new TranslatableString(getKey(@"fade_playfield_when_health_low"), @"Fade playfield to red when health is low"); + + /// + /// "Always show key overlay" + /// + public static LocalisableString KeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay"); + + /// + /// "Positional hitsounds" + /// + public static LocalisableString PositionalHitsounds => new TranslatableString(getKey(@"positional_hitsounds"), @"Positional hitsounds"); + + /// + /// "Always play first combo break sound" + /// + public static LocalisableString AlwaysPlayFirstComboBreak => new TranslatableString(getKey(@"always_play_first_combo_break"), @"Always play first combo break sound"); + + /// + /// "Score display mode" + /// + public static LocalisableString ScoreDisplayMode => new TranslatableString(getKey(@"score_display_mode"), @"Score display mode"); + + /// + /// "Disable Windows key during gameplay" + /// + public static LocalisableString DisableWinKey => new TranslatableString(getKey(@"disable_win_key"), @"Disable Windows key during gameplay"); + + /// + /// "Mods" + /// + public static LocalisableString ModsHeader => new TranslatableString(getKey(@"mods_header"), @"Mods"); + + /// + /// "Increase visibility of first object when visual impairment mods are enabled" + /// + public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled"); + + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 353292606f..efb586fdca 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -6,13 +6,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Rulesets.Scoring; namespace osu.Game.Overlays.Settings.Sections.Gameplay { public class GeneralSettings : SettingsSubsection { - protected override LocalisableString Header => "General"; + protected override LocalisableString Header => GameplaySettingsStrings.GeneralHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -21,62 +22,62 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsSlider { - LabelText = "Background dim", + LabelText = GameplaySettingsStrings.Dim, Current = config.GetBindable(OsuSetting.DimLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Background blur", + LabelText = GameplaySettingsStrings.Blur, Current = config.GetBindable(OsuSetting.BlurLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsCheckbox { - LabelText = "Lighten playfield during breaks", + LabelText = GameplaySettingsStrings.LightenDuringBreaks, Current = config.GetBindable(OsuSetting.LightenDuringBreaks) }, new SettingsEnumDropdown { - LabelText = "HUD overlay visibility mode", + LabelText = GameplaySettingsStrings.HUDVisibilityMode, Current = config.GetBindable(OsuSetting.HUDVisibilityMode) }, new SettingsCheckbox { - LabelText = "Show difficulty graph on progress bar", + LabelText = GameplaySettingsStrings.ShowProgressGraph, Current = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox { - LabelText = "Show health display even when you can't fail", + LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, Current = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), Keywords = new[] { "hp", "bar" } }, new SettingsCheckbox { - LabelText = "Fade playfield to red when health is low", + LabelText = GameplaySettingsStrings.FadePlayfieldWhenHealthLow, Current = config.GetBindable(OsuSetting.FadePlayfieldWhenHealthLow), }, new SettingsCheckbox { - LabelText = "Always show key overlay", + LabelText = GameplaySettingsStrings.KeyOverlay, Current = config.GetBindable(OsuSetting.KeyOverlay) }, new SettingsCheckbox { - LabelText = "Positional hitsounds", + LabelText = GameplaySettingsStrings.PositionalHitsounds, Current = config.GetBindable(OsuSetting.PositionalHitSounds) }, new SettingsCheckbox { - LabelText = "Always play first combo break sound", + LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak, Current = config.GetBindable(OsuSetting.AlwaysPlayFirstComboBreak) }, new SettingsEnumDropdown { - LabelText = "Score display mode", + LabelText = GameplaySettingsStrings.ScoreDisplayMode, Current = config.GetBindable(OsuSetting.ScoreDisplayMode), Keywords = new[] { "scoring" } }, @@ -86,7 +87,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Add(new SettingsCheckbox { - LabelText = "Disable Windows key during gameplay", + LabelText = GameplaySettingsStrings.DisableWinKey, Current = config.GetBindable(OsuSetting.GameplayDisableWinKey) }); } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index ec9ddde2da..dfa060e8d5 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -6,12 +6,13 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { public class ModsSettings : SettingsSubsection { - protected override LocalisableString Header => "Mods"; + protected override LocalisableString Header => GameplaySettingsStrings.ModsHeader; public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "mod" }); @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsCheckbox { - LabelText = "Increase visibility of first object when visual impairment mods are enabled", + LabelText = GameplaySettingsStrings.IncreaseFirstObjectVisibility, Current = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), }, }; diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index acb94a6a01..42d9d48d73 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -9,12 +9,14 @@ using osu.Game.Rulesets; using System.Linq; using osu.Framework.Graphics.Sprites; using osu.Framework.Logging; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections { public class GameplaySection : SettingsSection { - public override string Header => "Gameplay"; + public override LocalisableString Header => GameplaySettingsStrings.GameplaySectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 61502e977afcaa4731fb8d6f2b3d2f6c46eb11b8 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 11:40:22 +0800 Subject: [PATCH 409/600] Add SkinSettingsStrings --- osu.Game/Localisation/SkinSettingsStrings.cs | 54 +++++++++++++++++++ .../Overlays/Settings/Sections/SkinSection.cs | 17 +++--- 2 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Localisation/SkinSettingsStrings.cs diff --git a/osu.Game/Localisation/SkinSettingsStrings.cs b/osu.Game/Localisation/SkinSettingsStrings.cs new file mode 100644 index 0000000000..848c01b93a --- /dev/null +++ b/osu.Game/Localisation/SkinSettingsStrings.cs @@ -0,0 +1,54 @@ +// 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 SkinSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.SkinSettings"; + + /// + /// "Skin" + /// + public static LocalisableString SkinSectionHeader => new TranslatableString(getKey(@"skin_section_header"), @"Skin"); + + /// + /// "Skin layout editor" + /// + public static LocalisableString SkinLayoutEditor => new TranslatableString(getKey(@"skin_layout_editor"), @"Skin layout editor"); + + /// + /// "Gameplay cursor size" + /// + public static LocalisableString CursorSize => new TranslatableString(getKey(@"cursor_size"), @"Gameplay cursor size"); + + /// + /// "Adjust gameplay cursor size based on current beatmap" + /// + public static LocalisableString AutoCursorSize => new TranslatableString(getKey(@"auto_cursor_size"), @"Adjust gameplay cursor size based on current beatmap"); + + /// + /// "Beatmap skins" + /// + public static LocalisableString BeatmapSkins => new TranslatableString(getKey(@"beatmap_skins"), @"Beatmap skins"); + + /// + /// "Beatmap colours" + /// + public static LocalisableString BeatmapColours => new TranslatableString(getKey(@"beatmap_colours"), @"Beatmap colours"); + + /// + /// "Beatmap hitsounds" + /// + public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds"); + + /// + /// "Export selected skin" + /// + public static LocalisableString ExportSkinButton => new TranslatableString(getKey(@"export_skin_button"), @"Export selected skin"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 9f3543d059..007302c584 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -13,6 +13,7 @@ using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Skinning; using osu.Game.Skinning.Editor; using osuTK; @@ -23,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections { private SkinSettingsDropdown skinDropdown; - public override string Header => "Skin"; + public override LocalisableString Header => SkinSettingsStrings.SkinSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { @@ -69,34 +70,34 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown = new SkinSettingsDropdown(), new SettingsButton { - Text = "Skin layout editor", + Text = SkinSettingsStrings.SkinLayoutEditor, Action = () => skinEditor?.Toggle(), }, new ExportSkinButton(), new SettingsSlider { - LabelText = "Gameplay cursor size", + LabelText = SkinSettingsStrings.CursorSize, Current = config.GetBindable(OsuSetting.GameplayCursorSize), KeyboardStep = 0.01f }, new SettingsCheckbox { - LabelText = "Adjust gameplay cursor size based on current beatmap", + LabelText = SkinSettingsStrings.AutoCursorSize, Current = config.GetBindable(OsuSetting.AutoCursorSize) }, new SettingsCheckbox { - LabelText = "Beatmap skins", + LabelText = SkinSettingsStrings.BeatmapSkins, Current = config.GetBindable(OsuSetting.BeatmapSkins) }, new SettingsCheckbox { - LabelText = "Beatmap colours", + LabelText = SkinSettingsStrings.BeatmapColours, Current = config.GetBindable(OsuSetting.BeatmapColours) }, new SettingsCheckbox { - LabelText = "Beatmap hitsounds", + LabelText = SkinSettingsStrings.BeatmapHitsounds, Current = config.GetBindable(OsuSetting.BeatmapHitsounds) }, }; @@ -200,7 +201,7 @@ namespace osu.Game.Overlays.Settings.Sections [BackgroundDependencyLoader] private void load() { - Text = "Export selected skin"; + Text = SkinSettingsStrings.ExportSkinButton; Action = export; currentSkin = skins.CurrentSkin.GetBoundCopy(); From 9d391ad13817df8a81c5733fa7ee4f759852e095 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 11:57:51 +0800 Subject: [PATCH 410/600] Add OnlineSettingsStrings --- .../Localisation/OnlineSettingsStrings.cs | 69 +++++++++++++++++++ .../Online/AlertsAndPrivacySettings.cs | 7 +- .../Sections/Online/IntegrationSettings.cs | 5 +- .../Settings/Sections/Online/WebSettings.cs | 11 +-- .../Settings/Sections/OnlineSection.cs | 4 +- 5 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Localisation/OnlineSettingsStrings.cs diff --git a/osu.Game/Localisation/OnlineSettingsStrings.cs b/osu.Game/Localisation/OnlineSettingsStrings.cs new file mode 100644 index 0000000000..0ef98a720c --- /dev/null +++ b/osu.Game/Localisation/OnlineSettingsStrings.cs @@ -0,0 +1,69 @@ +// 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 OnlineSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.OnlineSettings"; + + /// + /// "Online" + /// + public static LocalisableString OnlineSectionHeader => new TranslatableString(getKey(@"online_section_header"), @"Online"); + + /// + /// "Alerts and Privacy" + /// + public static LocalisableString AlertsAndPrivacyHeader => new TranslatableString(getKey(@"alerts_and_privacy_header"), @"Alerts and Privacy"); + + /// + /// "Show a notification when someone mentions your name" + /// + public static LocalisableString NotifyOnMentioned => new TranslatableString(getKey(@"notify_on_mentioned"), @"Show a notification when someone mentions your name"); + + /// + /// "Show a notification when you receive a private message" + /// + public static LocalisableString NotifyOnPM => new TranslatableString(getKey(@"notify_on_pm"), @"Show a notification when you receive a private message"); + + /// + /// "Integrations" + /// + public static LocalisableString IntegrationHeader => new TranslatableString(getKey(@"integration_header"), @"Integrations"); + + /// + /// "Discord Rich Presence" + /// + public static LocalisableString DiscordRichPresence => new TranslatableString(getKey(@"discord_rich_presence"), @"Discord Rich Presence"); + + /// + /// "Web" + /// + public static LocalisableString WebHeader => new TranslatableString(getKey(@"web_header"), @"Web"); + + /// + /// "Warn about opening external links" + /// + public static LocalisableString ExternalLinkWarning => new TranslatableString(getKey(@"external_link_warning"), @"Warn about opening external links"); + + /// + /// "Prefer downloads without video" + /// + public static LocalisableString PreferNoVideo => new TranslatableString(getKey(@"prefer_no_video"), @"Prefer downloads without video"); + + /// + /// "Automatically download beatmaps when spectating" + /// + public static LocalisableString AutomaticallyDownload => new TranslatableString(getKey(@"automatically_download"), @"Automatically download beatmaps when spectating"); + + /// + /// "Show explicit content in search results" + /// + public static LocalisableString ShowExplicitContent => new TranslatableString(getKey(@"show_explicit_content"), @"Show explicit content in search results"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 3a2de2ee36..1728b565c2 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { public class AlertsAndPrivacySettings : SettingsSubsection { - protected override LocalisableString Header => "Alerts and Privacy"; + protected override LocalisableString Header => OnlineSettingsStrings.AlertsAndPrivacyHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,12 +20,12 @@ namespace osu.Game.Overlays.Settings.Sections.Online { new SettingsCheckbox { - LabelText = "Show a notification when someone mentions your name", + LabelText = OnlineSettingsStrings.NotifyOnMentioned, Current = config.GetBindable(OsuSetting.NotifyOnUsernameMentioned) }, new SettingsCheckbox { - LabelText = "Show a notification when you receive a private message", + LabelText = OnlineSettingsStrings.NotifyOnPM, Current = config.GetBindable(OsuSetting.NotifyOnPrivateMessage) }, }; diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index f2012f0d9c..f2a516feef 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { public class IntegrationSettings : SettingsSubsection { - protected override LocalisableString Header => "Integrations"; + protected override LocalisableString Header => OnlineSettingsStrings.IntegrationHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online { new SettingsEnumDropdown { - LabelText = "Discord Rich Presence", + LabelText = OnlineSettingsStrings.DiscordRichPresence, Current = config.GetBindable(OsuSetting.DiscordRichPresence) } }; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 89e7b096f3..4200ddda3d 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { public class WebSettings : SettingsSubsection { - protected override LocalisableString Header => "Web"; + protected override LocalisableString Header => OnlineSettingsStrings.WebHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,24 +20,24 @@ namespace osu.Game.Overlays.Settings.Sections.Online { new SettingsCheckbox { - LabelText = "Warn about opening external links", + LabelText = OnlineSettingsStrings.ExternalLinkWarning, Current = config.GetBindable(OsuSetting.ExternalLinkWarning) }, new SettingsCheckbox { - LabelText = "Prefer downloads without video", + LabelText = OnlineSettingsStrings.PreferNoVideo, Keywords = new[] { "no-video" }, Current = config.GetBindable(OsuSetting.PreferNoVideo) }, new SettingsCheckbox { - LabelText = "Automatically download beatmaps when spectating", + LabelText = OnlineSettingsStrings.AutomaticallyDownload, Keywords = new[] { "spectator" }, Current = config.GetBindable(OsuSetting.AutomaticallyDownloadWhenSpectating), }, new SettingsCheckbox { - LabelText = "Show explicit content in search results", + LabelText = OnlineSettingsStrings.ShowExplicitContent, Keywords = new[] { "nsfw", "18+", "offensive" }, Current = config.GetBindable(OsuSetting.ShowOnlineExplicitContent), } diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 680d11f7da..8b523b90b9 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Online; namespace osu.Game.Overlays.Settings.Sections { public class OnlineSection : SettingsSection { - public override string Header => "Online"; + public override LocalisableString Header => OnlineSettingsStrings.OnlineSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From ac52b891489afc591ee4d5b08c54547c5c43de52 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 12:26:42 +0800 Subject: [PATCH 411/600] Add Maintenance and Debug SettingsStrings --- osu.Game/Localisation/DebugSettingsStrings.cs | 49 ++++++++++++ .../MaintenanceSettingsStrings.cs | 74 +++++++++++++++++++ .../Sections/Debug/GeneralSettings.cs | 9 ++- .../Settings/Sections/Debug/MemorySettings.cs | 5 +- .../Settings/Sections/DebugSection.cs | 4 +- .../Maintenance/DirectorySelectScreen.cs | 3 +- .../Sections/Maintenance/GeneralSettings.cs | 21 +++--- .../Settings/Sections/MaintenanceSection.cs | 4 +- 8 files changed, 150 insertions(+), 19 deletions(-) create mode 100644 osu.Game/Localisation/DebugSettingsStrings.cs create mode 100644 osu.Game/Localisation/MaintenanceSettingsStrings.cs diff --git a/osu.Game/Localisation/DebugSettingsStrings.cs b/osu.Game/Localisation/DebugSettingsStrings.cs new file mode 100644 index 0000000000..dd21739096 --- /dev/null +++ b/osu.Game/Localisation/DebugSettingsStrings.cs @@ -0,0 +1,49 @@ +// 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 DebugSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.DebugSettings"; + + /// + /// "Debug" + /// + public static LocalisableString DebugSectionHeader => new TranslatableString(getKey(@"debug_section_header"), @"Debug"); + + /// + /// "General" + /// + public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General"); + + /// + /// "Show log overlay" + /// + public static LocalisableString ShowLogOverlay => new TranslatableString(getKey(@"show_log_overlay"), @"Show log overlay"); + + /// + /// "Bypass front-to-back render pass" + /// + public static LocalisableString BypassFrontToBackPass => new TranslatableString(getKey(@"bypass_front_to_back_pass"), @"Bypass front-to-back render pass"); + + /// + /// "Import files" + /// + public static LocalisableString ImportFiles => new TranslatableString(getKey(@"import_files"), @"Import files"); + + /// + /// "Memory" + /// + public static LocalisableString MemoryHeader => new TranslatableString(getKey(@"memory_header"), @"Memory"); + + /// + /// "Clear all caches" + /// + public static LocalisableString ClearAllCaches => new TranslatableString(getKey(@"clear_all_caches"), @"Clear all caches"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Localisation/MaintenanceSettingsStrings.cs b/osu.Game/Localisation/MaintenanceSettingsStrings.cs new file mode 100644 index 0000000000..a0e1a9ddab --- /dev/null +++ b/osu.Game/Localisation/MaintenanceSettingsStrings.cs @@ -0,0 +1,74 @@ +// 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 MaintenanceSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.MaintenanceSettings"; + + /// + /// "Maintenance" + /// + public static LocalisableString MaintenanceSectionHeader => new TranslatableString(getKey(@"maintenance_section_header"), @"Maintenance"); + + /// + /// "Select directory" + /// + public static LocalisableString SelectDirectory => new TranslatableString(getKey(@"select_directory"), @"Select directory"); + + /// + /// "Import beatmaps from stable" + /// + public static LocalisableString ImportBeatmapsFromStable => new TranslatableString(getKey(@"import_beatmaps_from_stable"), @"Import beatmaps from stable"); + + /// + /// "Delete ALL beatmaps" + /// + public static LocalisableString DeleteAllBeatmaps => new TranslatableString(getKey(@"delete_all_beatmaps"), @"Delete ALL beatmaps"); + + /// + /// "Import scores from stable" + /// + public static LocalisableString ImportScoresFromStable => new TranslatableString(getKey(@"import_scores_from_stable"), @"Import scores from stable"); + + /// + /// "Delete ALL scores" + /// + public static LocalisableString DeleteAllScores => new TranslatableString(getKey(@"delete_all_scores"), @"Delete ALL scores"); + + /// + /// "Import skins from stable" + /// + public static LocalisableString ImportSkinsFromStable => new TranslatableString(getKey(@"import_skins_from_stable"), @"Import skins from stable"); + + /// + /// "Delete ALL skins" + /// + public static LocalisableString DeleteAllSkins => new TranslatableString(getKey(@"delete_all_skins"), @"Delete ALL skins"); + + /// + /// "Import collections from stable" + /// + public static LocalisableString ImportCollectionsFromStable => new TranslatableString(getKey(@"import_collections_from_stable"), @"Import collections from stable"); + + /// + /// "Delete ALL collections" + /// + public static LocalisableString DeleteAllCollections => new TranslatableString(getKey(@"delete_all_collections"), @"Delete ALL collections"); + + /// + /// "Restore all hidden difficulties" + /// + public static LocalisableString RestoreAllHiddenDifficulties => new TranslatableString(getKey(@"restore_all_hidden_difficulties"), @"Restore all hidden difficulties"); + + /// + /// "Restore all recently deleted beatmaps" + /// + public static LocalisableString RestoreAllRecentlyDeletedBeatmaps => new TranslatableString(getKey(@"restore_all_recently_deleted_beatmaps"), @"Restore all recently deleted beatmaps"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index 2b868cab85..25e20911b8 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -6,13 +6,14 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Screens; +using osu.Game.Localisation; using osu.Game.Screens.Import; namespace osu.Game.Overlays.Settings.Sections.Debug { public class GeneralSettings : SettingsSubsection { - protected override LocalisableString Header => "General"; + protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader; [BackgroundDependencyLoader(true)] private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, OsuGame game) @@ -21,18 +22,18 @@ namespace osu.Game.Overlays.Settings.Sections.Debug { new SettingsCheckbox { - LabelText = "Show log overlay", + LabelText = DebugSettingsStrings.ShowLogOverlay, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowLogOverlay) }, new SettingsCheckbox { - LabelText = "Bypass front-to-back render pass", + LabelText = DebugSettingsStrings.BypassFrontToBackPass, Current = config.GetBindable(DebugSetting.BypassFrontToBackPass) } }; Add(new SettingsButton { - Text = "Import files", + Text = DebugSettingsStrings.ImportFiles, Action = () => game?.PerformFromScreen(menu => menu.Push(new FileImportScreen())) }); } diff --git a/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs index bf7fb351c0..07fb0aca5a 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Debug { public class MemorySettings : SettingsSubsection { - protected override LocalisableString Header => "Memory"; + protected override LocalisableString Header => DebugSettingsStrings.MemoryHeader; [BackgroundDependencyLoader] private void load(FrameworkDebugConfigManager config, GameHost host) @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug { new SettingsButton { - Text = "Clear all caches", + Text = DebugSettingsStrings.ClearAllCaches, Action = host.Collect }, }; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 44d4088972..aa85ec920c 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Debug; namespace osu.Game.Overlays.Settings.Sections { public class DebugSection : SettingsSection { - public override string Header => "Debug"; + public override LocalisableString Header => DebugSettingsStrings.DebugSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index 5392ba5d93..e509cac2f1 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -14,6 +14,7 @@ using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; using osu.Framework.Screens; using osu.Game.Graphics.Containers; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Maintenance { @@ -104,7 +105,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Origin = Anchor.Centre, Width = 300, Margin = new MarginPadding(10), - Text = "Select directory", + Text = MaintenanceSettingsStrings.SelectDirectory, Action = () => OnSelection(directorySelector.CurrentPath.Value) }, } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index b9a408b1f8..803c8332c1 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Collections; using osu.Game.Database; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Scoring; using osu.Game.Skinning; @@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importBeatmapsButton = new SettingsButton { - Text = "Import beatmaps from stable", + Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable, Action = () => { importBeatmapsButton.Enabled.Value = false; @@ -48,7 +49,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(deleteBeatmapsButton = new DangerousSettingsButton { - Text = "Delete ALL beatmaps", + Text = MaintenanceSettingsStrings.DeleteAllBeatmaps, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importScoresButton = new SettingsButton { - Text = "Import scores from stable", + Text = MaintenanceSettingsStrings.ImportScoresFromStable, Action = () => { importScoresButton.Enabled.Value = false; @@ -74,7 +75,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(deleteScoresButton = new DangerousSettingsButton { - Text = "Delete ALL scores", + Text = MaintenanceSettingsStrings.DeleteAllScores, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => @@ -89,7 +90,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importSkinsButton = new SettingsButton { - Text = "Import skins from stable", + Text = MaintenanceSettingsStrings.ImportSkinsFromStable, Action = () => { importSkinsButton.Enabled.Value = false; @@ -100,7 +101,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(deleteSkinsButton = new DangerousSettingsButton { - Text = "Delete ALL skins", + Text = MaintenanceSettingsStrings.DeleteAllSkins, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => @@ -117,7 +118,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importCollectionsButton = new SettingsButton { - Text = "Import collections from stable", + Text = MaintenanceSettingsStrings.ImportCollectionsFromStable, Action = () => { importCollectionsButton.Enabled.Value = false; @@ -128,7 +129,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(new DangerousSettingsButton { - Text = "Delete ALL collections", + Text = MaintenanceSettingsStrings.DeleteAllCollections, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(collectionManager.DeleteAll)); @@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { restoreButton = new SettingsButton { - Text = "Restore all hidden difficulties", + Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties, Action = () => { restoreButton.Enabled.Value = false; @@ -153,7 +154,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance }, undeleteButton = new SettingsButton { - Text = "Restore all recently deleted beatmaps", + Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps, Action = () => { undeleteButton.Enabled.Value = false; diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 73c88b8e71..fa0c06167b 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -3,6 +3,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Maintenance; using osuTK; @@ -10,7 +12,7 @@ namespace osu.Game.Overlays.Settings.Sections { public class MaintenanceSection : SettingsSection { - public override string Header => "Maintenance"; + public override LocalisableString Header => MaintenanceSettingsStrings.MaintenanceSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 3f434c8474f19be27afc46254461bd5bfceeadfe Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 13:42:16 +0800 Subject: [PATCH 412/600] Resolve code quality issue --- osu.Game/Localisation/GameplaySettingsStrings.cs | 1 - osu.sln.DotSettings | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 172387bbb8..4354272ab5 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -89,7 +89,6 @@ namespace osu.Game.Localisation /// public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled"); - private static string getKey(string key) => $"{prefix}:{key}"; } } diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 139ee02b96..d884ea31c5 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -304,6 +304,7 @@ AABB API BPM + FPS GC GL GLSL From 4d6101f4e5443438d95cd9c3df835b070e3aad78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 14:56:58 +0900 Subject: [PATCH 413/600] Lease selected room while in match screen to avoid lounge potentially changing it --- .../OnlinePlay/Lounge/Components/RoomsContainer.cs | 4 +++- .../Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index d2253b2d2c..e951caa8a8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -137,7 +137,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomFlow.Remove(toRemove); - selectedRoom.Value = null; + // selection may have a lease due to being in a sub screen. + if (!selectedRoom.Disabled) + selectedRoom.Value = null; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 68bd3cd613..64c068e07e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -49,6 +50,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private RoomsContainer roomsContainer; + [CanBeNull] + private LeasedBindable selectionLease; + [BackgroundDependencyLoader] private void load() { @@ -144,6 +148,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { base.OnResuming(last); + Debug.Assert(selectionLease != null); + + selectionLease.Return(); + selectionLease = null; + if (selectedRoom.Value?.RoomID.Value == null) selectedRoom.Value = new Room(); @@ -210,7 +219,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected virtual void OpenNewRoom(Room room) { - selectedRoom.Value = room; + selectionLease = selectedRoom.BeginLease(false); + Debug.Assert(selectionLease != null); + selectionLease.Value = room; this.Push(CreateRoomSubScreen(room)); } From 524128441ede2f5ab66a5582ad2a3cd3a1650d08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 15:03:05 +0900 Subject: [PATCH 414/600] Mark `PollingComponent` test as headless --- osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs index 2236f85b92..cc8503589d 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; +using osu.Framework.Testing; using osu.Game.Graphics.Sprites; using osu.Game.Online; using osuTK; @@ -15,6 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Components { + [HeadlessTest] public class TestScenePollingComponent : OsuTestScene { private Container pollBox; From b713ba1bd441ae1cf5c7cfcbb9f51c3d0666abe1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 15:11:32 +0900 Subject: [PATCH 415/600] Add test coverage --- .../TestScenePlaylistsLoungeSubScreen.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index ecdb046203..aff0e7ba4b 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -62,6 +62,24 @@ namespace osu.Game.Tests.Visual.Playlists AddUntilStep("last room is not masked", () => checkRoomVisible(roomsContainer.Rooms[^1])); } + [Test] + public void TestEnteringRoomTakesLeaseOnSelection() + { + AddStep("add rooms", () => RoomManager.AddRooms(1)); + + AddAssert("selected room is not disabled", () => !OnlinePlayDependencies.SelectedRoom.Disabled); + + AddStep("select room", () => roomsContainer.Rooms[0].TriggerClick()); + AddAssert("selected room is non-null", () => OnlinePlayDependencies.SelectedRoom.Value != null); + + AddStep("enter room", () => roomsContainer.Rooms[0].TriggerClick()); + + AddUntilStep("wait for match load", () => Stack.CurrentScreen is PlaylistsRoomSubScreen); + + AddAssert("selected room is non-null", () => OnlinePlayDependencies.SelectedRoom.Value != null); + AddAssert("selected room is disabled", () => OnlinePlayDependencies.SelectedRoom.Disabled); + } + private bool checkRoomVisible(DrawableRoom room) => loungeScreen.ChildrenOfType().First().ScreenSpaceDrawQuad .Contains(room.ScreenSpaceDrawQuad.Centre); From f4591b01d7a4bb4f8e6ef8a9eb02bd47fe527a39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 15:21:00 +0900 Subject: [PATCH 416/600] Add test step to show leaderboard in expanded state by default --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 17fe09f2c6..950f255a02 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -40,6 +40,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddStep("add local player", () => createLeaderboardScore(playerScore, new User { Username = "You", Id = 3 }, true)); + AddStep("toggle expanded", () => leaderboard.Expanded.Value = !leaderboard.Expanded.Value); AddSliderStep("set player score", 50, 5000000, 1222333, v => playerScore.Value = v); } From 14fe2eea2a907f5cf2130aed4204e350500909e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Aug 2021 19:40:29 +0900 Subject: [PATCH 417/600] Add empty step to multiplayer TestEmpty() test --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 0ffa5209e3..7ff0368fc2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -87,6 +87,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestEmpty() { // used to test the flow of multiplayer from visual tests. + AddStep("empty step", () => { }); } [Test] From 68dbbc17e88f89ca19cdd58436811e308f4411fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 16:17:14 +0900 Subject: [PATCH 418/600] Add support for automatic scrolling in gameplay leaderboard --- .../Gameplay/TestSceneGameplayLeaderboard.cs | 21 ++- .../Screens/Play/HUD/GameplayLeaderboard.cs | 131 ++++++++++++++++-- .../Play/HUD/GameplayLeaderboardScore.cs | 13 +- 3 files changed, 144 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 950f255a02..10257f9027 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -84,6 +84,23 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("add frenzibyte", () => createRandomScore(new User { Username = "frenzibyte", Id = 14210502 })); } + [Test] + public void TestMaxHeight() + { + int playerNumber = 1; + AddRepeatStep("add 3 other players", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 3); + checkHeight(4); + + AddRepeatStep("add 4 other players", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 4); + checkHeight(8); + + AddRepeatStep("add 4 other players", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 4); + checkHeight(8); + + void checkHeight(int panelCount) + => AddAssert($"leaderboard height is {panelCount} panels high", () => leaderboard.DrawHeight == (GameplayLeaderboardScore.PANEL_HEIGHT + leaderboard.Spacing) * panelCount); + } + private void createRandomScore(User user) => createLeaderboardScore(new BindableDouble(RNG.Next(0, 5_000_000)), user); private void createLeaderboardScore(BindableDouble score, User user, bool isTracked = false) @@ -94,9 +111,11 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestGameplayLeaderboard : GameplayLeaderboard { + public float Spacing => Flow.Spacing.Y; + public bool CheckPositionByUsername(string username, int? expectedPosition) { - var scoreItem = this.FirstOrDefault(i => i.User?.Username == username); + var scoreItem = Flow.FirstOrDefault(i => i.User?.Username == username); return scoreItem != null && scoreItem.ScorePosition == expectedPosition; } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 63cb4f89f5..807289d664 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -6,29 +6,58 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Caching; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; using osu.Game.Users; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { - public class GameplayLeaderboard : FillFlowContainer + public class GameplayLeaderboard : CompositeDrawable { + private readonly int maxPanels; private readonly Cached sorting = new Cached(); public Bindable Expanded = new Bindable(); - public GameplayLeaderboard() + protected readonly FillFlowContainer Flow; + + private bool requiresScroll; + private readonly OsuScrollContainer scroll; + + private GameplayLeaderboardScore trackedScore; + + /// + /// Create a new leaderboard. + /// + /// The maximum panels to show at once. Defines the maximum height of this component. + public GameplayLeaderboard(int maxPanels = 8) { + this.maxPanels = maxPanels; + Width = GameplayLeaderboardScore.EXTENDED_WIDTH + GameplayLeaderboardScore.SHEAR_WIDTH; - Direction = FillDirection.Vertical; - - Spacing = new Vector2(2.5f); - - LayoutDuration = 250; - LayoutEasing = Easing.OutQuint; + InternalChildren = new Drawable[] + { + scroll = new ManualScrollScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = Flow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + X = GameplayLeaderboardScore.SHEAR_WIDTH, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2.5f), + LayoutDuration = 450, + LayoutEasing = Easing.OutQuint, + } + } + }; } protected override void LoadComplete() @@ -50,22 +79,83 @@ namespace osu.Game.Screens.Play.HUD { var drawable = CreateLeaderboardScoreDrawable(user, isTracked); + if (isTracked) + { + if (trackedScore != null) + throw new InvalidOperationException("Cannot track more than one scores."); + + trackedScore = drawable; + } + drawable.Expanded.BindTo(Expanded); - base.Add(drawable); + Flow.Add(drawable); drawable.TotalScore.BindValueChanged(_ => sorting.Invalidate(), true); - Height = Count * (GameplayLeaderboardScore.PANEL_HEIGHT + Spacing.Y); + int displayCount = Math.Min(Flow.Count, maxPanels); + Height = displayCount * (GameplayLeaderboardScore.PANEL_HEIGHT + Flow.Spacing.Y); + requiresScroll = displayCount != Flow.Count; return drawable; } + public void Clear() + { + Flow.Clear(); + trackedScore = null; + scroll.ScrollToStart(false); + } + protected virtual GameplayLeaderboardScore CreateLeaderboardScoreDrawable(User user, bool isTracked) => new GameplayLeaderboardScore(user, isTracked); - public sealed override void Add(GameplayLeaderboardScore drawable) + protected override void Update() { - throw new NotSupportedException($"Use {nameof(AddPlayer)} instead."); + base.Update(); + + if (requiresScroll && trackedScore != null) + { + float scrollTarget = scroll.GetChildPosInContent(trackedScore) + trackedScore.DrawHeight / 2 - scroll.DrawHeight / 2; + scroll.ScrollTo(scrollTarget, false); + } + + const float panel_height = GameplayLeaderboardScore.PANEL_HEIGHT; + + float fadeBottom = scroll.Current + scroll.DrawHeight; + float fadeTop = scroll.Current + panel_height; + + if (scroll.Current <= 0) fadeTop -= panel_height; + if (!scroll.IsScrolledToEnd()) fadeBottom -= panel_height; + + // logic is mostly shared with Leaderboard, copied here for simplicity. + foreach (var c in Flow.Children) + { + float topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, Flow).Y; + float bottomY = topY + panel_height; + + bool requireTopFade = requiresScroll && topY <= fadeTop; + bool requireBottomFade = requiresScroll && bottomY >= fadeBottom; + + if (!requireTopFade && !requireBottomFade) + c.Colour = Color4.White; + else if (topY > fadeBottom + panel_height || bottomY < fadeTop - panel_height) + c.Colour = Color4.Transparent; + else + { + if (bottomY - fadeBottom > 0 && requiresScroll) + { + c.Colour = ColourInfo.GradientVertical( + Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / panel_height, 1)), + Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / panel_height, 1))); + } + else if (requiresScroll) + { + c.Colour = ColourInfo.GradientVertical( + Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / panel_height, 1)), + Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / panel_height, 1))); + } + } + } } private void sort() @@ -73,15 +163,26 @@ namespace osu.Game.Screens.Play.HUD if (sorting.IsValid) return; - var orderedByScore = this.OrderByDescending(i => i.TotalScore.Value).ToList(); + var orderedByScore = Flow.OrderByDescending(i => i.TotalScore.Value).ToList(); - for (int i = 0; i < Count; i++) + for (int i = 0; i < Flow.Count; i++) { - SetLayoutPosition(orderedByScore[i], i); + Flow.SetLayoutPosition(orderedByScore[i], i); orderedByScore[i].ScorePosition = i + 1; } sorting.Validate(); } + + private class ManualScrollScrollContainer : OsuScrollContainer + { + public ManualScrollScrollContainer() + { + ScrollbarVisible = false; + } + + public override bool HandlePositionalInput => false; + public override bool HandleNonPositionalInput => false; + } } } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 433bf78e9b..85cf9d1966 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -81,7 +81,10 @@ namespace osu.Game.Screens.Play.HUD [CanBeNull] public User User { get; } - private readonly bool trackedPlayer; + /// + /// Whether this score is the local user or a replay player (and should be focused / always visible). + /// + public readonly bool Tracked; private Container mainFillContainer; @@ -97,11 +100,11 @@ namespace osu.Game.Screens.Play.HUD /// Creates a new . /// /// The score's player. - /// Whether the player is the local user or a replay player. - public GameplayLeaderboardScore([CanBeNull] User user, bool trackedPlayer) + /// Whether the player is the local user or a replay player. + public GameplayLeaderboardScore([CanBeNull] User user, bool tracked) { User = user; - this.trackedPlayer = trackedPlayer; + Tracked = tracked; AutoSizeAxes = Axes.X; Height = PANEL_HEIGHT; @@ -338,7 +341,7 @@ namespace osu.Game.Screens.Play.HUD panelColour = BackgroundColour ?? Color4Extensions.FromHex("7fcc33"); textColour = TextColour ?? Color4.White; } - else if (trackedPlayer) + else if (Tracked) { widthExtension = true; panelColour = BackgroundColour ?? Color4Extensions.FromHex("ffd966"); From e84224f64c057f0d2caac52ad54ac06dc92a77e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 16:17:27 +0900 Subject: [PATCH 419/600] Rename `AddPlayer` method now that there's no conflict --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs | 2 +- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 2 +- osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 10257f9027..0441c5641e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void createLeaderboardScore(BindableDouble score, User user, bool isTracked = false) { - var leaderboardScore = leaderboard.AddPlayer(user, isTracked); + var leaderboardScore = leaderboard.Add(user, isTracked); leaderboardScore.TotalScore.BindTo(score); } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 807289d664..14fcaa91fa 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Play.HUD /// Whether the player should be tracked on the leaderboard. /// Set to true for the local player or a player whose replay is currently being played. /// - public ILeaderboardScore AddPlayer([CanBeNull] User user, bool isTracked) + public ILeaderboardScore Add([CanBeNull] User user, bool isTracked) { var drawable = CreateLeaderboardScoreDrawable(user, isTracked); diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 3f9258930e..1c5743a656 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -85,7 +85,7 @@ namespace osu.Game.Screens.Play.HUD var trackedUser = UserScores[user.Id]; - var leaderboardScore = AddPlayer(user, user.Id == api.LocalUser.Value.Id); + var leaderboardScore = Add(user, user.Id == api.LocalUser.Value.Id); leaderboardScore.Accuracy.BindTo(trackedUser.Accuracy); leaderboardScore.TotalScore.BindTo(trackedUser.Score); leaderboardScore.Combo.BindTo(trackedUser.CurrentCombo); From ab1cc6ad4856503da10296681e28b896d9be8a03 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 16:50:09 +0900 Subject: [PATCH 420/600] Fix padding around recent participants icon being uneven --- .../OnlinePlay/Lounge/Components/RecentParticipantsList.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index 7f3fdf01d0..6766a51840 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(4), - Padding = new MarginPadding { Left = 8, Right = 16 }, + Padding = new MarginPadding { Right = 16 }, Children = new Drawable[] { new SpriteIcon @@ -62,6 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(16), + Margin = new MarginPadding(8), Icon = FontAwesome.Solid.User, }, avatarFlow = new FillFlowContainer From d07bb10d0294fd4986442cb415b603248d022ed4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 16:52:30 +0900 Subject: [PATCH 421/600] Remove breadcrumbs from header --- osu.Game/Screens/OnlinePlay/Header.cs | 88 +++++---------------------- 1 file changed, 16 insertions(+), 72 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Header.cs b/osu.Game/Screens/OnlinePlay/Header.cs index bf0a53cbb6..c025099ebe 100644 --- a/osu.Game/Screens/OnlinePlay/Header.cs +++ b/osu.Game/Screens/OnlinePlay/Header.cs @@ -2,19 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using Humanizer; +using JetBrains.Annotations; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { @@ -22,52 +18,29 @@ namespace osu.Game.Screens.OnlinePlay { public const float HEIGHT = 80; + private readonly ScreenStack stack; + private readonly MultiHeaderTitle title; + public Header(string mainTitle, ScreenStack stack) { + this.stack = stack; + RelativeSizeAxes = Axes.X; Height = HEIGHT; + Padding = new MarginPadding { Left = WaveOverlayContainer.WIDTH_PADDING }; - HeaderBreadcrumbControl breadcrumbs; - MultiHeaderTitle title; - - Children = new Drawable[] + Child = title = new MultiHeaderTitle(mainTitle) { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#1f1921"), - }, - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = WaveOverlayContainer.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, - Children = new Drawable[] - { - title = new MultiHeaderTitle(mainTitle) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomLeft, - }, - breadcrumbs = new HeaderBreadcrumbControl(stack) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft - } - }, - }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomLeft, }; - breadcrumbs.Current.ValueChanged += screen => - { - if (screen.NewValue is IOnlinePlaySubScreen onlineSubScreen) - title.Screen = onlineSubScreen; - }; - - breadcrumbs.Current.TriggerChange(); + stack.ScreenPushed += (_, __) => updateSubScreenTitle(); + stack.ScreenExited += (_, __) => updateSubScreenTitle(); } + private void updateSubScreenTitle() => title.Screen = stack.CurrentScreen as IOnlinePlaySubScreen; + private class MultiHeaderTitle : CompositeDrawable { private const float spacing = 6; @@ -75,9 +48,10 @@ namespace osu.Game.Screens.OnlinePlay private readonly OsuSpriteText dot; private readonly OsuSpriteText pageTitle; + [CanBeNull] public IOnlinePlaySubScreen Screen { - set => pageTitle.Text = value.ShortTitle.Titleize(); + set => pageTitle.Text = value?.ShortTitle.Titleize() ?? string.Empty; } public MultiHeaderTitle(string mainTitle) @@ -125,35 +99,5 @@ namespace osu.Game.Screens.OnlinePlay pageTitle.Colour = dot.Colour = colours.Yellow; } } - - private class HeaderBreadcrumbControl : ScreenBreadcrumbControl - { - public HeaderBreadcrumbControl(ScreenStack stack) - : base(stack) - { - RelativeSizeAxes = Axes.X; - StripColour = Color4.Transparent; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - AccentColour = Color4Extensions.FromHex("#e35c99"); - } - - protected override TabItem CreateTabItem(IScreen value) => new HeaderBreadcrumbTabItem(value) - { - AccentColour = AccentColour - }; - - private class HeaderBreadcrumbTabItem : BreadcrumbTabItem - { - public HeaderBreadcrumbTabItem(IScreen value) - : base(value) - { - Bar.Colour = Color4.Transparent; - } - } - } } } From 3b7aa262d5b559f72511af9c8dfb6230f3c9ba1e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 16:52:35 +0900 Subject: [PATCH 422/600] Make header overlap content --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index fee612c0a5..6238000e85 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -101,7 +101,6 @@ namespace osu.Game.Screens.OnlinePlay new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Header.HEIGHT }, Children = new[] { header = new Container From b75c20fee421138d8b10b538fe55baf6d59c5d78 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 18:02:00 +0900 Subject: [PATCH 423/600] Adjust positioning and paddings --- osu.Game/Screens/OnlinePlay/Header.cs | 2 +- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 ++ osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs | 2 ++ osu.Game/Screens/Select/SongSelect.cs | 9 +++++---- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Header.cs b/osu.Game/Screens/OnlinePlay/Header.cs index c025099ebe..58c67a51e8 100644 --- a/osu.Game/Screens/OnlinePlay/Header.cs +++ b/osu.Game/Screens/OnlinePlay/Header.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay Child = title = new MultiHeaderTitle(mainTitle) { Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomLeft, + Origin = Anchor.CentreLeft, }; stack.ScreenPushed += (_, __) => updateSubScreenTitle(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index a53e253581..b29a1ab1b6 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -61,6 +61,8 @@ namespace osu.Game.Screens.OnlinePlay.Match protected RoomSubScreen() { + Padding = new MarginPadding { Top = Header.HEIGHT }; + AddRangeInternal(new Drawable[] { BeatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index be28de5c43..1502463022 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -59,6 +59,8 @@ namespace osu.Game.Screens.OnlinePlay [BackgroundDependencyLoader] private void load() { + LeftArea.Padding = new MarginPadding { Top = Header.HEIGHT }; + initialBeatmap = Beatmap.Value; initialRuleset = Ruleset.Value; initialMods = Mods.Value.ToList(); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 270addc8e6..0e113a71bc 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -79,6 +79,8 @@ namespace osu.Game.Screens.Select protected BeatmapCarousel Carousel { get; private set; } + protected Container LeftArea { get; private set; } + private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; @@ -186,12 +188,12 @@ namespace osu.Game.Screens.Select { new Drawable[] { - new Container + LeftArea = new Container { Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, - + Padding = new MarginPadding { Top = left_area_padding }, Children = new Drawable[] { beatmapInfoWedge = new BeatmapInfoWedge @@ -200,7 +202,6 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Margin = new MarginPadding { - Top = left_area_padding, Right = left_area_padding, }, }, @@ -210,7 +211,7 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Bottom = Footer.HEIGHT, - Top = WEDGE_HEIGHT + left_area_padding, + Top = WEDGE_HEIGHT, Left = left_area_padding, Right = left_area_padding * 2, }, From b58b5ec2b47af2376b9ff355c5591629af397d55 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Aug 2021 12:14:39 +0300 Subject: [PATCH 424/600] Apply horizontal offset changing once per frame The previous way was causing every-frame invalidation when an overlay is visible. --- osu.Game/OsuGame.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1539d984ae..b6809c0290 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1013,10 +1013,14 @@ namespace osu.Game ScreenOffsetContainer.Padding = new MarginPadding { Top = ToolbarOffset }; overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; - ScreenOffsetContainer.X = 0f; + var horizontalOffset = 0f; - if (Settings.IsLoaded) ScreenOffsetContainer.X += (ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X) * SCREEN_OFFSET_RATIO; - if (Notifications.IsLoaded) ScreenOffsetContainer.X += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SCREEN_OFFSET_RATIO; + if (Settings.IsLoaded) + horizontalOffset += (ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X) * SCREEN_OFFSET_RATIO; + if (Notifications.IsLoaded) + horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SCREEN_OFFSET_RATIO; + + ScreenOffsetContainer.X = horizontalOffset; MenuCursorContainer.CanShowCursor = (ScreenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; } From 8b29f52d9f119a2bfc72b1e6bbb85412f5e54dfb Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 12 Aug 2021 16:54:58 +0700 Subject: [PATCH 425/600] update supporter note text Co-authored-by: Dean Herbert --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index c0d78cc887..3d6a469247 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = colour.PinkLighter; }) { - Text = "Not only will you help speed development, but you will also get some extra features and customisations!", + Text = ChangelogStrings.SupportText2.ToString(), Margin = new MarginPadding { Top = 10 }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From 98859b3759a78649b85b5611c6ff6087e6a64610 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 12 Aug 2021 17:06:11 +0700 Subject: [PATCH 426/600] cache pink colour provider Co-authored-by: Dean Herbert --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 3d6a469247..9bfb141eea 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -25,6 +25,9 @@ namespace osu.Game.Overlays.Changelog private readonly FillFlowContainer textContainer; private readonly Container imageContainer; + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); + public ChangelogSupporterPromo() { RelativeSizeAxes = Axes.X; From 18684ad21f52e2821810181a0170f4a98eda66ed Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 12 Aug 2021 17:08:54 +0700 Subject: [PATCH 427/600] remove colour creation in add link --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 9bfb141eea..477745e0ba 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -125,11 +125,7 @@ namespace osu.Game.Overlays.Changelog }; supportLinkText.AddText("Support further development of osu! and "); - supportLinkText.AddLink("become an osu!supporter", "https://osu.ppy.sh/home/support", t => - { - t.Colour = colour.PinkDark; - t.Font = t.Font.With(weight: FontWeight.Bold); - }); + supportLinkText.AddLink("become an osu!supporter", "https://osu.ppy.sh/home/support", t => t.Font = t.Font.With(weight: FontWeight.Bold)); supportLinkText.AddText(" today!"); imageContainer.Children = new Drawable[] From ab7bd1df9dade8869369175d53055efcbf40a42d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 19:27:06 +0900 Subject: [PATCH 428/600] Use full-screen background --- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 62 ++++--------------- 1 file changed, 13 insertions(+), 49 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 6238000e85..21e4f047f0 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -21,8 +21,8 @@ using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; -using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { @@ -68,9 +68,6 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(CanBeNull = true)] private OsuLogo logo { get; set; } - private Drawable header; - private Drawable headerBackground; - protected OnlinePlayScreen() { Anchor = Anchor.Centre; @@ -101,41 +98,21 @@ namespace osu.Game.Screens.OnlinePlay new Container { RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { - header = new Container + new HeaderBackgroundSprite { - RelativeSizeAxes = Axes.X, - Height = 400, - Children = new[] - { - headerBackground = new Container - { - RelativeSizeAxes = Axes.Both, - Width = 1.25f, - Masking = true, - Children = new Drawable[] - { - new HeaderBackgroundSprite - { - RelativeSizeAxes = Axes.X, - Height = 400 // Keep a static height so the header doesn't change as it's resized between subscreens - }, - } - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Bottom = -1 }, // 1px padding to avoid a 1px gap due to masking - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(backgroundColour.Opacity(0.5f), backgroundColour) - }, - } - } + RelativeSizeAxes = Axes.Both }, - screenStack = new OnlinePlaySubScreenStack { RelativeSizeAxes = Axes.Both } + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.9f), Color4.Black.Opacity(0.6f)) + }, + screenStack = new OnlinePlaySubScreenStack + { + RelativeSizeAxes = Axes.Both + } } }, new Header(ScreenTitle, screenStack), @@ -288,19 +265,6 @@ namespace osu.Game.Screens.OnlinePlay private void subScreenChanged(IScreen lastScreen, IScreen newScreen) { - switch (newScreen) - { - case LoungeSubScreen _: - header.Delay(OnlinePlaySubScreen.RESUME_TRANSITION_DELAY).ResizeHeightTo(400, OnlinePlaySubScreen.APPEAR_DURATION, Easing.OutQuint); - headerBackground.MoveToX(0, OnlinePlaySubScreen.X_MOVE_DURATION, Easing.OutQuint); - break; - - case RoomSubScreen _: - header.ResizeHeightTo(135, OnlinePlaySubScreen.APPEAR_DURATION, Easing.OutQuint); - headerBackground.MoveToX(-OnlinePlaySubScreen.X_SHIFT, OnlinePlaySubScreen.X_MOVE_DURATION, Easing.OutQuint); - break; - } - if (lastScreen is IOsuScreen lastOsuScreen) Activity.UnbindFrom(lastOsuScreen.Activity); From 512382987e0e85d4fc6825f065fe94677627851a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 17:02:55 +0900 Subject: [PATCH 429/600] Add colour provider for multiplayer usage --- .../Visual/Multiplayer/TestSceneDrawableRoom.cs | 4 ++++ .../Multiplayer/TestSceneRecentParticipantsList.cs | 5 +++++ osu.Game/Overlays/OverlayColourProvider.cs | 7 ++++++- .../OnlinePlay/Lounge/Components/DrawableRoom.cs | 13 ++++++------- .../Lounge/Components/RecentParticipantsList.cs | 5 +++-- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 3 +++ 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index e6a1bbeb92..299bbacf08 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -13,6 +13,7 @@ using osu.Framework.Utils; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; +using osu.Game.Overlays; using osu.Game.Rulesets.Osu; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Beatmaps; @@ -26,6 +27,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Cached] private readonly Bindable selectedRoom = new Bindable(); + [Cached] + protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); + [Test] public void TestMultipleStatuses() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs index f05c092dfb..27ccd33440 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -3,9 +3,11 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Online.Rooms; +using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; @@ -17,6 +19,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { private RecentParticipantsList list; + [Cached] + protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); + [SetUp] public new void Setup() => Schedule(() => { diff --git a/osu.Game/Overlays/OverlayColourProvider.cs b/osu.Game/Overlays/OverlayColourProvider.cs index 008e7696e1..e7b3e6d873 100644 --- a/osu.Game/Overlays/OverlayColourProvider.cs +++ b/osu.Game/Overlays/OverlayColourProvider.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays public static OverlayColourProvider Green { get; } = new OverlayColourProvider(OverlayColourScheme.Green); public static OverlayColourProvider Purple { get; } = new OverlayColourProvider(OverlayColourScheme.Purple); public static OverlayColourProvider Blue { get; } = new OverlayColourProvider(OverlayColourScheme.Blue); + public static OverlayColourProvider Plum { get; } = new OverlayColourProvider(OverlayColourScheme.Plum); public OverlayColourProvider(OverlayColourScheme colourScheme) { @@ -80,6 +81,9 @@ namespace osu.Game.Overlays case OverlayColourScheme.Blue: return 200 / 360f; + + case OverlayColourScheme.Plum: + return 320 / 360f; } } } @@ -92,6 +96,7 @@ namespace osu.Game.Overlays Lime, Green, Purple, - Blue + Blue, + Plum, } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 3a56be64e0..c2a872efe5 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -28,6 +28,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; using osu.Game.Online.Rooms; +using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Components; using osuTK; using osuTK.Graphics; @@ -41,8 +42,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private const float transition_duration = 60; private const float height = 100; - private static readonly Color4 background_colour = Color4Extensions.FromHex(@"#27302E"); - public event Action StateChanged; protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(); @@ -154,7 +153,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } [BackgroundDependencyLoader] - private void load(OsuColour colours, AudioManager audio) + private void load(OverlayColourProvider colours, AudioManager audio) { Children = new Drawable[] { @@ -167,7 +166,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = background_colour, + Colour = colours.Background5, }, new OnlinePlayBackgroundSprite { @@ -208,12 +207,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = background_colour, + Colour = colours.Background5, }, new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(background_colour, background_colour.Opacity(0.3f)) + Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)) }, } } @@ -531,7 +530,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private OsuPasswordTextBox passwordTextbox; [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Child = new FillFlowContainer { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index 6766a51840..e22f55a716 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; @@ -31,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider colours) { InternalChildren = new Drawable[] { @@ -44,7 +45,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"#2E3835") + Colour = colours.Background4, } }, new FillFlowContainer diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index fee612c0a5..86ce61f845 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -29,6 +29,9 @@ namespace osu.Game.Screens.OnlinePlay [Cached] public abstract class OnlinePlayScreen : OsuScreen, IHasSubScreenStack { + [Cached] + protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); + public override bool CursorVisible => (screenStack?.CurrentScreen as IOnlinePlaySubScreen)?.CursorVisible ?? true; // this is required due to PlayerLoader eventually being pushed to the main stack From 2c07b68f6fca41f997dc32d642fe899e14ca4af1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 17:24:21 +0900 Subject: [PATCH 430/600] Fix incorrect colour for hidden user display --- .../Components/RecentParticipantsList.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index e22f55a716..e6e879d652 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -4,7 +4,6 @@ using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -14,7 +13,6 @@ using osu.Game.Overlays; using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { @@ -208,9 +206,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private int count; - private readonly SpriteText countText; + private readonly SpriteText countText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; - public HiddenUserCount() + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colours) { Size = new Vector2(avatar_size); Alpha = 0; @@ -224,13 +227,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black + Colour = colours.Background5, }, - countText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } + countText } }; } From 127fd4d292d9ac8c95e3f2ec3c6dfb7572e45377 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 17:28:10 +0900 Subject: [PATCH 431/600] Match font weight of design for hidden user count --- .../OnlinePlay/Lounge/Components/RecentParticipantsList.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index e6e879d652..32568f5058 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Users; @@ -210,6 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Font = OsuFont.Default.With(weight: FontWeight.Bold), }; [BackgroundDependencyLoader] From 8a67304b9fe6a93ac60105ae34ee570fa99b1ea0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 18:10:06 +0900 Subject: [PATCH 432/600] Fix recent participants hidden user logic not handling edge case correctly Hiding just one user never makes sense, so this will now always show up to the required circle count until two users are required to be hidden. This will make the listing more consistent with the width requirement spec. --- .../TestSceneRecentParticipantsList.cs | 46 +++++++++++++----- .../Lounge/Components/DrawableRoom.cs | 4 +- .../Components/RecentParticipantsList.cs | 48 +++++++++++++------ 3 files changed, 71 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs index 27ccd33440..2436da4655 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -31,12 +31,36 @@ namespace osu.Game.Tests.Visual.Multiplayer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - NumberOfAvatars = 3 + NumberOfCircles = 3 }; }); [Test] - public void TestAvatarCount() + public void TestCircleCountNearLimit() + { + AddStep("add 8 users", () => + { + for (int i = 0; i < 8; i++) + addUser(i); + }); + AddStep("set 8 circles", () => list.NumberOfCircles = 8); + AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); + + AddStep("add one more user", () => addUser(9)); + AddAssert("2 hidden users", () => list.ChildrenOfType().Single().Count == 2); + + AddStep("remove first user", () => removeUserAt(0)); + AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); + + AddStep("add one more user", () => addUser(9)); + AddAssert("2 hidden users", () => list.ChildrenOfType().Single().Count == 2); + + AddStep("remove last user", () => removeUserAt(8)); + AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); + } + + [Test] + public void TestCircleCount() { AddStep("add 50 users", () => { @@ -44,12 +68,12 @@ namespace osu.Game.Tests.Visual.Multiplayer addUser(i); }); - AddStep("set 3 avatars", () => list.NumberOfAvatars = 3); - AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddStep("set 3 circles", () => list.NumberOfCircles = 3); + AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("47 hidden users", () => list.ChildrenOfType().Single().Count == 47); - AddStep("set 10 avatars", () => list.NumberOfAvatars = 10); - AddAssert("10 avatars displayed", () => list.ChildrenOfType().Count() == 10); + AddStep("set 10 circles", () => list.NumberOfCircles = 10); + AddAssert("10 circles displayed", () => list.ChildrenOfType().Count() == 10); AddAssert("40 hidden users", () => list.ChildrenOfType().Single().Count == 40); } @@ -63,24 +87,24 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddStep("remove from start", () => removeUserAt(0)); - AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("46 hidden users", () => list.ChildrenOfType().Single().Count == 46); AddStep("remove from end", () => removeUserAt(SelectedRoom.Value.RecentParticipants.Count - 1)); - AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("45 hidden users", () => list.ChildrenOfType().Single().Count == 45); AddRepeatStep("remove 45 users", () => removeUserAt(0), 45); - AddAssert("3 avatars displayed", () => list.ChildrenOfType().Count() == 3); + AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3); AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); AddAssert("hidden users bubble hidden", () => list.ChildrenOfType().Single().Alpha < 0.5f); AddStep("remove another user", () => removeUserAt(0)); - AddAssert("2 avatars displayed", () => list.ChildrenOfType().Count() == 2); + AddAssert("2 circles displayed", () => list.ChildrenOfType().Count() == 2); AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); AddRepeatStep("remove the remaining two users", () => removeUserAt(0), 2); - AddAssert("0 avatars displayed", () => !list.ChildrenOfType().Any()); + AddAssert("0 circles displayed", () => !list.ChildrenOfType().Any()); } private void addUser(int id) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index c2a872efe5..193fb0cf57 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -120,7 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components numberOfAvatars = value; if (recentParticipantsList != null) - recentParticipantsList.NumberOfAvatars = value; + recentParticipantsList.NumberOfCircles = value; } } @@ -315,7 +315,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - NumberOfAvatars = NumberOfAvatars + NumberOfCircles = NumberOfAvatars } } }, diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index 32568f5058..ab13f27469 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -21,6 +22,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { private const float avatar_size = 36; + private bool canDisplayMoreUsers = true; + private FillFlowContainer avatarFlow; private HiddenUserCount hiddenUsers; @@ -91,14 +94,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components ParticipantCount.BindValueChanged(_ => updateHiddenUserCount(), true); } - private int numberOfAvatars = 3; + private int numberOfCircles = 3; - public int NumberOfAvatars + /// + /// The maximum number of circles visible (including the "hidden count" circle in the overflow case). + /// + public int NumberOfCircles { - get => numberOfAvatars; + get => numberOfCircles; set { - numberOfAvatars = value; + numberOfCircles = value; if (LoadState < LoadState.Loaded) return; @@ -107,6 +113,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components clearUsers(); foreach (var u in RecentParticipants) addUser(u); + + updateHiddenUserCount(); } } @@ -136,34 +144,46 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components addUser(u); break; } + + updateHiddenUserCount(); } private void addUser(User user) { - if (avatarFlow.Count < NumberOfAvatars) - avatarFlow.Add(new CircularAvatar { User = user }); + if (!canDisplayMoreUsers) + return; - updateHiddenUserCount(); + if (avatarFlow.Count < NumberOfCircles) + avatarFlow.Add(new CircularAvatar { User = user }); + else if (avatarFlow.Count == NumberOfCircles) + avatarFlow.Remove(avatarFlow.Last()); } private void removeUser(User user) { - if (avatarFlow.RemoveAll(a => a.User == user) > 0) - { - if (RecentParticipants.Count >= NumberOfAvatars) - avatarFlow.Add(new CircularAvatar { User = RecentParticipants.First(u => avatarFlow.All(a => a.User != u)) }); - } + var nextUser = RecentParticipants.FirstOrDefault(u => avatarFlow.All(a => a.User != u)); + if (nextUser == null) + return; - updateHiddenUserCount(); + if (canDisplayMoreUsers || NumberOfCircles == RecentParticipants.Count) + avatarFlow.Add(new CircularAvatar { User = nextUser }); } private void clearUsers() { + canDisplayMoreUsers = true; avatarFlow.Clear(); updateHiddenUserCount(); } - private void updateHiddenUserCount() => hiddenUsers.Count = ParticipantCount.Value - avatarFlow.Count; + private void updateHiddenUserCount() + { + int count = ParticipantCount.Value - avatarFlow.Count; + + Debug.Assert(count != 1); + + hiddenUsers.Count = count; + } private class CircularAvatar : CompositeDrawable { From 7b66616dc40df3f9f87ac0afe67d46915d4c2711 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 18:47:22 +0900 Subject: [PATCH 433/600] Simplify logic and test/fix edge case --- .../TestSceneRecentParticipantsList.cs | 36 ++++++++--- .../Components/RecentParticipantsList.cs | 60 ++++++++++--------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs index 2436da4655..7d3880dd16 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - NumberOfCircles = 3 + NumberOfCircles = 4 }; }); @@ -43,6 +43,7 @@ namespace osu.Game.Tests.Visual.Multiplayer for (int i = 0; i < 8; i++) addUser(i); }); + AddStep("set 8 circles", () => list.NumberOfCircles = 8); AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); @@ -59,6 +60,27 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0); } + [Test] + public void TestHiddenUsersBecomeDisplayed() + { + AddStep("add 8 users", () => + { + for (int i = 0; i < 8; i++) + addUser(i); + }); + + AddStep("set 3 circles", () => list.NumberOfCircles = 3); + + for (int i = 0; i < 8; i++) + { + AddStep("remove user", () => removeUserAt(0)); + int remainingUsers = 7 - i; + + int displayedUsers = remainingUsers > 3 ? 2 : remainingUsers; + AddAssert($"{displayedUsers} avatars displayed", () => list.ChildrenOfType().Count() == displayedUsers); + } + } + [Test] public void TestCircleCount() { @@ -69,12 +91,12 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddStep("set 3 circles", () => list.NumberOfCircles = 3); - AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3); - AddAssert("47 hidden users", () => list.ChildrenOfType().Single().Count == 47); + AddAssert("2 users displayed", () => list.ChildrenOfType().Count() == 2); + AddAssert("48 hidden users", () => list.ChildrenOfType().Single().Count == 48); AddStep("set 10 circles", () => list.NumberOfCircles = 10); - AddAssert("10 circles displayed", () => list.ChildrenOfType().Count() == 10); - AddAssert("40 hidden users", () => list.ChildrenOfType().Single().Count == 40); + AddAssert("9 users displayed", () => list.ChildrenOfType().Count() == 9); + AddAssert("41 hidden users", () => list.ChildrenOfType().Single().Count == 41); } [Test] @@ -109,18 +131,18 @@ namespace osu.Game.Tests.Visual.Multiplayer private void addUser(int id) { - SelectedRoom.Value.ParticipantCount.Value++; SelectedRoom.Value.RecentParticipants.Add(new User { Id = id, Username = $"User {id}" }); + SelectedRoom.Value.ParticipantCount.Value++; } private void removeUserAt(int index) { - SelectedRoom.Value.ParticipantCount.Value--; SelectedRoom.Value.RecentParticipants.RemoveAt(index); + SelectedRoom.Value.ParticipantCount.Value--; } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index ab13f27469..3085286ccb 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -22,8 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { private const float avatar_size = 36; - private bool canDisplayMoreUsers = true; - private FillFlowContainer avatarFlow; private HiddenUserCount hiddenUsers; @@ -91,10 +89,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components base.LoadComplete(); RecentParticipants.BindCollectionChanged(onParticipantsChanged, true); - ParticipantCount.BindValueChanged(_ => updateHiddenUserCount(), true); + ParticipantCount.BindValueChanged(_ => updateHiddenUsers(), true); } - private int numberOfCircles = 3; + private int numberOfCircles = 4; /// /// The maximum number of circles visible (including the "hidden count" circle in the overflow case). @@ -114,7 +112,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components foreach (var u in RecentParticipants) addUser(u); - updateHiddenUserCount(); + updateHiddenUsers(); } } @@ -145,44 +143,43 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components break; } - updateHiddenUserCount(); + updateHiddenUsers(); } + private int displayedCircles => avatarFlow.Count + (hiddenUsers.Count > 0 ? 1 : 0); + private void addUser(User user) { - if (!canDisplayMoreUsers) - return; - - if (avatarFlow.Count < NumberOfCircles) + if (displayedCircles < NumberOfCircles) avatarFlow.Add(new CircularAvatar { User = user }); - else if (avatarFlow.Count == NumberOfCircles) - avatarFlow.Remove(avatarFlow.Last()); } private void removeUser(User user) { - var nextUser = RecentParticipants.FirstOrDefault(u => avatarFlow.All(a => a.User != u)); - if (nextUser == null) - return; - - if (canDisplayMoreUsers || NumberOfCircles == RecentParticipants.Count) - avatarFlow.Add(new CircularAvatar { User = nextUser }); + avatarFlow.RemoveAll(a => a.User == user); } private void clearUsers() { - canDisplayMoreUsers = true; avatarFlow.Clear(); - updateHiddenUserCount(); + updateHiddenUsers(); } - private void updateHiddenUserCount() + private void updateHiddenUsers() { - int count = ParticipantCount.Value - avatarFlow.Count; + int hiddenCount = 0; + if (RecentParticipants.Count > NumberOfCircles) + hiddenCount = ParticipantCount.Value - NumberOfCircles + 1; - Debug.Assert(count != 1); + hiddenUsers.Count = hiddenCount; - hiddenUsers.Count = count; + if (displayedCircles > NumberOfCircles) + avatarFlow.Remove(avatarFlow.Last()); + else if (displayedCircles < NumberOfCircles) + { + var nextUser = RecentParticipants.FirstOrDefault(u => avatarFlow.All(a => a.User != u)); + if (nextUser != null) addUser(nextUser); + } } private class CircularAvatar : CompositeDrawable @@ -193,9 +190,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components set => avatar.User = value; } - private readonly UpdateableAvatar avatar; + private readonly UpdateableAvatar avatar = new UpdateableAvatar(showUsernameTooltip: true) { RelativeSizeAxes = Axes.Both }; - public CircularAvatar() + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colours) { Size = new Vector2(avatar_size); @@ -203,7 +201,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { RelativeSizeAxes = Axes.Both, Masking = true, - Child = avatar = new UpdateableAvatar(showUsernameTooltip: true) { RelativeSizeAxes = Axes.Both } + Children = new Drawable[] + { + new Box + { + Colour = colours.Background5, + RelativeSizeAxes = Axes.Both, + }, + avatar + } }; } } From 10195e0c53574a8036b691541357a2595fa878fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 18:51:50 +0900 Subject: [PATCH 434/600] Add total user count --- .../Components/RecentParticipantsList.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs index 3085286ccb..bc658f45e4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RecentParticipantsList.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Specialized; -using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -23,7 +22,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private const float avatar_size = 36; private FillFlowContainer avatarFlow; + private HiddenUserCount hiddenUsers; + private OsuSpriteText totalCount; public RecentParticipantsList() { @@ -63,16 +64,23 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(16), - Margin = new MarginPadding(8), + Margin = new MarginPadding { Left = 8 }, Icon = FontAwesome.Solid.User, }, + totalCount = new OsuSpriteText + { + Font = OsuFont.Default.With(weight: FontWeight.Bold), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, avatarFlow = new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(4) + Spacing = new Vector2(4), + Margin = new MarginPadding { Left = 4 }, }, hiddenUsers = new HiddenUserCount { @@ -89,7 +97,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components base.LoadComplete(); RecentParticipants.BindCollectionChanged(onParticipantsChanged, true); - ParticipantCount.BindValueChanged(_ => updateHiddenUsers(), true); + ParticipantCount.BindValueChanged(_ => + { + updateHiddenUsers(); + totalCount.Text = ParticipantCount.Value.ToString(); + }, true); } private int numberOfCircles = 4; From e89aea1fc2b91265ee518b450b9fb3ca02b781c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 19:38:53 +0900 Subject: [PATCH 435/600] Add some padding between scroll bar and content --- .../Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index b9b034272d..5e5863c7c4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -50,6 +50,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + // account for the fact we are in a scroll container and want a bit of spacing from the scroll bar. + Padding = new MarginPadding { Right = 5 }; + InternalChild = new OsuContextMenuContainer { RelativeSizeAxes = Axes.X, From 047b37788bb8087c248986de83a4b4732d362020 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 19:48:15 +0900 Subject: [PATCH 436/600] Merge online play filter control with the lounge subscreen --- .../TestScenePlaylistsFilterControl.cs | 23 ---- .../Lounge/Components/FilterControl.cs | 125 ----------------- .../Components/PlaylistsFilterControl.cs | 57 -------- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 129 ++++++++++++++---- .../Multiplayer/MultiplayerFilterControl.cs | 17 --- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 7 +- .../Playlists/PlaylistsLoungeSubScreen.cs | 44 +++++- 7 files changed, 154 insertions(+), 248 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Playlists/TestScenePlaylistsFilterControl.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerFilterControl.cs diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsFilterControl.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsFilterControl.cs deleted file mode 100644 index 40e191dd7e..0000000000 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsFilterControl.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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.Graphics; -using osu.Game.Screens.OnlinePlay.Lounge.Components; - -namespace osu.Game.Tests.Visual.Playlists -{ - public class TestScenePlaylistsFilterControl : OsuTestScene - { - public TestScenePlaylistsFilterControl() - { - Child = new PlaylistsFilterControl - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Width = 0.7f, - Height = 80, - }; - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs deleted file mode 100644 index e2f02fca68..0000000000 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterControl.cs +++ /dev/null @@ -1,125 +0,0 @@ -// 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.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Threading; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets; -using osuTK; - -namespace osu.Game.Screens.OnlinePlay.Lounge.Components -{ - public abstract class FilterControl : CompositeDrawable - { - protected readonly FillFlowContainer Filters; - - [Resolved(CanBeNull = true)] - private Bindable filter { get; set; } - - [Resolved] - private IBindable ruleset { get; set; } - - private readonly SearchTextBox search; - private readonly Dropdown statusDropdown; - - protected FilterControl() - { - RelativeSizeAxes = Axes.X; - Height = 70; - - InternalChild = new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(10), - Children = new Drawable[] - { - search = new FilterSearchTextBox - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.X, - Width = 0.6f, - }, - Filters = new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10), - Child = statusDropdown = new SlimEnumDropdown - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.None, - Width = 160, - } - }, - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - filter ??= new Bindable(); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - search.Current.BindValueChanged(_ => updateFilterDebounced()); - ruleset.BindValueChanged(_ => UpdateFilter()); - statusDropdown.Current.BindValueChanged(_ => UpdateFilter(), true); - } - - private ScheduledDelegate scheduledFilterUpdate; - - private void updateFilterDebounced() - { - scheduledFilterUpdate?.Cancel(); - scheduledFilterUpdate = Scheduler.AddDelayed(UpdateFilter, 200); - } - - protected void UpdateFilter() => Scheduler.AddOnce(updateFilter); - - private void updateFilter() - { - scheduledFilterUpdate?.Cancel(); - - var criteria = CreateCriteria(); - criteria.SearchString = search.Current.Value; - criteria.Status = statusDropdown.Current.Value; - criteria.Ruleset = ruleset.Value; - - filter.Value = criteria; - } - - protected virtual FilterCriteria CreateCriteria() => new FilterCriteria(); - - public bool HoldFocus - { - get => search.HoldFocus; - set => search.HoldFocus = value; - } - - public void TakeFocus() => search.TakeFocus(); - - private class FilterSearchTextBox : SearchTextBox - { - [BackgroundDependencyLoader] - private void load() - { - BackgroundUnfocused = OsuColour.Gray(0.06f); - BackgroundFocused = OsuColour.Gray(0.12f); - } - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs deleted file mode 100644 index bbf34d3893..0000000000 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistsFilterControl.cs +++ /dev/null @@ -1,57 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Screens.OnlinePlay.Lounge.Components -{ - public class PlaylistsFilterControl : FilterControl - { - private readonly Dropdown categoryDropdown; - - public PlaylistsFilterControl() - { - Filters.Add(categoryDropdown = new SlimEnumDropdown - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.None, - Width = 160, - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - categoryDropdown.Current.BindValueChanged(_ => UpdateFilter()); - } - - protected override FilterCriteria CreateCriteria() - { - var criteria = base.CreateCriteria(); - - switch (categoryDropdown.Current.Value) - { - case PlaylistsCategory.Normal: - criteria.Category = "normal"; - break; - - case PlaylistsCategory.Spotlight: - criteria.Category = "spotlight"; - break; - } - - return criteria; - } - - private enum PlaylistsCategory - { - Any, - Normal, - Spotlight - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 122b30b1d2..1c28405e40 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.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.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -9,24 +10,28 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Screens; +using osu.Framework.Threading; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Overlays; +using osu.Game.Rulesets; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge { [Cached] public abstract class LoungeSubScreen : OnlinePlaySubScreen { + private const float button_height = 25; + public override string Title => "Lounge"; protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); @@ -41,7 +46,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private readonly IBindable initialRoomsReceived = new Bindable(); private readonly IBindable operationInProgress = new Bindable(); - private FilterControl filter; private LoadingLayer loadingLayer; [Resolved] @@ -53,31 +57,33 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved(CanBeNull = true)] private OngoingOperationTracker ongoingOperationTracker { get; set; } + [Resolved(CanBeNull = true)] + private Bindable filter { get; set; } + + [Resolved] + private IBindable ruleset { get; set; } + [CanBeNull] private IDisposable joiningRoomOperation { get; set; } private RoomsContainer roomsContainer; + private SearchTextBox searchTextBox; + private Dropdown statusDropdown; [BackgroundDependencyLoader] private void load() { + filter ??= new Bindable(new FilterCriteria()); + OsuScrollContainer scrollContainer; InternalChildren = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.X, - Height = 100, - Colour = Color4.Black, - Alpha = 0.5f, - }, new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Top = 20, Left = WaveOverlayContainer.WIDTH_PADDING, Right = WaveOverlayContainer.WIDTH_PADDING, }, @@ -86,26 +92,48 @@ namespace osu.Game.Screens.OnlinePlay.Lounge RelativeSizeAxes = Axes.Both, RowDimensions = new[] { - new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, Header.HEIGHT), + new Dimension(GridSizeMode.Absolute, button_height), new Dimension(GridSizeMode.Absolute, 20) }, Content = new[] { + new Drawable[] + { + searchTextBox = new LoungeSearchTextBox + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.X, + Width = 0.6f, + }, + }, new Drawable[] { new Container { - RelativeSizeAxes = Axes.X, - Height = 70, - Depth = -1, + RelativeSizeAxes = Axes.Both, + Depth = float.MinValue, // Contained filters should appear over the top of rooms. Children = new Drawable[] { - filter = CreateFilterControl(), Buttons.WithChild(CreateNewRoomButton().With(d => { - d.Size = new Vector2(150, 25); + d.Size = new Vector2(150, button_height); d.Action = () => Open(); - })) + })), + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10), + ChildrenEnumerable = CreateFilterControls().Select(f => f.With(d => + { + d.Anchor = Anchor.TopRight; + d.Origin = Anchor.TopRight; + })) + } } } }, @@ -145,6 +173,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { base.LoadComplete(); + searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); + ruleset.BindValueChanged(_ => UpdateFilter()); + initialRoomsReceived.BindTo(RoomManager.InitialRoomsReceived); initialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); @@ -153,13 +184,50 @@ namespace osu.Game.Screens.OnlinePlay.Lounge operationInProgress.BindTo(ongoingOperationTracker.InProgress); operationInProgress.BindValueChanged(_ => updateLoadingLayer(), true); } + + updateFilter(); } - protected override void OnFocus(FocusEvent e) + #region Filtering + + protected void UpdateFilter() => Scheduler.AddOnce(updateFilter); + + private ScheduledDelegate scheduledFilterUpdate; + + private void updateFilterDebounced() { - filter.TakeFocus(); + scheduledFilterUpdate?.Cancel(); + scheduledFilterUpdate = Scheduler.AddDelayed(UpdateFilter, 200); } + private void updateFilter() + { + scheduledFilterUpdate?.Cancel(); + filter.Value = CreateFilterCriteria(); + } + + protected virtual FilterCriteria CreateFilterCriteria() => new FilterCriteria + { + SearchString = searchTextBox.Current.Value, + Ruleset = ruleset.Value, + Status = statusDropdown.Current.Value + }; + + protected virtual IEnumerable CreateFilterControls() + { + statusDropdown = new SlimEnumDropdown + { + RelativeSizeAxes = Axes.None, + Width = 160, + }; + + statusDropdown.Current.BindValueChanged(_ => UpdateFilter()); + + yield return statusDropdown; + } + + #endregion + public override void OnEntering(IScreen last) { base.OnEntering(last); @@ -191,14 +259,19 @@ namespace osu.Game.Screens.OnlinePlay.Lounge base.OnSuspending(next); } + protected override void OnFocus(FocusEvent e) + { + searchTextBox.TakeFocus(); + } + private void onReturning() { - filter.HoldFocus = true; + searchTextBox.HoldFocus = true; } private void onLeaving() { - filter.HoldFocus = false; + searchTextBox.HoldFocus = false; // ensure any password prompt is dismissed. this.HidePopover(); @@ -243,8 +316,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge this.Push(CreateRoomSubScreen(room)); } - protected abstract FilterControl CreateFilterControl(); - protected abstract OsuButton CreateNewRoomButton(); /// @@ -262,5 +333,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge else loadingLayer.Hide(); } + + private class LoungeSearchTextBox : SearchTextBox + { + [BackgroundDependencyLoader] + private void load() + { + BackgroundUnfocused = OsuColour.Gray(0.06f); + BackgroundFocused = OsuColour.Gray(0.12f); + } + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerFilterControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerFilterControl.cs deleted file mode 100644 index 37e0fd109a..0000000000 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerFilterControl.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Screens.OnlinePlay.Lounge.Components; - -namespace osu.Game.Screens.OnlinePlay.Multiplayer -{ - public class MultiplayerFilterControl : FilterControl - { - protected override FilterCriteria CreateCriteria() - { - var criteria = base.CreateCriteria(); - criteria.Category = "realtime"; - return criteria; - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 621ff8881f..a7eaa37faa 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -21,7 +21,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } - protected override FilterControl CreateFilterControl() => new MultiplayerFilterControl(); + protected override FilterCriteria CreateFilterCriteria() + { + var criteria = base.CreateFilterCriteria(); + criteria.Category = "realtime"; + return criteria; + } protected override OsuButton CreateNewRoomButton() => new CreateMultiplayerMatchButton(); diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index 4db1d6380d..254769d06b 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -1,7 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Rooms; @@ -16,7 +20,38 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved] private IAPIProvider api { get; set; } - protected override FilterControl CreateFilterControl() => new PlaylistsFilterControl(); + private Dropdown categoryDropdown; + + protected override IEnumerable CreateFilterControls() + { + categoryDropdown = new SlimEnumDropdown + { + RelativeSizeAxes = Axes.None, + Width = 160, + }; + + categoryDropdown.Current.BindValueChanged(_ => UpdateFilter()); + + return base.CreateFilterControls().Append(categoryDropdown); + } + + protected override FilterCriteria CreateFilterCriteria() + { + var criteria = base.CreateFilterCriteria(); + + switch (categoryDropdown.Current.Value) + { + case PlaylistsCategory.Normal: + criteria.Category = "normal"; + break; + + case PlaylistsCategory.Spotlight: + criteria.Category = "spotlight"; + break; + } + + return criteria; + } protected override OsuButton CreateNewRoomButton() => new CreatePlaylistsRoomButton(); @@ -30,5 +65,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists } protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room); + + private enum PlaylistsCategory + { + Any, + Normal, + Spotlight + } } } From 050f2d6b0d379a675c2d5dbee3d7ba80e85873f5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 19:51:03 +0900 Subject: [PATCH 437/600] Add background to room subscreen --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index b29a1ab1b6..0074479a4d 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -8,8 +8,10 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -65,6 +67,11 @@ namespace osu.Game.Screens.OnlinePlay.Match AddRangeInternal(new Drawable[] { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. + }, BeatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker { SelectedItem = { BindTarget = SelectedItem } From 03351cf434d100356e1d16fdc86e07d05541a374 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 20:01:53 +0900 Subject: [PATCH 438/600] Add blur to background --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 21e4f047f0..d1c701974e 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -22,6 +22,7 @@ using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Users; +using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay @@ -100,9 +101,14 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new HeaderBackgroundSprite + new BufferedContainer { - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, + BlurSigma = new Vector2(10), + Child = new HeaderBackgroundSprite + { + RelativeSizeAxes = Axes.Both + } }, new Box { From 83703e42835630d5d600f529efd900df38785c15 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Aug 2021 20:08:14 +0900 Subject: [PATCH 439/600] Add colour provider to online play dependencies --- .../Visual/Multiplayer/TestSceneRecentParticipantsList.cs | 5 ----- .../Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs index 7d3880dd16..50ec2bf3ac 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs @@ -3,11 +3,9 @@ using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Online.Rooms; -using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; @@ -19,9 +17,6 @@ namespace osu.Game.Tests.Visual.Multiplayer { private RecentParticipantsList list; - [Cached] - protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); - [SetUp] public new void Setup() => Schedule(() => { diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index ddbbfe501b..05ba509a73 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.Rooms; +using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge.Components; @@ -46,6 +47,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay CacheAs(Filter); CacheAs(OngoingOperationTracker); CacheAs(AvailabilityTracker); + CacheAs(new OverlayColourProvider(OverlayColourScheme.Plum)); } public object Get(Type type) From 3d7866e82da57bc422af3bb0cc22557653d10964 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Aug 2021 14:14:54 +0300 Subject: [PATCH 440/600] Calculate horizontal offset on present overlays only --- osu.Game/OsuGame.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b6809c0290..b8a4388282 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1015,9 +1015,9 @@ namespace osu.Game var horizontalOffset = 0f; - if (Settings.IsLoaded) + if (Settings.IsLoaded && Settings.IsPresent) horizontalOffset += (ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X) * SCREEN_OFFSET_RATIO; - if (Notifications.IsLoaded) + if (Notifications.IsLoaded && Notifications.IsPresent) horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SCREEN_OFFSET_RATIO; ScreenOffsetContainer.X = horizontalOffset; From bb1d74255e70081a806f9f3a9db773b6a3b06262 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Aug 2021 14:15:51 +0300 Subject: [PATCH 441/600] Remove unrequired parenthesis --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b8a4388282..f92f7e9e8c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1016,7 +1016,7 @@ namespace osu.Game var horizontalOffset = 0f; if (Settings.IsLoaded && Settings.IsPresent) - horizontalOffset += (ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X) * SCREEN_OFFSET_RATIO; + horizontalOffset += ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SCREEN_OFFSET_RATIO; if (Notifications.IsLoaded && Notifications.IsPresent) horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SCREEN_OFFSET_RATIO; From 40db228e910c90b87e719ff08da9f12e7219a5a5 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 12 Aug 2021 19:34:44 +0700 Subject: [PATCH 442/600] change to osu text flow container --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 477745e0ba..bdbba20f5c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, - new TextFlowContainer(t => + new OsuTextFlowContainer(t => { t.Font = t.Font.With(size: 12); t.Colour = colour.PinkLighter; From 66ba24e86540146fcab7ecba094e3d6d67c34da1 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 12 Aug 2021 20:36:47 +0700 Subject: [PATCH 443/600] create local link flow container --- .../Changelog/ChangelogSupporterPromo.cs | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index bdbba20f5c..f617b4fc82 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -12,6 +14,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -25,9 +28,6 @@ namespace osu.Game.Overlays.Changelog private readonly FillFlowContainer textContainer; private readonly Container imageContainer; - [Cached] - private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); - public ChangelogSupporterPromo() { RelativeSizeAxes = Axes.X; @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load(OsuColour colour, TextureStore textures) { - LinkFlowContainer supportLinkText; + SupporterPromoLinkFlowContainer supportLinkText; textContainer.Children = new Drawable[] { new OsuSpriteText @@ -102,7 +102,7 @@ namespace osu.Game.Overlays.Changelog Font = OsuFont.GetFont(size: 20, weight: FontWeight.Light), Margin = new MarginPadding { Bottom = 20 }, }, - supportLinkText = new LinkFlowContainer(t => + supportLinkText = new SupporterPromoLinkFlowContainer(t => { t.Font = t.Font.With(size: 14); t.Colour = colour.PinkLighter; @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Changelog }; supportLinkText.AddText("Support further development of osu! and "); - supportLinkText.AddLink("become an osu!supporter", "https://osu.ppy.sh/home/support", t => t.Font = t.Font.With(weight: FontWeight.Bold)); + supportLinkText.AddLink("become and osu!supporter", "https://osu.ppy.sh/home/support", t => t.Font = t.Font.With(weight: FontWeight.Bold)); supportLinkText.AddText(" today!"); imageContainer.Children = new Drawable[] @@ -149,5 +149,39 @@ namespace osu.Game.Overlays.Changelog }, }; } + + private class SupporterPromoLinkFlowContainer : LinkFlowContainer + { + public SupporterPromoLinkFlowContainer(Action defaultCreationParameters) + : base(defaultCreationParameters) + { + } + + public new void AddLink(string text, string url, Action creationParameters) => + AddInternal(new SupporterPromoLinkCompiler(AddText(text, creationParameters)) { Url = url }); + + private class SupporterPromoLinkCompiler : DrawableLinkCompiler + { + [Resolved(CanBeNull = true)] + private OsuGame game { get; set; } + + public string Url; + + public SupporterPromoLinkCompiler(IEnumerable parts) + : base(parts) + { + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + TooltipText = Url; + Action = () => game?.HandleLink(Url); + IdleColour = colour.PinkDark; + HoverColour = Color4.White; + } + } + } } } From 1069f9d50119bfc08e97cb28bc33a7608e568587 Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Fri, 13 Aug 2021 00:13:03 +1000 Subject: [PATCH 444/600] Always add cursor trail for legacy cursor with disjoint trail --- .../Skinning/Legacy/LegacyCursorTrail.cs | 24 ++++++++--- .../UI/Cursor/CursorTrail.cs | 43 ++++++++++++------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index f6fd3e36ab..f98d936b48 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -5,10 +5,12 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Shaders; using osu.Framework.Input.Events; using osu.Game.Configuration; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; +using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { @@ -21,14 +23,18 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private double lastTrailTime; private IBindable cursorSize; + private Vector2? currentPosition; + public LegacyCursorTrail(ISkin skin) { this.skin = skin; } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(ShaderManager shaders, OsuConfigManager config) { + Shader = shaders.Load(@"LegacyCursorTrail", FragmentShaderDescriptor.TEXTURE); + Texture = skin.GetTexture("cursortrail"); disjointTrail = skin.GetTexture("cursormiddle") == null; @@ -59,18 +65,24 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected override float IntervalMultiplier => 1 / Math.Max(cursorSize.Value, 1); - protected override bool OnMouseMove(MouseMoveEvent e) + protected override void Update() { - if (!disjointTrail) - return base.OnMouseMove(e); + base.Update(); + + if (!disjointTrail || !currentPosition.HasValue) + return; if (Time.Current - lastTrailTime >= disjoint_trail_time_separation) { lastTrailTime = Time.Current; - return base.OnMouseMove(e); + AddTrail(currentPosition.Value); } + } - return false; + protected override bool OnMouseMove(MouseMoveEvent e) + { + currentPosition = e.ScreenSpaceMousePosition; + return base.OnMouseMove(e); } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 7f86e9daf7..66a9302f5f 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -28,7 +28,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private int currentIndex; - private IShader shader; + + protected IShader Shader; + private double timeOffset; private float time; @@ -63,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor [BackgroundDependencyLoader] private void load(ShaderManager shaders) { - shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); + Shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); } protected override void LoadComplete() @@ -141,21 +143,32 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override bool OnMouseMove(MouseMoveEvent e) { - Vector2 pos = e.ScreenSpaceMousePosition; + Vector2 position = e.ScreenSpaceMousePosition; if (lastPosition == null) { - lastPosition = pos; + lastPosition = position; resampler.AddPosition(lastPosition.Value); return base.OnMouseMove(e); } - foreach (Vector2 pos2 in resampler.AddPosition(pos)) - { - Trace.Assert(lastPosition.HasValue); + if (InterpolateMovements) + AddTrail(position); - if (InterpolateMovements) + return base.OnMouseMove(e); + } + + protected void AddTrail(Vector2 position) + { + if (!lastPosition.HasValue) + return; + + if (InterpolateMovements) + { + foreach (Vector2 pos2 in resampler.AddPosition(position)) { + Trace.Assert(lastPosition.HasValue); + // ReSharper disable once PossibleInvalidOperationException Vector2 pos1 = lastPosition.Value; Vector2 diff = pos2 - pos1; @@ -170,14 +183,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor addPart(lastPosition.Value); } } - else - { - lastPosition = pos2; - addPart(lastPosition.Value); - } } - - return base.OnMouseMove(e); + else + { + lastPosition = position; + addPart(lastPosition.Value); + } } private void addPart(Vector2 screenSpacePosition) @@ -223,7 +234,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { base.ApplyState(); - shader = Source.shader; + shader = Source.Shader; texture = Source.texture; size = Source.partSize; time = Source.time; From 4d26bb67142d47283ea9ed7a223eaad2ccfd0957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 19:27:32 +0200 Subject: [PATCH 445/600] Scale score panel to remove overlap with team score display --- .../OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 0e4655e336..8b7aaa02e7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -15,6 +14,7 @@ using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play.HUD; +using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer { @@ -36,6 +36,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [BackgroundDependencyLoader] private void load() { + ScorePanelList.Anchor = ScorePanelList.Origin = Anchor.TopCentre; + ScorePanelList.Scale = new Vector2(0.9f); + ScorePanelList.Y = 75; + if (teamScores.Count == 2) { var redScore = teamScores.First().Value; From 828268ad4dfd50a83d7a919de8c29b9df7887047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 19:32:23 +0200 Subject: [PATCH 446/600] Add winner text background to increase contrast --- .../Multiplayer/MultiplayerResultsScreen.cs | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 8b7aaa02e7..92b20f4915 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -6,7 +6,10 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Localisation; @@ -22,6 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { private readonly SortedDictionary teamScores; + private Container winnerBackground; private Drawable winnerText; public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) @@ -36,6 +40,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [BackgroundDependencyLoader] private void load() { + const float winner_background_half_height = 250; + ScorePanelList.Anchor = ScorePanelList.Origin = Anchor.TopCentre; ScorePanelList.Scale = new Vector2(0.9f); ScorePanelList.Y = 75; @@ -59,6 +65,32 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Team1Score = { BindTarget = redScore }, Team2Score = { BindTarget = blueScore }, }, + winnerBackground = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.X, + Height = winner_background_half_height, + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0), Colour4.Black.Opacity(0.4f)) + }, + new Box + { + RelativeSizeAxes = Axes.X, + Height = winner_background_half_height, + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0.4f), Colour4.Black.Opacity(0)) + } + } + }, (winnerText = new OsuSpriteText { Alpha = 0, @@ -83,7 +115,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer using (BeginDelayedSequence(300)) { - winnerText.FadeInFromZero(600, Easing.InQuint); + const double fade_in_duration = 600; + + winnerText.FadeInFromZero(fade_in_duration, Easing.InQuint); + winnerBackground.FadeInFromZero(fade_in_duration, Easing.InQuint); winnerText .ScaleTo(10) @@ -91,6 +126,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer .Then() .ScaleTo(1.02f, 1600, Easing.OutQuint) .FadeOut(5000, Easing.InQuad); + winnerBackground.Delay(2200).FadeOut(2000); } } } From d08d22e3e943c5e411dfe5198cc09f1f06691306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 19:48:57 +0200 Subject: [PATCH 447/600] Ensure tests wait for screen load --- .../Multiplayer/TestSceneMultiplayerTeamResults.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index 2b04955d5e..94043c311a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -18,6 +18,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDisplayWithTeams() { + MultiplayerResultsScreen screen = null; + AddStep("show results screen", () => { var rulesetInfo = new OsuRuleset().RulesetInfo; @@ -48,13 +50,17 @@ namespace osu.Game.Tests.Visual.Multiplayer { 1, new BindableInt(1048576) } }; - Stack.Push(new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); + Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); }); + + AddUntilStep("wait for loaded", () => screen.IsLoaded); } [Test] public void TestDisplayWithoutTeams() { + MultiplayerResultsScreen screen = null; + AddStep("show results screen", () => { var rulesetInfo = new OsuRuleset().RulesetInfo; @@ -81,8 +87,10 @@ namespace osu.Game.Tests.Visual.Multiplayer SortedDictionary teamScores = new SortedDictionary(); - Stack.Push(new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); + Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); }); + + AddUntilStep("wait for loaded", () => screen.IsLoaded); } } } From f06f13215b731a39d9128a30d52d3449fd3277ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 20:01:31 +0200 Subject: [PATCH 448/600] Split off multiplayer team results screen to separate class The previous version tried to keep both normal multiplayer and team multiplayer results as one screen, but didn't check that team-specific components aren't null in `LoadComplete()`. To decrease number of conditional, split off the team results screen to a separate implementation, and choose one or the other at push time in `MultiplayerPlayer`, depending on team count. --- .../TestSceneMultiplayerTeamResults.cs | 6 +- .../Multiplayer/MultiplayerPlayer.cs | 4 +- .../Multiplayer/MultiplayerResultsScreen.cs | 118 +--------------- .../MultiplayerTeamResultsScreen.cs | 133 ++++++++++++++++++ 4 files changed, 139 insertions(+), 122 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index 94043c311a..8878cbdfcb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { 1, new BindableInt(1048576) } }; - Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); + Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, playlistItem, teamScores)); }); AddUntilStep("wait for loaded", () => screen.IsLoaded); @@ -85,9 +85,7 @@ namespace osu.Game.Tests.Visual.Multiplayer BeatmapID = beatmapInfo.ID, }; - SortedDictionary teamScores = new SortedDictionary(); - - Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem, teamScores)); + Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem)); }); AddUntilStep("wait for loaded", () => screen.IsLoaded); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 3c892d03df..ca1a3710ab 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -181,7 +181,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override ResultsScreen CreateResults(ScoreInfo score) { Debug.Assert(RoomId.Value != null); - return new MultiplayerResultsScreen(score, RoomId.Value.Value, PlaylistItem, leaderboard.TeamScores); + return leaderboard.TeamScores.Count == 2 + ? new MultiplayerTeamResultsScreen(score, RoomId.Value.Value, PlaylistItem, leaderboard.TeamScores) + : new MultiplayerResultsScreen(score, RoomId.Value.Value, PlaylistItem); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 92b20f4915..140b3c45d8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -1,133 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Localisation; using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; -using osu.Game.Screens.Play.HUD; -using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer { public class MultiplayerResultsScreen : PlaylistsResultsScreen { - private readonly SortedDictionary teamScores; - - private Container winnerBackground; - private Drawable winnerText; - - public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) + public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem) : base(score, roomId, playlistItem, false, false) { - this.teamScores = teamScores; - } - - [Resolved] - private OsuColour colours { get; set; } - - [BackgroundDependencyLoader] - private void load() - { - const float winner_background_half_height = 250; - - ScorePanelList.Anchor = ScorePanelList.Origin = Anchor.TopCentre; - ScorePanelList.Scale = new Vector2(0.9f); - ScorePanelList.Y = 75; - - if (teamScores.Count == 2) - { - var redScore = teamScores.First().Value; - var blueScore = teamScores.Last().Value; - - // eventually this will be replaced by team names coming from the multiplayer match state. - string winner = redScore.Value > blueScore.Value ? @"Red" : @"Blue"; - - var winnerColour = redScore.Value > blueScore.Value ? colours.TeamColourRed : colours.TeamColourBlue; - - AddRangeInternal(new Drawable[] - { - new MatchScoreDisplay - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Team1Score = { BindTarget = redScore }, - Team2Score = { BindTarget = blueScore }, - }, - winnerBackground = new Container - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Alpha = 0, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.X, - Height = winner_background_half_height, - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0), Colour4.Black.Opacity(0.4f)) - }, - new Box - { - RelativeSizeAxes = Axes.X, - Height = winner_background_half_height, - Anchor = Anchor.Centre, - Origin = Anchor.TopCentre, - Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0.4f), Colour4.Black.Opacity(0)) - } - } - }, - (winnerText = new OsuSpriteText - { - Alpha = 0, - Font = OsuFont.Torus.With(size: 80, weight: FontWeight.Bold), - Text = MultiplayerResultsScreenStrings.TeamWins(winner), - Blending = BlendingParameters.Additive - }).WithEffect(new GlowEffect - { - Colour = winnerColour, - }).With(e => - { - e.Anchor = Anchor.Centre; - e.Origin = Anchor.Centre; - }) - }); - } - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - using (BeginDelayedSequence(300)) - { - const double fade_in_duration = 600; - - winnerText.FadeInFromZero(fade_in_duration, Easing.InQuint); - winnerBackground.FadeInFromZero(fade_in_duration, Easing.InQuint); - - winnerText - .ScaleTo(10) - .ScaleTo(1, 600, Easing.InQuad) - .Then() - .ScaleTo(1.02f, 1600, Easing.OutQuint) - .FadeOut(5000, Easing.InQuad); - winnerBackground.Delay(2200).FadeOut(2000); - } } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs new file mode 100644 index 0000000000..fc5b72e210 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs @@ -0,0 +1,133 @@ +// 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 System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Localisation; +using osu.Game.Online.Rooms; +using osu.Game.Scoring; +using osu.Game.Screens.Play.HUD; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Multiplayer +{ + public class MultiplayerTeamResultsScreen : MultiplayerResultsScreen + { + private readonly SortedDictionary teamScores; + + private Container winnerBackground; + private Drawable winnerText; + + public MultiplayerTeamResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, SortedDictionary teamScores) + : base(score, roomId, playlistItem) + { + if (teamScores.Count != 2) + throw new NotSupportedException(@"This screen currently only supports 2 teams"); + + this.teamScores = teamScores; + } + + [Resolved] + private OsuColour colours { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + const float winner_background_half_height = 250; + + ScorePanelList.Anchor = ScorePanelList.Origin = Anchor.TopCentre; + ScorePanelList.Scale = new Vector2(0.9f); + ScorePanelList.Y = 75; + + var redScore = teamScores.First().Value; + var blueScore = teamScores.Last().Value; + + // eventually this will be replaced by team names coming from the multiplayer match state. + string winner = redScore.Value > blueScore.Value ? @"Red" : @"Blue"; + + var winnerColour = redScore.Value > blueScore.Value ? colours.TeamColourRed : colours.TeamColourBlue; + + AddRangeInternal(new Drawable[] + { + new MatchScoreDisplay + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Team1Score = { BindTarget = redScore }, + Team2Score = { BindTarget = blueScore }, + }, + winnerBackground = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.X, + Height = winner_background_half_height, + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0), Colour4.Black.Opacity(0.4f)) + }, + new Box + { + RelativeSizeAxes = Axes.X, + Height = winner_background_half_height, + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + Colour = ColourInfo.GradientVertical(Colour4.Black.Opacity(0.4f), Colour4.Black.Opacity(0)) + } + } + }, + (winnerText = new OsuSpriteText + { + Alpha = 0, + Font = OsuFont.Torus.With(size: 80, weight: FontWeight.Bold), + Text = MultiplayerResultsScreenStrings.TeamWins(winner), + Blending = BlendingParameters.Additive + }).WithEffect(new GlowEffect + { + Colour = winnerColour, + }).With(e => + { + e.Anchor = Anchor.Centre; + e.Origin = Anchor.Centre; + }) + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + using (BeginDelayedSequence(300)) + { + const double fade_in_duration = 600; + + winnerText.FadeInFromZero(fade_in_duration, Easing.InQuint); + winnerBackground.FadeInFromZero(fade_in_duration, Easing.InQuint); + + winnerText + .ScaleTo(10) + .ScaleTo(1, 600, Easing.InQuad) + .Then() + .ScaleTo(1.02f, 1600, Easing.OutQuint) + .FadeOut(5000, Easing.InQuad); + winnerBackground.Delay(2200).FadeOut(2000); + } + } + } +} From d9190607e43dfea970ea56e97d3b151c4cb9321a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 20:21:53 +0200 Subject: [PATCH 449/600] Add test coverage for both teams winning --- .../Multiplayer/TestSceneMultiplayerTeamResults.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index 8878cbdfcb..d6a2988685 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -15,8 +15,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerTeamResults : ScreenTestScene { - [Test] - public void TestDisplayWithTeams() + [TestCase(7483253, 1048576)] + [TestCase(1048576, 7483253)] + public void TestDisplayWithTeams(int team1Score, int team2Score) { MultiplayerResultsScreen screen = null; @@ -46,8 +47,8 @@ namespace osu.Game.Tests.Visual.Multiplayer SortedDictionary teamScores = new SortedDictionary { - { 0, new BindableInt(7483253) }, - { 1, new BindableInt(1048576) } + { 0, new BindableInt(team1Score) }, + { 1, new BindableInt(team2Score) } }; Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, playlistItem, teamScores)); From 53b4cdfb0269f5861c725fc33e8fc467ebe707e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 20:38:24 +0200 Subject: [PATCH 450/600] Handle ties in team vs. results screen --- .../TestSceneMultiplayerTeamResults.cs | 1 + ...=> MultiplayerTeamResultsScreenStrings.cs} | 9 +++++-- .../MultiplayerTeamResultsScreen.cs | 27 ++++++++++++++++--- 3 files changed, 31 insertions(+), 6 deletions(-) rename osu.Game/Localisation/{MultiplayerResultsScreenStrings.cs => MultiplayerTeamResultsScreenStrings.cs} (64%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index d6a2988685..a21996383f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -17,6 +17,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { [TestCase(7483253, 1048576)] [TestCase(1048576, 7483253)] + [TestCase(1048576, 1048576)] public void TestDisplayWithTeams(int team1Score, int team2Score) { MultiplayerResultsScreen screen = null; diff --git a/osu.Game/Localisation/MultiplayerResultsScreenStrings.cs b/osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs similarity index 64% rename from osu.Game/Localisation/MultiplayerResultsScreenStrings.cs rename to osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs index e586faba66..111c068bbd 100644 --- a/osu.Game/Localisation/MultiplayerResultsScreenStrings.cs +++ b/osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs @@ -5,15 +5,20 @@ using osu.Framework.Localisation; namespace osu.Game.Localisation { - public static class MultiplayerResultsScreenStrings + public static class MultiplayerTeamResultsScreenStrings { - private const string prefix = @"osu.Game.Resources.Localisation.MultiplayerResultsScreen"; + private const string prefix = @"osu.Game.Resources.Localisation.MultiplayerTeamResultsScreen"; /// /// "Team {0} wins!" /// public static LocalisableString TeamWins(string winner) => new TranslatableString(getKey(@"team_wins"), @"Team {0} wins!", winner); + /// + /// "The teams are tied!" + /// + public static LocalisableString TheTeamsAreTied => new TranslatableString(getKey(@"the_teams_are_tied"), @"The teams are tied!"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } \ No newline at end of file diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs index fc5b72e210..e98898b9da 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Localisation; @@ -52,10 +53,28 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer var redScore = teamScores.First().Value; var blueScore = teamScores.Last().Value; - // eventually this will be replaced by team names coming from the multiplayer match state. - string winner = redScore.Value > blueScore.Value ? @"Red" : @"Blue"; + LocalisableString winner; + Colour4 winnerColour; - var winnerColour = redScore.Value > blueScore.Value ? colours.TeamColourRed : colours.TeamColourBlue; + int comparison = redScore.Value.CompareTo(blueScore.Value); + + if (comparison < 0) + { + // team name should eventually be coming from the multiplayer match state. + winner = MultiplayerTeamResultsScreenStrings.TeamWins(@"Blue"); + winnerColour = colours.TeamColourBlue; + } + else if (comparison > 0) + { + // team name should eventually be coming from the multiplayer match state. + winner = MultiplayerTeamResultsScreenStrings.TeamWins(@"Red"); + winnerColour = colours.TeamColourRed; + } + else + { + winner = MultiplayerTeamResultsScreenStrings.TheTeamsAreTied; + winnerColour = Colour4.White.Opacity(0.5f); + } AddRangeInternal(new Drawable[] { @@ -96,7 +115,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { Alpha = 0, Font = OsuFont.Torus.With(size: 80, weight: FontWeight.Bold), - Text = MultiplayerResultsScreenStrings.TeamWins(winner), + Text = winner, Blending = BlendingParameters.Additive }).WithEffect(new GlowEffect { From 68f454b51a8ecc9753e21e323be29a9067b6b406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 21:09:08 +0200 Subject: [PATCH 451/600] Enable NRT in explosion-related classes and streamline null handling --- .../Skinning/Default/DefaultHitExplosion.cs | 3 --- .../Skinning/Legacy/LegacyHitExplosion.cs | 3 --- osu.Game.Rulesets.Catch/UI/HitExplosion.cs | 14 +++++++------- osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs | 2 ++ osu.Game.Rulesets.Catch/UI/IHitExplosion.cs | 2 ++ 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs index 680fbc7b15..e1fad564a3 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -72,9 +72,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default public void Animate(HitExplosionEntry entry) { - if (entry == null) - return; - X = entry.Position; Scale = new Vector2(entry.HitObject.Scale); setColour(entry.ObjectColour); diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index 78b0e1e327..08f86df2f3 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -62,9 +62,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy public void Animate(HitExplosionEntry entry) { - if (entry == null) - return; - Colour = entry.ObjectColour; using (BeginAbsoluteSequence(entry.LifetimeStart)) diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 35af39348d..955b1e6edb 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -1,28 +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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Skinning; +#nullable enable + namespace osu.Game.Rulesets.Catch.UI { public class HitExplosion : PoolableDrawableWithLifetime { - private SkinnableDrawable skinnableExplosion; + private readonly SkinnableDrawable skinnableExplosion; public HitExplosion() { RelativeSizeAxes = Axes.Both; Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; - } - [BackgroundDependencyLoader] - private void load() - { InternalChild = skinnableExplosion = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.HitExplosion), _ => new DefaultHitExplosion()) { CentreComponent = false, @@ -44,8 +41,11 @@ namespace osu.Game.Rulesets.Catch.UI apply(Entry); } - private void apply(HitExplosionEntry entry) + private void apply(HitExplosionEntry? entry) { + if (entry == null) + return; + ApplyTransformsAt(double.MinValue, true); ClearTransforms(true); diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs index 749a448314..815a0d8c98 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs @@ -6,6 +6,8 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; using osuTK.Graphics; +#nullable enable + namespace osu.Game.Rulesets.Catch.UI { public class HitExplosionEntry : LifetimeEntry diff --git a/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs b/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs index 4a9d7e8ac0..c744c00d9a 100644 --- a/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + namespace osu.Game.Rulesets.Catch.UI { /// From f3045b315285c1d82ce144c635055e47236df4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 21:13:45 +0200 Subject: [PATCH 452/600] Add comment about swapped sprite names --- osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index 08f86df2f3..c2570c4d1f 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -56,6 +56,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy { var defaultLegacySkin = skins.DefaultLegacySkin; + // sprite names intentionally swapped to match stable member naming / ease of cross-referencing explosion1.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-2"); explosion2.Texture = defaultLegacySkin.GetTexture("scoreboard-explosion-1"); } From e79150d4da09d35870380e2d92156ec9b011728e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 21:14:46 +0200 Subject: [PATCH 453/600] Reorder constructor arguments for `HitExplosionEntry` --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 2 +- osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index aec8e752a7..5cd85aac56 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -367,7 +367,7 @@ namespace osu.Game.Rulesets.Catch.UI } private void addLighting(JudgementResult judgementResult, Color4 colour, float x) => - hitExplosionContainer.Add(new HitExplosionEntry(judgementResult, colour, x, Time.Current)); + hitExplosionContainer.Add(new HitExplosionEntry(Time.Current, judgementResult, colour, x)); private CaughtObject getCaughtObject(PalpableCatchHitObject source) { diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs index 815a0d8c98..88871c77f6 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.UI /// public float Position { get; } - public HitExplosionEntry(JudgementResult judgementResult, Color4 objectColour, float position, double startTime) + public HitExplosionEntry(double startTime, JudgementResult judgementResult, Color4 objectColour, float position) { LifetimeStart = startTime; Position = position; From b84f2381065a00021c88361714387bf715441d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 12 Aug 2021 22:33:09 +0200 Subject: [PATCH 454/600] Adjust scaling numbers to be closer to stable --- osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index c2570c4d1f..c262b0a4ac 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; RelativeSizeAxes = Axes.Both; - Scale = new Vector2(0.4f); + Scale = new Vector2(0.5f); InternalChildren = new[] { @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy explosion1.Position = new Vector2(explosionOffset, 0); explosion1.FadeOutFromOne(300); - explosion1.ScaleTo(new Vector2(20 * scale, 1.1f), 160, Easing.Out); + explosion1.ScaleTo(new Vector2(16 * scale, 1.1f), 160, Easing.Out); } explosion2.Scale = new Vector2(0.9f, 1); From 7aa361d77280c14ea53d7a563a59d988a7b7f29c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 09:02:13 +0900 Subject: [PATCH 455/600] Remove now-incorrect test --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 7ff0368fc2..7f961d4c8b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -405,8 +405,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden); - testLeave("lounge tab item", () => this.ChildrenOfType.BreadcrumbTabItem>().First().TriggerClick()); - testLeave("back button", () => multiplayerScreen.OnBackButton()); // mimics home button and OS window close From 524102951348592f84312bb946e1eb85b40298c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 10:27:26 +0900 Subject: [PATCH 456/600] Use new FadeExponent shader uniform --- .../Skinning/Legacy/LegacyCursorTrail.cs | 6 ++---- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 17 +++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index f98d936b48..9493dc2ef1 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -5,7 +5,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Shaders; using osu.Framework.Input.Events; using osu.Game.Configuration; using osu.Game.Rulesets.Osu.UI.Cursor; @@ -31,10 +30,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy } [BackgroundDependencyLoader] - private void load(ShaderManager shaders, OsuConfigManager config) + private void load(OsuConfigManager config) { - Shader = shaders.Load(@"LegacyCursorTrail", FragmentShaderDescriptor.TEXTURE); - Texture = skin.GetTexture("cursortrail"); disjointTrail = skin.GetTexture("cursormiddle") == null; @@ -60,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy } protected override double FadeDuration => disjointTrail ? 150 : 500; + protected override float FadeExponent => 1; protected override bool InterpolateMovements => !disjointTrail; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 66a9302f5f..b05bf5c93e 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -26,11 +26,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { private const int max_sprites = 2048; + /// + /// An exponentiating factor to ease the trail fade. + /// + protected virtual float FadeExponent => 1.7f; + private readonly TrailPart[] parts = new TrailPart[max_sprites]; private int currentIndex; - - protected IShader Shader; - + private IShader shader; private double timeOffset; private float time; @@ -65,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor [BackgroundDependencyLoader] private void load(ShaderManager shaders) { - Shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); + shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); } protected override void LoadComplete() @@ -217,10 +220,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private Texture texture; private float time; + private float fadeExponent; private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private Vector2 originPosition; private readonly QuadBatch vertexBatch = new QuadBatch(max_sprites, 1); @@ -234,10 +237,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { base.ApplyState(); - shader = Source.Shader; + shader = Source.shader; texture = Source.texture; size = Source.partSize; time = Source.time; + fadeExponent = Source.FadeExponent; originPosition = Vector2.Zero; @@ -260,6 +264,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor shader.Bind(); shader.GetUniform("g_FadeClock").UpdateValue(ref time); + shader.GetUniform("g_FadeExponent").UpdateValue(ref fadeExponent); texture.TextureGL.Bind(); From 7cc0a2a76fdb8acecf4502bac1a75279c9b29e49 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 12:10:33 +0900 Subject: [PATCH 457/600] Refactor to fix InterpolateMovements=false --- .../Skinning/Legacy/LegacyCursorTrail.cs | 7 +++++- .../UI/Cursor/CursorTrail.cs | 24 +++++++------------ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index 9493dc2ef1..587ff4b573 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -79,8 +79,13 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected override bool OnMouseMove(MouseMoveEvent e) { + if (!disjointTrail) + return base.OnMouseMove(e); + currentPosition = e.ScreenSpaceMousePosition; - return base.OnMouseMove(e); + + // Intentionally block the base call as we're adding the trails ourselves. + return false; } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index b05bf5c93e..7a95111c91 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -146,33 +146,25 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override bool OnMouseMove(MouseMoveEvent e) { - Vector2 position = e.ScreenSpaceMousePosition; - - if (lastPosition == null) - { - lastPosition = position; - resampler.AddPosition(lastPosition.Value); - return base.OnMouseMove(e); - } - - if (InterpolateMovements) - AddTrail(position); - + AddTrail(e.ScreenSpaceMousePosition); return base.OnMouseMove(e); } protected void AddTrail(Vector2 position) { - if (!lastPosition.HasValue) - return; - if (InterpolateMovements) { + if (!lastPosition.HasValue) + { + lastPosition = position; + resampler.AddPosition(lastPosition.Value); + return; + } + foreach (Vector2 pos2 in resampler.AddPosition(position)) { Trace.Assert(lastPosition.HasValue); - // ReSharper disable once PossibleInvalidOperationException Vector2 pos1 = lastPosition.Value; Vector2 diff = pos2 - pos1; float distance = diff.Length; From 2b86416cb268e717633b8f6d65d9772bb1ea022b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 06:27:57 +0300 Subject: [PATCH 458/600] Hide player settings overlay on multi-spectator player loader --- .../Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs | 7 +++++++ osu.Game/Screens/Play/PlayerLoader.cs | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 5a1d28e9c4..52e4a6e012 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -3,6 +3,7 @@ using System; using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Game.Scoring; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; @@ -19,6 +20,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { } + [BackgroundDependencyLoader] + private void load() + { + PlayerSettingsGroups.Alpha = 0f; + } + protected override void LogoArriving(OsuLogo logo, bool resuming) { } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 5f6b4ca2b0..1f8387ac67 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -48,6 +48,11 @@ namespace osu.Game.Screens.Play protected BeatmapMetadataDisplay MetadataInfo; + /// + /// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader. + /// + protected FillFlowContainer PlayerSettingsGroups; + protected VisualSettings VisualSettings; protected Task LoadTask { get; private set; } @@ -140,7 +145,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new FillFlowContainer + PlayerSettingsGroups = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From c10320f23914fd8f15ff0c5ee30ca943a5de8519 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 06:28:07 +0300 Subject: [PATCH 459/600] Hide and disable player settings overlay on multi-spectator player --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 4 ++++ osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 +- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 2c157b0564..71defa2e07 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Scoring; @@ -34,6 +35,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private void load() { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); + + HUDOverlay.PlayerSettingsOverlay.State.Value = Visibility.Hidden; + HUDOverlay.PlayerSettingsOverlay.State.Disabled = true; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index ffcbb06fb3..efd37194d3 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play.HUD if (e.ControlPressed) { - if (e.Key == Key.H && ReplayLoaded) + if (e.Key == Key.H && ReplayLoaded && !State.Disabled) { ToggleVisibility(); return true; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 2cf2555b3e..919886cae7 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -240,13 +240,17 @@ namespace osu.Game.Screens.Play if (e.NewValue) { - PlayerSettingsOverlay.Show(); + if (!PlayerSettingsOverlay.State.Disabled) + PlayerSettingsOverlay.Show(); + ModDisplay.FadeIn(200); KeyCounter.Margin = new MarginPadding(10) { Bottom = 30 }; } else { - PlayerSettingsOverlay.Hide(); + if (!PlayerSettingsOverlay.State.Disabled) + PlayerSettingsOverlay.Hide(); + ModDisplay.Delay(2000).FadeOut(200); KeyCounter.Margin = new MarginPadding(10); } From 1892db7f37e0d916826fef0d4788da4d78ce2531 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 06:31:39 +0300 Subject: [PATCH 460/600] Add test coverage --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 65b1d6d53a..ad60582ace 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -6,6 +6,7 @@ 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.Beatmaps; using osu.Game.Online.Multiplayer; @@ -13,6 +14,8 @@ using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Tests.Beatmaps.IO; using osu.Game.Users; @@ -80,6 +83,19 @@ namespace osu.Game.Tests.Visual.Multiplayer AddWaitStep("wait a bit", 20); } + [Test] + public void TestSpectatorPlayerSettingsHidden() + { + start(new[] { PLAYER_1_ID, PLAYER_2_ID }); + loadSpectateScreen(false); + + AddUntilStep("wait for player loaders", () => this.ChildrenOfType().Count() == 2); + AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => l.ChildrenOfType>().Single().Alpha == 0f)); + + AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); + AddAssert("all player settings hidden", () => this.ChildrenOfType().All(p => p.ChildrenOfType().Single().State.Value == Visibility.Hidden)); + } + [Test] public void TestTeamDisplay() { From e913c8f92fdff9cd6f76c5b63cd079e15b8bbc8a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 13:07:02 +0900 Subject: [PATCH 461/600] Change strings to verbatim --- .../OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs | 2 +- .../Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index a7eaa37faa..ad7882abc2 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override FilterCriteria CreateFilterCriteria() { var criteria = base.CreateFilterCriteria(); - criteria.Category = "realtime"; + criteria.Category = @"realtime"; return criteria; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index 254769d06b..eee4d4f407 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -42,11 +42,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists switch (categoryDropdown.Current.Value) { case PlaylistsCategory.Normal: - criteria.Category = "normal"; + criteria.Category = @"normal"; break; case PlaylistsCategory.Spotlight: - criteria.Category = "spotlight"; + criteria.Category = @"spotlight"; break; } From cbeecff347b350458f4858ab97722f39c875bccf Mon Sep 17 00:00:00 2001 From: LiangXiang Shen Date: Fri, 13 Aug 2021 12:17:38 +0800 Subject: [PATCH 462/600] Apply suggestions from code review Co-authored-by: Joseph Madamba --- osu.Game/Localisation/GraphicsSettingsStrings.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 989eaf19b9..0e384f983f 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -55,14 +55,14 @@ namespace osu.Game.Localisation public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution"); /// - /// "UI Scaling" + /// "UI scaling" /// - public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI Scaling"); + public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI scaling"); /// - /// "Screen Scaling" + /// "Screen scaling" /// - public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen Scaling"); + public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen scaling"); /// /// "Horizontal position" @@ -95,14 +95,14 @@ namespace osu.Game.Localisation public static LocalisableString DetailSettingsHeader => new TranslatableString(getKey(@"detail_settings_header"), @"Detail Settings"); /// - /// "Storyboard / Video" + /// "Storyboard / video" /// - public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / Video"); + public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / video"); /// - /// "Hit Lighting" + /// "Hit lighting" /// - public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit Lighting"); + public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit lighting"); /// /// "Screenshot format" From e93660c0f4f0936828548479711d2c3031514128 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 13:19:34 +0900 Subject: [PATCH 463/600] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 454bb46059..33d3a623ed 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e6219fcb85..6ccd34dd48 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9904946363..b6623da540 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 2850f6ce95d9f9f258a68dce0874e75cdcc17ab2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 13:24:05 +0900 Subject: [PATCH 464/600] Privatise counter again --- .../Visual/Online/TestSceneOfflineCommentsContainer.cs | 4 +++- osu.Game/Overlays/Comments/CommentsContainer.cs | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index af0d06dce3..628ae0971b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; @@ -12,6 +13,7 @@ using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using JetBrains.Annotations; +using osu.Framework.Testing; namespace osu.Game.Tests.Visual.Online { @@ -186,7 +188,7 @@ namespace osu.Game.Tests.Visual.Online public void ShowComments(CommentBundle bundle) { - CommentCounter.Current.Value = 0; + this.ChildrenOfType().Single().Current.Value = 0; ClearComments(); OnSuccess(bundle); } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index ee24c4086b..fe8d6f0178 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Comments private FillFlowContainer content; private DeletedCommentsCounter deletedCommentsCounter; private CommentsShowMoreButton moreButton; - protected TotalCommentsCounter CommentCounter; + private TotalCommentsCounter commentCounter; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Comments Direction = FillDirection.Vertical, Children = new Drawable[] { - CommentCounter = new TotalCommentsCounter(), + commentCounter = new TotalCommentsCounter(), new CommentsHeader { Sort = { BindTarget = Sort }, @@ -143,7 +143,7 @@ namespace osu.Game.Overlays.Comments return; // only reset when changing ID/type. other refetch ops are generally just changing sort order. - CommentCounter.Current.Value = 0; + commentCounter.Current.Value = 0; refetchComments(); } @@ -181,7 +181,7 @@ namespace osu.Game.Overlays.Comments protected void OnSuccess(CommentBundle response) { - CommentCounter.Current.Value = response.Total; + commentCounter.Current.Value = response.Total; if (!response.Comments.Any()) { From 8dc7a925e7e4a05de0f288fa9bee5dc684169f54 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:28:57 +0300 Subject: [PATCH 465/600] Expire instead of hiding and disabling visibility state Since it's a temporary change until the spectator interface gets improved, no need to add further logic. --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 4 +--- .../Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs | 2 +- osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 +- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++------ 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 71defa2e07..b0ea361dbb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -4,7 +4,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Scoring; @@ -36,8 +35,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); - HUDOverlay.PlayerSettingsOverlay.State.Value = Visibility.Hidden; - HUDOverlay.PlayerSettingsOverlay.State.Disabled = true; + HUDOverlay.PlayerSettingsOverlay.Expire(); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 52e4a6e012..f28c2a1d48 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [BackgroundDependencyLoader] private void load() { - PlayerSettingsGroups.Alpha = 0f; + PlayerSettingsGroups.Expire(); } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index efd37194d3..ffcbb06fb3 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play.HUD if (e.ControlPressed) { - if (e.Key == Key.H && ReplayLoaded && !State.Disabled) + if (e.Key == Key.H && ReplayLoaded) { ToggleVisibility(); return true; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 919886cae7..2cf2555b3e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -240,17 +240,13 @@ namespace osu.Game.Screens.Play if (e.NewValue) { - if (!PlayerSettingsOverlay.State.Disabled) - PlayerSettingsOverlay.Show(); - + PlayerSettingsOverlay.Show(); ModDisplay.FadeIn(200); KeyCounter.Margin = new MarginPadding(10) { Bottom = 30 }; } else { - if (!PlayerSettingsOverlay.State.Disabled) - PlayerSettingsOverlay.Hide(); - + PlayerSettingsOverlay.Hide(); ModDisplay.Delay(2000).FadeOut(200); KeyCounter.Margin = new MarginPadding(10); } From e7cf6b2d2337168ecfd0442e3518efa87d7d2c07 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:29:55 +0300 Subject: [PATCH 466/600] Expire hold-to-quit button on multi-spectator player --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index b0ea361dbb..20381e0c48 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -36,6 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); HUDOverlay.PlayerSettingsOverlay.Expire(); + HUDOverlay.HoldToQuit.Expire(); } protected override void UpdateAfterChildren() From 34c2b317e240821b5c7038fa0b3d1afb45ac3be5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:30:09 +0300 Subject: [PATCH 467/600] Hide song progress bar on multi-spectator player --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 2 ++ osu.Game/Screens/Play/Player.cs | 12 +++++++++++- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 20381e0c48..1b1dee5ae2 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -35,6 +35,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); + AllowUserSeekingState.Value = false; + AllowUserSeekingState.Disabled = true; HUDOverlay.PlayerSettingsOverlay.Expire(); HUDOverlay.HoldToQuit.Expire(); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 09eaf1c543..dc37464a61 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -77,6 +77,10 @@ namespace osu.Game.Screens.Play protected readonly Bindable LocalUserPlaying = new Bindable(); + protected readonly Bindable AllowUserSeekingState = new Bindable(); + + public IBindable AllowUserSeeking => AllowUserSeekingState; + public int RestartCount; [Resolved] @@ -269,7 +273,13 @@ namespace osu.Game.Screens.Play DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); - DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); + DrawableRuleset.HasReplayLoaded.BindValueChanged(r => + { + if (!AllowUserSeekingState.Disabled) + AllowUserSeekingState.Value = r.NewValue; + + updateGameplayState(); + }); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index f28622f42e..8debe6243d 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Play if (drawableRuleset != null) { - AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded); + ((IBindable)AllowSeeking).BindTo(player.AllowUserSeeking); referenceClock = drawableRuleset.FrameStableClock; Objects = drawableRuleset.Objects; From fc22e806f44abddf493ab87bbe15f91a14e7c8c2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:30:24 +0300 Subject: [PATCH 468/600] Cover newly hidden/expired elements in existing test --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index ad60582ace..a9004987df 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -90,10 +90,13 @@ namespace osu.Game.Tests.Visual.Multiplayer loadSpectateScreen(false); AddUntilStep("wait for player loaders", () => this.ChildrenOfType().Count() == 2); - AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => l.ChildrenOfType>().Single().Alpha == 0f)); + AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => !l.ChildrenOfType>().Any())); AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); - AddAssert("all player settings hidden", () => this.ChildrenOfType().All(p => p.ChildrenOfType().Single().State.Value == Visibility.Hidden)); + AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => + !p.ChildrenOfType().Any() && + !p.ChildrenOfType().Any() && + !p.ChildrenOfType().Single().ShowHandle)); } [Test] From 8fc0edb283390c9f27955a0ecc8149312692877a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 13:54:52 +0900 Subject: [PATCH 469/600] Fix some multiplayer test failures --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 4 ++++ .../Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 0ffa5209e3..01e40e0247 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -312,6 +312,8 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.Click(MouseButton.Left); }); + AddUntilStep("wait for spectating user state", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddStep("start match externally", () => client.StartMatch()); AddAssert("play not started", () => multiplayerScreen.IsCurrentScreen()); @@ -348,6 +350,8 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.Click(MouseButton.Left); }); + AddUntilStep("wait for spectating user state", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddStep("start match externally", () => client.StartMatch()); AddStep("restore beatmap", () => diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 955be6ca21..ea10fc1b8b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -129,6 +129,8 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.Click(MouseButton.Left); }); + AddUntilStep("wait for spectating user state", () => Client.LocalUser?.State == MultiplayerUserState.Spectating); + AddUntilStep("wait for ready button to be enabled", () => this.ChildrenOfType().Single().ChildrenOfType().Single().Enabled.Value); AddStep("click ready button", () => From 8fd6a9eb4b403c33d656f79bea54df49782eb562 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:01:38 +0900 Subject: [PATCH 470/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 454bb46059..ecfaff0547 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e6219fcb85..9ee1ad167e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 9904946363..c378f24b69 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 755b6460b624c164f63f9e2419f38effce2124e0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 14:04:43 +0900 Subject: [PATCH 471/600] Fix multiplayer navigation test failure --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 4 ++-- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 +++++ .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 2 +- .../Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 0ffa5209e3..35beefaa2a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -25,7 +25,7 @@ using osu.Game.Screens; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; -using osu.Game.Screens.OnlinePlay.Match.Components; +using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Tests.Resources; @@ -396,7 +396,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddStep("open mod overlay", () => this.ChildrenOfType().ElementAt(2).TriggerClick()); + AddStep("open mod overlay", () => this.ChildrenOfType().Single().TriggerClick()); AddStep("invoke on back button", () => multiplayerScreen.OnBackButton()); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index a53e253581..2616abf825 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -17,6 +17,7 @@ using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Match { @@ -250,5 +251,9 @@ namespace osu.Game.Screens.OnlinePlay.Match private class UserModSelectOverlay : LocalPlayerModSelectOverlay { } + + public class UserModSelectButton : PurpleTriangleButton + { + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 9fa19aaf21..a8e44dd56c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -176,7 +176,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Spacing = new Vector2(10, 0), Children = new Drawable[] { - new PurpleTriangleButton + new UserModSelectButton { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 45aca24ab2..953c687087 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -163,7 +163,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Spacing = new Vector2(10, 0), Children = new Drawable[] { - new PurpleTriangleButton + new UserModSelectButton { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, From 89eded457c094701a1c4532a546cfe96df50db80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:27:28 +0900 Subject: [PATCH 472/600] Fix weird margins on loading display in lounge --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 122b30b1d2..910afb5540 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -63,6 +63,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { OsuScrollContainer scrollContainer; + Container filterContainer; + InternalChildren = new Drawable[] { new Box @@ -93,7 +95,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { new Drawable[] { - new Container + filterContainer = new Container { RelativeSizeAxes = Axes.X, Height = 70, @@ -123,13 +125,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge ScrollbarOverlapsContent = false, Child = roomsContainer = new RoomsContainer() }, - loadingLayer = new LoadingLayer(true), } }, } } }, - } + }, + loadingLayer = new LoadingLayer(true), + filterContainer.CreateProxy() }; // scroll selected room into view on selection. From 0f45155b8e1b25a7a64698af618b1dcd7cde57e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:29:28 +0900 Subject: [PATCH 473/600] Fix remaining cases of invalid bindable operations during lease --- .../Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 3b0f2c1eba..46d9850fde 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -154,7 +154,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected override bool OnClick(ClickEvent e) { - selectedRoom.Value = null; + if (!selectedRoom.Disabled) + selectedRoom.Value = null; return base.OnClick(e); } @@ -216,6 +217,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void selectNext(int direction) { + if (selectedRoom.Disabled) + return; + var visibleRooms = Rooms.AsEnumerable().Where(r => r.IsPresent); Room room; From b9721f5261c52a42e6eabec465a55e6b6d024431 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:37:43 +0900 Subject: [PATCH 474/600] Centralise screen exit logic and guard against non-current screen --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 36b86737bc..265b68afea 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -274,7 +274,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer isConnected.BindValueChanged(connected => { if (!connected.NewValue) - Schedule(this.Exit); + handleRoomLost(); }, true); currentRoom.BindValueChanged(room => @@ -284,7 +284,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // the room has gone away. // this could mean something happened during the join process, or an external connection issue occurred. // one specific scenario is where the underlying room is created, but the signalr server returns an error during the join process. this triggers a PartRoom operation (see https://github.com/ppy/osu/blob/7654df94f6f37b8382be7dfcb4f674e03bd35427/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs#L97) - Schedule(this.Exit); + handleRoomLost(); } }, true); } @@ -451,13 +451,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // may happen if the client is kicked or otherwise removed from the room. if (client.Room == null) { - Schedule(this.Exit); + handleRoomLost(); return; } Scheduler.AddOnce(UpdateMods); } + private void handleRoomLost() => Schedule(() => + { + if (this.IsCurrentScreen()) + this.Exit(); + else + ValidForResume = false; + }); + private void onLoadRequested() { if (BeatmapAvailability.Value.State != DownloadState.LocallyAvailable) From a1b72e7f97731b072a3a1fb204fd12310e239bdb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:41:07 +0900 Subject: [PATCH 475/600] Remove redundant array type specification --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 910afb5540..fb0b963167 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Container filterContainer; - InternalChildren = new Drawable[] + InternalChildren = new[] { new Box { From 641d57e5e1657cc8ca26aea5031e47de7d3256ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:46:28 +0900 Subject: [PATCH 476/600] Change scroll container subclass name to hopefully read better --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 14fcaa91fa..0f1ddedcf0 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play.HUD InternalChildren = new Drawable[] { - scroll = new ManualScrollScrollContainer + scroll = new InputDisabledScrollContainer { RelativeSizeAxes = Axes.Both, Child = Flow = new FillFlowContainer @@ -174,9 +174,9 @@ namespace osu.Game.Screens.Play.HUD sorting.Validate(); } - private class ManualScrollScrollContainer : OsuScrollContainer + private class InputDisabledScrollContainer : OsuScrollContainer { - public ManualScrollScrollContainer() + public InputDisabledScrollContainer() { ScrollbarVisible = false; } From 93574acf729981a8e925fc3edd0342bb444e56f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:46:57 +0900 Subject: [PATCH 477/600] Fix exception messaging --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 0f1ddedcf0..312eeec949 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play.HUD if (isTracked) { if (trackedScore != null) - throw new InvalidOperationException("Cannot track more than one scores."); + throw new InvalidOperationException("Cannot track more than one score."); trackedScore = drawable; } From 90755c0307b8af7de3c7c3d624be9d0b012e8d9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:50:59 +0900 Subject: [PATCH 478/600] Replace condition with matching precalculated bool --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 312eeec949..871555e5a3 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Play.HUD c.Colour = Color4.Transparent; else { - if (bottomY - fadeBottom > 0 && requiresScroll) + if (requireBottomFade) { c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / panel_height, 1)), From c5ee8753b43a3713073707aeb799d20fc1d82378 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 09:20:52 +0300 Subject: [PATCH 479/600] Notify users to read OpenTabletDriver's FAQ when tablet not detected --- .../Settings/Sections/Input/TabletSettings.cs | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index c7342c251d..7595ca59cb 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -1,6 +1,7 @@ // 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; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -9,9 +10,12 @@ using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Framework.Threading; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; using osu.Game.Localisation; +using osu.Game.Online.Chat; namespace osu.Game.Overlays.Settings.Sections.Input { @@ -52,7 +56,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private FillFlowContainer mainSettings; - private OsuSpriteText noTabletMessage; + private FillFlowContainer noTabletMessage; protected override LocalisableString Header => TabletSettingsStrings.Tablet; @@ -62,7 +66,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { Children = new Drawable[] { @@ -73,12 +77,41 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.TopCentre, Current = tabletHandler.Enabled }, - noTabletMessage = new OsuSpriteText + noTabletMessage = new FillFlowContainer { - Text = TabletSettingsStrings.NoTabletDetected, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, + Spacing = new Vector2(5f), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = TabletSettingsStrings.NoTabletDetected, + }, + new LinkFlowContainer + { + TextAnchor = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }.With(t => + { + t.NewLine(); + t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); + t.NewParagraph(); + t.AddText("read ", s => s.Colour = colours.Yellow); + t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows + ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" + : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); + + t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + }), + } }, mainSettings = new FillFlowContainer { From 5cec50bdd14ad16b4b07e14605cb9d5d3dd2eddf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 15:24:43 +0900 Subject: [PATCH 480/600] Add comment mentioning why event bindings are not unbound --- osu.Game/Screens/OnlinePlay/Header.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/Header.cs b/osu.Game/Screens/OnlinePlay/Header.cs index 58c67a51e8..b0db9256f5 100644 --- a/osu.Game/Screens/OnlinePlay/Header.cs +++ b/osu.Game/Screens/OnlinePlay/Header.cs @@ -35,6 +35,7 @@ namespace osu.Game.Screens.OnlinePlay Origin = Anchor.CentreLeft, }; + // unnecessary to unbind these as this header has the same lifetime as the screen stack we are attaching to. stack.ScreenPushed += (_, __) => updateSubScreenTitle(); stack.ScreenExited += (_, __) => updateSubScreenTitle(); } From 3b6a8a2bae61e342da76a735cc49c97cf9c5d99d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 15:24:53 +0900 Subject: [PATCH 481/600] Rename background sprite and reduce load delay --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 978b35e4b1..c2ad0285b1 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -108,7 +108,7 @@ namespace osu.Game.Screens.OnlinePlay { RelativeSizeAxes = Axes.Both, BlurSigma = new Vector2(10), - Child = new HeaderBackgroundSprite + Child = new BeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } @@ -304,13 +304,13 @@ namespace osu.Game.Screens.OnlinePlay } } - private class HeaderBackgroundSprite : OnlinePlayBackgroundSprite + private class BeatmapBackgroundSprite : OnlinePlayBackgroundSprite { protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; private class BackgroundSprite : UpdateableBeatmapBackgroundSprite { - protected override double TransformDuration => 200; + protected override double LoadDelay => 200; } } From 543f6039e24071c28e18ae838185d863257638cb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 09:26:53 +0300 Subject: [PATCH 482/600] Display on Windows and Linux only --- .../Settings/Sections/Input/TabletSettings.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 7595ca59cb..9ed85e44ec 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -101,15 +101,18 @@ namespace osu.Game.Overlays.Settings.Sections.Input AutoSizeAxes = Axes.Y, }.With(t => { - t.NewLine(); - t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); - t.NewParagraph(); - t.AddText("read ", s => s.Colour = colours.Yellow); - t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows - ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" - : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); + if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux) + { + t.NewLine(); + t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); + t.NewParagraph(); + t.AddText("read ", s => s.Colour = colours.Yellow); + t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows + ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" + : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); - t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + } }), } }, From dd7ca4b77b45ae0f69078afd1fdbedf7e82cad80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 15:35:45 +0900 Subject: [PATCH 483/600] Increase "create room" button height --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 1c28405e40..7249ccdd93 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -30,8 +30,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Cached] public abstract class LoungeSubScreen : OnlinePlaySubScreen { - private const float button_height = 25; - public override string Title => "Lounge"; protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); @@ -93,7 +91,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, Header.HEIGHT), - new Dimension(GridSizeMode.Absolute, button_height), + new Dimension(GridSizeMode.Absolute, 25), new Dimension(GridSizeMode.Absolute, 20) }, Content = new[] @@ -118,7 +116,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { Buttons.WithChild(CreateNewRoomButton().With(d => { - d.Size = new Vector2(150, button_height); + d.Anchor = Anchor.BottomLeft; + d.Origin = Anchor.BottomLeft; + d.Size = new Vector2(150, 37.5f); d.Action = () => Open(); })), new FillFlowContainer From f9f3339885152bed5bf6eaf46ba4bbf9e024b396 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 16:14:23 +0900 Subject: [PATCH 484/600] Fix vertical offset not being handled correctly during score panel detach process --- .../Multiplayer/MultiplayerTeamResultsScreen.cs | 6 +++--- osu.Game/Screens/Ranking/ResultsScreen.cs | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs index e98898b9da..14a779dedf 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs @@ -46,9 +46,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { const float winner_background_half_height = 250; - ScorePanelList.Anchor = ScorePanelList.Origin = Anchor.TopCentre; - ScorePanelList.Scale = new Vector2(0.9f); - ScorePanelList.Y = 75; + VerticalScrollContent.Anchor = VerticalScrollContent.Origin = Anchor.TopCentre; + VerticalScrollContent.Scale = new Vector2(0.9f); + VerticalScrollContent.Y = 75; var redScore = teamScores.First().Value; var blueScore = teamScores.Last().Value; diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index b458d7c17f..d44d1f2cc9 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -40,6 +40,8 @@ namespace osu.Game.Screens.Ranking protected ScorePanelList ScorePanelList { get; private set; } + protected VerticalScrollContainer VerticalScrollContent { get; private set; } + [Resolved(CanBeNull = true)] private Player player { get; set; } @@ -77,7 +79,7 @@ namespace osu.Game.Screens.Ranking { new Drawable[] { - new VerticalScrollContainer + VerticalScrollContent = new VerticalScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, @@ -343,7 +345,7 @@ namespace osu.Game.Screens.Ranking { } - private class VerticalScrollContainer : OsuScrollContainer + protected class VerticalScrollContainer : OsuScrollContainer { protected override Container Content => content; @@ -351,6 +353,8 @@ namespace osu.Game.Screens.Ranking public VerticalScrollContainer() { + Masking = false; + base.Content.Add(content = new Container { RelativeSizeAxes = Axes.X }); } From cd842ccef8f1221eb59a71defb2dc19348e9ccd9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 10:15:50 +0300 Subject: [PATCH 485/600] Improve message Co-authored-by: Dean Herbert --- .../Overlays/Settings/Sections/Input/TabletSettings.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 9ed85e44ec..af94dcdaca 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -104,14 +104,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux) { t.NewLine(); - t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); - t.NewParagraph(); - t.AddText("read ", s => s.Colour = colours.Yellow); - t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows + t.AddText("If your tablet is not detected, please read ", s => s.Colour = colours.Yellow); + t.AddLink("this FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); - - t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + t.AddText(" for troubleshooting steps.", s => s.Colour = colours.Yellow); } }), } From db52549152f56e28cf22bb018ff22f32d19bb8de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 16:20:53 +0900 Subject: [PATCH 486/600] Move below everything rather than proxying (works better with new design) --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 43da62d466..ceec609f6d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -75,10 +75,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge OsuScrollContainer scrollContainer; - Container filterContainer; - InternalChildren = new[] { + loadingLayer = new LoadingLayer(true), new Container { RelativeSizeAxes = Axes.Both, @@ -159,8 +158,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } }, }, - loadingLayer = new LoadingLayer(true), - filterContainer.CreateProxy() }; // scroll selected room into view on selection. From c1d67976e6accf5ca2980a6aa116e791e8e9432a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 16:29:36 +0900 Subject: [PATCH 487/600] Rename const, add xmldoc and make protected --- osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs | 4 ++-- osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs | 2 ++ osu.Game/OsuGame.cs | 9 ++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index 21db7e2802..e58f85b0b3 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Menus public void TestScreenOffsettingOnSettingsOverlay() { AddStep("open settings", () => Game.Settings.Show()); - AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * TestOsuGame.SIDE_OVERLAY_OFFSET_RATIO); AddStep("hide settings", () => Game.Settings.Hide()); AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Menus public void TestScreenOffsettingOnNotificationOverlay() { AddStep("open notifications", () => Game.Notifications.Show()); - AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == -NotificationOverlay.WIDTH * OsuGame.SCREEN_OFFSET_RATIO); + AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == -NotificationOverlay.WIDTH * TestOsuGame.SIDE_OVERLAY_OFFSET_RATIO); AddStep("hide notifications", () => Game.Notifications.Hide()); AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs index 5cd55ed233..c9a1471e41 100644 --- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs +++ b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs @@ -96,6 +96,8 @@ namespace osu.Game.Tests.Visual.Navigation public class TestOsuGame : OsuGame { + public new const float SIDE_OVERLAY_OFFSET_RATIO = OsuGame.SIDE_OVERLAY_OFFSET_RATIO; + public new ScreenStack ScreenStack => base.ScreenStack; public new BackButton BackButton => base.BackButton; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f92f7e9e8c..6d76fec7c1 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -64,7 +64,10 @@ namespace osu.Game /// public class OsuGame : OsuGameBase, IKeyBindingHandler { - public const float SCREEN_OFFSET_RATIO = 0.125f; + /// + /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). + /// + protected const float SIDE_OVERLAY_OFFSET_RATIO = 0.125f; public Toolbar Toolbar; @@ -1016,9 +1019,9 @@ namespace osu.Game var horizontalOffset = 0f; if (Settings.IsLoaded && Settings.IsPresent) - horizontalOffset += ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SCREEN_OFFSET_RATIO; + horizontalOffset += ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO; if (Notifications.IsLoaded && Notifications.IsPresent) - horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SCREEN_OFFSET_RATIO; + horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SIDE_OVERLAY_OFFSET_RATIO; ScreenOffsetContainer.X = horizontalOffset; From da18c399e2d7cd531e019c8b140155a02135a4dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 16:33:00 +0900 Subject: [PATCH 488/600] Remove unnecessary `IsPresent` override --- osu.Game/Overlays/SettingsPanel.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 8b953e8655..f1c41c4b50 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -42,12 +42,6 @@ namespace osu.Game.Overlays protected override Container Content => ContentContainer; - /// - /// The always needs to be present for to process transforms while overlay is masked away. - /// todo: there may be a better solution for this and the existing , likely requires a refactor. - /// - public override bool IsPresent => true; - protected Sidebar Sidebar; private SidebarButton selectedSidebarButton; From 93b97e5110774787b27ba91cb595158a65491cbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 16:35:22 +0900 Subject: [PATCH 489/600] Adjust ratio to match previous behaviour --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6d76fec7c1..fb682e0909 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -67,7 +67,7 @@ namespace osu.Game /// /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). /// - protected const float SIDE_OVERLAY_OFFSET_RATIO = 0.125f; + protected const float SIDE_OVERLAY_OFFSET_RATIO = 0.05f; public Toolbar Toolbar; From 5a60b39643b172dd679cd5e81712c99422fff024 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 16:42:58 +0900 Subject: [PATCH 490/600] Remove unnecessary delimiters from song select filter splitting --- osu.Game/Screens/Select/FilterCriteria.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index b9e912df8e..f47bc5f466 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Select set { searchText = value; - SearchTerms = searchText.Split(new[] { ',', ' ', '!' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); + SearchTerms = searchText.Split(' ', StringSplitOptions.RemoveEmptyEntries).ToArray(); SearchNumber = null; From f43ab323ffad425b250c0ed761c8c00c8895349b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 11:12:26 +0300 Subject: [PATCH 491/600] Add shared class for notice text in settings --- .../Settings/Sections/Input/TabletSettings.cs | 9 +++----- osu.Game/Overlays/Settings/SettingsItem.cs | 8 +------ .../Overlays/Settings/SettingsNoticeText.cs | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 osu.Game/Overlays/Settings/SettingsNoticeText.cs diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index af94dcdaca..2816eb7037 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -11,7 +11,6 @@ using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; using osu.Game.Localisation; @@ -92,23 +91,21 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.TopCentre, Text = TabletSettingsStrings.NoTabletDetected, }, - new LinkFlowContainer + new SettingsNoticeText { TextAnchor = Anchor.TopCentre, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, }.With(t => { if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux) { t.NewLine(); - t.AddText("If your tablet is not detected, please read ", s => s.Colour = colours.Yellow); + t.AddText("If your tablet is not detected, please read "); t.AddLink("this FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); - t.AddText(" for troubleshooting steps.", s => s.Colour = colours.Yellow); + t.AddText(" for troubleshooting steps."); } }), } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index bd17c02af9..5d25605360 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -73,13 +73,7 @@ namespace osu.Game.Overlays.Settings return; // construct lazily for cases where the label is not needed (may be provided by the Control). - FlowContent.Add(warningText = new OsuTextFlowContainer - { - Colour = colours.Yellow, - Margin = new MarginPadding { Bottom = 5 }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }); + FlowContent.Add(warningText = new SettingsNoticeText { Margin = new MarginPadding { Bottom = 5 } }); } warningText.Alpha = hasValue ? 0 : 1; diff --git a/osu.Game/Overlays/Settings/SettingsNoticeText.cs b/osu.Game/Overlays/Settings/SettingsNoticeText.cs new file mode 100644 index 0000000000..6bb4a3f11c --- /dev/null +++ b/osu.Game/Overlays/Settings/SettingsNoticeText.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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.Settings +{ + public class SettingsNoticeText : LinkFlowContainer + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + } + } +} From 8910781bcdb4dac3a18e17c1962c6dd34421b550 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 17:39:09 +0900 Subject: [PATCH 492/600] Move listing polling component to LoungeSubScreen --- .../TestSceneLoungeRoomsContainer.cs | 2 +- .../TestSceneMultiplayerRoomManager.cs | 314 +++++++++--------- .../TestScenePlaylistsMatchSettingsOverlay.cs | 12 + osu.Game/Online/Rooms/Room.cs | 2 +- .../Components/ListingPollingComponent.cs | 23 +- .../OnlinePlay/Components/RoomManager.cs | 73 ++-- .../Components/RoomPollingComponent.cs | 15 +- .../Components/SelectionPollingComponent.cs | 14 +- osu.Game/Screens/OnlinePlay/IRoomManager.cs | 11 +- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 53 ++- .../OnlinePlay/Multiplayer/Multiplayer.cs | 30 -- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 33 ++ .../Multiplayer/MultiplayerMatchSubScreen.cs | 9 +- .../Multiplayer/MultiplayerRoomManager.cs | 73 ---- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 22 +- .../Screens/OnlinePlay/Playlists/Playlists.cs | 39 --- .../Playlists/PlaylistsLoungeSubScreen.cs | 3 + .../Playlists/PlaylistsRoomManager.cs | 21 -- .../Visual/OnlinePlay/BasicTestRoomManager.cs | 10 +- 19 files changed, 308 insertions(+), 451 deletions(-) delete mode 100644 osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index bcbdcd2a4f..f3d961a646 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var room = RoomManager.Rooms[1]; RoomManager.RemoveRoom(room); - RoomManager.AddRoom(room); + RoomManager.AddOrUpdateRoom(room); }); AddAssert("no selection", () => checkRoomSelected(null)); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index b17427a30b..15e9112c47 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -1,157 +1,157 @@ -// 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 NUnit.Framework; -using osu.Framework.Testing; -using osu.Game.Online.Rooms; -using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Tests.Beatmaps; -using osu.Game.Tests.Visual.OnlinePlay; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - [HeadlessTest] - public class TestSceneMultiplayerRoomManager : MultiplayerTestScene - { - protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); - - public TestSceneMultiplayerRoomManager() - : base(false) - { - } - - [Test] - public void TestPollsInitially() - { - AddStep("create room manager with a few rooms", () => - { - RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); - RoomManager.PartRoom(); - RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); - RoomManager.PartRoom(); - RoomManager.ClearRooms(); - }); - - AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); - AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestRoomsClearedOnDisconnection() - { - AddStep("create room manager with a few rooms", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - }); - - AddStep("disconnect", () => Client.Disconnect()); - - AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); - AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestRoomsPolledOnReconnect() - { - AddStep("create room manager with a few rooms", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - }); - - AddStep("disconnect", () => Client.Disconnect()); - AddStep("connect", () => Client.Connect()); - - AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); - AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestRoomsNotPolledWhenJoined() - { - AddStep("create room manager with a room", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.ClearRooms(); - }); - - AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); - AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestMultiplayerRoomJoinedWhenCreated() - { - AddStep("create room manager with a room", () => - { - RoomManager.CreateRoom(createRoom()); - }); - - AddUntilStep("multiplayer room joined", () => Client.Room != null); - } - - [Test] - public void TestMultiplayerRoomPartedWhenAPIRoomParted() - { - AddStep("create room manager with a room", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - }); - - AddAssert("multiplayer room parted", () => Client.Room == null); - } - - [Test] - public void TestMultiplayerRoomJoinedWhenAPIRoomJoined() - { - AddStep("create room manager with a room", () => - { - var r = createRoom(); - RoomManager.CreateRoom(r); - RoomManager.PartRoom(); - RoomManager.JoinRoom(r); - }); - - AddUntilStep("multiplayer room joined", () => Client.Room != null); - } - - private Room createRoom(Action initFunc = null) - { - var room = new Room - { - Name = - { - Value = "test room" - }, - Playlist = - { - new PlaylistItem - { - Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, - Ruleset = { Value = Ruleset.Value } - } - } - }; - - initFunc?.Invoke(room); - return room; - } - - private class TestDependencies : MultiplayerTestSceneDependencies - { - public TestDependencies() - { - // Need to set these values as early as possible. - RoomManager.TimeBetweenListingPolls.Value = 1; - RoomManager.TimeBetweenSelectionPolls.Value = 1; - } - } - } -} +// // 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 NUnit.Framework; +// using osu.Framework.Testing; +// using osu.Game.Online.Rooms; +// using osu.Game.Screens.OnlinePlay.Components; +// using osu.Game.Tests.Beatmaps; +// using osu.Game.Tests.Visual.OnlinePlay; +// +// namespace osu.Game.Tests.Visual.Multiplayer +// { +// [HeadlessTest] +// public class TestSceneMultiplayerRoomManager : MultiplayerTestScene +// { +// protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); +// +// public TestSceneMultiplayerRoomManager() +// : base(false) +// { +// } +// +// [Test] +// public void TestPollsInitially() +// { +// AddStep("create room manager with a few rooms", () => +// { +// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); +// RoomManager.PartRoom(); +// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); +// RoomManager.PartRoom(); +// RoomManager.ClearRooms(); +// }); +// +// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); +// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestRoomsClearedOnDisconnection() +// { +// AddStep("create room manager with a few rooms", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// }); +// +// AddStep("disconnect", () => Client.Disconnect()); +// +// AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); +// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestRoomsPolledOnReconnect() +// { +// AddStep("create room manager with a few rooms", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// }); +// +// AddStep("disconnect", () => Client.Disconnect()); +// AddStep("connect", () => Client.Connect()); +// +// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); +// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestRoomsNotPolledWhenJoined() +// { +// AddStep("create room manager with a room", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.ClearRooms(); +// }); +// +// AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); +// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestMultiplayerRoomJoinedWhenCreated() +// { +// AddStep("create room manager with a room", () => +// { +// RoomManager.CreateRoom(createRoom()); +// }); +// +// AddUntilStep("multiplayer room joined", () => Client.Room != null); +// } +// +// [Test] +// public void TestMultiplayerRoomPartedWhenAPIRoomParted() +// { +// AddStep("create room manager with a room", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// }); +// +// AddAssert("multiplayer room parted", () => Client.Room == null); +// } +// +// [Test] +// public void TestMultiplayerRoomJoinedWhenAPIRoomJoined() +// { +// AddStep("create room manager with a room", () => +// { +// var r = createRoom(); +// RoomManager.CreateRoom(r); +// RoomManager.PartRoom(); +// RoomManager.JoinRoom(r); +// }); +// +// AddUntilStep("multiplayer room joined", () => Client.Room != null); +// } +// +// private Room createRoom(Action initFunc = null) +// { +// var room = new Room +// { +// Name = +// { +// Value = "test room" +// }, +// Playlist = +// { +// new PlaylistItem +// { +// Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, +// Ruleset = { Value = Ruleset.Value } +// } +// } +// }; +// +// initFunc?.Invoke(room); +// return room; +// } +// +// private class TestDependencies : MultiplayerTestSceneDependencies +// { +// public TestDependencies() +// { +// // Need to set these values as early as possible. +// RoomManager.TimeBetweenListingPolls.Value = 1; +// RoomManager.TimeBetweenSelectionPolls.Value = 1; +// } +// } +// } +// } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index cdc655500d..79af2d3099 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -141,6 +141,18 @@ namespace osu.Game.Tests.Visual.Playlists public IBindableList Rooms => null; + public void AddOrUpdateRoom(Room room) + { + } + + public void RemoveRoom(Room room) + { + } + + public void ClearRooms() + { + } + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { if (CreateRequested == null) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 4bd5b1a788..364336783d 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -134,7 +134,7 @@ namespace osu.Game.Online.Rooms /// The position of this in the list. This is not read from or written to the API. /// [JsonIgnore] - public readonly Bindable Position = new Bindable(-1); + public readonly Bindable Position = new Bindable(-1); public Room() { diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index e50784fcbe..f686326d08 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -14,6 +15,9 @@ namespace osu.Game.Screens.OnlinePlay.Components /// public class ListingPollingComponent : RoomPollingComponent { + public IBindable HasPolledOnce => hasPolledOnce; + private readonly Bindable hasPolledOnce = new Bindable(); + [Resolved] private Bindable currentFilter { get; set; } @@ -25,7 +29,9 @@ namespace osu.Game.Screens.OnlinePlay.Components { currentFilter.BindValueChanged(_ => { - NotifyRoomsReceived(null); + RoomManager.ClearRooms(); + hasPolledOnce.Value = false; + if (IsLoaded) PollImmediately(); }); @@ -45,17 +51,16 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { - for (int i = 0; i < result.Count; i++) + foreach (var existing in RoomManager.Rooms.ToArray()) { - if (result[i].RoomID.Value == selectedRoom.Value?.RoomID.Value) - { - // The listing request always has less information than the opened room, so don't include it. - result[i] = selectedRoom.Value; - break; - } + if (result.All(r => r.RoomID.Value != existing.RoomID.Value)) + RoomManager.RemoveRoom(existing); } - NotifyRoomsReceived(result); + foreach (var incoming in result) + RoomManager.AddOrUpdateRoom(incoming); + + hasPolledOnce.Value = true; tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 422576648c..ab92adcac7 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -8,7 +8,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Online.API; @@ -17,15 +16,12 @@ using osu.Game.Rulesets; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class RoomManager : CompositeDrawable, IRoomManager + public class RoomManager : Component, IRoomManager { public event Action RoomsUpdated; private readonly BindableList rooms = new BindableList(); - public IBindable InitialRoomsReceived => initialRoomsReceived; - private readonly Bindable initialRoomsReceived = new Bindable(); - public IBindableList Rooms => rooms; protected IBindable JoinedRoom => joinedRoom; @@ -40,15 +36,9 @@ namespace osu.Game.Screens.OnlinePlay.Components [Resolved] private IAPIProvider api { get; set; } - protected RoomManager() + public RoomManager() { RelativeSizeAxes = Axes.Both; - - InternalChildren = CreatePollingComponents().Select(p => - { - p.RoomsReceived = onRoomsReceived; - return p; - }).ToList(); } protected override void Dispose(bool isDisposing) @@ -118,56 +108,41 @@ namespace osu.Game.Screens.OnlinePlay.Components private readonly HashSet ignoredRooms = new HashSet(); - private void onRoomsReceived(List received) + public void AddOrUpdateRoom(Room room) { - if (received == null) - { - ClearRooms(); + Debug.Assert(room.RoomID.Value != null); + + if (ignoredRooms.Contains(room.RoomID.Value.Value)) return; - } - // Remove past matches - foreach (var r in rooms.ToList()) + room.Position.Value = -room.RoomID.Value.Value; + + try { - if (received.All(e => e.RoomID.Value != r.RoomID.Value)) - rooms.Remove(r); + update(room, room); + addRoom(room); } - - for (int i = 0; i < received.Count; i++) + catch (Exception ex) { - var room = received[i]; + Logger.Error(ex, $"Failed to update room: {room.Name.Value}."); - Debug.Assert(room.RoomID.Value != null); - - if (ignoredRooms.Contains(room.RoomID.Value.Value)) - continue; - - room.Position.Value = i; - - try - { - update(room, room); - addRoom(room); - } - catch (Exception ex) - { - Logger.Error(ex, $"Failed to update room: {room.Name.Value}."); - - ignoredRooms.Add(room.RoomID.Value.Value); - rooms.Remove(room); - } + ignoredRooms.Add(room.RoomID.Value.Value); + rooms.Remove(room); } - RoomsUpdated?.Invoke(); - initialRoomsReceived.Value = true; + notifyRoomsUpdated(); } - protected void RemoveRoom(Room room) => rooms.Remove(room); + public void RemoveRoom(Room room) + { + rooms.Remove(room); + notifyRoomsUpdated(); + } - protected void ClearRooms() + public void ClearRooms() { rooms.Clear(); - initialRoomsReceived.Value = false; + notifyRoomsUpdated(); } /// @@ -196,6 +171,6 @@ namespace osu.Game.Screens.OnlinePlay.Components existing.CopyFrom(room); } - protected abstract IEnumerable CreatePollingComponents(); + private void notifyRoomsUpdated() => Scheduler.AddOnce(() => RoomsUpdated?.Invoke()); } } diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index b2ea3a05d6..95b4c4284c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -1,29 +1,18 @@ // 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 osu.Framework.Allocation; using osu.Game.Online; using osu.Game.Online.API; -using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { public abstract class RoomPollingComponent : PollingComponent { - /// - /// Invoked when any s have been received from the API. - /// - /// Any s present locally but not returned by this event are to be removed from display. - /// If null, the display of local rooms is reset to an initial state. - /// - /// - public Action> RoomsReceived; - [Resolved] protected IAPIProvider API { get; private set; } - protected void NotifyRoomsReceived(List rooms) => RoomsReceived?.Invoke(rooms); + [Resolved] + protected IRoomManager RoomManager { get; set; } } } diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index dcf3c94b76..88d9469f8c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.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. -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -48,17 +46,7 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { - // existing rooms need to be ordered by their position because the received of NotifyRoomsReceives expects to be able to sort them based on this order. - var rooms = new List(roomManager.Rooms.OrderBy(r => r.Position.Value)); - - int index = rooms.FindIndex(r => r.RoomID.Value == result.RoomID.Value); - - if (index < 0) - return; - - rooms[index] = result; - - NotifyRoomsReceived(rooms); + RoomManager.AddOrUpdateRoom(result); tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OnlinePlay/IRoomManager.cs b/osu.Game/Screens/OnlinePlay/IRoomManager.cs index 34c1393ff1..baf84e25f9 100644 --- a/osu.Game/Screens/OnlinePlay/IRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/IRoomManager.cs @@ -18,16 +18,17 @@ namespace osu.Game.Screens.OnlinePlay /// event Action RoomsUpdated; - /// - /// Whether an initial listing of rooms has been received. - /// - IBindable InitialRoomsReceived { get; } - /// /// All the active s. /// IBindableList Rooms { get; } + void AddOrUpdateRoom(Room room); + + void RemoveRoom(Room room); + + void ClearRooms(); + /// /// Creates a new . /// diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 7249ccdd93..50f7baa44c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -12,14 +12,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.Logging; using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Input; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; @@ -41,10 +44,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge AutoSizeAxes = Axes.Both }; - private readonly IBindable initialRoomsReceived = new Bindable(); - private readonly IBindable operationInProgress = new Bindable(); - - private LoadingLayer loadingLayer; + protected ListingPollingComponent ListingPollingComponent { get; private set; } [Resolved] private Bindable selectedRoom { get; set; } @@ -61,9 +61,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved] private IBindable ruleset { get; set; } + [Resolved(CanBeNull = true)] + private IdleTracker idleTracker { get; set; } + [CanBeNull] private IDisposable joiningRoomOperation { get; set; } + private readonly IBindable operationInProgress = new Bindable(); + private readonly IBindable isIdle = new BindableBool(); + private LoadingLayer loadingLayer; private RoomsContainer roomsContainer; private SearchTextBox searchTextBox; private Dropdown statusDropdown; @@ -77,6 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { + ListingPollingComponent = CreatePollingComponent(), new Container { RelativeSizeAxes = Axes.Both, @@ -176,8 +183,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - initialRoomsReceived.BindTo(RoomManager.InitialRoomsReceived); - initialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); + ListingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); + + if (idleTracker != null) + { + isIdle.BindTo(idleTracker.IsIdle); + isIdle.BindValueChanged(_ => updatePollingRate(), true); + } if (ongoingOperationTracker != null) { @@ -231,7 +243,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge public override void OnEntering(IScreen last) { base.OnEntering(last); - onReturning(); } @@ -266,11 +277,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void onReturning() { + updatePollingRate(); searchTextBox.HoldFocus = true; } private void onLeaving() { + updatePollingRate(); searchTextBox.HoldFocus = false; // ensure any password prompt is dismissed. @@ -316,6 +329,24 @@ namespace osu.Game.Screens.OnlinePlay.Lounge this.Push(CreateRoomSubScreen(room)); } + private void updateLoadingLayer() + { + if (operationInProgress.Value || !ListingPollingComponent.HasPolledOnce.Value) + loadingLayer.Show(); + else + loadingLayer.Hide(); + } + + private void updatePollingRate() + { + if (!this.IsCurrentScreen()) + ListingPollingComponent.TimeBetweenPolls.Value = 0; + else + ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; + + Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})"); + } + protected abstract OsuButton CreateNewRoomButton(); /// @@ -326,13 +357,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected abstract RoomSubScreen CreateRoomSubScreen(Room room); - private void updateLoadingLayer() - { - if (operationInProgress.Value || !initialRoomsReceived.Value) - loadingLayer.Show(); - else - loadingLayer.Hide(); - } + protected abstract ListingPollingComponent CreatePollingComponent(); private class LoungeSearchTextBox : SearchTextBox { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 45928505bb..58b5b7bbeb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay.Components; @@ -23,35 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer client.ChangeState(MultiplayerUserState.Idle); } - protected override void UpdatePollingRate(bool isIdle) - { - var multiplayerRoomManager = (MultiplayerRoomManager)RoomManager; - - if (!this.IsCurrentScreen()) - { - multiplayerRoomManager.TimeBetweenListingPolls.Value = 0; - multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0; - } - else - { - switch (CurrentSubScreen) - { - case LoungeSubScreen _: - multiplayerRoomManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000; - multiplayerRoomManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000; - break; - - // Don't poll inside the match or anywhere else. - default: - multiplayerRoomManager.TimeBetweenListingPolls.Value = 0; - multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0; - break; - } - } - - Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})"); - } - protected override string ScreenTitle => "Multiplayer"; protected override RoomManager CreateRoomManager() => new MultiplayerRoomManager(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index ad7882abc2..db6096e93b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -21,6 +25,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } + public override void OnResuming(IScreen last) + { + base.OnResuming(last); + ListingPollingComponent.PollImmediately(); + } + protected override FilterCriteria CreateFilterCriteria() { var criteria = base.CreateFilterCriteria(); @@ -39,6 +49,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); + protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent(); + protected override void OpenNewRoom(Room room) { if (client?.IsConnected.Value != true) @@ -49,5 +61,26 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.OpenNewRoom(room); } + + private class MultiplayerListingPollingComponent : ListingPollingComponent + { + public readonly IBindable AllowPolling = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + AllowPolling.BindValueChanged(allowPolling => + { + if (!allowPolling.NewValue) + return; + + if (IsLoaded) + PollImmediately(); + }); + } + + protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index a8e44dd56c..ec011634b1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -49,9 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private OngoingOperationTracker ongoingOperationTracker { get; set; } [Resolved] - private Bindable currentRoom { get; set; } - - private MultiplayerMatchSettingsOverlay settingsOverlay; + private Bindable currentRoom { get; set; } // Todo: This should not exist. private readonly IBindable isConnected = new Bindable(); @@ -59,6 +57,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private IDisposable readyClickOperation; private GridContainer mainContent; + private MultiplayerMatchSettingsOverlay settingsOverlay; public MultiplayerMatchSubScreen(Room room) { @@ -324,6 +323,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override bool OnExiting(IScreen next) { + // We don't know whether we're the only participant in the room, and whether the room will close after we leave it as a result. + // To work around this, temporarily remove the room until the next listing poll retrieves it. + RoomManager?.RemoveRoom(currentRoom.Value); + // the room may not be left immediately after a disconnection due to async flow, // so checking the IsConnected status is also required. if (client.Room == null || !client.IsConnected.Value) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index cbba4babe5..ae8c3113ff 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.ExceptionExtensions; @@ -21,13 +19,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient multiplayerClient { get; set; } - public readonly Bindable TimeBetweenListingPolls = new Bindable(); - public readonly Bindable TimeBetweenSelectionPolls = new Bindable(); private readonly IBindable isConnected = new Bindable(); private readonly Bindable allowPolling = new Bindable(); - private ListingPollingComponent listingPollingComponent; - protected override void LoadComplete() { base.LoadComplete(); @@ -64,19 +58,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (JoinedRoom.Value == null) return; - var joinedRoom = JoinedRoom.Value; - base.PartRoom(); - multiplayerClient.LeaveRoom(); - - // Todo: This is not the way to do this. Basically when we're the only participant and the room closes, there's no way to know if this is actually the case. - // This is delayed one frame because upon exiting the match subscreen, multiplayer updates the polling rate and messes with polling. - Schedule(() => - { - RemoveRoom(joinedRoom); - listingPollingComponent.PollImmediately(); - }); } private void joinMultiplayerRoom(Room room, string password, Action onSuccess = null, Action onError = null) @@ -108,61 +91,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // Don't poll when not connected or when a room has been joined. allowPolling.Value = isConnected.Value && JoinedRoom.Value == null; } - - protected override IEnumerable CreatePollingComponents() => new RoomPollingComponent[] - { - listingPollingComponent = new MultiplayerListingPollingComponent - { - TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls }, - AllowPolling = { BindTarget = allowPolling } - }, - new MultiplayerSelectionPollingComponent - { - TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls }, - AllowPolling = { BindTarget = allowPolling } - } - }; - - private class MultiplayerListingPollingComponent : ListingPollingComponent - { - public readonly IBindable AllowPolling = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - AllowPolling.BindValueChanged(allowPolling => - { - if (!allowPolling.NewValue) - return; - - if (IsLoaded) - PollImmediately(); - }); - } - - protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); - } - - private class MultiplayerSelectionPollingComponent : SelectionPollingComponent - { - public readonly IBindable AllowPolling = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - AllowPolling.BindValueChanged(allowPolling => - { - if (!allowPolling.NewValue) - return; - - if (IsLoaded) - PollImmediately(); - }); - } - - protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); - } } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index c2ad0285b1..cfb19ca3d7 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -13,7 +13,6 @@ using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; -using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Overlays; @@ -43,8 +42,6 @@ namespace osu.Game.Screens.OnlinePlay private LoungeSubScreen loungeSubScreen; private ScreenStack screenStack; - private readonly IBindable isIdle = new BindableBool(); - [Cached(Type = typeof(IRoomManager))] protected RoomManager RoomManager { get; private set; } @@ -66,9 +63,6 @@ namespace osu.Game.Screens.OnlinePlay [Resolved] protected IAPIProvider API { get; private set; } - [Resolved(CanBeNull = true)] - private IdleTracker idleTracker { get; set; } - [Resolved(CanBeNull = true)] private OsuLogo logo { get; set; } @@ -151,12 +145,6 @@ namespace osu.Game.Screens.OnlinePlay apiState.BindTo(API.State); apiState.BindValueChanged(onlineStateChanged, true); - - if (idleTracker != null) - { - isIdle.BindTo(idleTracker.IsIdle); - isIdle.BindValueChanged(idle => UpdatePollingRate(idle.NewValue), true); - } } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -166,8 +154,6 @@ namespace osu.Game.Screens.OnlinePlay return dependencies; } - protected abstract void UpdatePollingRate(bool isIdle); - private void forcefullyExit() { // This is temporary since we don't currently have a way to force screens to be exited @@ -203,8 +189,6 @@ namespace osu.Game.Screens.OnlinePlay screenStack.CurrentScreen.OnResuming(last); base.OnResuming(last); - - UpdatePollingRate(isIdle.Value); } public override void OnSuspending(IScreen next) @@ -214,8 +198,6 @@ namespace osu.Game.Screens.OnlinePlay Debug.Assert(screenStack.CurrentScreen != null); screenStack.CurrentScreen.OnSuspending(next); - - UpdatePollingRate(isIdle.Value); } public override bool OnExiting(IScreen next) @@ -279,15 +261,13 @@ namespace osu.Game.Screens.OnlinePlay if (newScreen is IOsuScreen newOsuScreen) ((IBindable)Activity).BindTo(newOsuScreen.Activity); - - UpdatePollingRate(isIdle.Value); } protected IScreen CurrentSubScreen => screenStack.CurrentScreen; protected abstract string ScreenTitle { get; } - protected abstract RoomManager CreateRoomManager(); + protected virtual RoomManager CreateRoomManager() => new RoomManager(); protected abstract LoungeSubScreen CreateLounge(); diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index 6a78e24ba1..1edeef77df 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -1,53 +1,14 @@ // 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.Logging; -using osu.Framework.Screens; -using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; -using osu.Game.Screens.OnlinePlay.Match; namespace osu.Game.Screens.OnlinePlay.Playlists { public class Playlists : OnlinePlayScreen { - protected override void UpdatePollingRate(bool isIdle) - { - var playlistsManager = (PlaylistsRoomManager)RoomManager; - - if (!this.IsCurrentScreen()) - { - playlistsManager.TimeBetweenListingPolls.Value = 0; - playlistsManager.TimeBetweenSelectionPolls.Value = 0; - } - else - { - switch (CurrentSubScreen) - { - case LoungeSubScreen _: - playlistsManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000; - playlistsManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000; - break; - - case RoomSubScreen _: - playlistsManager.TimeBetweenListingPolls.Value = 0; - playlistsManager.TimeBetweenSelectionPolls.Value = isIdle ? 30000 : 5000; - break; - - default: - playlistsManager.TimeBetweenListingPolls.Value = 0; - playlistsManager.TimeBetweenSelectionPolls.Value = 0; - break; - } - } - - Logger.Log($"Polling adjusted (listing: {playlistsManager.TimeBetweenListingPolls.Value}, selection: {playlistsManager.TimeBetweenSelectionPolls.Value})"); - } - protected override string ScreenTitle => "Playlists"; - protected override RoomManager CreateRoomManager() => new PlaylistsRoomManager(); - protected override LoungeSubScreen CreateLounge() => new PlaylistsLoungeSubScreen(); } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index eee4d4f407..dced9b8691 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -66,6 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room); + protected override ListingPollingComponent CreatePollingComponent() => new ListingPollingComponent(); + private enum PlaylistsCategory { Any, diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs deleted file mode 100644 index c55d1c3e94..0000000000 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.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. - -using System.Collections.Generic; -using osu.Framework.Bindables; -using osu.Game.Screens.OnlinePlay.Components; - -namespace osu.Game.Screens.OnlinePlay.Playlists -{ - public class PlaylistsRoomManager : RoomManager - { - public readonly Bindable TimeBetweenListingPolls = new Bindable(); - public readonly Bindable TimeBetweenSelectionPolls = new Bindable(); - - protected override IEnumerable CreatePollingComponents() => new RoomPollingComponent[] - { - new ListingPollingComponent { TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls } }, - new SelectionPollingComponent { TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls } } - }; - } -} diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index d37a64fa4b..2e9c0d1d53 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -33,10 +33,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; onSuccess?.Invoke(room); - AddRoom(room); + AddOrUpdateRoom(room); } - public void AddRoom(Room room) + public void AddOrUpdateRoom(Room room) { Rooms.Add(room); RoomsUpdated?.Invoke(); @@ -48,6 +48,12 @@ namespace osu.Game.Tests.Visual.OnlinePlay RoomsUpdated?.Invoke(); } + public void ClearRooms() + { + Rooms.Clear(); + RoomsUpdated?.Invoke(); + } + public void JoinRoom(Room room, string password, Action onSuccess = null, Action onError = null) { JoinRoomRequested?.Invoke(room, password); From 7cbf4c48edc94af45f10468eb34ca24565d55e28 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 17:59:18 +0900 Subject: [PATCH 493/600] Fix multiplayer polling when not connected --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 15 ++++---- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 37 ++++++++++++++----- .../Multiplayer/MultiplayerRoomManager.cs | 22 ----------- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 50f7baa44c..4525599a52 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -44,8 +44,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge AutoSizeAxes = Axes.Both }; - protected ListingPollingComponent ListingPollingComponent { get; private set; } - [Resolved] private Bindable selectedRoom { get; set; } @@ -73,6 +71,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private RoomsContainer roomsContainer; private SearchTextBox searchTextBox; private Dropdown statusDropdown; + private ListingPollingComponent listingPollingComponent; [BackgroundDependencyLoader] private void load() @@ -83,7 +82,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { - ListingPollingComponent = CreatePollingComponent(), + listingPollingComponent = CreatePollingComponent(), new Container { RelativeSizeAxes = Axes.Both, @@ -183,7 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - ListingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); + listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); if (idleTracker != null) { @@ -331,7 +330,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updateLoadingLayer() { - if (operationInProgress.Value || !ListingPollingComponent.HasPolledOnce.Value) + if (operationInProgress.Value || !listingPollingComponent.HasPolledOnce.Value) loadingLayer.Show(); else loadingLayer.Hide(); @@ -340,11 +339,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updatePollingRate() { if (!this.IsCurrentScreen()) - ListingPollingComponent.TimeBetweenPolls.Value = 0; + listingPollingComponent.TimeBetweenPolls.Value = 0; else - ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; + listingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; - Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})"); + Logger.Log($"Polling adjusted (listing: {listingPollingComponent.TimeBetweenPolls.Value})"); } protected abstract OsuButton CreateNewRoomButton(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index db6096e93b..3f20202ec7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -25,10 +25,23 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } + private MultiplayerListingPollingComponent listingPollingComponent; + + private readonly IBindable isConnected = new Bindable(); + private readonly Bindable allowPolling = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + isConnected.BindTo(client.IsConnected); + isConnected.BindValueChanged(c => Scheduler.AddOnce(() => listingPollingComponent.AllowPolling = c.NewValue)); + } + public override void OnResuming(IScreen last) { base.OnResuming(last); - ListingPollingComponent.PollImmediately(); + listingPollingComponent.PollImmediately(); } protected override FilterCriteria CreateFilterCriteria() @@ -49,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); - protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent(); + protected override ListingPollingComponent CreatePollingComponent() => listingPollingComponent = new MultiplayerListingPollingComponent(); protected override void OpenNewRoom(Room room) { @@ -64,23 +77,27 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private class MultiplayerListingPollingComponent : ListingPollingComponent { - public readonly IBindable AllowPolling = new Bindable(); + private bool allowPolling; - protected override void LoadComplete() + public bool AllowPolling { - base.LoadComplete(); - - AllowPolling.BindValueChanged(allowPolling => + get => allowPolling; + set { - if (!allowPolling.NewValue) + if (allowPolling == value) + return; + + allowPolling = value; + + if (!allowPolling) return; if (IsLoaded) PollImmediately(); - }); + } } - protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); + protected override Task Poll() => !AllowPolling ? Task.CompletedTask : base.Poll(); } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index ae8c3113ff..2d94b2328d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Logging; using osu.Game.Online.Multiplayer; @@ -19,18 +18,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient multiplayerClient { get; set; } - private readonly IBindable isConnected = new Bindable(); - private readonly Bindable allowPolling = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - isConnected.BindTo(multiplayerClient.IsConnected); - isConnected.BindValueChanged(_ => Scheduler.AddOnce(updatePolling)); - JoinedRoom.BindValueChanged(_ => Scheduler.AddOnce(updatePolling), true); - } - public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); @@ -82,14 +69,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } }); } - - private void updatePolling() - { - if (!isConnected.Value) - ClearRooms(); - - // Don't poll when not connected or when a room has been joined. - allowPolling.Value = isConnected.Value && JoinedRoom.Value == null; - } } } From 83935540caf400882750283724326934c556110b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:11:52 +0900 Subject: [PATCH 494/600] Add selection polling component to PlaylistsRoomSubScreen --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 16 +++++-------- .../Playlists/PlaylistsRoomSubScreen.cs | 24 +++++++++++++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 4525599a52..06db462205 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -59,9 +59,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved] private IBindable ruleset { get; set; } - [Resolved(CanBeNull = true)] - private IdleTracker idleTracker { get; set; } - [CanBeNull] private IDisposable joiningRoomOperation { get; set; } @@ -73,9 +70,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private Dropdown statusDropdown; private ListingPollingComponent listingPollingComponent; - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] IdleTracker idleTracker) { + if (idleTracker != null) + isIdle.BindTo(idleTracker.IsIdle); + filter ??= new Bindable(new FilterCriteria()); OsuScrollContainer scrollContainer; @@ -184,11 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); - if (idleTracker != null) - { - isIdle.BindTo(idleTracker.IsIdle); - isIdle.BindValueChanged(_ => updatePollingRate(), true); - } + isIdle.BindValueChanged(_ => updatePollingRate(), true); if (ongoingOperationTracker != null) { diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 953c687087..682b055766 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -3,11 +3,14 @@ using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; @@ -33,12 +36,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved(typeof(Room), nameof(Room.Playlist))] private BindableList playlist { get; set; } + private readonly IBindable isIdle = new BindableBool(); + private MatchSettingsOverlay settingsOverlay; private MatchLeaderboard leaderboard; - private OverlinedHeader participantsHeader; - private GridContainer mainContent; + private SelectionPollingComponent selectionPollingComponent; public PlaylistsRoomSubScreen(Room room) { @@ -46,11 +50,15 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Activity.Value = new UserActivity.InLobby(room); } - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] IdleTracker idleTracker) { + if (idleTracker != null) + isIdle.BindTo(idleTracker.IsIdle); + AddRangeInternal(new Drawable[] { + selectionPollingComponent = new SelectionPollingComponent(), mainContent = new GridContainer { RelativeSizeAxes = Axes.Both, @@ -260,6 +268,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { base.LoadComplete(); + isIdle.BindValueChanged(_ => updatePollingRate(), true); + roomId.BindValueChanged(id => { if (id.NewValue == null) @@ -275,6 +285,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, true); } + private void updatePollingRate() + { + selectionPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 30000 : 5000; + Logger.Log($"Polling adjusted (selection: {selectionPollingComponent.TimeBetweenPolls.Value})"); + } + protected override Screen CreateGameplayScreen() => new PlayerLoader(() => new PlaylistsPlayer(SelectedItem.Value) { Exited = () => leaderboard.RefreshScores() From f5cea0cacd34535f58b43c216f03ed60b1bb31ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 12:12:20 +0300 Subject: [PATCH 495/600] Fix failing test and rename to match new behaviour --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index a9004987df..080a1502b0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -84,7 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] - public void TestSpectatorPlayerSettingsHidden() + public void TestSpectatorPlayerInteractiveElementsHidden() { start(new[] { PLAYER_1_ID, PLAYER_2_ID }); loadSpectateScreen(false); @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - !p.ChildrenOfType().Single().ShowHandle)); + p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); } [Test] From 6a46105b5efe9b6a2fcaa95838f53d1793daeb90 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:12:32 +0900 Subject: [PATCH 496/600] Fix incorrect dependency --- osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index 95b4c4284c..cd224a7347 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -13,6 +13,6 @@ namespace osu.Game.Screens.OnlinePlay.Components protected IAPIProvider API { get; private set; } [Resolved] - protected IRoomManager RoomManager { get; set; } + protected IRoomManager RoomManager { get; private set; } } } From 1bae7173d3794d1cecca63fb31fecbc4a64ef3f9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:13:55 +0900 Subject: [PATCH 497/600] Fix initial multiplayer poll --- .../OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 3f20202ec7..d36462f482 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -28,7 +28,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerListingPollingComponent listingPollingComponent; private readonly IBindable isConnected = new Bindable(); - private readonly Bindable allowPolling = new Bindable(); protected override void LoadComplete() { @@ -36,6 +35,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer isConnected.BindTo(client.IsConnected); isConnected.BindValueChanged(c => Scheduler.AddOnce(() => listingPollingComponent.AllowPolling = c.NewValue)); + listingPollingComponent.AllowPolling = isConnected.Value; } public override void OnResuming(IScreen last) From d527eb3d8b8f89bafa8870fe691f3ef6127fca67 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Fri, 13 Aug 2021 17:15:18 +0800 Subject: [PATCH 498/600] Apply suggestions from code review Co-authored-by: Dean Herbert --- osu.Game/Localisation/GameplaySettingsStrings.cs | 6 +++--- osu.Game/Localisation/GeneralSettingsStrings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 6 +++--- .../Overlays/Settings/Sections/General/LanguageSettings.cs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 4354272ab5..c63fa5ddcc 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -22,12 +22,12 @@ namespace osu.Game.Localisation /// /// "Background dim" /// - public static LocalisableString Dim => new TranslatableString(getKey(@"dim"), @"Background dim"); + public static LocalisableString BackgroundDim => new TranslatableString(getKey(@"dim"), @"Background dim"); /// /// "Background blur" /// - public static LocalisableString Blur => new TranslatableString(getKey(@"blur"), @"Background blur"); + public static LocalisableString BackgroundBlur => new TranslatableString(getKey(@"blur"), @"Background blur"); /// /// "Lighten playfield during breaks" @@ -57,7 +57,7 @@ namespace osu.Game.Localisation /// /// "Always show key overlay" /// - public static LocalisableString KeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay"); + public static LocalisableString AlwaysShowKeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay"); /// /// "Positional hitsounds" diff --git a/osu.Game/Localisation/GeneralSettingsStrings.cs b/osu.Game/Localisation/GeneralSettingsStrings.cs index 19fb8de972..a60e4891f4 100644 --- a/osu.Game/Localisation/GeneralSettingsStrings.cs +++ b/osu.Game/Localisation/GeneralSettingsStrings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Localisation /// /// "Prefer metadata in original language" /// - public static LocalisableString PreferOriginal => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); + public static LocalisableString PreferOriginalMetadataLanguage => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); /// /// "Updates" diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index efb586fdca..04332fcdd3 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -22,14 +22,14 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsSlider { - LabelText = GameplaySettingsStrings.Dim, + LabelText = GameplaySettingsStrings.BackgroundDim, Current = config.GetBindable(OsuSetting.DimLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = GameplaySettingsStrings.Blur, + LabelText = GameplaySettingsStrings.BackgroundBlur, Current = config.GetBindable(OsuSetting.BlurLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = GameplaySettingsStrings.KeyOverlay, + LabelText = GameplaySettingsStrings.AlwaysShowKeyOverlay, Current = config.GetBindable(OsuSetting.KeyOverlay) }, new SettingsCheckbox diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index ac95a713bf..200618c469 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.General }, new SettingsCheckbox { - LabelText = GeneralSettingsStrings.PreferOriginal, + LabelText = GeneralSettingsStrings.PreferOriginalMetadataLanguage, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowUnicode) }, }; From 1f992e67f3b29f63a0f965eb6c4e3ed26a6699c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:17:18 +0900 Subject: [PATCH 499/600] Fix listing polling rate when entering room --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 06db462205..abe06bae9e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); - isIdle.BindValueChanged(_ => updatePollingRate(), true); + isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true); if (ongoingOperationTracker != null) { @@ -272,13 +272,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void onReturning() { - updatePollingRate(); + updatePollingRate(true); searchTextBox.HoldFocus = true; } private void onLeaving() { - updatePollingRate(); + updatePollingRate(false); searchTextBox.HoldFocus = false; // ensure any password prompt is dismissed. @@ -332,9 +332,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge loadingLayer.Hide(); } - private void updatePollingRate() + private void updatePollingRate(bool isCurrentScreen) { - if (!this.IsCurrentScreen()) + if (!isCurrentScreen) listingPollingComponent.TimeBetweenPolls.Value = 0; else listingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; From c71a581106f1640a4303ead14755820cfc1c29d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:24:19 +0900 Subject: [PATCH 500/600] Fix exception when leaving match --- .../OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs | 9 ++++++++- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index d36462f482..0756c78211 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -41,7 +41,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override void OnResuming(IScreen last) { base.OnResuming(last); - listingPollingComponent.PollImmediately(); + + // Upon having left a room, we don't know whether we were the only participant, and whether the room is now closed as a result of leaving it. + // To work around this, temporarily clear all rooms until the next listing poll. + if (last is MultiplayerMatchSubScreen match) + { + RoomManager.RemoveRoom(match.Room); + listingPollingComponent.PollImmediately(); + } } protected override FilterCriteria CreateFilterCriteria() diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index ec011634b1..72ba4d62fb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -42,6 +42,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override string ShortTitle => "room"; + public readonly Room Room; + [Resolved] private MultiplayerClient client { get; set; } @@ -61,6 +63,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public MultiplayerMatchSubScreen(Room room) { + Room = room; + Title = room.RoomID.Value == null ? "New room" : room.Name.Value; Activity.Value = new UserActivity.InLobby(room); } @@ -323,10 +327,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override bool OnExiting(IScreen next) { - // We don't know whether we're the only participant in the room, and whether the room will close after we leave it as a result. - // To work around this, temporarily remove the room until the next listing poll retrieves it. - RoomManager?.RemoveRoom(currentRoom.Value); - // the room may not be left immediately after a disconnection due to async flow, // so checking the IsConnected status is also required. if (client.Room == null || !client.IsConnected.Value) From fbadc4897e211db035eb495d19cc797535e4fbc1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:28:20 +0900 Subject: [PATCH 501/600] Remove test scene --- .../TestSceneMultiplayerRoomManager.cs | 157 ------------------ 1 file changed, 157 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs deleted file mode 100644 index 15e9112c47..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ /dev/null @@ -1,157 +0,0 @@ -// // 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 NUnit.Framework; -// using osu.Framework.Testing; -// using osu.Game.Online.Rooms; -// using osu.Game.Screens.OnlinePlay.Components; -// using osu.Game.Tests.Beatmaps; -// using osu.Game.Tests.Visual.OnlinePlay; -// -// namespace osu.Game.Tests.Visual.Multiplayer -// { -// [HeadlessTest] -// public class TestSceneMultiplayerRoomManager : MultiplayerTestScene -// { -// protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); -// -// public TestSceneMultiplayerRoomManager() -// : base(false) -// { -// } -// -// [Test] -// public void TestPollsInitially() -// { -// AddStep("create room manager with a few rooms", () => -// { -// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); -// RoomManager.PartRoom(); -// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); -// RoomManager.PartRoom(); -// RoomManager.ClearRooms(); -// }); -// -// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); -// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestRoomsClearedOnDisconnection() -// { -// AddStep("create room manager with a few rooms", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// }); -// -// AddStep("disconnect", () => Client.Disconnect()); -// -// AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); -// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestRoomsPolledOnReconnect() -// { -// AddStep("create room manager with a few rooms", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// }); -// -// AddStep("disconnect", () => Client.Disconnect()); -// AddStep("connect", () => Client.Connect()); -// -// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); -// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestRoomsNotPolledWhenJoined() -// { -// AddStep("create room manager with a room", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.ClearRooms(); -// }); -// -// AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); -// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestMultiplayerRoomJoinedWhenCreated() -// { -// AddStep("create room manager with a room", () => -// { -// RoomManager.CreateRoom(createRoom()); -// }); -// -// AddUntilStep("multiplayer room joined", () => Client.Room != null); -// } -// -// [Test] -// public void TestMultiplayerRoomPartedWhenAPIRoomParted() -// { -// AddStep("create room manager with a room", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// }); -// -// AddAssert("multiplayer room parted", () => Client.Room == null); -// } -// -// [Test] -// public void TestMultiplayerRoomJoinedWhenAPIRoomJoined() -// { -// AddStep("create room manager with a room", () => -// { -// var r = createRoom(); -// RoomManager.CreateRoom(r); -// RoomManager.PartRoom(); -// RoomManager.JoinRoom(r); -// }); -// -// AddUntilStep("multiplayer room joined", () => Client.Room != null); -// } -// -// private Room createRoom(Action initFunc = null) -// { -// var room = new Room -// { -// Name = -// { -// Value = "test room" -// }, -// Playlist = -// { -// new PlaylistItem -// { -// Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, -// Ruleset = { Value = Ruleset.Value } -// } -// } -// }; -// -// initFunc?.Invoke(room); -// return room; -// } -// -// private class TestDependencies : MultiplayerTestSceneDependencies -// { -// public TestDependencies() -// { -// // Need to set these values as early as possible. -// RoomManager.TimeBetweenListingPolls.Value = 1; -// RoomManager.TimeBetweenSelectionPolls.Value = 1; -// } -// } -// } -// } From 7cf6b551d353ffd8393b3ed4d7489f5c6d23bca3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 13:01:17 +0300 Subject: [PATCH 502/600] Replace until step with wait step with explanatory comment --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 080a1502b0..62a9b597ad 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -93,10 +93,15 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => !l.ChildrenOfType>().Any())); AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); - AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => + + // components wrapped in skinnable target containers load asynchronously, potentially taking more than one frame to load. + // wait once to properly execute the assert. + AddWaitStep("wait for async load", 1); + + AddAssert("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); + !p.ChildrenOfType().Single().ShowHandle)); } [Test] From c32ba9e38fe45f6200c8305fcc0938046cb792e6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 15:06:11 +0300 Subject: [PATCH 503/600] Remove arbitrarily-set wait step with until step instead, keeping the comment --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 62a9b597ad..f1ddfefe33 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -95,10 +95,8 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); // components wrapped in skinnable target containers load asynchronously, potentially taking more than one frame to load. - // wait once to properly execute the assert. - AddWaitStep("wait for async load", 1); - - AddAssert("all interactive elements removed", () => this.ChildrenOfType().All(p => + // therefore use until step rather than direct assert to account for that. + AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && !p.ChildrenOfType().Single().ShowHandle)); From 1fed9193f86c4052393c1a58ea09c0f8c2756272 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 15:24:10 +0300 Subject: [PATCH 504/600] Revert reverted segment to fix failure --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index f1ddfefe33..9bb9c24c6b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - !p.ChildrenOfType().Single().ShowHandle)); + p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); } [Test] From 1fcb1cdb108fb4049a8aa3f0d0de78408e50e187 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 22:01:47 +0900 Subject: [PATCH 505/600] Add todo --- osu.Game/Online/Rooms/Room.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 364336783d..d964060f10 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -134,7 +134,7 @@ namespace osu.Game.Online.Rooms /// The position of this in the list. This is not read from or written to the API. /// [JsonIgnore] - public readonly Bindable Position = new Bindable(-1); + public readonly Bindable Position = new Bindable(-1); // Todo: This does not need to exist. public Room() { From 155e9e16a5d08d2bcb52dfaeda81af6903e478f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 22:08:34 +0900 Subject: [PATCH 506/600] Refactorings --- osu.Game/Screens/OnlinePlay/IRoomManager.cs | 12 ++++++++++++ .../Multiplayer/MultiplayerLoungeSubScreen.cs | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/IRoomManager.cs b/osu.Game/Screens/OnlinePlay/IRoomManager.cs index baf84e25f9..6e1ffbda74 100644 --- a/osu.Game/Screens/OnlinePlay/IRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/IRoomManager.cs @@ -23,10 +23,22 @@ namespace osu.Game.Screens.OnlinePlay /// IBindableList Rooms { get; } + /// + /// Adds a to this . + /// If already existing, the local room will be updated with the given one. + /// + /// The incoming . void AddOrUpdateRoom(Room room); + /// + /// Removes a from this . + /// + /// The to remove. void RemoveRoom(Room room); + /// + /// Removes all s from this . + /// void ClearRooms(); /// diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 0756c78211..77db955f0a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.OnResuming(last); // Upon having left a room, we don't know whether we were the only participant, and whether the room is now closed as a result of leaving it. - // To work around this, temporarily clear all rooms until the next listing poll. + // To work around this, temporarily remove the room and trigger an immediate listing poll. if (last is MultiplayerMatchSubScreen match) { RoomManager.RemoveRoom(match.Room); From 0e66a0596340722b6175438a28f3682825b38d46 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 22:29:22 +0900 Subject: [PATCH 507/600] Hide left border of beatmap wedge --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 3 ++- osu.Game/Screens/Select/SongSelect.cs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 3779523094..5b4e077100 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -35,6 +35,7 @@ namespace osu.Game.Screens.Select { public class BeatmapInfoWedge : VisibilityContainer { + public const float BORDER_THICKNESS = 2.5f; private const float shear_width = 36.75f; private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.WEDGE_HEIGHT, 0); @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Select Shear = wedged_container_shear; Masking = true; BorderColour = new Color4(221, 255, 255, 255); - BorderThickness = 2.5f; + BorderThickness = BORDER_THICKNESS; Alpha = 0; EdgeEffect = new EdgeEffectParameters { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 0e113a71bc..bb3df0d4e0 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -203,6 +203,7 @@ namespace osu.Game.Screens.Select Margin = new MarginPadding { Right = left_area_padding, + Left = -BeatmapInfoWedge.BORDER_THICKNESS, // Hide the left border }, }, new Container From 2e9ab78275353624a45fcfcb58347f160fdeea42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 13 Aug 2021 21:30:26 +0200 Subject: [PATCH 508/600] Split test scene into two to follow class split --- .../TestSceneMultiplayerResults.cs | 51 +++++++++++++++++++ .../TestSceneMultiplayerTeamResults.cs | 37 +------------- 2 files changed, 52 insertions(+), 36 deletions(-) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs new file mode 100644 index 0000000000..ff06d4d9c7 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs @@ -0,0 +1,51 @@ +// 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 NUnit.Framework; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Osu; +using osu.Game.Scoring; +using osu.Game.Screens.OnlinePlay.Multiplayer; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMultiplayerResults : ScreenTestScene + { + [Test] + public void TestDisplayResults() + { + MultiplayerResultsScreen screen = null; + + AddStep("show results screen", () => + { + var rulesetInfo = new OsuRuleset().RulesetInfo; + var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo; + + var score = new ScoreInfo + { + Rank = ScoreRank.B, + TotalScore = 987654, + Accuracy = 0.8, + MaxCombo = 500, + Combo = 250, + Beatmap = beatmapInfo, + User = new User { Username = "Test user" }, + Date = DateTimeOffset.Now, + OnlineScoreID = 12345, + Ruleset = rulesetInfo, + }; + + PlaylistItem playlistItem = new PlaylistItem + { + BeatmapID = beatmapInfo.ID, + }; + + Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem)); + }); + + AddUntilStep("wait for loaded", () => screen.IsLoaded); + } + } +} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index a21996383f..0a8bda7ec0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [TestCase(7483253, 1048576)] [TestCase(1048576, 7483253)] [TestCase(1048576, 1048576)] - public void TestDisplayWithTeams(int team1Score, int team2Score) + public void TestDisplayTeamResults(int team1Score, int team2Score) { MultiplayerResultsScreen screen = null; @@ -57,40 +57,5 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for loaded", () => screen.IsLoaded); } - - [Test] - public void TestDisplayWithoutTeams() - { - MultiplayerResultsScreen screen = null; - - AddStep("show results screen", () => - { - var rulesetInfo = new OsuRuleset().RulesetInfo; - var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo; - - var score = new ScoreInfo - { - Rank = ScoreRank.B, - TotalScore = 987654, - Accuracy = 0.8, - MaxCombo = 500, - Combo = 250, - Beatmap = beatmapInfo, - User = new User { Username = "Test user" }, - Date = DateTimeOffset.Now, - OnlineScoreID = 12345, - Ruleset = rulesetInfo, - }; - - PlaylistItem playlistItem = new PlaylistItem - { - BeatmapID = beatmapInfo.ID, - }; - - Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem)); - }); - - AddUntilStep("wait for loaded", () => screen.IsLoaded); - } } } From 00317c0e30b4896f5086ec1d202013799e174cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 13 Aug 2021 23:44:07 +0200 Subject: [PATCH 509/600] Round when totalling up team scores instead of truncating Matches score handling in `ScoreManager`. --- osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 3f9258930e..362ee4a373 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.Play.HUD continue; if (TeamScores.TryGetValue(u.Team.Value, out var team)) - team.Value += (int)u.Score.Value; + team.Value += (int)Math.Round(u.Score.Value); } } From e2cc96097f1d53591bb8656bd4da2175b150d76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 13 Aug 2021 23:48:03 +0200 Subject: [PATCH 510/600] Unify match score display formatting Commas are already applied on the multiplayer leaderboard, as well as the results screen. --- osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 607d08b8ed..68e3f0df7d 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -171,6 +172,8 @@ namespace osu.Game.Screens.Play.HUD => displayedSpriteText.Font = winning ? OsuFont.Torus.With(weight: FontWeight.Bold, size: font_size, fixedWidth: true) : OsuFont.Torus.With(weight: FontWeight.Regular, size: font_size * 0.8f, fixedWidth: true); + + protected override LocalisableString FormatCount(double count) => count.ToLocalisableString(@"N0"); } } } From 5cfb89f18ac02d26168569846255e73703dde9d2 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 10:56:52 +0800 Subject: [PATCH 511/600] Apply suggestions from code review Co-authored-by: Joseph Madamba --- osu.Game/Localisation/UserInterfaceStrings.cs | 2 +- .../Settings/Sections/UserInterface/SongSelectSettings.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs index 18a9257732..fcfaf661dc 100644 --- a/osu.Game/Localisation/UserInterfaceStrings.cs +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -77,7 +77,7 @@ namespace osu.Game.Localisation /// /// "Song Select" /// - public static LocalisableString SoneSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select"); + public static LocalisableString SongSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select"); /// /// "Right mouse drag to absolute scroll" diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 8596cecbb8..6290046987 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface private Bindable minStars; private Bindable maxStars; - protected override LocalisableString Header => UserInterfaceStrings.SoneSelectHeader; + protected override LocalisableString Header => UserInterfaceStrings.SongSelectHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) From e26ccf786e6812a8aca382f061e346f3b5b64a76 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 11:04:38 +0800 Subject: [PATCH 512/600] code style format --- osu.Game/Localisation/OnlineSettingsStrings.cs | 4 ++-- osu.Game/Localisation/SkinSettingsStrings.cs | 2 +- .../Settings/Sections/Online/AlertsAndPrivacySettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Localisation/OnlineSettingsStrings.cs b/osu.Game/Localisation/OnlineSettingsStrings.cs index 0ef98a720c..0173cc7cbb 100644 --- a/osu.Game/Localisation/OnlineSettingsStrings.cs +++ b/osu.Game/Localisation/OnlineSettingsStrings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Localisation /// /// "Show a notification when you receive a private message" /// - public static LocalisableString NotifyOnPM => new TranslatableString(getKey(@"notify_on_pm"), @"Show a notification when you receive a private message"); + public static LocalisableString NotifyOnPrivateMessage => new TranslatableString(getKey(@"notify_on_private_message"), @"Show a notification when you receive a private message"); /// /// "Integrations" @@ -57,7 +57,7 @@ namespace osu.Game.Localisation /// /// "Automatically download beatmaps when spectating" /// - public static LocalisableString AutomaticallyDownload => new TranslatableString(getKey(@"automatically_download"), @"Automatically download beatmaps when spectating"); + public static LocalisableString AutomaticallyDownloadWhenSpectating => new TranslatableString(getKey(@"automatically_download_when_spectating"), @"Automatically download beatmaps when spectating"); /// /// "Show explicit content in search results" diff --git a/osu.Game/Localisation/SkinSettingsStrings.cs b/osu.Game/Localisation/SkinSettingsStrings.cs index 848c01b93a..f22b4d6bf5 100644 --- a/osu.Game/Localisation/SkinSettingsStrings.cs +++ b/osu.Game/Localisation/SkinSettingsStrings.cs @@ -22,7 +22,7 @@ namespace osu.Game.Localisation /// /// "Gameplay cursor size" /// - public static LocalisableString CursorSize => new TranslatableString(getKey(@"cursor_size"), @"Gameplay cursor size"); + public static LocalisableString GameplayCursorSize => new TranslatableString(getKey(@"gameplay_cursor_size"), @"Gameplay cursor size"); /// /// "Adjust gameplay cursor size based on current beatmap" diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 1728b565c2..351a32c72e 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online }, new SettingsCheckbox { - LabelText = OnlineSettingsStrings.NotifyOnPM, + LabelText = OnlineSettingsStrings.NotifyOnPrivateMessage, Current = config.GetBindable(OsuSetting.NotifyOnPrivateMessage) }, }; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 4200ddda3d..e864260cc6 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online }, new SettingsCheckbox { - LabelText = OnlineSettingsStrings.AutomaticallyDownload, + LabelText = OnlineSettingsStrings.AutomaticallyDownloadWhenSpectating, Keywords = new[] { "spectator" }, Current = config.GetBindable(OsuSetting.AutomaticallyDownloadWhenSpectating), }, diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 007302c584..e0d8252930 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Settings.Sections new ExportSkinButton(), new SettingsSlider { - LabelText = SkinSettingsStrings.CursorSize, + LabelText = SkinSettingsStrings.GameplayCursorSize, Current = config.GetBindable(OsuSetting.GameplayCursorSize), KeyboardStep = 0.01f }, From e6b3aba6e19557e2f2d493fb6d5c57a9c71d3b23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Aug 2021 14:08:29 +0900 Subject: [PATCH 513/600] Fix incorrectly directed call in `TestMultiplayerClient` --- osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index a28b4140ca..67b79d7390 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -178,7 +178,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Debug.Assert(Room != null); - return ((IMultiplayerClient)this).UserLeft(Room.Users.Single(u => u.UserID == userId)); + return ((IMultiplayerClient)this).UserKicked(Room.Users.Single(u => u.UserID == userId)); } public override async Task ChangeSettings(MultiplayerRoomSettings settings) From f87f86e671190c2836b95b801fee7be50aa52b1a Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 21:52:09 +0800 Subject: [PATCH 514/600] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Localisation/GameplaySettingsStrings.cs | 2 +- osu.Game/Localisation/OnlineSettingsStrings.cs | 2 +- osu.Game/Localisation/UserInterfaceStrings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- .../Overlays/Settings/Sections/Online/IntegrationSettings.cs | 2 +- .../Settings/Sections/UserInterface/GeneralSettings.cs | 2 +- .../Settings/Sections/UserInterface/MainMenuSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsSubsection.cs | 5 +++++ 10 files changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index c63fa5ddcc..868eb6b98a 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -42,7 +42,7 @@ namespace osu.Game.Localisation /// /// "Show difficulty graph on progress bar" /// - public static LocalisableString ShowProgressGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); + public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); /// /// "Show health display even when you can't fail" diff --git a/osu.Game/Localisation/OnlineSettingsStrings.cs b/osu.Game/Localisation/OnlineSettingsStrings.cs index 0173cc7cbb..6862f4ac2c 100644 --- a/osu.Game/Localisation/OnlineSettingsStrings.cs +++ b/osu.Game/Localisation/OnlineSettingsStrings.cs @@ -32,7 +32,7 @@ namespace osu.Game.Localisation /// /// "Integrations" /// - public static LocalisableString IntegrationHeader => new TranslatableString(getKey(@"integration_header"), @"Integrations"); + public static LocalisableString IntegrationsHeader => new TranslatableString(getKey(@"integrations_header"), @"Integrations"); /// /// "Discord Rich Presence" diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs index fcfaf661dc..4be403edb4 100644 --- a/osu.Game/Localisation/UserInterfaceStrings.cs +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Localisation /// /// "Hold-to-confirm activation time" /// - public static LocalisableString HoldActivationDelay => new TranslatableString(getKey(@"hold_activation_delay"), @"Hold-to-confirm activation time"); + public static LocalisableString HoldToConfirmActivationTime => new TranslatableString(getKey(@"hold_to_confirm_activation_time"), @"Hold-to-confirm activation time"); /// /// "Main Menu" diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 04332fcdd3..3a0265e453 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = GameplaySettingsStrings.ShowProgressGraph, + LabelText = GameplaySettingsStrings.ShowDifficultyGraph, Current = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 50bd8184ee..124b3b804c 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -146,7 +146,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { updateResolutionDropdown(); - windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : string.Empty; + windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : default; }, true); windowModes.BindCollectionChanged((sender, args) => diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 9747f6b373..653f30a018 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics frameLimiterDropdown.Current.BindValueChanged(limit => { - frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : string.Empty; + frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : default; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index f2a516feef..0207f2fd01 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online { public class IntegrationSettings : SettingsSubsection { - protected override LocalisableString Header => OnlineSettingsStrings.IntegrationHeader; + protected override LocalisableString Header => OnlineSettingsStrings.IntegrationsHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index b26363a9da..0afbed5df5 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface }, new SettingsSlider { - LabelText = UserInterfaceStrings.HoldActivationDelay, + LabelText = UserInterfaceStrings.HoldToConfirmActivationTime, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), KeyboardStep = 50 }, diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 976893bf0a..40485a070c 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface user.BindValueChanged(u => { - backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : string.Empty; + backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : default; }, true); } } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index df32424b67..4aa9360452 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -24,6 +24,11 @@ namespace osu.Game.Overlays.Settings protected abstract LocalisableString Header { get; } public IEnumerable FilterableChildren => Children.OfType(); + + // FilterTerms should contains both original string and localised string for user to search. + // Since LocalisableString is unable to get original string at this time (2021-08-14), + // only call .ToString() to use localised one. + // TODO: Update here when FilterTerms accept LocalisableString. public virtual IEnumerable FilterTerms => new[] { Header.ToString() }; public bool MatchingFilter From c2bbe175627ce35f1d63bc7c627b35b4883de5a0 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 22:35:15 +0800 Subject: [PATCH 515/600] Rename element in OsuSettings enum `ShowProgressGraph` -> `ShowDifficultyGraph` --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 60a0d5a0ac..6c7adcc806 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -101,7 +101,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.HitLighting, true); SetDefault(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); - SetDefault(OsuSetting.ShowProgressGraph, true); + SetDefault(OsuSetting.ShowDifficultyGraph, true); SetDefault(OsuSetting.ShowHealthDisplayWhenCantFail, true); SetDefault(OsuSetting.FadePlayfieldWhenHealthLow, true); SetDefault(OsuSetting.KeyOverlay, false); @@ -217,7 +217,7 @@ namespace osu.Game.Configuration AlwaysPlayFirstComboBreak, FloatingComments, HUDVisibilityMode, - ShowProgressGraph, + ShowDifficultyGraph, ShowHealthDisplayWhenCantFail, FadePlayfieldWhenHealthLow, MouseDisableButtons, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 353292606f..69aa57082a 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Show difficulty graph on progress bar", - Current = config.GetBindable(OsuSetting.ShowProgressGraph) + Current = config.GetBindable(OsuSetting.ShowDifficultyGraph) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index f28622f42e..6aa7e017ce 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -125,7 +125,7 @@ namespace osu.Game.Screens.Play Objects = drawableRuleset.Objects; } - config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph); + config.BindWith(OsuSetting.ShowDifficultyGraph, ShowGraph); graph.FillColour = bar.FillColour = colours.BlueLighter; } From 498462dfd0751fbbe480161d4c66487e4f58cc39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 14 Aug 2021 17:24:14 +0200 Subject: [PATCH 516/600] Fix room null-check racing against async schedule --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 57dbfbb507..2a0635c98c 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -190,8 +190,7 @@ namespace osu.Game.Online.Multiplayer return joinOrLeaveTaskChain.Add(async () => { await scheduledReset.ConfigureAwait(false); - if (Room != null) - await LeaveRoomInternal().ConfigureAwait(false); + await LeaveRoomInternal().ConfigureAwait(false); }); } From 246a8882ce248f35ba238875db35d281473e12f6 Mon Sep 17 00:00:00 2001 From: LiangXiang Shen Date: Sun, 15 Aug 2021 00:23:14 +0800 Subject: [PATCH 517/600] Update translation key --- osu.Game/Localisation/GameplaySettingsStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 868eb6b98a..6d6381b429 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -42,7 +42,7 @@ namespace osu.Game.Localisation /// /// "Show difficulty graph on progress bar" /// - public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); + public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_difficulty_graph"), @"Show difficulty graph on progress bar"); /// /// "Show health display even when you can't fail" From 2ddf28346aa2873bef9cb9edf313f8fe0b52e721 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 14 Aug 2021 19:58:20 +0300 Subject: [PATCH 518/600] PlayerSettingsGroups -> PlayerSettings --- .../Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index f28c2a1d48..14bd8fa6dc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [BackgroundDependencyLoader] private void load() { - PlayerSettingsGroups.Expire(); + PlayerSettings.Expire(); } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 1f8387ac67..a6592e4d24 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play /// /// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader. /// - protected FillFlowContainer PlayerSettingsGroups; + protected FillFlowContainer PlayerSettings; protected VisualSettings VisualSettings; @@ -145,7 +145,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - PlayerSettingsGroups = new FillFlowContainer + PlayerSettings = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From c8fb79666064f6ead2485aeec1757d1407cda909 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 14 Aug 2021 20:14:21 +0300 Subject: [PATCH 519/600] Fix settings notice text class tinting everything with yellow --- osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- osu.Game/Overlays/Settings/SettingsNoticeText.cs | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 2816eb7037..c561b693d8 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.TopCentre, Text = TabletSettingsStrings.NoTabletDetected, }, - new SettingsNoticeText + new SettingsNoticeText(colours) { TextAnchor = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 5d25605360..ef2027fdab 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings return; // construct lazily for cases where the label is not needed (may be provided by the Control). - FlowContent.Add(warningText = new SettingsNoticeText { Margin = new MarginPadding { Bottom = 5 } }); + FlowContent.Add(warningText = new SettingsNoticeText(colours) { Margin = new MarginPadding { Bottom = 5 } }); } warningText.Alpha = hasValue ? 0 : 1; diff --git a/osu.Game/Overlays/Settings/SettingsNoticeText.cs b/osu.Game/Overlays/Settings/SettingsNoticeText.cs index 6bb4a3f11c..76ecf7edd4 100644 --- a/osu.Game/Overlays/Settings/SettingsNoticeText.cs +++ b/osu.Game/Overlays/Settings/SettingsNoticeText.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -10,10 +9,9 @@ namespace osu.Game.Overlays.Settings { public class SettingsNoticeText : LinkFlowContainer { - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public SettingsNoticeText(OsuColour colours) + : base(s => s.Colour = colours.Yellow) { - Colour = colours.Yellow; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; } From 95943fdb25c763a10849f9dff6dffb4fa7466919 Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 20:00:26 -0400 Subject: [PATCH 520/600] Add glow to supporter promo on changelog Added glow to the supporter promo at the end of the changelog, as it is on the website. --- .../Changelog/ChangelogSupporterPromo.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index f617b4fc82..46fab30d5e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -138,14 +138,28 @@ namespace osu.Game.Overlays.Changelog FillMode = FillMode.Fill, Texture = textures.Get(@"Online/supporter-pippi"), }, - new Sprite + new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Width = 75, Height = 75, - Margin = new MarginPadding { Top = 70 }, - Texture = textures.Get(@"Online/supporter-heart"), + Margin = new MarginPadding { Top = 83 }, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.HotPink.Opacity(0.88f), + Offset = new Vector2(0, 0), + Radius = 17, + Roundness = 39f, + }, + Child = new Sprite + { + Width = 75, + Height = 75, + Texture = textures.Get(@"Online/supporter-heart"), + }, }, }; } From 772860232cbbfad9ca85c68d413465405828279b Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 20:32:38 -0400 Subject: [PATCH 521/600] Removed empty offset and corrected colour --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 46fab30d5e..203a371f43 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -149,8 +149,7 @@ namespace osu.Game.Overlays.Changelog EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, - Colour = Color4.HotPink.Opacity(0.88f), - Offset = new Vector2(0, 0), + Colour = colour.Pink, Radius = 17, Roundness = 39f, }, From 71ccd38bb35e6276205152edb953daedc0affb34 Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 20:36:43 -0400 Subject: [PATCH 522/600] Corrected pippi background and promo positioning --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 203a371f43..f8613b101e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -134,6 +134,7 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Margin = new MarginPadding { Bottom = 28 }, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, Texture = textures.Get(@"Online/supporter-pippi"), @@ -144,7 +145,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.TopCentre, Width = 75, Height = 75, - Margin = new MarginPadding { Top = 83 }, + Margin = new MarginPadding { Top = 70 }, Masking = true, EdgeEffect = new EdgeEffectParameters { From 7d6f7ac75e496c6cff379c7f471e805267e02047 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 02:57:11 +0200 Subject: [PATCH 523/600] Fix mark channel as read error --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 3136a3960d..1937019ef6 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -553,7 +553,7 @@ namespace osu.Game.Online.Chat if (channel.LastMessageId == channel.LastReadId) return; - var message = channel.Messages.LastOrDefault(); + var message = channel.Messages.FindLast(msg => !(msg is LocalMessage)); if (message == null) return; From 6472d85aae3377c7f37bb233aace478cfad8ab06 Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 21:48:57 -0400 Subject: [PATCH 524/600] Added heart_size constant and adjusted the glow radius value Added heart_size constant and adjusted the glow radius value to be more in line with the website --- .../Overlays/Changelog/ChangelogSupporterPromo.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index f8613b101e..c51f927f9f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Changelog public class ChangelogSupporterPromo : CompositeDrawable { private const float image_container_width = 164; + private const float heart_size = 75; private readonly FillFlowContainer textContainer; private readonly Container imageContainer; @@ -143,21 +144,21 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Width = 75, - Height = 75, + Width = heart_size, + Height = heart_size, Margin = new MarginPadding { Top = 70 }, Masking = true, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, Colour = colour.Pink, - Radius = 17, - Roundness = 39f, + Radius = 10, + Roundness = heart_size / 2, }, Child = new Sprite { - Width = 75, - Height = 75, + Width = heart_size, + Height = heart_size, Texture = textures.Get(@"Online/supporter-heart"), }, }, From f9e2e808743403cafd862f1fd1177a1bc0f8b4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 15:04:14 +0200 Subject: [PATCH 525/600] Add testing for auto-restart behaviour --- .../Visual/Mods/TestSceneModFailCondition.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs new file mode 100644 index 0000000000..af874cec91 --- /dev/null +++ b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Mods +{ + public class TestSceneModFailCondition : ModTestScene + { + private bool restartRequested; + + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + protected override TestPlayer CreateModPlayer(Ruleset ruleset) + { + var player = base.CreateModPlayer(ruleset); + player.RestartRequested = () => restartRequested = true; + return player; + } + + protected override bool AllowFail => true; + + [SetUpSteps] + public void SetUp() + { + AddStep("reset flag", () => restartRequested = false); + } + + [Test] + public void TestRestartOnFailDisabled() => CreateModTest(new ModTestData + { + Autoplay = false, + Mod = new OsuModSuddenDeath(), + PassCondition = () => !restartRequested && Player.ChildrenOfType().Single().State.Value == Visibility.Visible + }); + + [Test] + public void TestRestartOnFailEnabled() => CreateModTest(new ModTestData + { + Autoplay = false, + Mod = new OsuModSuddenDeath + { + Restart = { Value = true } + }, + PassCondition = () => restartRequested && Player.ChildrenOfType().Single().State.Value == Visibility.Hidden + }); + } +} From 2f9f1ba862cf7c54dca3063e0c33dee9fef55c01 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 15:44:23 +0200 Subject: [PATCH 526/600] Add test for `ChannelManager.MarkChannelAsRead` --- .../Chat/TestSceneChannelManager.cs | 57 ++++++++++++++++++- .../API/Requests/MarkChannelAsReadRequest.cs | 10 ++-- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index 0ec21a4c7b..7b6d2078ca 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -19,6 +20,7 @@ namespace osu.Game.Tests.Chat { private ChannelManager channelManager; private int currentMessageId; + List sentMessages; [SetUp] public void Setup() => Schedule(() => @@ -34,6 +36,7 @@ namespace osu.Game.Tests.Chat AddStep("register request handling", () => { currentMessageId = 0; + sentMessages = new List(); ((DummyAPIAccess)API).HandleRequest = req => { @@ -44,7 +47,7 @@ namespace osu.Game.Tests.Chat return true; case PostMessageRequest postMessage: - postMessage.TriggerSuccess(new Message(++currentMessageId) + var message = new Message(++currentMessageId) { IsAction = postMessage.Message.IsAction, ChannelId = postMessage.Message.ChannelId, @@ -52,7 +55,10 @@ namespace osu.Game.Tests.Chat Links = postMessage.Message.Links, Timestamp = postMessage.Message.Timestamp, Sender = postMessage.Message.Sender - }); + }; + + sentMessages.Add(message); + postMessage.TriggerSuccess(message); return true; } @@ -83,12 +89,59 @@ namespace osu.Game.Tests.Chat AddAssert("/np command received by channel 2", () => channel2.Messages.Last().Content.Contains("is listening to")); } + [Test] + public void TestMarkAsReadIgnoringLocalMessages() { + Channel channel = null; + + AddStep("join channel and select it", () => + { + channelManager.JoinChannel(channel = createChannel(1, ChannelType.Public)); + + channelManager.CurrentChannel.Value = channel; + }); + + AddStep("post message", () => channelManager.PostMessage("Something interesting")); + AddUntilStep("wait until the message is posted", () => channel.Messages.Count == sentMessages.Count); + + AddStep("post /help command", () => channelManager.PostCommand("help", channel)); + AddStep("post /me command with no action", () => channelManager.PostCommand("me", channel)); + AddStep("post /join command with no channel", () => channelManager.PostCommand("join", channel)); + AddStep("post /join command with non-existent channel", () => channelManager.PostCommand("join i-dont-exist", channel)); + AddStep("post non-existent command", () => channelManager.PostCommand("non-existent-cmd arg", channel)); + + AddStep("register mark channel as read request handler", () => { + ((DummyAPIAccess)API).HandleRequest = req => + { + switch (req) + { + case MarkChannelAsReadRequest markRead: + var isSentMessage = sentMessages.Contains(markRead.Message); + + AddAssert("mark channel as read called with a real message", () => isSentMessage); + + if(isSentMessage) { + markRead.TriggerSuccess(); + } else { + markRead.TriggerFailure(new APIException("unknown message!", null)); + } + + return true; + } + + return false; + }; + }); + + AddStep("mark channel as read", () => channelManager.MarkChannelAsRead(channel)); + } + private Channel createChannel(int id, ChannelType type) => new Channel(new User()) { Id = id, Name = $"Channel {id}", Topic = $"Topic of channel {id} with type {type}", Type = type, + LastMessageId = 0, }; private class ChannelManagerContainer : CompositeDrawable diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 95a5d0acbd..594ab2accc 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -9,16 +9,16 @@ namespace osu.Game.Online.API.Requests { public class MarkChannelAsReadRequest : APIRequest { - private readonly Channel channel; - private readonly Message message; + public readonly Channel Channel; + public readonly Message Message; public MarkChannelAsReadRequest(Channel channel, Message message) { - this.channel = channel; - this.message = message; + this.Channel = channel; + this.Message = message; } - protected override string Target => $"chat/channels/{channel.Id}/mark-as-read/{message.Id}"; + protected override string Target => $"chat/channels/{Channel.Id}/mark-as-read/{Message.Id}"; protected override WebRequest CreateWebRequest() { From 7d7c5c06f06a3d5f987623defcdc878e518fed26 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 16:02:25 +0200 Subject: [PATCH 527/600] Fix code formatting --- .../Chat/TestSceneChannelManager.cs | 41 ++++++++++--------- .../API/Requests/MarkChannelAsReadRequest.cs | 4 +- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index 7b6d2078ca..fcb602cb04 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Chat { private ChannelManager channelManager; private int currentMessageId; - List sentMessages; + private List sentMessages; [SetUp] public void Setup() => Schedule(() => @@ -90,46 +90,49 @@ namespace osu.Game.Tests.Chat } [Test] - public void TestMarkAsReadIgnoringLocalMessages() { + public void TestMarkAsReadIgnoringLocalMessages() + { Channel channel = null; AddStep("join channel and select it", () => { channelManager.JoinChannel(channel = createChannel(1, ChannelType.Public)); - channelManager.CurrentChannel.Value = channel; }); AddStep("post message", () => channelManager.PostMessage("Something interesting")); AddUntilStep("wait until the message is posted", () => channel.Messages.Count == sentMessages.Count); - AddStep("post /help command", () => channelManager.PostCommand("help", channel)); AddStep("post /me command with no action", () => channelManager.PostCommand("me", channel)); AddStep("post /join command with no channel", () => channelManager.PostCommand("join", channel)); AddStep("post /join command with non-existent channel", () => channelManager.PostCommand("join i-dont-exist", channel)); AddStep("post non-existent command", () => channelManager.PostCommand("non-existent-cmd arg", channel)); - AddStep("register mark channel as read request handler", () => { + AddStep("register mark channel as read request handler", () => + { ((DummyAPIAccess)API).HandleRequest = req => + { + switch (req) { - switch (req) - { - case MarkChannelAsReadRequest markRead: - var isSentMessage = sentMessages.Contains(markRead.Message); + case MarkChannelAsReadRequest markRead: + var isSentMessage = sentMessages.Contains(markRead.Message); - AddAssert("mark channel as read called with a real message", () => isSentMessage); + AddAssert("mark channel as read called with a real message", () => isSentMessage); - if(isSentMessage) { - markRead.TriggerSuccess(); - } else { - markRead.TriggerFailure(new APIException("unknown message!", null)); - } + if (isSentMessage) + { + markRead.TriggerSuccess(); + } + else + { + markRead.TriggerFailure(new APIException("unknown message!", null)); + } - return true; - } + return true; + } - return false; - }; + return false; + }; }); AddStep("mark channel as read", () => channelManager.MarkChannelAsRead(channel)); diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 594ab2accc..b24669e6d5 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -14,8 +14,8 @@ namespace osu.Game.Online.API.Requests public MarkChannelAsReadRequest(Channel channel, Message message) { - this.Channel = channel; - this.Message = message; + Channel = channel; + Message = message; } protected override string Target => $"chat/channels/{Channel.Id}/mark-as-read/{Message.Id}"; From 7c88a1c6dee143dbea7f60530c7fe17acd50cf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:00:22 +0200 Subject: [PATCH 528/600] Add a way to change custom combo colours via `IHasComboColours` `IHasComboColours` was already mutable (via a strange `AddComboColours()` method) and exposing a straight list is easier to work with. `IHasCustomColours` is also similarly externally mutable (in a way which is not easily removable). --- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 5 +++-- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 9 +++++++++ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- osu.Game/Skinning/DefaultLegacySkin.cs | 6 ++++-- osu.Game/Skinning/SkinConfiguration.cs | 8 ++++---- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 4 ++-- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index c15d804a19..aadabec100 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -133,11 +133,12 @@ namespace osu.Game.Tests.Skins [Test] public void TestEmptyComboColoursNoFallback() { - AddStep("Add custom combo colours to user skin", () => userSource.Configuration.AddComboColours( + AddStep("Add custom combo colours to user skin", () => userSource.Configuration.CustomComboColours = new List + { new Color4(100, 150, 200, 255), new Color4(55, 110, 166, 255), new Color4(75, 125, 175, 255) - )); + }); AddStep("Disallow default colours fallback in beatmap skin", () => beatmapSource.Configuration.AllowDefaultComboColoursFallback = false); diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 41c85db063..91d960a2fb 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -1,6 +1,7 @@ // 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 osuTK.Graphics; @@ -13,9 +14,17 @@ namespace osu.Game.Beatmaps.Formats /// IReadOnlyList ComboColours { get; } + /// + /// The list of custom combo colours. + /// If non-empty, will return these colours; + /// if empty, will fall back to default combo colours. + /// + List CustomComboColours { get; } + /// /// Adds combo colours to the list. /// + [Obsolete("Use SkinConfiguration.ComboColours directly.")] // can be removed 20220215 void AddComboColours(params Color4[] colours); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index b39890084f..20080308f9 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -123,7 +123,7 @@ namespace osu.Game.Beatmaps.Formats { if (!(output is IHasComboColours tHasComboColours)) return; - tHasComboColours.AddComboColours(colour); + tHasComboColours.CustomComboColours.Add(colour); } else { diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 30192182f3..16ac17546d 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using JetBrains.Annotations; using osu.Framework.IO.Stores; using osu.Game.Extensions; @@ -21,12 +22,13 @@ namespace osu.Game.Skinning : base(skin, new NamespacedResourceStore(resources.Resources, "Skins/Legacy"), resources, string.Empty) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); - Configuration.AddComboColours( + Configuration.CustomComboColours = new List + { new Color4(255, 192, 0, 255), new Color4(0, 202, 0, 255), new Color4(18, 124, 255, 255), new Color4(242, 24, 57, 255) - ); + }; Configuration.LegacyVersion = 2.7m; } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 25a924c929..a18144246f 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -27,14 +27,14 @@ namespace osu.Game.Skinning new Color4(242, 24, 57, 255), }; - private readonly List comboColours = new List(); + public List CustomComboColours { get; set; } = new List(); public IReadOnlyList ComboColours { get { - if (comboColours.Count > 0) - return comboColours; + if (CustomComboColours.Count > 0) + return CustomComboColours; if (AllowDefaultComboColoursFallback) return DefaultComboColours; @@ -43,7 +43,7 @@ namespace osu.Game.Skinning } } - public void AddComboColours(params Color4[] colours) => comboColours.AddRange(colours); + void IHasComboColours.AddComboColours(params Color4[] colours) => CustomComboColours.AddRange(colours); public Dictionary CustomColours { get; } = new Dictionary(); diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index cdf6a9a2b4..356d2c848c 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -116,7 +116,7 @@ namespace osu.Game.Tests.Beatmaps { if (hasColours) { - Configuration.AddComboColours(Colours); + Configuration.CustomComboColours = Colours.ToList(); Configuration.CustomColours.Add("HyperDash", HYPER_DASH_COLOUR); Configuration.CustomColours.Add("HyperDashAfterImage", HYPER_DASH_AFTER_IMAGE_COLOUR); Configuration.CustomColours.Add("HyperDashFruit", HYPER_DASH_FRUIT_COLOUR); @@ -145,7 +145,7 @@ namespace osu.Game.Tests.Beatmaps { if (hasCustomColours) { - Configuration.AddComboColours(Colours); + Configuration.CustomComboColours = Colours.ToList(); Configuration.CustomColours.Add("HyperDash", HYPER_DASH_COLOUR); Configuration.CustomColours.Add("HyperDashAfterImage", HYPER_DASH_AFTER_IMAGE_COLOUR); Configuration.CustomColours.Add("HyperDashFruit", HYPER_DASH_FRUIT_COLOUR); From 8f698a42f727472723668931713ae4671af2ace0 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 20:35:52 +0200 Subject: [PATCH 529/600] Refactor `MarkChannelAsRead` test assert --- .../Chat/TestSceneChannelManager.cs | 75 +++++++++---------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index fcb602cb04..5e22101e5c 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -47,19 +47,11 @@ namespace osu.Game.Tests.Chat return true; case PostMessageRequest postMessage: - var message = new Message(++currentMessageId) - { - IsAction = postMessage.Message.IsAction, - ChannelId = postMessage.Message.ChannelId, - Content = postMessage.Message.Content, - Links = postMessage.Message.Links, - Timestamp = postMessage.Message.Timestamp, - Sender = postMessage.Message.Sender - }; - - sentMessages.Add(message); - postMessage.TriggerSuccess(message); + handlePostMessageRequest(postMessage); + return true; + case MarkChannelAsReadRequest markRead: + handleMarkChannelAsReadRequest(markRead); return true; } @@ -101,41 +93,44 @@ namespace osu.Game.Tests.Chat }); AddStep("post message", () => channelManager.PostMessage("Something interesting")); - AddUntilStep("wait until the message is posted", () => channel.Messages.Count == sentMessages.Count); + AddStep("post /help command", () => channelManager.PostCommand("help", channel)); AddStep("post /me command with no action", () => channelManager.PostCommand("me", channel)); AddStep("post /join command with no channel", () => channelManager.PostCommand("join", channel)); AddStep("post /join command with non-existent channel", () => channelManager.PostCommand("join i-dont-exist", channel)); AddStep("post non-existent command", () => channelManager.PostCommand("non-existent-cmd arg", channel)); - AddStep("register mark channel as read request handler", () => - { - ((DummyAPIAccess)API).HandleRequest = req => - { - switch (req) - { - case MarkChannelAsReadRequest markRead: - var isSentMessage = sentMessages.Contains(markRead.Message); - - AddAssert("mark channel as read called with a real message", () => isSentMessage); - - if (isSentMessage) - { - markRead.TriggerSuccess(); - } - else - { - markRead.TriggerFailure(new APIException("unknown message!", null)); - } - - return true; - } - - return false; - }; - }); - AddStep("mark channel as read", () => channelManager.MarkChannelAsRead(channel)); + AddAssert("channel's last read ID is set to the latest message", () => channel.LastReadId == sentMessages.Last().Id); + } + + private void handlePostMessageRequest(PostMessageRequest request) + { + var message = new Message(++currentMessageId) + { + IsAction = request.Message.IsAction, + ChannelId = request.Message.ChannelId, + Content = request.Message.Content, + Links = request.Message.Links, + Timestamp = request.Message.Timestamp, + Sender = request.Message.Sender + }; + + sentMessages.Add(message); + request.TriggerSuccess(message); + } + + private void handleMarkChannelAsReadRequest(MarkChannelAsReadRequest request) + { + // only accept messages that were sent through the API + if (sentMessages.Contains(request.Message)) + { + request.TriggerSuccess(); + } + else + { + request.TriggerFailure(new APIException("unknown message!", null)); + } } private Channel createChannel(int id, ChannelType type) => new Channel(new User()) From 29a22bd11f4b82304a14a1501ec48a373d4c1651 Mon Sep 17 00:00:00 2001 From: emu1337 Date: Sun, 15 Aug 2021 20:48:00 +0200 Subject: [PATCH 530/600] added rhythm multiplier for strain sections --- osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 15 +++++++++++++++ .../Rulesets/Difficulty/Skills/StrainSkill.cs | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index f0eb199e5f..b1373cd215 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -34,6 +34,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills { } + private double calculateRhythmBonus(double time) + { + return 1.0; + } + + protected override double StrainValueOf(DifficultyHitObject current) { if (current.BaseObject is Spinner) @@ -66,5 +72,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime; } + protected override double GetTotalCurrentStrain(DifficultyHitObject current) + { + return base.GetTotalCurrentStrain(current) * calculateRhythmBonus(current.StartTime); + } + + protected override double GetPeakStrain(double time) + { + return base.GetPeakStrain(time) * calculateRhythmBonus(time); + } } } diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index d4fcefab9b..95b0fe43fc 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -71,7 +71,12 @@ namespace osu.Game.Rulesets.Difficulty.Skills CurrentStrain *= strainDecay(current.DeltaTime); CurrentStrain += StrainValueOf(current) * SkillMultiplier; - currentSectionPeak = Math.Max(CurrentStrain, currentSectionPeak); + currentSectionPeak = Math.Max(GetTotalCurrentStrain(current), currentSectionPeak); + } + + protected virtual double GetTotalCurrentStrain(DifficultyHitObject current) + { + return CurrentStrain; } /// From df43e758ee18c95ca49e36c05e526517b38646b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:13:59 +0200 Subject: [PATCH 531/600] Add editable beatmap skin --- osu.Game/Screens/Edit/EditorBeatmap.cs | 5 +- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 59 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorBeatmapSkin.cs diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 7de98e5e85..3402bf653a 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Edit private readonly Bindable hasTiming = new Bindable(); [CanBeNull] - public readonly ISkin BeatmapSkin; + public readonly EditorBeatmapSkin BeatmapSkin; [Resolved] private BindableBeatDivisor beatDivisor { get; set; } @@ -69,7 +69,8 @@ namespace osu.Game.Screens.Edit public EditorBeatmap(IBeatmap playableBeatmap, ISkin beatmapSkin = null) { PlayableBeatmap = playableBeatmap; - BeatmapSkin = beatmapSkin; + if (beatmapSkin is Skin skin) + BeatmapSkin = new EditorBeatmapSkin(skin); beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset?.CreateInstance().CreateBeatmapProcessor(PlayableBeatmap); diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs new file mode 100644 index 0000000000..6745f08b80 --- /dev/null +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -0,0 +1,59 @@ +// 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.Linq; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.OpenGL.Textures; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Skinning; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit +{ + /// + /// A beatmap skin which is being edited. + /// + public class EditorBeatmapSkin : ISkin + { + public event Action BeatmapSkinChanged; + + /// + /// The combo colours of this skin. + /// If empty, the default combo colours will be used. + /// + public BindableList ComboColours; + + private readonly Skin skin; + + public EditorBeatmapSkin(Skin skin) + { + this.skin = skin; + + ComboColours = new BindableList(); + if (skin.Configuration.ComboColours != null) + ComboColours.AddRange(skin.Configuration.ComboColours.Select(c => (Colour4)c)); + ComboColours.BindCollectionChanged((_, __) => updateColours()); + } + + private void invokeSkinChanged() => BeatmapSkinChanged?.Invoke(); + + private void updateColours() + { + skin.Configuration.CustomComboColours = ComboColours.Select(c => (Color4)c).ToList(); + invokeSkinChanged(); + } + + #region Delegated ISkin implementation + + public Drawable GetDrawableComponent(ISkinComponent component) => skin.GetDrawableComponent(component); + public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => skin.GetTexture(componentName, wrapModeS, wrapModeT); + public ISample GetSample(ISampleInfo sampleInfo) => skin.GetSample(sampleInfo); + public IBindable GetConfig(TLookup lookup) => skin.GetConfig(lookup); + + #endregion + } +} From 0d64da8c63f1e6533f62defaddc21d6b6bc727ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:14:41 +0200 Subject: [PATCH 532/600] Add skin providing container responding to beatmap skin edits --- .../Screens/Edit/Compose/ComposeScreen.cs | 3 +- .../Edit/EditorSkinProvidingContainer.cs | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 4a1f1196a9..62b3d33069 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -15,7 +15,6 @@ using osu.Game.Extensions; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; -using osu.Game.Skinning; namespace osu.Game.Screens.Edit.Compose { @@ -73,7 +72,7 @@ namespace osu.Game.Screens.Edit.Compose { Debug.Assert(ruleset != null); - return new RulesetSkinProvidingContainer(ruleset, EditorBeatmap.PlayableBeatmap, beatmap.Value.Skin).WithChild(content); + return new EditorSkinProvidingContainer(EditorBeatmap).WithChild(content); } #region Input Handling diff --git a/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs new file mode 100644 index 0000000000..27563b5a0f --- /dev/null +++ b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Skinning; + +#nullable enable + +namespace osu.Game.Screens.Edit +{ + /// + /// A that fires when users have made a change to the beatmap skin + /// of the map being edited. + /// + public class EditorSkinProvidingContainer : RulesetSkinProvidingContainer + { + private readonly EditorBeatmapSkin? beatmapSkin; + + public EditorSkinProvidingContainer(EditorBeatmap editorBeatmap) + : base(editorBeatmap.PlayableBeatmap.BeatmapInfo.Ruleset.CreateInstance(), editorBeatmap, editorBeatmap.BeatmapSkin) + { + beatmapSkin = editorBeatmap.BeatmapSkin; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (beatmapSkin != null) + beatmapSkin.BeatmapSkinChanged += TriggerSourceChanged; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmapSkin != null) + beatmapSkin.BeatmapSkinChanged -= TriggerSourceChanged; + } + } +} From 81280dfd257fe482e0baeab20c828849b26837a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:32:26 +0200 Subject: [PATCH 533/600] Use editable skin structure in combo colour picker --- osu.Game/Screens/Edit/Setup/ColoursSection.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/ColoursSection.cs b/osu.Game/Screens/Edit/Setup/ColoursSection.cs index d7e16645f2..05d9855a24 100644 --- a/osu.Game/Screens/Edit/Setup/ColoursSection.cs +++ b/osu.Game/Screens/Edit/Setup/ColoursSection.cs @@ -1,14 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Skinning; -using osuTK.Graphics; namespace osu.Game.Screens.Edit.Setup { @@ -31,9 +27,8 @@ namespace osu.Game.Screens.Edit.Setup } }; - var colours = Beatmap.BeatmapSkin?.GetConfig>(GlobalSkinColours.ComboColours)?.Value; - if (colours != null) - comboColours.Colours.AddRange(colours.Select(c => (Colour4)c)); + if (Beatmap.BeatmapSkin != null) + comboColours.Colours.BindTo(Beatmap.BeatmapSkin.ComboColours); } } } From 6108451449c8b5a56734a28b4fb034226b01ee53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 18:38:01 +0200 Subject: [PATCH 534/600] Retrieve separated skin instance from working beatmap for editing --- .../Beatmaps/Formats/LegacyBeatmapEncoderTest.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs | 2 +- .../Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs | 2 +- osu.Game.Tests/WaveformTestBeatmap.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 10 +++++++++- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs | 2 +- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 2 +- osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs | 2 +- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- 14 files changed, 22 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index 059432eeaf..855a75117d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -169,7 +169,7 @@ namespace osu.Game.Tests.Beatmaps.Formats protected override Track GetBeatmapTrack() => throw new NotImplementedException(); - protected override ISkin GetSkin() => throw new NotImplementedException(); + protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); } diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index aed28f5f84..3bf6aaac7a 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -204,7 +204,7 @@ namespace osu.Game.Tests.Gameplay this.resources = resources; } - protected override ISkin GetSkin() => new TestSkin("test-sample", resources); + protected internal override ISkin GetSkin() => new TestSkin("test-sample", resources); } private class TestDrawableStoryboardSample : DrawableStoryboardSample diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs index 13e84e335d..e560c81fb2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.Gameplay this.beatmapSkin = beatmapSkin; } - protected override ISkin GetSkin() => beatmapSkin; + protected internal override ISkin GetSkin() => beatmapSkin; } private class TestOsuRuleset : OsuRuleset diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 5477e4a0f8..9c85fa0c9c 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0d16294c68..4a78ceb299 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -534,7 +534,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetBeatmapTrack() => null; - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index d78ffbbfb6..45112ae74c 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -128,7 +128,7 @@ namespace osu.Game.Beatmaps return storyboard; } - protected override ISkin GetSkin() + protected internal override ISkin GetSkin() { try { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index ea7f45e53f..acfd01a3c8 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -50,7 +50,7 @@ namespace osu.Game.Beatmaps protected override Track GetBeatmapTrack() => GetVirtualTrack(); - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 662d24cc83..61760e69b0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -327,7 +327,15 @@ namespace osu.Game.Beatmaps public bool SkinLoaded => skin.IsResultAvailable; public ISkin Skin => skin.Value; - protected abstract ISkin GetSkin(); + /// + /// Creates a new skin instance for this beatmap. + /// + /// + /// This should only be called externally in scenarios where it is explicitly desired to get a new instance of a skin + /// (e.g. for editing purposes, to avoid state pollution). + /// For standard reading purposes, should always be used directly. + /// + protected internal abstract ISkin GetSkin(); private readonly RecyclableLazy skin; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 61a3b0f5cc..e8d919311b 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -153,7 +153,7 @@ namespace osu.Game.Screens.Edit // todo: remove caching of this and consume via editorBeatmap? dependencies.Cache(beatDivisor); - AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.Skin)); + AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.GetSkin())); dependencies.CacheAs(editorBeatmap); changeHandler = new EditorChangeHandler(editorBeatmap); dependencies.CacheAs(changeHandler); diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index 6f92db98ee..d26856365e 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit protected override Track GetBeatmapTrack() => throw new NotImplementedException(); - protected override ISkin GetSkin() => throw new NotImplementedException(); + protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 4935f7fc13..64f1ee4a7a 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -217,7 +217,7 @@ namespace osu.Game.Tests.Beatmaps protected override Track GetBeatmapTrack() => throw new NotImplementedException(); - protected override ISkin GetSkin() => throw new NotImplementedException(); + protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 7ee6c519b7..bb5dd09e16 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -211,7 +211,7 @@ namespace osu.Game.Tests.Beatmaps this.resources = resources; } - protected override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, resources); + protected internal override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, resources); } } } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index 356d2c848c..27162b1d66 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps HasColours = hasColours; } - protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, HasColours); + protected internal override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, HasColours); } protected class TestBeatmapSkin : LegacyBeatmapSkin diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index bfce59c7de..19974701db 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Beatmaps protected override Storyboard GetStoryboard() => storyboard ?? base.GetStoryboard(); - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; From f6773522d1652a94ea1618a5482e8d668758dfd7 Mon Sep 17 00:00:00 2001 From: Daniel Kariv <38776931+danielkariv@users.noreply.github.com> Date: Mon, 16 Aug 2021 00:12:27 +0300 Subject: [PATCH 535/600] Correct icons in beatmap details In relation to #13968. Replacing incorrect icons in beatmap details panel to correct ones from BeatmapStatisticsIcon class. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 3f1034759e..21bb75b960 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -78,10 +78,10 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Horizontal, Children = new[] { - length = new Statistic(FontAwesome.Regular.Clock, "Length") { Width = 0.25f }, - bpm = new Statistic(FontAwesome.Regular.Circle, "BPM") { Width = 0.25f }, - circleCount = new Statistic(FontAwesome.Regular.Circle, "Circle Count") { Width = 0.25f }, - sliderCount = new Statistic(FontAwesome.Regular.Circle, "Slider Count") { Width = 0.25f }, + length = new Statistic(BeatmapStatisticsIconType.Length, "Length") { Width = 0.25f }, + bpm = new Statistic(BeatmapStatisticsIconType.Bpm, "BPM") { Width = 0.25f }, + circleCount = new Statistic(BeatmapStatisticsIconType.Circles, "Circle Count") { Width = 0.25f }, + sliderCount = new Statistic(BeatmapStatisticsIconType.Sliders, "Slider Count") { Width = 0.25f }, }, }; } @@ -104,7 +104,7 @@ namespace osu.Game.Overlays.BeatmapSet set => this.value.Text = value; } - public Statistic(IconUsage icon, string name) + public Statistic(BeatmapStatisticsIconType icon, string name) { TooltipText = name; RelativeSizeAxes = Axes.X; @@ -129,11 +129,9 @@ namespace osu.Game.Overlays.BeatmapSet Rotation = 45, Colour = Color4Extensions.FromHex(@"441288"), }, - new SpriteIcon - { + new BeatmapStatisticIcon(icon){ Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, - Icon = icon, Size = new Vector2(12), Colour = Color4Extensions.FromHex(@"f7dd55"), Scale = new Vector2(0.8f), From 38828b6b82976ee3041bce446e9c21b525027ae3 Mon Sep 17 00:00:00 2001 From: Daniel Kariv <38776931+danielkariv@users.noreply.github.com> Date: Mon, 16 Aug 2021 00:40:31 +0300 Subject: [PATCH 536/600] Updating beatmap details icons changes the sizing and add yellow circle so the UI will fit more with osu-web style. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 21bb75b960..757698e1aa 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -129,10 +129,20 @@ namespace osu.Game.Overlays.BeatmapSet Rotation = 45, Colour = Color4Extensions.FromHex(@"441288"), }, - new BeatmapStatisticIcon(icon){ + new SpriteIcon + { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, - Size = new Vector2(12), + Icon = FontAwesome.Regular.Circle, + Size = new Vector2(10), + Rotation = 0, + Colour = Color4Extensions.FromHex(@"f7dd55"), + }, + new BeatmapStatisticIcon(icon) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + Size = new Vector2(10), Colour = Color4Extensions.FromHex(@"f7dd55"), Scale = new Vector2(0.8f), }, From e744629a4167586e87e41ab1ba6da547b7f5a530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 16 Aug 2021 01:01:56 +0200 Subject: [PATCH 537/600] Fix broken obsoletion message --- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 91d960a2fb..853a590595 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps.Formats /// /// Adds combo colours to the list. /// - [Obsolete("Use SkinConfiguration.ComboColours directly.")] // can be removed 20220215 + [Obsolete("Use CustomComboColours directly.")] // can be removed 20220215 void AddComboColours(params Color4[] colours); } } From e8e387b549d1f1caa50b790bf1633ece3d0b1b7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 08:02:23 +0900 Subject: [PATCH 538/600] Cache buffered background to fix multiplayer lounge performance Consider this a request for comment. It's the cleanest solution I can come up with without dropping either the blur, or use of `ModelBackedDrawable`. Intended to resolve https://github.com/ppy/osu/issues/14276. --- .../Components/OnlinePlayBackgroundSprite.cs | 6 +-- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 48 +++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index d8dfac496d..e2ba0b03b0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -10,12 +10,12 @@ namespace osu.Game.Screens.OnlinePlay.Components { public class OnlinePlayBackgroundSprite : OnlinePlayComposite { - private readonly BeatmapSetCoverType beatmapSetCoverType; + protected readonly BeatmapSetCoverType BeatmapSetCoverType; private UpdateableBeatmapBackgroundSprite sprite; public OnlinePlayBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover) { - this.beatmapSetCoverType = beatmapSetCoverType; + BeatmapSetCoverType = beatmapSetCoverType; } [BackgroundDependencyLoader] @@ -33,6 +33,6 @@ namespace osu.Game.Screens.OnlinePlay.Components sprite.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value; } - protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(beatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; + protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index c2ad0285b1..72b63ab4d4 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Input; @@ -104,14 +105,9 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new BufferedContainer + new BeatmapBackgroundSprite { - RelativeSizeAxes = Axes.Both, - BlurSigma = new Vector2(10), - Child = new BeatmapBackgroundSprite - { - RelativeSizeAxes = Axes.Both - } + RelativeSizeAxes = Axes.Both }, new Box { @@ -306,11 +302,45 @@ namespace osu.Game.Screens.OnlinePlay private class BeatmapBackgroundSprite : OnlinePlayBackgroundSprite { - protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; + protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BlurredBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; - private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + public class BlurredBackgroundSprite : UpdateableBeatmapBackgroundSprite { + public BlurredBackgroundSprite(BeatmapSetCoverType type) + : base(type) + { + } + protected override double LoadDelay => 200; + + protected override Drawable CreateDrawable(BeatmapInfo model) => + new BufferedLoader(base.CreateDrawable(model)); + } + + // This class is an unfortunate requirement due to `LongRunningLoad` requiring direct async loading. + // It means that if the web request fetching the beatmap background takes too long, it will suddenly appear. + internal class BufferedLoader : BufferedContainer + { + private readonly Drawable drawable; + + public BufferedLoader(Drawable drawable) + { + this.drawable = drawable; + + RelativeSizeAxes = Axes.Both; + BlurSigma = new Vector2(10); + CacheDrawnFrameBuffer = true; + } + + [BackgroundDependencyLoader] + private void load() + { + LoadComponentAsync(drawable, d => + { + Add(d); + ForceRedraw(); + }); + } } } From d35886ef196c032075e68bfcc1913f6469187465 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 11:03:49 +0900 Subject: [PATCH 539/600] Reduce frame buffer render scale for blurred background --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 72b63ab4d4..fd265e9978 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -329,6 +329,7 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both; BlurSigma = new Vector2(10); + FrameBufferScale = new Vector2(0.5f); CacheDrawnFrameBuffer = true; } From f0fe79b568724b5151a8b9544438463ee56014a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 11:04:21 +0900 Subject: [PATCH 540/600] Remove buffered container workarounds for now --- .../Lounge/Components/DrawableRoom.cs | 65 +++++++------------ 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 193fb0cf57..c8ecd65574 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -158,21 +158,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Children = new Drawable[] { // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. - new BufferedContainer + new Box { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Background5, - }, - new OnlinePlayBackgroundSprite - { - RelativeSizeAxes = Axes.Both - }, - } + Colour = colours.Background5, + }, + new OnlinePlayBackgroundSprite + { + RelativeSizeAxes = Axes.Both }, new Container { @@ -187,37 +180,29 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components CornerRadius = corner_radius, Children = new Drawable[] { - // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. - new BufferedContainer + new GridContainer { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + ColumnDimensions = new[] { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Relative, 0.2f) - }, - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Background5, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)) - }, - } - } - }, + new Dimension(GridSizeMode.Relative, 0.2f) }, + Content = new[] + { + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Background5, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)) + }, + } + } }, new Container { From 76a8d4329fe570a10532d3cb87cd09210523abcf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 12:43:09 +0900 Subject: [PATCH 541/600] Make TestRoomManager update existing room --- osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index 2e9c0d1d53..d7c5a0a0e4 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -38,7 +38,13 @@ namespace osu.Game.Tests.Visual.OnlinePlay public void AddOrUpdateRoom(Room room) { - Rooms.Add(room); + var existing = Rooms.FirstOrDefault(r => r.RoomID.Value != null && r.RoomID.Value == room.RoomID.Value); + + if (existing != null) + existing.CopyFrom(room); + else + Rooms.Add(room); + RoomsUpdated?.Invoke(); } From 3db0b69f9247ae4037a6c6621fa7bcb9b7078f6e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 12:44:12 +0900 Subject: [PATCH 542/600] Throw not implemented exceptions --- .../TestScenePlaylistsMatchSettingsOverlay.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 79af2d3099..98882b659c 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -141,17 +141,11 @@ namespace osu.Game.Tests.Visual.Playlists public IBindableList Rooms => null; - public void AddOrUpdateRoom(Room room) - { - } + public void AddOrUpdateRoom(Room room) => throw new NotImplementedException(); - public void RemoveRoom(Room room) - { - } + public void RemoveRoom(Room room) => throw new NotImplementedException(); - public void ClearRooms() - { - } + public void ClearRooms() => throw new NotImplementedException(); public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { From 9d9974166379c78ab3208c0c3ffbaf94e985e31a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 06:56:59 +0300 Subject: [PATCH 543/600] Add failing test case --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index b7e92a79a0..3017428039 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -12,6 +12,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Skinning; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -142,6 +143,22 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("return value", () => config.SetValue(OsuSetting.KeyOverlay, keyCounterVisibleValue)); } + [Test] + public void TestHiddenHUDDoesntBlockSkinnableComponentsLoad() + { + HUDVisibilityMode originalConfigValue = default; + + AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); + + AddStep("set hud to never show", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + + createNew(); + AddUntilStep("wait for hud load", () => hudOverlay.IsLoaded); + AddUntilStep("skinnable components loaded", () => hudOverlay.ChildrenOfType().Single().ComponentsLoaded); + + AddStep("set original config value", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); + } + private void createNew(Action action = null) { AddStep("create overlay", () => From 554b09ac1b28e36416c929397ffb45fa60337caf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 06:57:45 +0300 Subject: [PATCH 544/600] Fix `SkinnableTargetsContainer` blocked from processing scheduled tasks --- osu.Game/Screens/Play/HUDOverlay.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 2cf2555b3e..13df9fefa7 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -57,8 +57,6 @@ namespace osu.Game.Screens.Play private Bindable configVisibilityMode; - private readonly Container visibilityContainer; - private readonly BindableBool replayLoaded = new BindableBool(); private static bool hasShownNotificationOnce; @@ -72,7 +70,7 @@ namespace osu.Game.Screens.Play private readonly SkinnableTargetContainer mainComponents; - private IEnumerable hideTargets => new Drawable[] { visibilityContainer, KeyCounter, topRightElements }; + private IEnumerable hideTargets => new Drawable[] { mainComponents, KeyCounter, topRightElements }; public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList mods) { @@ -84,13 +82,9 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { CreateFailingLayer(), - visibilityContainer = new Container + mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents) { RelativeSizeAxes = Axes.Both, - Child = mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents) - { - RelativeSizeAxes = Axes.Both, - }, }, topRightElements = new FillFlowContainer { From 81f94424713470101867c541b8e83d4dd719e15d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 13:04:06 +0900 Subject: [PATCH 545/600] Inline update/addRoom in usage sites --- .../OnlinePlay/Components/RoomManager.cs | 43 +++++-------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index ab92adcac7..43bf3a2ce5 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -57,11 +57,10 @@ namespace osu.Game.Screens.OnlinePlay.Components { joinedRoom.Value = room; - update(room, result); - addRoom(room); + AddOrUpdateRoom(result); + room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere. - RoomsUpdated?.Invoke(); - onSuccess?.Invoke(room); + onSuccess?.Invoke(result); }; req.Failure += exception => @@ -119,8 +118,14 @@ namespace osu.Game.Screens.OnlinePlay.Components try { - update(room, room); - addRoom(room); + foreach (var pi in room.Playlist) + pi.MapObjects(beatmaps, rulesets); + + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); + if (existing == null) + rooms.Add(room); + else + existing.CopyFrom(room); } catch (Exception ex) { @@ -145,32 +150,6 @@ namespace osu.Game.Screens.OnlinePlay.Components notifyRoomsUpdated(); } - /// - /// Updates a local with a remote copy. - /// - /// The local to update. - /// The remote to update with. - private void update(Room local, Room remote) - { - foreach (var pi in remote.Playlist) - pi.MapObjects(beatmaps, rulesets); - - local.CopyFrom(remote); - } - - /// - /// Adds a to the list of available rooms. - /// - /// The to add. - private void addRoom(Room room) - { - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); - if (existing == null) - rooms.Add(room); - else - existing.CopyFrom(room); - } - private void notifyRoomsUpdated() => Scheduler.AddOnce(() => RoomsUpdated?.Invoke()); } } From b6a2020c59ebd7667d821277fcc25493f07ff4e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 13:09:04 +0900 Subject: [PATCH 546/600] General refactorings from PR review --- .../Components/ListingPollingComponent.cs | 8 ++++---- .../Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 15 ++++++++------- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 12 ++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index f686326d08..bc6480d05e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -15,8 +15,8 @@ namespace osu.Game.Screens.OnlinePlay.Components /// public class ListingPollingComponent : RoomPollingComponent { - public IBindable HasPolledOnce => hasPolledOnce; - private readonly Bindable hasPolledOnce = new Bindable(); + public IBindable InitialRoomsReceived => initialRoomsReceived; + private readonly Bindable initialRoomsReceived = new Bindable(); [Resolved] private Bindable currentFilter { get; set; } @@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components currentFilter.BindValueChanged(_ => { RoomManager.ClearRooms(); - hasPolledOnce.Value = false; + initialRoomsReceived.Value = false; if (IsLoaded) PollImmediately(); @@ -60,7 +60,7 @@ namespace osu.Game.Screens.OnlinePlay.Components foreach (var incoming in result) RoomManager.AddOrUpdateRoom(incoming); - hasPolledOnce.Value = true; + initialRoomsReceived.Value = true; tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 4e3f37f814..bd2648791c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -45,6 +45,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge AutoSizeAxes = Axes.Both }; + protected ListingPollingComponent ListingPollingComponent { get; private set; } + [Resolved] private Bindable selectedRoom { get; set; } @@ -72,7 +74,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private RoomsContainer roomsContainer; private SearchTextBox searchTextBox; private Dropdown statusDropdown; - private ListingPollingComponent listingPollingComponent; [BackgroundDependencyLoader(true)] private void load([CanBeNull] IdleTracker idleTracker) @@ -86,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { - listingPollingComponent = CreatePollingComponent(), + ListingPollingComponent = CreatePollingComponent(), loadingLayer = new LoadingLayer(true), new Container { @@ -186,7 +187,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); + ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true); @@ -337,7 +338,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updateLoadingLayer() { - if (operationInProgress.Value || !listingPollingComponent.HasPolledOnce.Value) + if (operationInProgress.Value || !ListingPollingComponent.InitialRoomsReceived.Value) loadingLayer.Show(); else loadingLayer.Hide(); @@ -346,11 +347,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updatePollingRate(bool isCurrentScreen) { if (!isCurrentScreen) - listingPollingComponent.TimeBetweenPolls.Value = 0; + ListingPollingComponent.TimeBetweenPolls.Value = 0; else - listingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; + ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; - Logger.Log($"Polling adjusted (listing: {listingPollingComponent.TimeBetweenPolls.Value})"); + Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})"); } protected abstract OsuButton CreateNewRoomButton(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 77db955f0a..97fed2040d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } - private MultiplayerListingPollingComponent listingPollingComponent; + private MultiplayerListingPollingComponent multiplayerListingPollingComponent => (MultiplayerListingPollingComponent)ListingPollingComponent; private readonly IBindable isConnected = new Bindable(); @@ -34,8 +34,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.LoadComplete(); isConnected.BindTo(client.IsConnected); - isConnected.BindValueChanged(c => Scheduler.AddOnce(() => listingPollingComponent.AllowPolling = c.NewValue)); - listingPollingComponent.AllowPolling = isConnected.Value; + isConnected.BindValueChanged(c => Scheduler.AddOnce(() => multiplayerListingPollingComponent.AllowPolling = c.NewValue)); + multiplayerListingPollingComponent.AllowPolling = isConnected.Value; } public override void OnResuming(IScreen last) @@ -47,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (last is MultiplayerMatchSubScreen match) { RoomManager.RemoveRoom(match.Room); - listingPollingComponent.PollImmediately(); + multiplayerListingPollingComponent.PollImmediately(); } } @@ -69,7 +69,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); - protected override ListingPollingComponent CreatePollingComponent() => listingPollingComponent = new MultiplayerListingPollingComponent(); + protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent(); protected override void OpenNewRoom(Room room) { @@ -104,7 +104,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } - protected override Task Poll() => !AllowPolling ? Task.CompletedTask : base.Poll(); + protected override Task Poll() => AllowPolling ? base.Poll() : Task.CompletedTask; } } } From 53c3eccfb50bfc6bd3238fa84e2c371a83b4a388 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 07:21:37 +0300 Subject: [PATCH 547/600] Force HUD visibility mode to "Always" during testing --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 9bb9c24c6b..18e4a6c575 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.UI; @@ -26,6 +27,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } + [Resolved] + private OsuConfigManager config { get; set; } + [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -86,6 +90,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestSpectatorPlayerInteractiveElementsHidden() { + HUDVisibilityMode originalConfigValue = default; + + AddStep("get original config hud visibility", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); + AddStep("set config hud visibility to always", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); + start(new[] { PLAYER_1_ID, PLAYER_2_ID }); loadSpectateScreen(false); @@ -100,6 +109,8 @@ namespace osu.Game.Tests.Visual.Multiplayer !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); + + AddStep("restore config hud visibility", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } [Test] From f82ed64aa7afc735f7092b96810c66eb45222b9d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:06:56 +0300 Subject: [PATCH 548/600] Fix participant panel null user test no longer functioning properly I guess the changes that involved `MultiplayerTestScene` having a test user lookup cache caused this test case to false-pass silently. Added an explicit assert which ensures the added user indeed has a null `User` value. --- .../TestSceneMultiplayerParticipantsList.cs | 4 +++- .../Multiplayer/TestMultiplayerClient.cs | 2 +- osu.Game/Tests/Visual/TestUserLookupCache.cs | 20 +++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index a3e6c8de3b..a44ce87738 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; @@ -48,7 +49,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddAssert("one unique panel", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 1); - AddStep("add non-resolvable user", () => Client.AddNullUser(-3)); + AddStep("add non-resolvable user", () => Client.AddNullUser()); + AddAssert("null user added", () => Client.Room.AsNonNull().Users.Count(u => u.User == null) == 1); AddUntilStep("two unique panels", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 2); } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 67b79d7390..f2da66d666 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual.Multiplayer return roomUser; } - public void AddNullUser(int userId) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(userId)); + public void AddNullUser() => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(TestUserLookupCache.NULL_USER_ID)); public void RemoveUser(User user) { diff --git a/osu.Game/Tests/Visual/TestUserLookupCache.cs b/osu.Game/Tests/Visual/TestUserLookupCache.cs index d2941b5bd5..b73e81d0dd 100644 --- a/osu.Game/Tests/Visual/TestUserLookupCache.cs +++ b/osu.Game/Tests/Visual/TestUserLookupCache.cs @@ -10,10 +10,22 @@ namespace osu.Game.Tests.Visual { public class TestUserLookupCache : UserLookupCache { - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) => Task.FromResult(new User + /// + /// A special user ID which would return a for. + /// As a simulation to what a regular would return in the case of failing to fetch the user. + /// + public const int NULL_USER_ID = -1; + + protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) { - Id = lookup, - Username = $"User {lookup}" - }); + if (lookup == NULL_USER_ID) + return Task.FromResult((User)null); + + return Task.FromResult(new User + { + Id = lookup, + Username = $"User {lookup}" + }); + } } } From 67bac207cfce01649c201721cfca1d595a388ff8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:37:29 +0300 Subject: [PATCH 549/600] Cover kicking a multiplayer room user with null `User` --- .../Multiplayer/TestSceneMultiplayerParticipantsList.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index a44ce87738..c4ebc13245 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -53,6 +53,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("null user added", () => Client.Room.AsNonNull().Users.Count(u => u.User == null) == 1); AddUntilStep("two unique panels", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 2); + + AddStep("kick null user", () => this.ChildrenOfType().Single(p => p.User.User == null) + .ChildrenOfType().Single().TriggerClick()); + + AddAssert("null user kicked", () => Client.Room.AsNonNull().Users.Count == 1); } [Test] From 79cd06278426fbc73c7f90f044e25a2047bed488 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:26:00 +0300 Subject: [PATCH 550/600] Let `TeamDisplay` take the full `MultiplayerRoomUser` rather than the underlying `User` --- .../Participants/ParticipantPanel.cs | 2 +- .../Multiplayer/Participants/TeamDisplay.cs | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index 1787480e1f..c4b4dbb777 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -83,7 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Colour = Color4Extensions.FromHex("#F7E65D"), Alpha = 0 }, - new TeamDisplay(user), + new TeamDisplay(User), new Container { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs index 5a7073f9de..351b9b3673 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs @@ -11,7 +11,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; -using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -19,16 +18,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { internal class TeamDisplay : MultiplayerRoomComposite { - private readonly User user; + private readonly MultiplayerRoomUser user; + private Drawable box; [Resolved] private OsuColour colours { get; set; } - [Resolved] - private MultiplayerClient client { get; set; } - - public TeamDisplay(User user) + public TeamDisplay(MultiplayerRoomUser user) { this.user = user; @@ -61,7 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants } }; - if (user.Id == client.LocalUser?.UserID) + if (Client.LocalUser?.Equals(user) == true) { InternalChild = new OsuClickableContainer { @@ -79,9 +76,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants private void changeTeam() { - client.SendMatchRequest(new ChangeTeamRequest + Client.SendMatchRequest(new ChangeTeamRequest { - TeamID = ((client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0, + TeamID = ((Client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0, }); } @@ -93,7 +90,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants // we don't have a way of knowing when an individual user's state has updated, so just handle on RoomUpdated for now. - var userRoomState = Room?.Users.FirstOrDefault(u => u.UserID == user.Id)?.MatchState; + var userRoomState = Room?.Users.FirstOrDefault(u => u.Equals(user))?.MatchState; const double duration = 400; From 7fe6f6dd149c97a6c0a6bae80ecdcac66691543d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:26:45 +0300 Subject: [PATCH 551/600] Fix kick button action asserting and using `User.User.ID` rather than `User.UserID` --- .../Multiplayer/Participants/ParticipantPanel.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index c4b4dbb777..6f8c735b6e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -168,12 +167,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Origin = Anchor.Centre, Alpha = 0, Margin = new MarginPadding(4), - Action = () => - { - Debug.Assert(user != null); - - Client.KickUser(user.Id); - } + Action = () => Client.KickUser(User.UserID), }, }, } From 81480ac4fc5ea2e14b7790284e8eec3528329bd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:16:02 +0900 Subject: [PATCH 552/600] Use `PlayerConfiguration` to convey no-seek state --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 4 +--- osu.Game/Screens/Play/Player.cs | 8 ++++---- osu.Game/Screens/Play/PlayerConfiguration.cs | 5 +++++ osu.Game/Screens/Play/SpectatorPlayer.cs | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 1b1dee5ae2..feb1af770b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// The score containing the player's replay. /// The clock controlling the gameplay running state. public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock) - : base(score) + : base(score, new PlayerConfiguration { AllowSeeking = false }) { this.spectatorPlayerClock = spectatorPlayerClock; } @@ -35,8 +35,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); - AllowUserSeekingState.Value = false; - AllowUserSeekingState.Disabled = true; HUDOverlay.PlayerSettingsOverlay.Expire(); HUDOverlay.HoldToQuit.Expire(); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index dc37464a61..73bf3f9bda 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -77,9 +77,9 @@ namespace osu.Game.Screens.Play protected readonly Bindable LocalUserPlaying = new Bindable(); - protected readonly Bindable AllowUserSeekingState = new Bindable(); + private readonly Bindable allowUserSeeking = new Bindable(); - public IBindable AllowUserSeeking => AllowUserSeekingState; + public IBindable AllowUserSeeking => allowUserSeeking; public int RestartCount; @@ -275,8 +275,8 @@ namespace osu.Game.Screens.Play DrawableRuleset.HasReplayLoaded.BindValueChanged(r => { - if (!AllowUserSeekingState.Disabled) - AllowUserSeekingState.Value = r.NewValue; + if (Configuration.AllowSeeking) + allowUserSeeking.Value = r.NewValue; updateGameplayState(); }); diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index 18ee73374f..39c7a7568e 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -20,6 +20,11 @@ namespace osu.Game.Screens.Play /// public bool AllowRestart { get; set; } = true; + /// + /// Whether the player should be allowed to seek in a displayed replay. + /// + public bool AllowSeeking { get; set; } = true; + /// /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. /// diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index f662a479ec..1dae28092a 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -23,7 +23,8 @@ namespace osu.Game.Screens.Play protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap - public SpectatorPlayer(Score score) + public SpectatorPlayer(Score score, PlayerConfiguration configuration = null) + : base(configuration) { this.score = score; } From 838bcc51b2922f6403a8e459aafe8d8ecde41a4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:27:19 +0900 Subject: [PATCH 553/600] Avoid new bindable requirement --- osu.Game/Screens/Play/Player.cs | 20 ++++++++------------ osu.Game/Screens/Play/SongProgress.cs | 3 ++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 73bf3f9bda..c43b701ebf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -77,10 +77,6 @@ namespace osu.Game.Screens.Play protected readonly Bindable LocalUserPlaying = new Bindable(); - private readonly Bindable allowUserSeeking = new Bindable(); - - public IBindable AllowUserSeeking => allowUserSeeking; - public int RestartCount; [Resolved] @@ -273,13 +269,7 @@ namespace osu.Game.Screens.Play DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); - DrawableRuleset.HasReplayLoaded.BindValueChanged(r => - { - if (Configuration.AllowSeeking) - allowUserSeeking.Value = r.NewValue; - - updateGameplayState(); - }); + DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); @@ -592,7 +582,13 @@ namespace osu.Game.Screens.Play /// Seek to a specific time in gameplay. /// /// The destination time to seek to. - public void Seek(double time) => GameplayClockContainer.Seek(time); + public void Seek(double time) + { + if (!Configuration.AllowSeeking) + throw new InvalidOperationException($"Seeking has ben disabled by the current {nameof(Configuration)}."); + + GameplayClockContainer.Seek(time); + } private ScheduledDelegate frameStablePlaybackResetDelegate; diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 8debe6243d..3e30cf17b3 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -119,7 +119,8 @@ namespace osu.Game.Screens.Play if (drawableRuleset != null) { - ((IBindable)AllowSeeking).BindTo(player.AllowUserSeeking); + if (player?.Configuration.AllowSeeking == true) + ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); referenceClock = drawableRuleset.FrameStableClock; Objects = drawableRuleset.Objects; From ae8a1adae838648807431fec10b41826abbd9849 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:47:57 +0900 Subject: [PATCH 554/600] Allow seeking via `Player.Seek` even if disabled --- osu.Game/Screens/Play/Player.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c43b701ebf..09eaf1c543 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -582,13 +582,7 @@ namespace osu.Game.Screens.Play /// Seek to a specific time in gameplay. /// /// The destination time to seek to. - public void Seek(double time) - { - if (!Configuration.AllowSeeking) - throw new InvalidOperationException($"Seeking has ben disabled by the current {nameof(Configuration)}."); - - GameplayClockContainer.Seek(time); - } + public void Seek(double time) => GameplayClockContainer.Seek(time); private ScheduledDelegate frameStablePlaybackResetDelegate; From 8d45f86bd3ded0bb0b7c901c3fb30e1b1f7fff93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:48:40 +0900 Subject: [PATCH 555/600] Rename variable to better reflect its purpose --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs | 2 +- osu.Game/Screens/Play/PlayerConfiguration.cs | 4 ++-- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index feb1af770b..ececa1e497 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// The score containing the player's replay. /// The clock controlling the gameplay running state. public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock) - : base(score, new PlayerConfiguration { AllowSeeking = false }) + : base(score, new PlayerConfiguration { AllowUserInteraction = false }) { this.spectatorPlayerClock = spectatorPlayerClock; } diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index 39c7a7568e..3aa424e5d5 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -21,9 +21,9 @@ namespace osu.Game.Screens.Play public bool AllowRestart { get; set; } = true; /// - /// Whether the player should be allowed to seek in a displayed replay. + /// Whether the player should be able to interact with this player instance. /// - public bool AllowSeeking { get; set; } = true; + public bool AllowUserInteraction { get; set; } = true; /// /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 3e30cf17b3..b27a9c5f5d 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Play if (drawableRuleset != null) { - if (player?.Configuration.AllowSeeking == true) + if (player?.Configuration.AllowUserInteraction == true) ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); referenceClock = drawableRuleset.FrameStableClock; From fc89f2bac4a3971835beeeb104a10026dfb13782 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:56:48 +0900 Subject: [PATCH 556/600] Revert "Rename element in OsuSettings enum" This reverts commit c2bbe175627ce35f1d63bc7c627b35b4883de5a0. --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6c7adcc806..60a0d5a0ac 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -101,7 +101,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.HitLighting, true); SetDefault(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); - SetDefault(OsuSetting.ShowDifficultyGraph, true); + SetDefault(OsuSetting.ShowProgressGraph, true); SetDefault(OsuSetting.ShowHealthDisplayWhenCantFail, true); SetDefault(OsuSetting.FadePlayfieldWhenHealthLow, true); SetDefault(OsuSetting.KeyOverlay, false); @@ -217,7 +217,7 @@ namespace osu.Game.Configuration AlwaysPlayFirstComboBreak, FloatingComments, HUDVisibilityMode, - ShowDifficultyGraph, + ShowProgressGraph, ShowHealthDisplayWhenCantFail, FadePlayfieldWhenHealthLow, MouseDisableButtons, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 69aa57082a..353292606f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Show difficulty graph on progress bar", - Current = config.GetBindable(OsuSetting.ShowDifficultyGraph) + Current = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 6aa7e017ce..f28622f42e 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -125,7 +125,7 @@ namespace osu.Game.Screens.Play Objects = drawableRuleset.Objects; } - config.BindWith(OsuSetting.ShowDifficultyGraph, ShowGraph); + config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph); graph.FillColour = bar.FillColour = colours.BlueLighter; } From 71fab416d8902bbf6b1657de800773e0f78fa2bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:59:59 +0900 Subject: [PATCH 557/600] Add a note against `OsuSetting` --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 60a0d5a0ac..9b0d7f51da 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -201,6 +201,8 @@ namespace osu.Game.Configuration public Func LookupKeyBindings { get; set; } } + // IMPORTANT: These are used in user configuration files. + // The naming of these keys should not be changed once they are deployed in a release, unless migration logic is also added. public enum OsuSetting { Ruleset, From 1c7cbc862156659d31651b3cfb748d4490e6ac6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 17:14:13 +0900 Subject: [PATCH 558/600] Add missing `readonly` keyword to new bindable --- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs index 6745f08b80..429df85904 100644 --- a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit /// The combo colours of this skin. /// If empty, the default combo colours will be used. /// - public BindableList ComboColours; + public readonly BindableList ComboColours; private readonly Skin skin; From db1a0ebb55448903587ce59bbdf99c5ed90744a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 18:46:44 +0900 Subject: [PATCH 559/600] Fix preview track crashes --- .../BeatmapListing/Panels/PlayButton.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs b/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs index 4bbc3569fe..3aa9aa5ca5 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs @@ -139,19 +139,24 @@ namespace osu.Game.Overlays.BeatmapListing.Panels LoadComponentAsync(Preview = previewTrackManager.Get(beatmapSet), preview => { - // beatmapset may have changed. - if (Preview != preview) - return; + // Make sure that we schedule to after the next audio frame to fix crashes in single-threaded execution. + // See: https://github.com/ppy/osu-framework/issues/4692 + Schedule(() => + { + // beatmapset may have changed. + if (Preview != preview) + return; - AddInternal(preview); - loading = false; - // make sure that the update of value of Playing (and the ensuing value change callbacks) - // are marshaled back to the update thread. - preview.Stopped += () => Schedule(() => playing.Value = false); + AddInternal(preview); + loading = false; + // make sure that the update of value of Playing (and the ensuing value change callbacks) + // are marshaled back to the update thread. + preview.Stopped += () => Schedule(() => playing.Value = false); - // user may have changed their mind. - if (playing.Value) - attemptStart(); + // user may have changed their mind. + if (playing.Value) + attemptStart(); + }); }); } else From 855fff1486477eb490ed851a33a26be57b96c095 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 12:47:56 +0300 Subject: [PATCH 560/600] Fix `DifficultyAdjustSettingsControl.SliderControl` not following up with the current pattern This was causing any `ValueChanged` event bind (such as the one in `SettingsItem` to invoke `SettingsChanged`) to be overwritten when `Current` is set afterwards. --- osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 067657159b..186514e868 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -91,7 +91,13 @@ namespace osu.Game.Rulesets.Mods { // This is required as SettingsItem relies heavily on this bindable for internal use. // The actual update flow is done via the bindable provided in the constructor. - public Bindable Current { get; set; } = new Bindable(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } public SliderControl(BindableNumber currentNumber) { From 6653a78e659774213635568d5fd2bdcc7d693170 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 12:48:49 +0300 Subject: [PATCH 561/600] Add test coverage --- .../TestSceneModDifficultyAdjustSettings.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs index e0d76b3e4a..f8652573f4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -174,6 +176,60 @@ namespace osu.Game.Tests.Visual.UserInterface checkBindableAtValue("Circle Size", null); } + [Test] + public void TestModSettingChangeTracker() + { + ModSettingChangeTracker tracker = null; + Queue settingsChangedQueue = null; + + setBeatmapWithDifficultyParameters(5); + + AddStep("add mod settings change tracker", () => + { + settingsChangedQueue = new Queue(); + + tracker = new ModSettingChangeTracker(modDifficultyAdjust.Yield()) + { + SettingChanged = settingsChangedQueue.Enqueue + }; + }); + + AddAssert("no settings changed", () => settingsChangedQueue.Count == 0); + + setSliderValue("Circle Size", 3); + + settingsChangedFired(); + + setSliderValue("Circle Size", 5); + checkBindableAtValue("Circle Size", 5); + + settingsChangedFired(); + + AddStep("reset mod settings", () => modDifficultyAdjust.CircleSize.SetDefault()); + checkBindableAtValue("Circle Size", null); + + settingsChangedFired(); + + setExtendedLimits(true); + + settingsChangedFired(); + + AddStep("dispose tracker", () => + { + tracker.Dispose(); + tracker = null; + }); + + void settingsChangedFired() + { + AddAssert("setting changed event fired", () => + { + settingsChangedQueue.Dequeue(); + return settingsChangedQueue.Count == 0; + }); + } + } + private void resetToDefault(string name) { AddStep($"Reset {name} to default", () => From e39a295c5c417ec6d71ded0f07b1029849436c89 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 13:45:50 +0300 Subject: [PATCH 562/600] Hide tablet settings content when input handler is disabled --- .../Settings/Sections/Input/TabletSettings.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index c561b693d8..8303fee3ef 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input { private readonly ITabletHandler tabletHandler; + private readonly Bindable enabled = new BindableBool(true); + private readonly Bindable areaOffset = new Bindable(); private readonly Bindable areaSize = new Bindable(); private readonly IBindable tablet = new Bindable(); @@ -74,7 +76,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input LabelText = CommonStrings.Enabled, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Current = tabletHandler.Enabled + Current = enabled, }, noTabletMessage = new FillFlowContainer { @@ -194,6 +196,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input { base.LoadComplete(); + enabled.BindTo(tabletHandler.Enabled); + enabled.BindValueChanged(_ => Scheduler.AddOnce(updateVisibility)); + rotation.BindTo(tabletHandler.Rotation); areaOffset.BindTo(tabletHandler.AreaOffset); @@ -239,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input tablet.BindTo(tabletHandler.Tablet); tablet.BindValueChanged(val => { - Scheduler.AddOnce(toggleVisibility); + Scheduler.AddOnce(updateVisibility); var tab = val.NewValue; @@ -259,8 +264,15 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, true); } - private void toggleVisibility() + private void updateVisibility() { + if (!tabletHandler.Enabled.Value) + { + mainSettings.Hide(); + noTabletMessage.Hide(); + return; + } + bool tabletFound = tablet.Value != null; if (!tabletFound) From e485728109869c1e3704056e1c2b9c98708c43d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:54:45 +0900 Subject: [PATCH 563/600] Add keywords to make finding audio offset adjustments easier in settings --- osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index 7f2e377c83..eaa557bb37 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -13,6 +15,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override LocalisableString Header => "Offset Adjustment"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "universal", "uo", "timing" }); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 568d027013a67ddcc3ff58525001301cf353da8a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 22:07:41 +0900 Subject: [PATCH 564/600] Simplify weird conditionals --- .../Settings/Sections/Input/TabletSettings.cs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 8303fee3ef..b8b86d9069 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -266,24 +266,16 @@ namespace osu.Game.Overlays.Settings.Sections.Input private void updateVisibility() { - if (!tabletHandler.Enabled.Value) - { - mainSettings.Hide(); - noTabletMessage.Hide(); - return; - } - - bool tabletFound = tablet.Value != null; - - if (!tabletFound) - { - mainSettings.Hide(); - noTabletMessage.Show(); - return; - } - - mainSettings.Show(); + mainSettings.Hide(); noTabletMessage.Hide(); + + if (!tabletHandler.Enabled.Value) + return; + + if (tablet.Value != null) + mainSettings.Show(); + else + noTabletMessage.Show(); } private void applyAspectRatio(BindableNumber sizeChanged) From c3a86769323e11c637cd738393928be1e1499b47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 23:38:13 +0900 Subject: [PATCH 565/600] Simplify size specifications --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index c51f927f9f..508c8399b6 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -144,8 +144,7 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Width = heart_size, - Height = heart_size, + Size = new Vector2(heart_size), Margin = new MarginPadding { Top = 70 }, Masking = true, EdgeEffect = new EdgeEffectParameters @@ -157,8 +156,7 @@ namespace osu.Game.Overlays.Changelog }, Child = new Sprite { - Width = heart_size, - Height = heart_size, + Size = new Vector2(heart_size), Texture = textures.Get(@"Online/supporter-heart"), }, }, From df6e4664e0aaa47788c1064be78126fe57fa1d75 Mon Sep 17 00:00:00 2001 From: emu1337 Date: Mon, 16 Aug 2021 16:42:07 +0200 Subject: [PATCH 566/600] changed history length in speed --- osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index b1373cd215..5b8ec5103a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -29,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double max_speed_bonus = 45; // ~330BPM private const double speed_balancing_factor = 40; + protected override int HistoryLength => 32; + public Speed(Mod[] mods) : base(mods) { From 4bf22db4ff9ff21123d9a0cc35a6aa2ed099b65d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 00:23:30 +0900 Subject: [PATCH 567/600] Attempt to reduce skin lookup overhead where file access is not required --- osu.Game/Database/MutableDatabaseBackedStore.cs | 5 +++++ osu.Game/Skinning/SkinManager.cs | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index c9d0c4bc41..b0feb7bb78 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -36,6 +36,11 @@ namespace osu.Game.Database /// public IQueryable ConsumableItems => AddIncludesForConsumption(ContextFactory.Get().Set()); + /// + /// Access barebones items with no includes. + /// + public IQueryable Items => ContextFactory.Get().Set(); + /// /// Add a to the database. /// diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index ea55fd28c2..fca1670419 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -105,12 +105,12 @@ namespace osu.Game.Skinning /// Returns a list of all usable s that have been loaded by the user. /// /// A newly allocated list of available . - public List GetAllUserSkins() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + public List GetAllUserSkins() => ModelStore.Items.Where(s => !s.DeletePending).ToList(); public void SelectRandomSkin() { // choose from only user skins, removing the current selection to ensure a new one is chosen. - var randomChoices = GetAllUsableSkins().Where(s => s.ID != CurrentSkinInfo.Value.ID).ToArray(); + var randomChoices = ModelStore.Items.Where(s => !s.DeletePending && s.ID != CurrentSkinInfo.Value.ID).ToArray(); if (randomChoices.Length == 0) { @@ -118,7 +118,8 @@ namespace osu.Game.Skinning return; } - CurrentSkinInfo.Value = randomChoices.ElementAt(RNG.Next(0, randomChoices.Length)); + var chosen = randomChoices.ElementAt(RNG.Next(0, randomChoices.Length)); + CurrentSkinInfo.Value = ModelStore.ConsumableItems.Single(i => i.ID == chosen.ID); } protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name }; From 19cdd5c3234ad368f81d2c3df8f66abf63fb51df Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 15:25:35 +0000 Subject: [PATCH 568/600] recoded and added rhythm complexity calculator (untested) --- .../Difficulty/Skills/Speed.cs | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 5b8ec5103a..73704735d0 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; + private const double rhythmMultiplier = 1.0; protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; protected override int ReducedSectionCount => 5; @@ -31,16 +32,91 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override int HistoryLength => 32; + private const int HistoryTimeMax = 4; // 4 seconds of calculatingRhythmBonus max. + public Speed(Mod[] mods) : base(mods) { } - private double calculateRhythmBonus(double time) + private bool isRatioEqual(double ratio, double a, double b) { - return 1.0; + return a + 15 > ratio * b && a - 15 < ratio * b; } + /// + /// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current . + /// + private double calculateRhythmBonus(double startTime) + { + // {doubles, triplets, quads, quints, 6-tuplets, 7 Tuplets, greater} + int previousIslandSize = -1; + double[] islandTimes = {0, 0, 0, 0, 0, 0, 0}; + int islandSize = 0; + + bool firstDeltaSwitch = false; + + for (int i = Previous.Count - 1; i < 0; i--) + { + double currDelta = ((OsuDifficultyHitObject)Previous[i - 1]).StrainTime; + double prevDelta = ((OsuDifficultyHitObject)Previous[i]).StrainTime; + double effectiveRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta); + + double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; + + // if (historyTime > HistoryTimeMax) + // break; // not sure if this even does what I want.. + + if (firstDeltaSwitch) + { + if (isRatioEqual(1.0, prevDelta, currDelta)) + { + islandSize++; // island is still progressing, count size. + } + + else + { + if (islandSize > 6) + islandSize = 6; + + if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window + effectiveRatio *= 0.5; + + if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle + effectiveRatio *= 0.75; + + if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet) + effectiveRatio *= 0.5; + + islandTimes[islandSize] = islandTimes[islandSize] + effectiveRatio * currHistoricalDecay; + + previousIslandSize = islandSize; // log the last island size. + + if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting + firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size. + + islandSize = 0; + } + } + else if (prevDelta > 1.25 * currDelta) // we want to be speeding up. + { + // Begin counting island until we change speed again. + firstDeltaSwitch = true; + islandSize = 0; + } + } + + double rhythmComplexitySum = 0.0; + + for (int i = 0; i < islandTimes.Length; i++) + { + rhythmComplexitySum += islandTimes[i]; // sum the total amount of rhythm variance + } + +Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); + + return Math.Min(1.5, Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); + } protected override double StrainValueOf(DifficultyHitObject current) { @@ -81,7 +157,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override double GetPeakStrain(double time) { - return base.GetPeakStrain(time) * calculateRhythmBonus(time); + return base.GetPeakStrain(time);// * calculateRhythmBonus(current.StartTime); } } } From 7d46b3f9c5fe9062afa5528d025908173c5ca812 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 16:06:50 +0000 Subject: [PATCH 569/600] initial testing and debugging --- .../Difficulty/Skills/Speed.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 73704735d0..433150a025 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -20,7 +20,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; - private const double rhythmMultiplier = 1.0; + private const double rhythmMultiplier = 1.5; + protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; protected override int ReducedSectionCount => 5; @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override int HistoryLength => 32; - private const int HistoryTimeMax = 4; // 4 seconds of calculatingRhythmBonus max. + private const int HistoryTimeMax = 3000; // 4 seconds of calculatingRhythmBonus max. public Speed(Mod[] mods) : base(mods) @@ -56,16 +57,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills bool firstDeltaSwitch = false; - for (int i = Previous.Count - 1; i < 0; i--) + for (int i = Previous.Count - 1; i > 0; i--) { double currDelta = ((OsuDifficultyHitObject)Previous[i - 1]).StrainTime; double prevDelta = ((OsuDifficultyHitObject)Previous[i]).StrainTime; double effectiveRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta); - double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; + if (effectiveRatio > 0.5) + effectiveRatio = 0.5 + (effectiveRatio - 0.5) * 5; // extra buff for 1/3 -> 1/4 etc transitions. - // if (historyTime > HistoryTimeMax) - // break; // not sure if this even does what I want.. + double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; if (firstDeltaSwitch) { @@ -113,9 +114,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills rhythmComplexitySum += islandTimes[i]; // sum the total amount of rhythm variance } -Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); +// Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); - return Math.Min(1.5, Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); + return Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2; } protected override double StrainValueOf(DifficultyHitObject current) From 176b3e75335476273ceb305a60c2b4a0fc9fa3f4 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:14:29 +0000 Subject: [PATCH 570/600] changed decay system to allow for customizing the currentStrain --- .../Difficulty/Skills/Movement.cs | 2 +- .../Difficulty/Skills/Strain.cs | 4 +- .../Difficulty/Skills/Aim.cs | 2 +- .../Difficulty/Skills/OsuStrainSkill.cs | 4 +- .../Difficulty/Skills/Speed.cs | 11 +--- .../Difficulty/Skills/Colour.cs | 2 +- .../Difficulty/Skills/Rhythm.cs | 2 +- .../Difficulty/Skills/Stamina.cs | 2 +- .../Difficulty/Skills/StrainDecaySkill.cs | 64 +++++++++++++++++++ .../Rulesets/Difficulty/Skills/StrainSkill.cs | 44 +++---------- 10 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 4372ed938c..cfb3fe40be 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { - public class Movement : StrainSkill + public class Movement : StrainDecaySkill { private const float absolute_player_positioning_error = 16f; private const float normalized_hitobject_radius = 41.0f; diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs index 2ba2ee6b4a..01d930d585 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty.Skills { - public class Strain : StrainSkill + public class Strain : StrainDecaySkill { private const double individual_decay_base = 0.125; private const double overall_decay_base = 0.30; @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills return individualStrain + overallStrain - CurrentStrain; } - protected override double GetPeakStrain(double offset) + protected override double CalculateInitialStrain(double offset) => applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base) + applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base); diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index 16a18cbcb9..f08c19af76 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances. /// - public class Aim : OsuStrainSkill + public class Aim : OsuStrainDecaySkill { private const double angle_bonus_begin = Math.PI / 3; private const double timing_threshold = 107; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index e47edc37cc..c1bee9b202 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -10,7 +10,7 @@ using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { - public abstract class OsuStrainSkill : StrainSkill + public abstract class OsuStrainDecaySkill : StrainDecaySkill { /// /// The number of sections with the highest strains, which the peak strain reductions will apply to. @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// protected virtual double DifficultyMultiplier => 1.06; - protected OsuStrainSkill(Mod[] mods) + protected OsuStrainDecaySkill(Mod[] mods) : base(mods) { } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 433150a025..bb40ff657a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit. /// - public class Speed : OsuStrainSkill + public class Speed : OsuStrainDecaySkill { private const double single_spacing_threshold = 125; @@ -151,14 +151,5 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime; } - protected override double GetTotalCurrentStrain(DifficultyHitObject current) - { - return base.GetTotalCurrentStrain(current) * calculateRhythmBonus(current.StartTime); - } - - protected override double GetPeakStrain(double time) - { - return base.GetPeakStrain(time);// * calculateRhythmBonus(current.StartTime); - } } } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs index 769d021362..0c17ca66b9 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills /// /// Calculates the colour coefficient of taiko difficulty. /// - public class Colour : StrainSkill + public class Colour : StrainDecaySkill { protected override double SkillMultiplier => 1; protected override double StrainDecayBase => 0.4; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs index a32f6ebe0d..973e55f4b4 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills /// /// Calculates the rhythm coefficient of taiko difficulty. /// - public class Rhythm : StrainSkill + public class Rhythm : StrainDecaySkill { protected override double SkillMultiplier => 10; protected override double StrainDecayBase => 0; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs index 4cceadb23f..54cf233d69 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills /// /// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit). /// - public class Stamina : StrainSkill + public class Stamina : StrainDecaySkill { protected override double SkillMultiplier => 1; protected override double StrainDecayBase => 0.4; diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs new file mode 100644 index 0000000000..dab1081abb --- /dev/null +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -0,0 +1,64 @@ +// 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 System.Linq; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Difficulty.Skills +{ + /// + /// Used to processes strain values of s, keep track of strain levels caused by the processed objects + /// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects. + /// + public abstract class StrainDecaySkill : StrainSkill + { + /// + /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. + /// + protected abstract double SkillMultiplier { get; } + + /// + /// Determines how quickly strain decays for the given skill. + /// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second. + /// + protected abstract double StrainDecayBase { get; } + + /// + /// The current strain level. + /// + protected double CurrentStrain { get; private set; } = 1; + + protected StrainDecaySkill(Mod[] mods) + : base(mods) + { + } + + /// + /// Retrieves the peak strain at a point in time. + /// + /// The time to retrieve the peak strain at. + /// The peak strain. + protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); + + /// + /// Returns the strain value of . This value is calculated with or without respect to previous objects. + /// + protected override double StrainValueAt(DifficultyHitObject current) + { + CurrentStrain *= strainDecay(current.DeltaTime); + CurrentStrain += StrainValueOf(current) * SkillMultiplier; + + return CurrentStrain; + } + + /// + /// Calculates the strain value of a . This value is affected by previously processed objects. + /// + protected abstract double StrainValueOf(DifficultyHitObject current); + + private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000); + } +} diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index 95b0fe43fc..e8ae452506 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -15,27 +15,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// public abstract class StrainSkill : Skill { - /// - /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. - /// - protected abstract double SkillMultiplier { get; } - - /// - /// Determines how quickly strain decays for the given skill. - /// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second. - /// - protected abstract double StrainDecayBase { get; } - /// /// The weight by which each strain value decays. /// protected virtual double DecayWeight => 0.9; - /// - /// The current strain level. - /// - protected double CurrentStrain { get; private set; } = 1; - /// /// The length of each strain section. /// @@ -52,6 +36,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills { } + /// + /// Returns the strain value of . This value is calculated with or without respect to previous objects. + /// + protected abstract double StrainValueAt(DifficultyHitObject current); + /// /// Process a and update current strain values accordingly. /// @@ -68,15 +57,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills currentSectionEnd += SectionLength; } - CurrentStrain *= strainDecay(current.DeltaTime); - CurrentStrain += StrainValueOf(current) * SkillMultiplier; - - currentSectionPeak = Math.Max(GetTotalCurrentStrain(current), currentSectionPeak); - } - - protected virtual double GetTotalCurrentStrain(DifficultyHitObject current) - { - return CurrentStrain; + currentSectionPeak = Math.Max(StrainValueAt(current), currentSectionPeak); } /// @@ -93,9 +74,9 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// The beginning of the new section in milliseconds. private void startNewSectionFrom(double time) { - // The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries. + // The maximum strain of the new section is not zero by default // This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level. - currentSectionPeak = GetPeakStrain(time); + currentSectionPeak = CalculateInitialStrain(time); } /// @@ -103,7 +84,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// /// The time to retrieve the peak strain at. /// The peak strain. - protected virtual double GetPeakStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); + protected abstract double CalculateInitialStrain(double time); /// /// Returns a live enumerable of the peak strains for each section of the beatmap, @@ -129,12 +110,5 @@ namespace osu.Game.Rulesets.Difficulty.Skills return difficulty; } - - /// - /// Calculates the strain value of a . This value is affected by previously processed objects. - /// - protected abstract double StrainValueOf(DifficultyHitObject current); - - private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000); } } From 5561e4852e838c226257d09088e3f51e42d6f2d2 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:23:40 +0000 Subject: [PATCH 571/600] removed stuff --- .../Difficulty/Skills/Speed.cs | 85 ------------------- 1 file changed, 85 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index bb40ff657a..78d1438923 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; - private const double rhythmMultiplier = 1.5; - protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; protected override int ReducedSectionCount => 5; @@ -31,94 +29,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double max_speed_bonus = 45; // ~330BPM private const double speed_balancing_factor = 40; - protected override int HistoryLength => 32; - - private const int HistoryTimeMax = 3000; // 4 seconds of calculatingRhythmBonus max. - public Speed(Mod[] mods) : base(mods) { } - private bool isRatioEqual(double ratio, double a, double b) - { - return a + 15 > ratio * b && a - 15 < ratio * b; - } - - /// - /// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current . - /// - private double calculateRhythmBonus(double startTime) - { - // {doubles, triplets, quads, quints, 6-tuplets, 7 Tuplets, greater} - int previousIslandSize = -1; - double[] islandTimes = {0, 0, 0, 0, 0, 0, 0}; - int islandSize = 0; - - bool firstDeltaSwitch = false; - - for (int i = Previous.Count - 1; i > 0; i--) - { - double currDelta = ((OsuDifficultyHitObject)Previous[i - 1]).StrainTime; - double prevDelta = ((OsuDifficultyHitObject)Previous[i]).StrainTime; - double effectiveRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta); - - if (effectiveRatio > 0.5) - effectiveRatio = 0.5 + (effectiveRatio - 0.5) * 5; // extra buff for 1/3 -> 1/4 etc transitions. - - double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; - - if (firstDeltaSwitch) - { - if (isRatioEqual(1.0, prevDelta, currDelta)) - { - islandSize++; // island is still progressing, count size. - } - - else - { - if (islandSize > 6) - islandSize = 6; - - if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window - effectiveRatio *= 0.5; - - if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle - effectiveRatio *= 0.75; - - if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet) - effectiveRatio *= 0.5; - - islandTimes[islandSize] = islandTimes[islandSize] + effectiveRatio * currHistoricalDecay; - - previousIslandSize = islandSize; // log the last island size. - - if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting - firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size. - - islandSize = 0; - } - } - else if (prevDelta > 1.25 * currDelta) // we want to be speeding up. - { - // Begin counting island until we change speed again. - firstDeltaSwitch = true; - islandSize = 0; - } - } - - double rhythmComplexitySum = 0.0; - - for (int i = 0; i < islandTimes.Length; i++) - { - rhythmComplexitySum += islandTimes[i]; // sum the total amount of rhythm variance - } - -// Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); - - return Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2; - } - protected override double StrainValueOf(DifficultyHitObject current) { if (current.BaseObject is Spinner) From 61045bd0876afac630c9611de1398c0c65677141 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:36:14 +0000 Subject: [PATCH 572/600] adjusted code comments --- osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs | 8 -------- osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs index dab1081abb..dbac132faf 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -36,16 +36,8 @@ namespace osu.Game.Rulesets.Difficulty.Skills { } - /// - /// Retrieves the peak strain at a point in time. - /// - /// The time to retrieve the peak strain at. - /// The peak strain. protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); - /// - /// Returns the strain value of . This value is calculated with or without respect to previous objects. - /// protected override double StrainValueAt(DifficultyHitObject current) { CurrentStrain *= strainDecay(current.DeltaTime); diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index e8ae452506..0880f1b08e 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills } /// - /// Returns the strain value of . This value is calculated with or without respect to previous objects. + /// Returns the strain value at . This value is calculated with or without respect to previous objects. /// protected abstract double StrainValueAt(DifficultyHitObject current); From 9b21016eed1aadc232c0023b23624d61775659c3 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:46:56 +0000 Subject: [PATCH 573/600] accidently renamed osuStrainSkill, fixed --- osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs | 2 +- osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 4 ++-- osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index f08c19af76..16a18cbcb9 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances. /// - public class Aim : OsuStrainDecaySkill + public class Aim : OsuStrainSkill { private const double angle_bonus_begin = Math.PI / 3; private const double timing_threshold = 107; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index c1bee9b202..7bcd867a9c 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -10,7 +10,7 @@ using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { - public abstract class OsuStrainDecaySkill : StrainDecaySkill + public abstract class OsuStrainSkill : StrainDecaySkill { /// /// The number of sections with the highest strains, which the peak strain reductions will apply to. @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// protected virtual double DifficultyMultiplier => 1.06; - protected OsuStrainDecaySkill(Mod[] mods) + protected OsuStrainSkill(Mod[] mods) : base(mods) { } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 78d1438923..f0eb199e5f 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit. /// - public class Speed : OsuStrainDecaySkill + public class Speed : OsuStrainSkill { private const double single_spacing_threshold = 125; From 97d5b80834568d76ca423cf876aaf9955681a72f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:18:21 +0900 Subject: [PATCH 574/600] Fix joining with incorrect password --- .../Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 2d94b2328d..776307e20e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerClient multiplayerClient { get; set; } public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); + => base.CreateRoom(room, r => joinMultiplayerRoom(r, room.Password.Value, onSuccess, onError), onError); public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null) { From 352949069a4a3130c8db14ea8412ac11c93d57aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:36:43 +0900 Subject: [PATCH 575/600] Move filter to LoungeSubScreen --- .../TestSceneLoungeRoomsContainer.cs | 10 ++++----- .../Multiplayer/TestSceneMultiplayer.cs | 22 +++++++++++-------- .../Components/ListingPollingComponent.cs | 10 +++++---- .../Lounge/Components/RoomsContainer.cs | 9 ++++---- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 15 ++++++------- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 4 ---- ...stRequestHandlingMultiplayerRoomManager.cs | 5 ----- .../IOnlinePlayTestSceneDependencies.cs | 6 ----- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 2 -- .../OnlinePlayTestSceneDependencies.cs | 4 ---- 10 files changed, 35 insertions(+), 52 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index f3d961a646..7e822f898e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -115,11 +115,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4); - AddStep("filter one room", () => container.Filter(new FilterCriteria { SearchString = "1" })); + AddStep("filter one room", () => container.Filter.Value = new FilterCriteria { SearchString = "1" }); AddUntilStep("1 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 1); - AddStep("remove filter", () => container.Filter(null)); + AddStep("remove filter", () => container.Filter.Value = null); AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4); } @@ -131,13 +131,13 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo)); // Todo: What even is this case...? - AddStep("set empty filter criteria", () => container.Filter(null)); + AddStep("set empty filter criteria", () => container.Filter.Value = null); AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5); - AddStep("filter osu! rooms", () => container.Filter(new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo })); + AddStep("filter osu! rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo }); AddUntilStep("2 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 2); - AddStep("filter catch rooms", () => container.Filter(new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo })); + AddStep("filter catch rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo }); AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 08b3fb98a8..cf2f2f259e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -132,11 +132,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestExitMidJoin() { - Room room = null; - AddStep("create room", () => { - room = new Room + multiplayerScreen.RoomManager.AddRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -147,14 +145,16 @@ namespace osu.Game.Tests.Visual.Multiplayer Ruleset = { Value = new OsuRuleset().RulesetInfo }, } } - }; + }); }); - AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria()); + AddStep("refresh rooms", () => this.ChildrenOfType().Single().UpdateFilter()); + AddUntilStep("wait for room", () => this.ChildrenOfType().Any()); + AddStep("select room", () => InputManager.Key(Key.Down)); - AddStep("join room and immediately exit", () => + AddStep("join room and immediately exit select", () => { - multiplayerScreen.ChildrenOfType().Single().Open(room); + InputManager.Key(Key.Enter); Schedule(() => Stack.CurrentScreen.Exit()); }); } @@ -178,7 +178,9 @@ namespace osu.Game.Tests.Visual.Multiplayer }); }); - AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria()); + AddStep("refresh rooms", () => this.ChildrenOfType().Single().UpdateFilter()); + AddUntilStep("wait for room", () => this.ChildrenOfType().Any()); + AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("join room", () => InputManager.Key(Key.Enter)); @@ -226,7 +228,9 @@ namespace osu.Game.Tests.Visual.Multiplayer }); }); - AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria()); + AddStep("refresh rooms", () => this.ChildrenOfType().Single().UpdateFilter()); + AddUntilStep("wait for room", () => this.ChildrenOfType().Any()); + AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("join room", () => InputManager.Key(Key.Enter)); diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index bc6480d05e..1387b5a671 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -18,8 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Components public IBindable InitialRoomsReceived => initialRoomsReceived; private readonly Bindable initialRoomsReceived = new Bindable(); - [Resolved] - private Bindable currentFilter { get; set; } + public readonly Bindable Filter = new Bindable(); [Resolved] private Bindable selectedRoom { get; set; } @@ -27,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - currentFilter.BindValueChanged(_ => + Filter.BindValueChanged(_ => { RoomManager.ClearRooms(); initialRoomsReceived.Value = false; @@ -44,10 +43,13 @@ namespace osu.Game.Screens.OnlinePlay.Components if (!API.IsLoggedIn) return base.Poll(); + if (Filter.Value == null) + return base.Poll(); + var tcs = new TaskCompletionSource(); pollReq?.Cancel(); - pollReq = new GetRoomsRequest(currentFilter.Value.Status, currentFilter.Value.Category); + pollReq = new GetRoomsRequest(Filter.Value.Status, Filter.Value.Category); pollReq.Success += result => { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 46d9850fde..e243477a8c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -30,8 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public IReadOnlyList Rooms => roomFlow.FlowingChildren.Cast().ToArray(); - [Resolved(CanBeNull = true)] - private Bindable filter { get; set; } + public readonly Bindable Filter = new Bindable(); [Resolved] private Bindable selectedRoom { get; set; } @@ -74,7 +73,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components rooms.BindTo(roomManager.Rooms); - filter?.BindValueChanged(criteria => Filter(criteria.NewValue)); + Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true); selectedRoom.BindValueChanged(selection => { @@ -85,7 +84,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void updateSelection() => roomFlow.Children.ForEach(r => r.State = r.Room == selectedRoom.Value ? SelectionState.Selected : SelectionState.NotSelected); - public void Filter(FilterCriteria criteria) + private void applyFilterCriteria(FilterCriteria criteria) { roomFlow.Children.ForEach(r => { @@ -126,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomFlow.Add(new DrawableRoom(room)); } - Filter(filter?.Value); + applyFilterCriteria(Filter?.Value); updateSelection(); } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index bd2648791c..3e8d07d002 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -56,9 +56,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved(CanBeNull = true)] private OngoingOperationTracker ongoingOperationTracker { get; set; } - [Resolved(CanBeNull = true)] - private Bindable filter { get; set; } - [Resolved] private IBindable ruleset { get; set; } @@ -68,6 +65,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [CanBeNull] private LeasedBindable selectionLease; + private readonly Bindable filter = new Bindable(new FilterCriteria()); private readonly IBindable operationInProgress = new Bindable(); private readonly IBindable isIdle = new BindableBool(); private LoadingLayer loadingLayer; @@ -81,13 +79,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); - filter ??= new Bindable(new FilterCriteria()); - OsuScrollContainer scrollContainer; InternalChildren = new Drawable[] { - ListingPollingComponent = CreatePollingComponent(), + ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter), loadingLayer = new LoadingLayer(true), new Container { @@ -161,7 +157,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { RelativeSizeAxes = Axes.Both, ScrollbarOverlapsContent = false, - Child = roomsContainer = new RoomsContainer() + Child = roomsContainer = new RoomsContainer + { + Filter = { BindTarget = filter } + } }, } }, @@ -202,7 +201,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge #region Filtering - protected void UpdateFilter() => Scheduler.AddOnce(updateFilter); + public void UpdateFilter() => Scheduler.AddOnce(updateFilter); private ScheduledDelegate scheduledFilterUpdate; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 183b7e51f9..e5962db608 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -20,7 +20,6 @@ using osu.Game.Overlays; using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -49,9 +48,6 @@ namespace osu.Game.Screens.OnlinePlay [Cached] private readonly Bindable selectedRoom = new Bindable(); - [Cached] - private readonly Bindable currentFilter = new Bindable(new FilterCriteria()); - [Cached] private readonly OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker(); diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index 2e56c8a094..31b59be61e 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -5,14 +5,12 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; namespace osu.Game.Tests.Visual.Multiplayer @@ -32,9 +30,6 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } - [Cached] - public readonly Bindable Filter = new Bindable(new FilterCriteria()); - public new readonly List Rooms = new List(); private int currentRoomId; diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index 6e1e831d9b..71acefb158 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -4,7 +4,6 @@ using osu.Framework.Bindables; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -23,11 +22,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// IRoomManager RoomManager { get; } - /// - /// The cached . - /// - Bindable Filter { get; } - /// /// The cached . /// diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 997c910dd4..8716646074 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -20,7 +19,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay { public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; - public Bindable Filter => OnlinePlayDependencies?.Filter; public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker; public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 05ba509a73..e39711b7ce 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -20,7 +19,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay { public Bindable SelectedRoom { get; } public IRoomManager RoomManager { get; } - public Bindable Filter { get; } public OngoingOperationTracker OngoingOperationTracker { get; } public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } @@ -36,7 +34,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay { SelectedRoom = new Bindable(); RoomManager = CreateRoomManager(); - Filter = new Bindable(new FilterCriteria()); OngoingOperationTracker = new OngoingOperationTracker(); AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); @@ -44,7 +41,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay CacheAs(SelectedRoom); CacheAs(RoomManager); - CacheAs(Filter); CacheAs(OngoingOperationTracker); CacheAs(AvailabilityTracker); CacheAs(new OverlayColourProvider(OverlayColourScheme.Plum)); From c4a42c4db007af794104c65c8c768506eb4f5b12 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:36:59 +0900 Subject: [PATCH 576/600] Fix BasicTestRoomManager overriding rooms --- .../Tests/Visual/OnlinePlay/BasicTestRoomManager.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index d7c5a0a0e4..55fbb9f1a6 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -28,6 +28,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay IBindableList IRoomManager.Rooms => Rooms; + private int currentRoomId; + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; @@ -76,9 +78,9 @@ namespace osu.Game.Tests.Visual.OnlinePlay { var room = new Room { - RoomID = { Value = i }, - Position = { Value = i }, - Name = { Value = $"Room {i}" }, + RoomID = { Value = currentRoomId }, + Position = { Value = currentRoomId }, + Name = { Value = $"Room {currentRoomId}" }, Host = { Value = new User { Username = "Host" } }, EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal }, @@ -101,6 +103,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay } CreateRoom(room); + + currentRoomId++; } } } From 1e282432c90397d976164da3f9e03b99876199da Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:40:25 +0900 Subject: [PATCH 577/600] Fix password in a better way --- osu.Game/Screens/OnlinePlay/Components/RoomManager.cs | 3 ++- .../Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 43bf3a2ce5..3b6c1c8be0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -60,7 +60,8 @@ namespace osu.Game.Screens.OnlinePlay.Components AddOrUpdateRoom(result); room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere. - onSuccess?.Invoke(result); + // The server may not contain all properties (such as password), so invoke success with the given room. + onSuccess?.Invoke(room); }; req.Failure += exception => diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 776307e20e..2d94b2328d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerClient multiplayerClient { get; set; } public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - => base.CreateRoom(room, r => joinMultiplayerRoom(r, room.Password.Value, onSuccess, onError), onError); + => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null) { From b672d4b9366d0a695b8085b649c91c037b59878f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:42:17 +0900 Subject: [PATCH 578/600] Refactor RequestHandlingMultiplayerRoomManager to avoid confusion --- .../Multiplayer/TestSceneMultiplayer.cs | 6 +++--- .../Multiplayer/TestMultiplayerClient.cs | 4 ++-- ...stRequestHandlingMultiplayerRoomManager.cs | 20 +++++++------------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index cf2f2f259e..8b96f5dc80 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddRoom(new Room + multiplayerScreen.RoomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddRoom(new Room + multiplayerScreen.RoomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -213,7 +213,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddRoom(new Room + multiplayerScreen.RoomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Password = { Value = "password" }, diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index f2da66d666..2c0ca0b872 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.Multiplayer protected override Task JoinRoom(long roomId, string? password = null) { - var apiRoom = roomManager.Rooms.Single(r => r.RoomID.Value == roomId); + var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == roomId); if (password != apiRoom.Password.Value) throw new InvalidOperationException("Invalid password."); @@ -260,7 +260,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Debug.Assert(Room != null); - var apiRoom = roomManager.Rooms.Single(r => r.RoomID.Value == Room.RoomID); + var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == Room.RoomID); var set = apiRoom.Playlist.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet ?? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId)?.BeatmapSet; diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index 31b59be61e..41102ae7b5 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } - public new readonly List Rooms = new List(); + public readonly List ServerSideRooms = new List(); private int currentRoomId; private int currentPlaylistItemId; @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Multiplayer apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value); apiRoom.Password.Value = createRoomRequest.Room.Password.Value; - AddRoom(apiRoom); + AddServerSideRoom(apiRoom); var responseRoom = new APICreatedRoom(); responseRoom.CopyFrom(createResponseRoom(apiRoom, false)); @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.Multiplayer case JoinRoomRequest joinRoomRequest: { - var room = Rooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); + var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); if (joinRoomRequest.Password != room.Password.Value) { @@ -84,14 +84,14 @@ namespace osu.Game.Tests.Visual.Multiplayer case GetRoomsRequest getRoomsRequest: var roomsWithoutParticipants = new List(); - foreach (var r in Rooms) + foreach (var r in ServerSideRooms) roomsWithoutParticipants.Add(createResponseRoom(r, false)); getRoomsRequest.TriggerSuccess(roomsWithoutParticipants); return true; case GetRoomRequest getRoomRequest: - getRoomRequest.TriggerSuccess(createResponseRoom(Rooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); + getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); return true; case GetBeatmapSetRequest getBeatmapSetRequest: @@ -127,17 +127,15 @@ namespace osu.Game.Tests.Visual.Multiplayer }; } - public void AddRoom(Room room) + public void AddServerSideRoom(Room room) { room.RoomID.Value ??= currentRoomId++; for (int i = 0; i < room.Playlist.Count; i++) room.Playlist[i].ID = currentPlaylistItemId++; - Rooms.Add(room); + ServerSideRooms.Add(room); } - public new void RemoveRoom(Room room) => base.RemoveRoom(room); - private Room createResponseRoom(Room room, bool withParticipants) { var responseRoom = new Room(); @@ -147,9 +145,5 @@ namespace osu.Game.Tests.Visual.Multiplayer responseRoom.RecentParticipants.Clear(); return responseRoom; } - - public new void ClearRooms() => base.ClearRooms(); - - public new void Schedule(Action action) => base.Schedule(action); } } From 5214731dc1be8fdfe638143386319377ad839f54 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:45:10 +0900 Subject: [PATCH 579/600] Refactor test a bit --- .../Visual/Multiplayer/TestSceneMultiplayer.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 8b96f5dc80..e618b28f40 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -44,6 +44,8 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestMultiplayer multiplayerScreen; private TestMultiplayerClient client; + private TestRequestHandlingMultiplayerRoomManager roomManager => multiplayerScreen.RoomManager; + [Cached(typeof(UserLookupCache))] private UserLookupCache lookupCache = new TestUserLookupCache(); @@ -68,7 +70,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("load dependencies", () => { - client = new TestMultiplayerClient(multiplayerScreen.RoomManager); + client = new TestMultiplayerClient(roomManager); // The screen gets suspended so it stops receiving updates. Child = client; @@ -134,7 +136,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddServerSideRoom(new Room + roomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -164,7 +166,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddServerSideRoom(new Room + roomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -213,7 +215,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddServerSideRoom(new Room + roomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Password = { Value = "password" }, From f2340c6dac64d6c7dda95e84699586e35d81b964 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:48:33 +0900 Subject: [PATCH 580/600] Privatise mutable list --- .../Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index 41102ae7b5..c3a944f93c 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -30,7 +30,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } - public readonly List ServerSideRooms = new List(); + public IReadOnlyList ServerSideRooms => serverSideRooms; + private readonly List serverSideRooms = new List(); private int currentRoomId; private int currentPlaylistItemId; @@ -133,7 +134,7 @@ namespace osu.Game.Tests.Visual.Multiplayer for (int i = 0; i < room.Playlist.Count; i++) room.Playlist[i].ID = currentPlaylistItemId++; - ServerSideRooms.Add(room); + serverSideRooms.Add(room); } private Room createResponseRoom(Room room, bool withParticipants) From 1e2c0031d7473302f2f39bee34f4e4d2d4088048 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 13:34:44 +0900 Subject: [PATCH 581/600] Remove unused usings --- osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs index dbac132faf..73bab31e82 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; From 081524b6c862af923b6f1084e3182f0abd85f59f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 13:44:21 +0900 Subject: [PATCH 582/600] Privatise setters --- osu.Game/Screens/Play/PlayerLoader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index a6592e4d24..969527a758 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -46,14 +46,14 @@ namespace osu.Game.Screens.Play protected override bool PlayResumeSound => false; - protected BeatmapMetadataDisplay MetadataInfo; + protected BeatmapMetadataDisplay MetadataInfo { get; private set; } /// /// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader. /// - protected FillFlowContainer PlayerSettings; + protected FillFlowContainer PlayerSettings { get; private set; } - protected VisualSettings VisualSettings; + protected VisualSettings VisualSettings { get; private set; } protected Task LoadTask { get; private set; } From 3a7b9bf096d1b3c259c8db8c7c44f9c99dc44ff5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 08:56:49 +0300 Subject: [PATCH 583/600] Fix `MatchSettingsOverlay` not resetting focus on hide properly --- .../Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs index 2676453a7e..62a968b508 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs @@ -41,11 +41,13 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override void PopIn() { + base.PopIn(); Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint); } protected override void PopOut() { + base.PopOut(); Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); } From 82eddeffefe1a33035cd44a7a7435c650c316d00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 16:13:45 +0900 Subject: [PATCH 584/600] Add `LocalUserPlayInfo` interface to convey common information about player status --- osu.Desktop/Windows/GameplayWinKeyBlocker.cs | 8 ++++---- osu.Game/Input/ConfineMouseTracker.cs | 5 +++-- osu.Game/OsuGame.cs | 4 +++- osu.Game/Performance/HighPerformanceSession.cs | 5 +++-- osu.Game/Screens/Play/ILocalUserPlayInfo.cs | 17 +++++++++++++++++ osu.Game/Screens/Play/Player.cs | 4 +++- 6 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Screens/Play/ILocalUserPlayInfo.cs diff --git a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs index efc3f21149..dbfd170ea1 100644 --- a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs +++ b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs @@ -5,23 +5,23 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Platform; -using osu.Game; using osu.Game.Configuration; +using osu.Game.Screens.Play; namespace osu.Desktop.Windows { public class GameplayWinKeyBlocker : Component { private Bindable disableWinKey; - private Bindable localUserPlaying; + private IBindable localUserPlaying; [Resolved] private GameHost host { get; set; } [BackgroundDependencyLoader] - private void load(OsuGame game, OsuConfigManager config) + private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config) { - localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); + localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy(); localUserPlaying.BindValueChanged(_ => updateBlocking()); disableWinKey = config.GetBindable(OsuSetting.GameplayDisableWinKey); diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index 75d9c8debb..d2bf953dbc 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -7,6 +7,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Game.Configuration; +using osu.Game.Screens.Play; namespace osu.Game.Input { @@ -24,14 +25,14 @@ namespace osu.Game.Input private IBindable localUserPlaying; [BackgroundDependencyLoader] - private void load(OsuGame game, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager) + private void load(ILocalUserPlayInfo localUserInfo, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager) { frameworkConfineMode = frameworkConfigManager.GetBindable(FrameworkSetting.ConfineMouseMode); frameworkWindowMode = frameworkConfigManager.GetBindable(FrameworkSetting.WindowMode); frameworkWindowMode.BindValueChanged(_ => updateConfineMode()); osuConfineMode = osuConfigManager.GetBindable(OsuSetting.ConfineMouseMode); - localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); + localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy(); osuConfineMode.ValueChanged += _ => updateConfineMode(); localUserPlaying.BindValueChanged(_ => updateConfineMode(), true); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fb682e0909..0db63df69b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -62,7 +62,7 @@ namespace osu.Game /// The full osu! experience. Builds on top of to add menus and binding logic /// for initial components that are generally retrieved via DI. /// - public class OsuGame : OsuGameBase, IKeyBindingHandler + public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo { /// /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). @@ -1085,5 +1085,7 @@ namespace osu.Game if (newScreen == null) Exit(); } + + IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } } diff --git a/osu.Game/Performance/HighPerformanceSession.cs b/osu.Game/Performance/HighPerformanceSession.cs index 661c1046f1..3ef0e0bf93 100644 --- a/osu.Game/Performance/HighPerformanceSession.cs +++ b/osu.Game/Performance/HighPerformanceSession.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Screens.Play; namespace osu.Game.Performance { @@ -12,9 +13,9 @@ namespace osu.Game.Performance private readonly IBindable localUserPlaying = new Bindable(); [BackgroundDependencyLoader] - private void load(OsuGame game) + private void load(ILocalUserPlayInfo localUserInfo) { - localUserPlaying.BindTo(game.LocalUserPlaying); + localUserPlaying.BindTo(localUserInfo.IsPlaying); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs new file mode 100644 index 0000000000..64c3f97305 --- /dev/null +++ b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs @@ -0,0 +1,17 @@ +// 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.Allocation; +using osu.Framework.Bindables; + +namespace osu.Game.Screens.Play +{ + [Cached] + public interface ILocalUserPlayInfo + { + /// + /// Whether the local user is currently playing. + /// + public IBindable IsPlaying { get; } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 09eaf1c543..5461c6ac6c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play { [Cached] [Cached(typeof(ISamplePlaybackDisabler))] - public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler + public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler, ILocalUserPlayInfo { /// /// The delay upon completion of the beatmap before displaying the results screen. @@ -1052,5 +1052,7 @@ namespace osu.Game.Screens.Play #endregion IBindable ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled; + + IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } } From 6ee6a468941525b3b6d98369c4f3fdcdd30c58d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 16:22:12 +0900 Subject: [PATCH 585/600] Remove unnecessary `public` prefix in interface specification --- osu.Game/Screens/Play/ILocalUserPlayInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs index 64c3f97305..9a2259b12f 100644 --- a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs +++ b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs @@ -12,6 +12,6 @@ namespace osu.Game.Screens.Play /// /// Whether the local user is currently playing. /// - public IBindable IsPlaying { get; } + IBindable IsPlaying { get; } } } From 8a1651e8308f1ee865d22cc81f9bc87192e962a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:04:32 +0900 Subject: [PATCH 586/600] Reorganise methods in `PollingComponent` --- osu.Game/Online/PollingComponent.cs | 73 ++++++++++++++--------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index 806c0047e7..243be8da44 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -47,39 +47,13 @@ namespace osu.Game.Online pollIfNecessary(); } - private bool pollIfNecessary() + /// + /// Immediately performs a . + /// + public void PollImmediately() { - // we must be loaded so we have access to clock. - if (!IsLoaded) return false; - - // there's already a poll process running. - if (pollingActive) return false; - - // don't try polling if the time between polls hasn't been set. - if (TimeBetweenPolls.Value == 0) return false; - - if (!lastTimePolled.HasValue) - { - doPoll(); - return true; - } - - if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value) - { - doPoll(); - return true; - } - - // not enough time has passed since the last poll. we do want to schedule a poll to happen, though. + lastTimePolled = Time.Current - TimeBetweenPolls.Value; scheduleNextPoll(); - return false; - } - - private void doPoll() - { - scheduledPoll = null; - pollingActive = true; - Poll().ContinueWith(_ => pollComplete()); } /// @@ -90,13 +64,11 @@ namespace osu.Game.Online return Task.CompletedTask; } - /// - /// Immediately performs a . - /// - public void PollImmediately() + private void doPoll() { - lastTimePolled = Time.Current - TimeBetweenPolls.Value; - scheduleNextPoll(); + scheduledPoll = null; + pollingActive = true; + Poll().ContinueWith(_ => pollComplete()); } /// @@ -111,6 +83,33 @@ namespace osu.Game.Online pollIfNecessary(); } + private void pollIfNecessary() + { + // we must be loaded so we have access to clock. + if (!IsLoaded) return; + + // there's already a poll process running. + if (pollingActive) return; + + // don't try polling if the time between polls hasn't been set. + if (TimeBetweenPolls.Value == 0) return; + + if (!lastTimePolled.HasValue) + { + doPoll(); + return; + } + + if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value) + { + doPoll(); + return; + } + + // not enough time has passed since the last poll. we do want to schedule a poll to happen, though. + scheduleNextPoll(); + } + private void scheduleNextPoll() { scheduledPoll?.Cancel(); From 9eb16fa61de76cd0432cb199503ef9a4f31f6d2c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:16:21 +0900 Subject: [PATCH 587/600] Move poll allowance logic based on signalr connection inside polling component --- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 97fed2040d..d152fc3913 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -25,19 +25,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } - private MultiplayerListingPollingComponent multiplayerListingPollingComponent => (MultiplayerListingPollingComponent)ListingPollingComponent; - - private readonly IBindable isConnected = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - isConnected.BindTo(client.IsConnected); - isConnected.BindValueChanged(c => Scheduler.AddOnce(() => multiplayerListingPollingComponent.AllowPolling = c.NewValue)); - multiplayerListingPollingComponent.AllowPolling = isConnected.Value; - } - public override void OnResuming(IScreen last) { base.OnResuming(last); @@ -47,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (last is MultiplayerMatchSubScreen match) { RoomManager.RemoveRoom(match.Room); - multiplayerListingPollingComponent.PollImmediately(); + ListingPollingComponent.PollImmediately(); } } @@ -84,27 +71,29 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private class MultiplayerListingPollingComponent : ListingPollingComponent { - private bool allowPolling; + [Resolved] + private MultiplayerClient client { get; set; } - public bool AllowPolling + private readonly IBindable isConnected = new Bindable(); + + [BackgroundDependencyLoader] + private void load() { - get => allowPolling; - set + isConnected.BindTo(client.IsConnected); + isConnected.BindValueChanged(c => Scheduler.AddOnce(() => { - if (allowPolling == value) - return; - - allowPolling = value; - - if (!allowPolling) - return; - - if (IsLoaded) + if (isConnected.Value && IsLoaded) PollImmediately(); - } + }), true); } - protected override Task Poll() => AllowPolling ? base.Poll() : Task.CompletedTask; + protected override Task Poll() + { + if (!isConnected.Value) + return Task.CompletedTask; + + return base.Poll(); + } } } } From 3b5fc6d10ff17fb06f43cdd107036a6e7da0164a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:18:23 +0900 Subject: [PATCH 588/600] Ensure `updateLoadingLayer` is run at least once --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 3e8d07d002..8bed3d6049 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -186,16 +186,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); - isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true); if (ongoingOperationTracker != null) { operationInProgress.BindTo(ongoingOperationTracker.InProgress); - operationInProgress.BindValueChanged(_ => updateLoadingLayer(), true); + operationInProgress.BindValueChanged(_ => updateLoadingLayer()); } + ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer(), true); + updateFilter(); } From f16468b7063ea85c7b610f0d761151ad181f02f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 18:17:55 +0900 Subject: [PATCH 589/600] Improve visibility of repeat ticks / drag areas on timeline --- .../Timeline/TimelineHitObjectBlueprint.cs | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 6e57b8e88c..911c9fea51 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -166,14 +166,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } if (IsSelected) - { border.Show(); - colour = colour.Lighten(0.3f); - } else - { border.Hide(); - } if (Item is IHasDuration duration && duration.Duration > 0) circle.Colour = ColourInfo.GradientHorizontal(colour, colour.Lighten(0.4f)); @@ -212,14 +207,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (int i = 0; i < repeats.RepeatCount; i++) { - repeatsContainer.Add(new Circle + repeatsContainer.Add(new Tick { - Size = new Vector2(circle_size / 3), - Alpha = 0.2f, - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.X, - X = (float)(i + 1) / (repeats.RepeatCount + 1), + X = (float)(i + 1) / (repeats.RepeatCount + 1) }); } } @@ -233,6 +223,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public override Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.TopLeft; + private class Tick : Circle + { + public Tick() + { + Size = new Vector2(circle_size / 4); + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + RelativePositionAxes = Axes.X; + } + } + public class DragArea : Circle { private readonly HitObject hitObject; @@ -304,20 +305,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void updateState() { - if (hasMouseDown) - { - this.ScaleTo(0.7f, 200, Easing.OutQuint); - } - else if (IsHovered) - { - this.ScaleTo(0.8f, 200, Easing.OutQuint); - } - else - { - this.ScaleTo(0.6f, 200, Easing.OutQuint); - } + float scale = 0.5f; - this.FadeTo(IsHovered || hasMouseDown ? 0.8f : 0.2f, 200, Easing.OutQuint); + if (hasMouseDown) + scale = 0.6f; + else if (IsHovered) + scale = 0.7f; + + this.ScaleTo(scale, 200, Easing.OutQuint); + this.FadeTo(IsHovered || hasMouseDown ? 1f : 0.9f, 200, Easing.OutQuint); } [Resolved] From d66f7cb6b597ce62acd5460771958bfc59c1c97f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 19:21:22 +0900 Subject: [PATCH 590/600] Fix tests by allowing retrieval with files where required --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 16 ++++++++-------- osu.Game/Skinning/SkinManager.cs | 10 ++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 8124bd4199..bab8dfc983 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -50,10 +50,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Count, Is.EqualTo(1)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(1)); // the first should be overwritten by the second import. - Assert.That(osu.Dependencies.Get().GetAllUserSkins().First().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); } finally { @@ -76,10 +76,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Count, Is.EqualTo(2)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); } finally { @@ -101,10 +101,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2.1", "skinner"), "skin2.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Count, Is.EqualTo(2)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); } finally { diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index fca1670419..51aaac1f79 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -95,7 +95,7 @@ namespace osu.Game.Skinning /// A newly allocated list of available . public List GetAllUsableSkins() { - var userSkins = GetAllUserSkins(); + var userSkins = GetAllUserSkins(false); userSkins.Insert(0, DefaultSkin.SkinInfo); userSkins.Insert(1, DefaultLegacySkin.SkinInfo); return userSkins; @@ -105,7 +105,13 @@ namespace osu.Game.Skinning /// Returns a list of all usable s that have been loaded by the user. /// /// A newly allocated list of available . - public List GetAllUserSkins() => ModelStore.Items.Where(s => !s.DeletePending).ToList(); + public List GetAllUserSkins(bool includeFiles = false) + { + if (includeFiles) + return ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + + return ModelStore.Items.Where(s => !s.DeletePending).ToList(); + } public void SelectRandomSkin() { From 58ecee543ad546c7c1e1f91ae6fb1187920f0b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 17 Aug 2021 23:00:10 +0200 Subject: [PATCH 591/600] Trim redundant default argument value --- osu.Game/Skinning/SkinManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 51aaac1f79..0f805990b9 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -95,7 +95,7 @@ namespace osu.Game.Skinning /// A newly allocated list of available . public List GetAllUsableSkins() { - var userSkins = GetAllUserSkins(false); + var userSkins = GetAllUserSkins(); userSkins.Insert(0, DefaultSkin.SkinInfo); userSkins.Insert(1, DefaultLegacySkin.SkinInfo); return userSkins; From 8c5d99ab21c71fe5e1c743835c8b5245c8b17246 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 04:16:57 +0300 Subject: [PATCH 592/600] Override `CreateInstance()` in osu! bindable subclasses Three bindables are left which don't have this overriden due to them already not having a value-only constructor and not supporting `GetBoundCopy()` properly: - `BeatmapDifficultyCache.BindableStarDifficulty`. - `TotalScoreBindable` - `TotalScoreStringBindable` I could add support for them by passing the required data to them, as they seem to be able to have that shared, but I'm hesitant to support something which was already broken and never used, not sure. --- osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs | 2 +- osu.Game/Rulesets/Mods/DifficultyBindable.cs | 2 +- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 186514e868..3978378c3a 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mods { // Intercept and extract the internal number bindable from DifficultyBindable. // This will provide bounds and precision specifications for the slider bar. - difficultyBindable = ((DifficultyBindable)value).GetBoundCopy(); + difficultyBindable = (DifficultyBindable)value.GetBoundCopy(); sliderDisplayCurrent.BindTo(difficultyBindable.CurrentNumber); base.Current = difficultyBindable; diff --git a/osu.Game/Rulesets/Mods/DifficultyBindable.cs b/osu.Game/Rulesets/Mods/DifficultyBindable.cs index 664b88eef4..e4304795f2 100644 --- a/osu.Game/Rulesets/Mods/DifficultyBindable.cs +++ b/osu.Game/Rulesets/Mods/DifficultyBindable.cs @@ -128,6 +128,6 @@ namespace osu.Game.Rulesets.Mods ExtendedLimits.UnbindFrom(otherDifficultyBindable.ExtendedLimits); } - public new DifficultyBindable GetBoundCopy() => new DifficultyBindable { BindTarget = this }; + protected override Bindable CreateInstance() => new DifficultyBindable(); } } diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index ff33f0c70d..dfe2992a7c 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -41,6 +41,8 @@ namespace osu.Game.Screens.Edit protected override int DefaultMaxValue => VALID_DIVISORS.Last(); protected override int DefaultPrecision => 1; + protected override Bindable CreateInstance() => new BindableBeatDivisor(); + /// /// Retrieves the appropriate colour for a beat divisor. /// From 5671820d92011d83f3d170df01e0f5f07fcc1837 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 10:35:34 +0900 Subject: [PATCH 593/600] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index ec223f98c2..24d07b4588 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d4dba9330f..928620b32e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 7e514afe74..77f9052e85 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From f5923508564b8d24f3d9ca475c7144aa466b9332 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 04:59:08 +0300 Subject: [PATCH 594/600] Fix config pollution in HUD overlay test scene --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 3017428039..4f15032c62 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -19,6 +19,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneHUDOverlay : OsuManualInputManagerTestScene { + private OsuConfigManager localConfig; + private HUDOverlay hudOverlay; [Cached] @@ -31,8 +33,14 @@ namespace osu.Game.Tests.Visual.Gameplay private Drawable hideTarget => hudOverlay.KeyCounter; private FillFlowContainer keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().First(); - [Resolved] - private OsuConfigManager config { get; set; } + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); + } + + [SetUpSteps] + public void SetUp() => Schedule(() => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); [Test] public void TestComboCounterIncrementing() @@ -85,11 +93,7 @@ namespace osu.Game.Tests.Visual.Gameplay { createNew(); - HUDVisibilityMode originalConfigValue = HUDVisibilityMode.HideDuringGameplay; - - AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); - - AddStep("set hud to never show", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); AddUntilStep("wait for fade", () => !hideTarget.IsPresent); @@ -98,37 +102,28 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("stop trigering", () => InputManager.ReleaseKey(Key.ControlLeft)); AddUntilStep("wait for fade", () => !hideTarget.IsPresent); - - AddStep("set original config value", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } [Test] public void TestExternalHideDoesntAffectConfig() { - HUDVisibilityMode originalConfigValue = HUDVisibilityMode.HideDuringGameplay; - createNew(); - AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); - AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); - AddAssert("config unchanged", () => originalConfigValue == config.Get(OsuSetting.HUDVisibilityMode)); + AddAssert("config unchanged", () => localConfig.GetBindable(OsuSetting.HUDVisibilityMode).IsDefault); AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true); - AddAssert("config unchanged", () => originalConfigValue == config.Get(OsuSetting.HUDVisibilityMode)); + AddAssert("config unchanged", () => localConfig.GetBindable(OsuSetting.HUDVisibilityMode).IsDefault); } [Test] public void TestChangeHUDVisibilityOnHiddenKeyCounter() { - bool keyCounterVisibleValue = false; - createNew(); - AddStep("save keycounter visible value", () => keyCounterVisibleValue = config.Get(OsuSetting.KeyOverlay)); - AddStep("set keycounter visible false", () => + AddStep("hide key overlay", () => { - config.SetValue(OsuSetting.KeyOverlay, false); + localConfig.SetValue(OsuSetting.KeyOverlay, false); hudOverlay.KeyCounter.AlwaysVisible.Value = false; }); @@ -139,24 +134,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true); AddUntilStep("hidetarget is visible", () => hideTarget.IsPresent); AddAssert("key counters still hidden", () => !keyCounterFlow.IsPresent); - - AddStep("return value", () => config.SetValue(OsuSetting.KeyOverlay, keyCounterVisibleValue)); } [Test] public void TestHiddenHUDDoesntBlockSkinnableComponentsLoad() { - HUDVisibilityMode originalConfigValue = default; - - AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); - - AddStep("set hud to never show", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); createNew(); AddUntilStep("wait for hud load", () => hudOverlay.IsLoaded); AddUntilStep("skinnable components loaded", () => hudOverlay.ChildrenOfType().Single().ComponentsLoaded); - - AddStep("set original config value", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } private void createNew(Action action = null) @@ -175,5 +162,11 @@ namespace osu.Game.Tests.Visual.Gameplay Child = hudOverlay; }); } + + protected override void Dispose(bool isDisposing) + { + localConfig?.Dispose(); + base.Dispose(isDisposing); + } } } From 6ed3e469f7549b0346314d31e606d2ff942e542c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 06:50:01 +0300 Subject: [PATCH 595/600] Fix wrong attribute used for setup method --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 4f15032c62..290ba3317b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); } - [SetUpSteps] + [SetUp] public void SetUp() => Schedule(() => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); [Test] From 3d88a745cd2f5184e114447c329b89f45ca339ca Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 18 Aug 2021 14:27:05 +0900 Subject: [PATCH 596/600] Fix osu editor transforms not specified in the absolute time --- .../Edit/DrawableOsuEditorRuleset.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs index d4f1602a46..c89527d8bd 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs @@ -64,11 +64,14 @@ namespace osu.Game.Rulesets.Osu.Edit if (hitObject is DrawableHitCircle circle) { - circle.ApproachCircle - .FadeOutFromOne(EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION * 4) - .Expire(); + using (circle.BeginAbsoluteSequence(circle.HitStateUpdateTime)) + { + circle.ApproachCircle + .FadeOutFromOne(EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION * 4) + .Expire(); - circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint); + circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint); + } } if (hitObject is IHasMainCirclePiece mainPieceContainer) From 74d6c2652023e2f603c053ded54bac6b768aa551 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 11:03:35 +0300 Subject: [PATCH 597/600] Refactor star rating display layout with flexibility in mind --- .../TestSceneStarRatingDisplay.cs | 11 ++-- .../Beatmaps/Drawables/StarRatingDisplay.cs | 63 ++++++++++++++----- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index a8bc5664f3..7883049df2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -8,17 +8,15 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Graphics.Containers; using osuTK; namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStarRatingDisplay : OsuTestScene { - [TestCase(52f, 20f)] - [TestCase(52f, 16f)] - [TestCase(50f, 14f)] - public void TestDisplay(float width, float height) + [TestCase(StarRatingDisplaySize.Regular)] + [TestCase(StarRatingDisplaySize.Small)] + public void TestDisplay(StarRatingDisplaySize size) { AddStep("load displays", () => { @@ -36,11 +34,10 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i * (i >= 11 ? 25f : 1f) + j * 0.1f, 0)) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i * (i >= 11 ? 25f : 1f) + j * 0.1f, 0), size) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(width, height), }), }) }; diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 2c40aebbe1..ed2fee23d5 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -44,40 +44,63 @@ namespace osu.Game.Beatmaps.Drawables /// Creates a new using an already computed . /// /// The already computed to display. - public StarRatingDisplay(StarDifficulty starDifficulty) + /// The size of the star rating display. + public StarRatingDisplay(StarDifficulty starDifficulty, StarRatingDisplaySize size = StarRatingDisplaySize.Regular) { Current.Value = starDifficulty; - Size = new Vector2(52f, 20f); + AutoSizeAxes = Axes.Both; InternalChild = new CircularContainer { Masking = true, - RelativeSizeAxes = Axes.Both, + AutoSizeAxes = Axes.Both, Children = new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, }, - starIcon = new SpriteIcon + new GridContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Right = 30f }, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(8f), + AutoSizeAxes = Axes.Both, + Margin = size == StarRatingDisplaySize.Small + ? new MarginPadding { Horizontal = 7f } + : new MarginPadding { Horizontal = 8f, Vertical = 2f }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 3f), + new Dimension(GridSizeMode.AutoSize, minSize: 25f), + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + Content = new[] + { + new[] + { + starIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(8f), + }, + Empty(), + starsText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Bottom = 1.5f }, + // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f + // see https://github.com/ppy/osu-framework/issues/3271. + Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), + Shadow = false, + } + } + } }, - starsText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 10f, Bottom = 2f }, - // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f - // see https://github.com/ppy/osu-framework/issues/3271. - Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), - Shadow = false, - } } }; } @@ -97,4 +120,10 @@ namespace osu.Game.Beatmaps.Drawables }, true); } } + + public enum StarRatingDisplaySize + { + Small, + Regular, + } } From 5e91ec73e3bf888f5aaf305478d5fceb317106ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 11:36:27 +0300 Subject: [PATCH 598/600] Handle star rating range display sizing --- .../Beatmaps/Drawables/StarRatingDisplay.cs | 22 ++++++++++++++++--- .../Components/StarRatingRangeDisplay.cs | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index ed2fee23d5..192ebe79d7 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -51,6 +51,23 @@ namespace osu.Game.Beatmaps.Drawables AutoSizeAxes = Axes.Both; + MarginPadding margin = default; + + switch (size) + { + case StarRatingDisplaySize.Small: + margin = new MarginPadding { Horizontal = 7f }; + break; + + case StarRatingDisplaySize.Range: + margin = new MarginPadding { Horizontal = 8f }; + break; + + case StarRatingDisplaySize.Regular: + margin = new MarginPadding { Horizontal = 8f, Vertical = 2f }; + break; + } + InternalChild = new CircularContainer { Masking = true, @@ -66,9 +83,7 @@ namespace osu.Game.Beatmaps.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, - Margin = size == StarRatingDisplaySize.Small - ? new MarginPadding { Horizontal = 7f } - : new MarginPadding { Horizontal = 8f, Vertical = 2f }, + Margin = margin, ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize), @@ -124,6 +139,7 @@ namespace osu.Game.Beatmaps.Drawables public enum StarRatingDisplaySize { Small, + Range, Regular, } } diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 8e62153225..7b14acf924 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -64,8 +64,8 @@ namespace osu.Game.Screens.OnlinePlay.Components AutoSizeAxes = Axes.Both, Children = new Drawable[] { - minDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) }, - maxDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) } + minDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Range), + maxDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Range) } } }; From d2df09432f040d29ae08a92b2104c8d4fca5eda2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 11:49:33 +0300 Subject: [PATCH 599/600] Center the star rating display text rather than left --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 192ebe79d7..25cde5fb82 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -105,8 +105,8 @@ namespace osu.Game.Beatmaps.Drawables Empty(), starsText = new OsuSpriteText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Margin = new MarginPadding { Bottom = 1.5f }, // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f // see https://github.com/ppy/osu-framework/issues/3271. From 28e2b6cec7cff82d007d44a7aa2026ff0679ed73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 18:34:09 +0900 Subject: [PATCH 600/600] Add transform test for fun --- .../TestSceneStarRatingDisplay.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 7883049df2..052251d5a8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -44,6 +45,31 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestSpectrum() + { + StarRatingDisplay starRating = null; + + BindableDouble starRatingNumeric; + + AddStep("load display", () => + { + Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3f), + }; + }); + + AddStep("transform over spectrum", () => + { + starRatingNumeric = new BindableDouble(); + starRatingNumeric.BindValueChanged(val => starRating.Current.Value = new StarDifficulty(val.NewValue, 1)); + this.TransformBindableTo(starRatingNumeric, 10, 10000, Easing.OutQuint); + }); + } + [Test] public void TestChangingStarRatingDisplay() {