diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 09d882a265..5c7ad7616d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -24,14 +24,12 @@ namespace osu.Game.Tests.Visual.Multiplayer private RulesetStore rulesetStore { get; set; } - private MatchBeatmapDetailArea detailArea; - [SetUp] public void Setup() => Schedule(() => { Room.Playlist.Clear(); - Child = detailArea = new MatchBeatmapDetailArea + Child = new MatchBeatmapDetailArea { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 07da707724..44fccdaa13 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -5,17 +5,23 @@ using System; using System.Linq; 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.Screens; using osu.Game.Audio; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; -using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem; +using osu.Game.Screens.Select; +using osuTK.Graphics; +using Footer = osu.Game.Screens.Multi.Match.Components.Footer; namespace osu.Game.Screens.Multi.Match { @@ -31,26 +37,21 @@ namespace osu.Game.Screens.Multi.Match [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } - [Resolved(typeof(Room), nameof(Room.Name))] - private Bindable name { get; set; } - [Resolved(typeof(Room), nameof(Room.Type))] private Bindable type { get; set; } - [Resolved(typeof(Room))] - protected BindableList Playlist { get; private set; } + [Resolved(typeof(Room), nameof(Room.Playlist))] + private BindableList playlist { get; set; } [Resolved] private BeatmapManager beatmapManager { get; set; } - [Resolved] - private PreviewTrackManager previewTrackManager { get; set; } - - [Resolved(CanBeNull = true)] - private OsuGame game { get; set; } + [Resolved(canBeNull: true)] + private Multiplayer multiplayer { get; set; } private readonly Bindable selectedItem = new Bindable(); - private MatchLeaderboard leaderboard; + private LeaderboardChatDisplay leaderboardChatDisplay; + private MatchSettingsOverlay settingsOverlay; public MatchSubScreen(Room room) { @@ -60,12 +61,14 @@ namespace osu.Game.Screens.Multi.Match [BackgroundDependencyLoader] private void load() { - Components.Header header; - GridContainer bottomRow; - MatchSettingsOverlay settings; - InternalChildren = new Drawable[] { + new HeaderBackgroundSprite + { + RelativeSizeAxes = Axes.X, + Height = 200, + Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.4f), Color4.White.Opacity(0)) + }, new GridContainer { RelativeSizeAxes = Axes.Both, @@ -73,143 +76,155 @@ namespace osu.Game.Screens.Multi.Match { new Drawable[] { - header = new Components.Header + new Container { - Depth = -1, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Horizontal = 105, + Vertical = 20 + }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new Components.Header() }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 65 }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = new OverlinedParticipants() + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 5 }, + Child = new OverlinedPlaylist(true) // Temporarily always allow selection + { + SelectedItem = { BindTarget = selectedItem } + } + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 5 }, + Child = leaderboardChatDisplay = new LeaderboardChatDisplay() + } + }, + } + } + } + } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } + } } }, new Drawable[] { - bottomRow = new GridContainer + new Footer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - leaderboard = new MatchLeaderboard - { - Padding = new MarginPadding - { - Left = 10 + HORIZONTAL_OVERFLOW_PADDING, - Right = 10, - Vertical = 10, - }, - RelativeSizeAxes = Axes.Both - }, - new Container - { - Padding = new MarginPadding - { - Left = 10, - Right = 10 + HORIZONTAL_OVERFLOW_PADDING, - Vertical = 10, - }, - RelativeSizeAxes = Axes.Both, - Child = new MatchChatDisplay - { - RelativeSizeAxes = Axes.Both - } - }, - }, - }, + OnStart = onStart, + SelectedItem = { BindTarget = selectedItem } } - }, + } }, RowDimensions = new[] { + new Dimension(), new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Distributed), } }, - new Container + settingsOverlay = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Components.Header.HEIGHT }, - Child = settings = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both }, - }, + EditPlaylist = () => this.Push(new MatchSongSelect()), + State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden } + } }; - - beatmapManager.ItemAdded += beatmapAdded; } protected override void LoadComplete() { base.LoadComplete(); - Playlist.ItemsAdded += _ => updateSelectedItem(); - Playlist.ItemsRemoved += _ => updateSelectedItem(); + roomId.BindValueChanged(id => + { + if (id.NewValue == null) + settingsOverlay.Show(); + else + settingsOverlay.Hide(); + }, true); - updateSelectedItem(); - } + selectedItem.BindValueChanged(selectedItemChanged); + selectedItem.Value = playlist.FirstOrDefault(); - private void updateSelectedItem() - { - selectedItem.Value = Playlist.FirstOrDefault(); - currentItemChanged(); + beatmapManager.ItemAdded += beatmapAdded; } public override bool OnExiting(IScreen next) { RoomManager?.PartRoom(); Mods.Value = Array.Empty(); - previewTrackManager.StopAnyPlaying(this); return base.OnExiting(next); } - /// - /// Handles propagation of the current playlist item's content to game-wide mechanisms. - /// - private void currentItemChanged() + private void selectedItemChanged(ValueChangedEvent e) { - var item = selectedItem.Value; + updateWorkingBeatmap(); - // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info - var localBeatmap = item?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.Beatmap.Value.OnlineBeatmapID); + Mods.Value = e.NewValue?.RequiredMods?.ToArray() ?? Array.Empty(); - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - Mods.Value = item?.RequiredMods?.ToArray() ?? Array.Empty(); - - if (item?.Ruleset != null) - Ruleset.Value = item.Ruleset.Value; - - previewTrackManager.StopAnyPlaying(this); + if (e.NewValue?.Ruleset != null) + Ruleset.Value = e.NewValue.Ruleset.Value; + } + + private void updateWorkingBeatmap() + { + var beatmap = selectedItem.Value?.Beatmap.Value; + + // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info + var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID); + + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); } - /// - /// Handle the case where a beatmap is imported (and can be used by this match). - /// private void beatmapAdded(BeatmapSetInfo model) => Schedule(() => { if (Beatmap.Value != beatmapManager.DefaultBeatmap) return; - if (selectedItem.Value == null) - return; - - // Try to retrieve the corresponding local beatmap - var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == selectedItem.Value.Beatmap.Value.OnlineBeatmapID); - - if (localBeatmap != null) - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); + updateWorkingBeatmap(); }); - [Resolved(canBeNull: true)] - private Multiplayer multiplayer { get; set; } - private void onStart() { - previewTrackManager.StopAnyPlaying(this); - switch (type.Value) { default: case GameTypeTimeshift _: multiplayer?.Start(() => new TimeshiftPlayer(selectedItem.Value) { - Exited = () => leaderboard.RefreshScores() + Exited = () => leaderboardChatDisplay.RefreshScores() }); break; } @@ -222,5 +237,15 @@ namespace osu.Game.Screens.Multi.Match if (beatmapManager != null) beatmapManager.ItemAdded -= beatmapAdded; } + + private class HeaderBackgroundSprite : MultiplayerBackgroundSprite + { + protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; + + private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double TransformDuration => 200; + } + } } }