From 3b4e02e5c78fd77325f188c0379785e47b61d6aa Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 17 Feb 2021 07:29:45 +0300 Subject: [PATCH 01/17] Fix user population not immediate on bracket loading --- osu.Game.Tournament/TournamentGameBase.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 4224da4bbe..327d8f67b8 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -152,7 +152,7 @@ namespace osu.Game.Tournament { if (string.IsNullOrEmpty(p.Username) || p.Statistics == null) { - PopulateUser(p); + PopulateUser(p, immediate: true); addedInfo = true; } } @@ -211,7 +211,7 @@ namespace osu.Game.Tournament return addedInfo; } - public void PopulateUser(User user, Action success = null, Action failure = null) + public void PopulateUser(User user, Action success = null, Action failure = null, bool immediate = false) { var req = new GetUserRequest(user.Id, Ruleset.Value); @@ -231,7 +231,10 @@ namespace osu.Game.Tournament failure?.Invoke(); }; - API.Queue(req); + if (immediate) + API.Perform(req); + else + API.Queue(req); } protected override void LoadComplete() From 705e9267497bc1eec01da9d73ec2630ad2be327d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 17 Feb 2021 07:48:23 +0300 Subject: [PATCH 02/17] Fix attempting to populate users with invalid IDs --- osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 582f72429b..263bbc533c 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -277,7 +277,8 @@ namespace osu.Game.Tournament.Screens.Editors userId.Value = user.Id.ToString(); userId.BindValueChanged(idString => { - int.TryParse(idString.NewValue, out var parsed); + if (!(int.TryParse(idString.NewValue, out var parsed))) + return; user.Id = parsed; From 85ebc8e06cd45be8e66f40c059dac6b20c926cc8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 17 Feb 2021 07:49:28 +0300 Subject: [PATCH 03/17] Fix potentially overwriting user ID from failed request --- osu.Game.Tournament/TournamentGameBase.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 327d8f67b8..0b101f050f 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -225,11 +225,7 @@ namespace osu.Game.Tournament success?.Invoke(); }; - req.Failure += _ => - { - user.Id = 1; - failure?.Invoke(); - }; + req.Failure += _ => failure?.Invoke(); if (immediate) API.Perform(req); From 61bf9a64bb117483093318b99ce135cd50a2e8c0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 17 Feb 2021 11:21:33 +0300 Subject: [PATCH 04/17] Revert failed user requests changes with returning user ID instead --- osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs | 3 +-- osu.Game.Tournament/TournamentGameBase.cs | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 263bbc533c..582f72429b 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -277,8 +277,7 @@ namespace osu.Game.Tournament.Screens.Editors userId.Value = user.Id.ToString(); userId.BindValueChanged(idString => { - if (!(int.TryParse(idString.NewValue, out var parsed))) - return; + int.TryParse(idString.NewValue, out var parsed); user.Id = parsed; diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 0b101f050f..ffda101ee0 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -217,6 +217,8 @@ namespace osu.Game.Tournament req.Success += res => { + user.Id = res.Id; + user.Username = res.Username; user.Statistics = res.Statistics; user.Country = res.Country; @@ -225,7 +227,11 @@ namespace osu.Game.Tournament success?.Invoke(); }; - req.Failure += _ => failure?.Invoke(); + req.Failure += _ => + { + user.Id = 1; + failure?.Invoke(); + }; if (immediate) API.Perform(req); From e7308193e7bd33a8c6e38f90d7dca112bda6e084 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 13:03:29 +0900 Subject: [PATCH 05/17] Add xmldoc explaining how PreviewTime is intended to work --- osu.Game/Beatmaps/BeatmapMetadata.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 39b3c23ddd..367f612dc8 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -51,7 +51,12 @@ namespace osu.Game.Beatmaps [JsonProperty(@"tags")] public string Tags { get; set; } + /// + /// The time in milliseconds to begin playing the track for preview purposes. + /// If -1, the track should begin playing at 40% of its length. + /// public int PreviewTime { get; set; } + public string AudioFile { get; set; } public string BackgroundFile { get; set; } From 90dce5204218ac9132e929d374a123f3da7abe34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 14:10:28 +0900 Subject: [PATCH 06/17] Fix potential crash from cross-thread drawable manipulation in CollectionFilterDropdown --- osu.Game/Collections/CollectionFilterDropdown.cs | 13 ++++++------- osu.Game/Screens/Select/FilterControl.cs | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index ec0e9d5a89..3e55ecb084 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -41,19 +41,18 @@ namespace osu.Game.Collections ItemSource = filters; } - [BackgroundDependencyLoader(permitNulls: true)] - private void load([CanBeNull] CollectionManager collectionManager) + [Resolved(CanBeNull = true)] + private CollectionManager collectionManager { get; set; } + + protected override void LoadComplete() { + base.LoadComplete(); + if (collectionManager != null) collections.BindTo(collectionManager.Collections); collections.CollectionChanged += (_, __) => collectionsChanged(); collectionsChanged(); - } - - protected override void LoadComplete() - { - base.LoadComplete(); Current.BindValueChanged(filterChanged, true); } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 952a5d1eaa..eafd8a87d1 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Select Sort = sortMode.Value, AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value, - Collection = collectionDropdown?.Current.Value.Collection + Collection = collectionDropdown?.Current.Value?.Collection }; if (!minimumStars.IsDefault) From 49589b64c34792ac07d19f8f3d4efb97fd4c7aad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 14:55:15 +0900 Subject: [PATCH 07/17] Intro track should not restart from preview point --- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 71b83d4aab..71f3b60026 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -168,7 +168,7 @@ namespace osu.Game.Screens.Menu { // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. if (UsingThemedIntro) - Track.Restart(); + Track.Start(); } protected override void LogoArriving(OsuLogo logo, bool resuming) From dfedea9ea2abf6c09dead571889915a37570c0ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 14:55:44 +0900 Subject: [PATCH 08/17] Move preview point logic to a specific method in WorkingBeatmap --- osu.Game/Beatmaps/WorkingBeatmap.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 30382c444f..aab8ff6bd6 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -266,6 +266,26 @@ namespace osu.Game.Beatmaps [NotNull] public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000); + /// + /// Reads the correct track restart point from beatmap metadata and sets looping to enabled. + /// + public void PrepareTrackForPreviewLooping() + { + Track.Looping = true; + Track.RestartPoint = Metadata.PreviewTime; + + if (Track.RestartPoint == -1) + { + if (!Track.IsLoaded) + { + // force length to be populated (https://github.com/ppy/osu-framework/issues/4202) + Track.Seek(Track.CurrentTime); + } + + Track.RestartPoint = 0.4f * Track.Length; + } + } + /// /// Transfer a valid audio track into this working beatmap. Used as an optimisation to avoid reload / track swap /// across difficulties in the same beatmap set. From 421cdb6650246d249d685812c8ea7dbd3c07a015 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 15:01:11 +0900 Subject: [PATCH 09/17] Consume new method in existing usages (and remove some unnecessary set/unset code) --- osu.Game/Screens/Menu/MainMenu.cs | 11 ++++++----- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 7 +------ osu.Game/Screens/Select/SongSelect.cs | 7 +++---- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 97fd58318b..424e6d2cd5 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -179,14 +179,15 @@ namespace osu.Game.Screens.Menu base.OnEntering(last); buttons.FadeInFromZero(500); - var metadata = Beatmap.Value.Metadata; - if (last is IntroScreen && musicController.TrackLoaded) { - if (!musicController.CurrentTrack.IsRunning) + var track = musicController.CurrentTrack; + + // presume the track is the current beatmap's track. not sure how correct this assumption is but it has worked until now. + if (!track.IsRunning) { - musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length); - musicController.CurrentTrack.Start(); + Beatmap.Value.PrepareTrackForPreviewLooping(); + track.Restart(); } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index e755f8c405..86422085a1 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -173,9 +173,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (track != null) { - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - track.Looping = true; - + Beatmap.Value.PrepareTrackForPreviewLooping(); music?.EnsurePlayingSomething(); } } @@ -185,10 +183,7 @@ namespace osu.Game.Screens.OnlinePlay.Match var track = Beatmap?.Value?.Track; if (track != null) - { track.Looping = false; - track.RestartPoint = 0; - } } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index edbab083cd..b7f7c40539 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -648,8 +648,9 @@ namespace osu.Game.Screens.Select { Debug.Assert(!isHandlingLooping); - music.CurrentTrack.Looping = isHandlingLooping = true; + isHandlingLooping = true; + ensureTrackLooping(Beatmap.Value, TrackChangeDirection.None); music.TrackChanged += ensureTrackLooping; } @@ -665,7 +666,7 @@ namespace osu.Game.Screens.Select } private void ensureTrackLooping(WorkingBeatmap beatmap, TrackChangeDirection changeDirection) - => music.CurrentTrack.Looping = true; + => beatmap.PrepareTrackForPreviewLooping(); public override bool OnBackButton() { @@ -719,8 +720,6 @@ namespace osu.Game.Screens.Select bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - if (!track.IsRunning && (music.UserPauseRequested != true || isNewTrack)) music.Play(true); From 46ba5de32c5e0dc63d94ab618121a61df655c2a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Feb 2021 16:19:36 +0900 Subject: [PATCH 10/17] Fix collections being imported from BDL thread --- osu.Game/Collections/CollectionManager.cs | 48 +++++++++++++---------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/osu.Game/Collections/CollectionManager.cs b/osu.Game/Collections/CollectionManager.cs index 569ac749a4..a65d9a415d 100644 --- a/osu.Game/Collections/CollectionManager.cs +++ b/osu.Game/Collections/CollectionManager.cs @@ -139,35 +139,43 @@ namespace osu.Game.Collections PostNotification?.Invoke(notification); var collection = readCollections(stream, notification); - bool importCompleted = false; - - Schedule(() => - { - importCollections(collection); - importCompleted = true; - }); - - while (!IsDisposed && !importCompleted) - await Task.Delay(10); + await importCollections(collection); notification.CompletionText = $"Imported {collection.Count} collections"; notification.State = ProgressNotificationState.Completed; } - private void importCollections(List newCollections) + private Task importCollections(List newCollections) { - foreach (var newCol in newCollections) - { - var existing = Collections.FirstOrDefault(c => c.Name == newCol.Name); - if (existing == null) - Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } }); + var tcs = new TaskCompletionSource(); - foreach (var newBeatmap in newCol.Beatmaps) + Schedule(() => + { + try { - if (!existing.Beatmaps.Contains(newBeatmap)) - existing.Beatmaps.Add(newBeatmap); + foreach (var newCol in newCollections) + { + var existing = Collections.FirstOrDefault(c => c.Name == newCol.Name); + if (existing == null) + Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } }); + + foreach (var newBeatmap in newCol.Beatmaps) + { + if (!existing.Beatmaps.Contains(newBeatmap)) + existing.Beatmaps.Add(newBeatmap); + } + } + + tcs.SetResult(true); } - } + catch (Exception e) + { + Logger.Error(e, "Failed to import collection."); + tcs.SetException(e); + } + }); + + return tcs.Task; } private List readCollections(Stream stream, ProgressNotification notification = null) From c3a98b6ad15475a86565c2501fe0faeb2e898b14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 16:59:43 +0900 Subject: [PATCH 11/17] Fix carousel items' borders getting blown out when selected and hovered I tried restructuring the hierarchy to avoid needing this added property (moving the hover layer out of the border container) but this leads to some subpixel leakage outside the borders which looks even worse. Closes #6915. --- .../Screens/Select/Carousel/CarouselHeader.cs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs index 947334c747..73324894ee 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs @@ -24,9 +24,13 @@ namespace osu.Game.Screens.Select.Carousel public Container BorderContainer; public readonly Bindable State = new Bindable(CarouselItemState.NotSelected); + private HoverLayer hoverLayer; protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; + private const float corner_radius = 10; + private const float border_thickness = 2.5f; + public CarouselHeader() { RelativeSizeAxes = Axes.X; @@ -36,12 +40,12 @@ namespace osu.Game.Screens.Select.Carousel { RelativeSizeAxes = Axes.Both, Masking = true, - CornerRadius = 10, + CornerRadius = corner_radius, BorderColour = new Color4(221, 255, 255, 255), Children = new Drawable[] { Content, - new HoverLayer() + hoverLayer = new HoverLayer() } }; } @@ -59,6 +63,8 @@ namespace osu.Game.Screens.Select.Carousel { case CarouselItemState.Collapsed: case CarouselItemState.NotSelected: + hoverLayer.InsetForBorder = false; + BorderContainer.BorderThickness = 0; BorderContainer.EdgeEffect = new EdgeEffectParameters { @@ -70,7 +76,9 @@ namespace osu.Game.Screens.Select.Carousel break; case CarouselItemState.Selected: - BorderContainer.BorderThickness = 2.5f; + hoverLayer.InsetForBorder = true; + + BorderContainer.BorderThickness = border_thickness; BorderContainer.EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, @@ -107,6 +115,26 @@ namespace osu.Game.Screens.Select.Carousel sampleHover = audio.Samples.Get("SongSelect/song-ping"); } + public bool InsetForBorder + { + set + { + if (value) + { + // apply same border as above to avoid applying additive overlay to it (and blowing out the colour). + Masking = true; + CornerRadius = corner_radius; + BorderThickness = border_thickness; + } + else + { + BorderThickness = 0; + CornerRadius = 0; + Masking = false; + } + } + } + protected override bool OnHover(HoverEvent e) { box.FadeIn(100, Easing.OutQuint); From b713eb2eae259e086ca3b62ff6e3d7b79bed06a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 17:13:48 +0900 Subject: [PATCH 12/17] Make field readonly --- osu.Game/Screens/Select/Carousel/CarouselHeader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs index 73324894ee..2fbf64de29 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs @@ -24,7 +24,8 @@ namespace osu.Game.Screens.Select.Carousel public Container BorderContainer; public readonly Bindable State = new Bindable(CarouselItemState.NotSelected); - private HoverLayer hoverLayer; + + private readonly HoverLayer hoverLayer; protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; From 668cc144f68c339ab03a4601c4d36faae86b051e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Feb 2021 17:39:01 +0900 Subject: [PATCH 13/17] Fix test failures + multiple filter operations firing --- .../Collections/CollectionFilterDropdown.cs | 22 ++++++++++++++----- .../Collections/CollectionFilterMenuItem.cs | 8 ++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index 3e55ecb084..aad8400faa 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -29,6 +29,14 @@ namespace osu.Game.Collections /// protected virtual bool ShowManageCollectionsItem => true; + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public new Bindable Current + { + get => current.Current; + set => current.Current = value; + } + private readonly IBindableList collections = new BindableList(); private readonly IBindableList beatmaps = new BindableList(); private readonly BindableList filters = new BindableList(); @@ -36,14 +44,15 @@ namespace osu.Game.Collections [Resolved(CanBeNull = true)] private ManageCollectionsDialog manageCollectionsDialog { get; set; } + [Resolved(CanBeNull = true)] + private CollectionManager collectionManager { get; set; } + public CollectionFilterDropdown() { ItemSource = filters; + Current.Value = new AllBeatmapsCollectionFilterMenuItem(); } - [Resolved(CanBeNull = true)] - private CollectionManager collectionManager { get; set; } - protected override void LoadComplete() { base.LoadComplete(); @@ -51,9 +60,12 @@ namespace osu.Game.Collections if (collectionManager != null) collections.BindTo(collectionManager.Collections); - collections.CollectionChanged += (_, __) => collectionsChanged(); - collectionsChanged(); + // Dropdown has logic which triggers a change on the bindable with every change to the contained items. + // This is not desirable here, as it leads to multiple filter operations running even though nothing has changed. + // An extra bindable is enough to subvert this behaviour. + base.Current.BindTo(Current); + collections.BindCollectionChanged((_, __) => collectionsChanged(), true); Current.BindValueChanged(filterChanged, true); } diff --git a/osu.Game/Collections/CollectionFilterMenuItem.cs b/osu.Game/Collections/CollectionFilterMenuItem.cs index 4a489d2945..fe79358223 100644 --- a/osu.Game/Collections/CollectionFilterMenuItem.cs +++ b/osu.Game/Collections/CollectionFilterMenuItem.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 JetBrains.Annotations; using osu.Framework.Bindables; @@ -9,7 +10,7 @@ namespace osu.Game.Collections /// /// A filter. /// - public class CollectionFilterMenuItem + public class CollectionFilterMenuItem : IEquatable { /// /// The collection to filter beatmaps from. @@ -33,6 +34,11 @@ namespace osu.Game.Collections Collection = collection; CollectionName = Collection?.Name.GetBoundCopy() ?? new Bindable("All beatmaps"); } + + public bool Equals(CollectionFilterMenuItem other) + => other != null && CollectionName.Value == other.CollectionName.Value; + + public override int GetHashCode() => CollectionName.Value.GetHashCode(); } public class AllBeatmapsCollectionFilterMenuItem : CollectionFilterMenuItem From 71316bbee568c7ded598d502204054db85ffbb53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 17:45:58 +0900 Subject: [PATCH 14/17] Allow using OnlineViewContainer without deriving it --- osu.Game/Online/OnlineViewContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index c9fb70f0cc..8868f90524 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Online /// A for displaying online content which require a local user to be logged in. /// Shows its children only when the local user is logged in and supports displaying a placeholder if not. /// - public abstract class OnlineViewContainer : Container + public class OnlineViewContainer : Container { protected LoadingSpinner LoadingSpinner { get; private set; } @@ -30,7 +30,7 @@ namespace osu.Game.Online [Resolved] protected IAPIProvider API { get; private set; } - protected OnlineViewContainer(string placeholderMessage) + public OnlineViewContainer(string placeholderMessage) { this.placeholderMessage = placeholderMessage; } From c3f66a0c745ce7c53fbf948625f5ad620dd2d730 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 17:46:07 +0900 Subject: [PATCH 15/17] Add login placeholder for chat overlay --- osu.Game/Overlays/ChatOverlay.cs | 73 ++++++++++++++++---------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 8bc7e21047..f5dd4fae2c 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -24,6 +24,7 @@ using osu.Game.Overlays.Chat.Tabs; using osuTK.Input; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Online; namespace osu.Game.Overlays { @@ -118,40 +119,47 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, }, - currentChannelContainer = new Container + new OnlineViewContainer("Sign in to chat") { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Bottom = textbox_height - }, - }, - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = textbox_height, - Padding = new MarginPadding - { - Top = padding * 2, - Bottom = padding * 2, - Left = ChatLine.LEFT_PADDING + padding * 2, - Right = padding * 2, - }, Children = new Drawable[] { - textbox = new FocusedTextBox + currentChannelContainer = new Container { RelativeSizeAxes = Axes.Both, - Height = 1, - PlaceholderText = "type your message", - ReleaseFocusOnCommit = false, - HoldFocus = true, - } - } - }, - loading = new LoadingSpinner(), + Padding = new MarginPadding + { + Bottom = textbox_height + }, + }, + new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = textbox_height, + Padding = new MarginPadding + { + Top = padding * 2, + Bottom = padding * 2, + Left = ChatLine.LEFT_PADDING + padding * 2, + Right = padding * 2, + }, + Children = new Drawable[] + { + textbox = new FocusedTextBox + { + RelativeSizeAxes = Axes.Both, + Height = 1, + PlaceholderText = "type your message", + ReleaseFocusOnCommit = false, + HoldFocus = true, + } + } + }, + loading = new LoadingSpinner(), + }, + } } }, tabsArea = new TabsArea @@ -184,9 +192,7 @@ namespace osu.Game.Overlays }, }, }; - textbox.OnCommit += postMessage; - ChannelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; ChannelTabControl.ChannelSelectorActive.ValueChanged += active => ChannelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden; ChannelSelectionOverlay.State.ValueChanged += state => @@ -203,10 +209,8 @@ namespace osu.Game.Overlays else textbox.HoldFocus = true; }; - ChannelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel); ChannelSelectionOverlay.OnRequestLeave = channelManager.LeaveChannel; - ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); ChatHeight.BindValueChanged(height => { @@ -214,9 +218,7 @@ namespace osu.Game.Overlays channelSelectionContainer.Height = 1f - height.NewValue; tabBackground.FadeTo(height.NewValue == 1f ? 1f : 0.8f, 200); }, true); - chatBackground.Colour = colours.ChatBlue; - loading.Show(); // This is a relatively expensive (and blocking) operation. @@ -226,13 +228,10 @@ namespace osu.Game.Overlays { // TODO: consider scheduling bindable callbacks to not perform when overlay is not present. channelManager.JoinedChannels.CollectionChanged += joinedChannelsChanged; - foreach (Channel channel in channelManager.JoinedChannels) ChannelTabControl.AddChannel(channel); - channelManager.AvailableChannels.CollectionChanged += availableChannelsChanged; availableChannelsChanged(null, null); - currentChannel = channelManager.CurrentChannel.GetBoundCopy(); currentChannel.BindValueChanged(currentChannelChanged, true); }); From 990c1b1d6ef118c755b8cdff7150601542f47535 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Feb 2021 18:19:57 +0900 Subject: [PATCH 16/17] Revert accidental removal of newlines --- osu.Game/Overlays/ChatOverlay.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index f5dd4fae2c..28f2287514 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -192,7 +192,9 @@ namespace osu.Game.Overlays }, }, }; + textbox.OnCommit += postMessage; + ChannelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; ChannelTabControl.ChannelSelectorActive.ValueChanged += active => ChannelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden; ChannelSelectionOverlay.State.ValueChanged += state => @@ -209,8 +211,10 @@ namespace osu.Game.Overlays else textbox.HoldFocus = true; }; + ChannelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel); ChannelSelectionOverlay.OnRequestLeave = channelManager.LeaveChannel; + ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); ChatHeight.BindValueChanged(height => { @@ -218,7 +222,9 @@ namespace osu.Game.Overlays channelSelectionContainer.Height = 1f - height.NewValue; tabBackground.FadeTo(height.NewValue == 1f ? 1f : 0.8f, 200); }, true); + chatBackground.Colour = colours.ChatBlue; + loading.Show(); // This is a relatively expensive (and blocking) operation. @@ -228,10 +234,13 @@ namespace osu.Game.Overlays { // TODO: consider scheduling bindable callbacks to not perform when overlay is not present. channelManager.JoinedChannels.CollectionChanged += joinedChannelsChanged; + foreach (Channel channel in channelManager.JoinedChannels) ChannelTabControl.AddChannel(channel); + channelManager.AvailableChannels.CollectionChanged += availableChannelsChanged; availableChannelsChanged(null, null); + currentChannel = channelManager.CurrentChannel.GetBoundCopy(); currentChannel.BindValueChanged(currentChannelChanged, true); }); From 8a1a4ea2d42874d1dc752d4ec6a3371d02940054 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Feb 2021 19:33:04 +0900 Subject: [PATCH 17/17] Set Current directly --- osu.Game/Collections/CollectionFilterDropdown.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index aad8400faa..bb743d4ccc 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -63,7 +63,7 @@ namespace osu.Game.Collections // Dropdown has logic which triggers a change on the bindable with every change to the contained items. // This is not desirable here, as it leads to multiple filter operations running even though nothing has changed. // An extra bindable is enough to subvert this behaviour. - base.Current.BindTo(Current); + base.Current = Current; collections.BindCollectionChanged((_, __) => collectionsChanged(), true); Current.BindValueChanged(filterChanged, true);