diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index 01156ad4a1..a3f6fa6671 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -140,13 +140,14 @@ namespace osu.Game.Tests.Visual.Playlists room = new Room { RoomID = 1, + MaxAttempts = 10, Playlist = [ // osu! beatmap new PlaylistItem(importedSet.Beatmaps[0]) { RulesetID = new OsuRuleset().RulesetInfo.OnlineID, - Freestyle = true + Freestyle = true, }, // osu! beatmap converted played in taiko new PlaylistItem(importedSet.Beatmaps[1]) diff --git a/osu.Game/Graphics/UserInterface/SectionHeader.cs b/osu.Game/Graphics/UserInterface/SectionHeader.cs index 0ee430c501..eefdef42ce 100644 --- a/osu.Game/Graphics/UserInterface/SectionHeader.cs +++ b/osu.Game/Graphics/UserInterface/SectionHeader.cs @@ -2,6 +2,7 @@ // 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.Shapes; @@ -14,8 +15,20 @@ namespace osu.Game.Graphics.UserInterface { public partial class SectionHeader : CompositeDrawable { + /// + /// Extra text to be shown in brackets next to the header. + /// Unlike the header itself, this can be updated during runtime. + /// + public readonly Bindable DetailsText = new Bindable(); + private readonly LocalisableString text; + private OsuTextFlowContainer textFlow = null!; + private ITextPart? detailsPart; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + public SectionHeader(LocalisableString text) { this.text = text; @@ -27,7 +40,7 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load() { InternalChild = new FillFlowContainer { @@ -37,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface Spacing = new Vector2(2), Children = new Drawable[] { - new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: 16, weight: FontWeight.SemiBold)) + textFlow = new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: 16, weight: FontWeight.SemiBold)) { Text = text, RelativeSizeAxes = Axes.X, @@ -51,5 +64,21 @@ namespace osu.Game.Graphics.UserInterface } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + DetailsText.BindValueChanged(updateDetails, true); + } + + private void updateDetails(ValueChangedEvent details) + { + if (detailsPart != null) + textFlow.RemovePart(detailsPart); + + if (!string.IsNullOrEmpty(details.NewValue)) + detailsPart = textFlow.AddText($" ({details.NewValue})", t => t.Colour = colourProvider.Highlight1); + } } } diff --git a/osu.Game/Localisation/OnlinePlayStrings.cs b/osu.Game/Localisation/OnlinePlayStrings.cs index 32ef5d66fc..52f4908f60 100644 --- a/osu.Game/Localisation/OnlinePlayStrings.cs +++ b/osu.Game/Localisation/OnlinePlayStrings.cs @@ -49,6 +49,31 @@ namespace osu.Game.Localisation /// public static LocalisableString PlaylistTrayDescription => new TranslatableString(getKey(@"playlist_tray_description"), @"Manage items on previous screen"); + /// + /// "Beatmap queue" + /// + public static LocalisableString MultiplayerBeatmapQueue => new TranslatableString(getKey(@"multiplayer_beatmap_queue"), @"Beatmap queue"); + + /// + /// "Progress" + /// + public static LocalisableString PlaylistProgress => new TranslatableString(getKey(@"playlist_progress"), @"Progress"); + + /// + /// "Leaderboard" + /// + public static LocalisableString PlaylistLeaderboard => new TranslatableString(getKey(@"playlist_leaderboard"), @"Leaderboard"); + + /// + /// "Difficulty" + /// + public static LocalisableString Difficulty => new TranslatableString(getKey(@"difficulty"), @"Difficulty"); + + /// + /// "Chat" + /// + public static LocalisableString Chat => new TranslatableString(getKey(@"chat"), @"Chat"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs deleted file mode 100644 index 6dfde183f0..0000000000 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.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 osu.Framework.Allocation; -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 osuTK; - -namespace osu.Game.Screens.OnlinePlay.Components -{ - /// - /// A header used in the multiplayer interface which shows text / details beneath a line. - /// - public partial class OverlinedHeader : CompositeDrawable - { - private bool showLine = true; - - public bool ShowLine - { - get => showLine; - set - { - showLine = value; - line.Alpha = value ? 1 : 0; - } - } - - public Bindable Details = new Bindable(); - - private readonly Circle line; - private readonly OsuSpriteText details; - - public OverlinedHeader(LocalisableString title) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Margin = new MarginPadding { Bottom = 5 }; - - InternalChild = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - line = new Circle - { - RelativeSizeAxes = Axes.X, - Height = 2, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new OsuSpriteText - { - Text = title, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold) - }, - details = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold) - }, - } - }, - } - }; - - Details.BindValueChanged(val => details.Text = val.NewValue); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - line.Colour = colours.Yellow; - details.Colour = colours.Yellow; - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistHeader.cs similarity index 83% rename from osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs rename to osu.Game/Screens/OnlinePlay/Components/PlaylistHeader.cs index 55d9f273e9..2efe990397 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistHeader.cs @@ -3,19 +3,20 @@ using System.ComponentModel; using osu.Framework.Allocation; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Rulesets; namespace osu.Game.Screens.OnlinePlay.Components { - public partial class OverlinedPlaylistHeader : OverlinedHeader + public partial class PlaylistHeader : SectionHeader { private readonly Room room; [Resolved] private RulesetStore rulesets { get; set; } = null!; - public OverlinedPlaylistHeader(Room room) + public PlaylistHeader(Room room) : base("Playlist") { this.room = room; @@ -36,7 +37,7 @@ namespace osu.Game.Screens.OnlinePlay.Components } private void updateDuration() - => Details.Value = room.Playlist.GetTotalDuration(rulesets); + => DetailsText.Value = $"{room.Playlist.GetTotalDuration(rulesets)}"; protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs b/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs index 6db293ec71..97f80e1111 100644 --- a/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs +++ b/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs @@ -252,7 +252,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge { new Drawable[] { - new SectionHeader("Chat") + new SectionHeader(OnlinePlayStrings.Chat) }, [new MatchChatDisplay(room) { RelativeSizeAxes = Axes.Both }] }, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 9b66c37402..ca8c4c7cfe 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -19,6 +19,8 @@ using osu.Framework.Screens; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; @@ -225,7 +227,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer new GridContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(content_padding), + Padding = new MarginPadding(content_padding) { Top = 10 }, ColumnDimensions = new[] { new Dimension(), @@ -277,7 +279,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { new Drawable[] { - new OverlinedHeader("Beatmap queue") + new SectionHeader(OnlinePlayStrings.MultiplayerBeatmapQueue) }, new Drawable[] { @@ -309,7 +311,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Alpha = 0, Children = new Drawable[] { - new OverlinedHeader("Extra mods"), + new SectionHeader("Extra mods"), new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -347,7 +349,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Alpha = 0, Children = new Drawable[] { - new OverlinedHeader("Difficulty"), + new SectionHeader(OnlinePlayStrings.Difficulty), userStyleDisplayContainer = new Container { RelativeSizeAxes = Axes.X, @@ -370,7 +372,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { new Drawable[] { - new OverlinedHeader("Chat") + new SectionHeader(OnlinePlayStrings.Chat) }, new Drawable[] { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs index 79c6fb33cd..cd695a0143 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs @@ -2,13 +2,13 @@ // 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.Multiplayer; using osu.Game.Resources.Localisation.Web; -using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { - public partial class ParticipantsListHeader : OverlinedHeader + public partial class ParticipantsListHeader : SectionHeader { [Resolved] private MultiplayerClient client { get; set; } = null!; @@ -26,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants if (room == null) return; - Details.Value = room.Users.Count.ToString(); + DetailsText.Value = $"{room.Users.Count}"; } } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 646da4e967..219bed9055 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -20,7 +20,9 @@ using osu.Framework.Screens; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.UserInterface; using osu.Game.Input; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Rooms; @@ -218,7 +220,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists new GridContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(content_padding), + Padding = new MarginPadding(content_padding) { Top = 10 }, ColumnDimensions = new[] { new Dimension(), @@ -244,7 +246,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { new Drawable[] { - new OverlinedPlaylistHeader(room), + new PlaylistHeader(room), }, new Drawable[] { @@ -291,7 +293,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Alpha = 0, Children = new Drawable[] { - new OverlinedHeader("Extra mods"), + new SectionHeader("Extra mods"), new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -330,7 +332,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Alpha = 0, Children = new Drawable[] { - new OverlinedHeader("Difficulty"), + new SectionHeader(OnlinePlayStrings.Difficulty), userStyleDisplayContainer = new Container { RelativeSizeAxes = Axes.X, @@ -350,14 +352,14 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Direction = FillDirection.Vertical, Children = new Drawable[] { - new OverlinedHeader("Progress"), - new RoomLocalUserInfo(room), + new SectionHeader(OnlinePlayStrings.PlaylistProgress), + new RoomLocalUserInfo(room) { Margin = new MarginPadding { Horizontal = 5 } }, } } }, new Drawable[] { - new OverlinedHeader("Leaderboard") + new SectionHeader(OnlinePlayStrings.PlaylistLeaderboard) }, new Drawable[] { @@ -380,7 +382,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { new Drawable[] { - new OverlinedHeader("Chat") + new SectionHeader(OnlinePlayStrings.Chat) }, new Drawable[] {