diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs index de58323abe..32af330f44 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs @@ -38,12 +38,26 @@ namespace osu.Desktop.VisualTests.Tests first.Room.Name.Value = @"Great Room Right Here"; first.Room.Host.Value = new User { Username = @"Naeferith", Id = 9492835, Country = new Country { FlagName = @"FR" }}; first.Room.Status.Value = new RoomStatusOpen(); - first.Room.Beatmap.Value = new BeatmapMetadata { Title = @"Seiryu", Artist = @"Critical Crystal" }; + first.Room.Beatmap.Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = @"Seiryu", + Artist = @"Critical Crystal", + }, + }; second.Room.Name.Value = @"Relax It's The Weekend"; second.Room.Host.Value = new User { Username = @"peppy", Id = 2, Country = new Country { FlagName = @"AU" }}; second.Room.Status.Value = new RoomStatusPlaying(); - second.Room.Beatmap.Value = new BeatmapMetadata { Title = @"ZAQ", Artist = @"Serendipity" }; + second.Room.Beatmap.Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = @"Serendipity", + Artist = @"ZAQ", + }, + }; AddStep(@"change state", () => { diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs new file mode 100644 index 0000000000..8ec1f66f8b --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Testing; +using osu.Framework.Graphics; +using osu.Game.Screens.Multiplayer; +using osu.Game.Database; +using osu.Game.Online.Multiplayer; +using osu.Game.Users; +using osu.Framework.Allocation; + +namespace osu.Desktop.VisualTests.Tests +{ + internal class TestCaseRoomInspector : TestCase + { + public override string Description => @"from the multiplayer lobby"; + + private RulesetDatabase rulesets; + + public override void Reset() + { + base.Reset(); + + var room = new Room(); + room.Name.Value = @"My Awesome Room"; + room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" }}; + room.Status.Value = new RoomStatusOpen(); + room.Beatmap.Value = new BeatmapInfo + { + StarDifficulty = 3.7, + Ruleset = rulesets.GetRuleset(3), + Metadata = new BeatmapMetadata + { + Title = @"Platina", + Artist = @"Maaya Sakamoto", + Author = @"uwutm8", + }, + }; + room.MaxParticipants.Value = 200; + room.Participants.Value = new[] { new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 }, + new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 }, + new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 }, + new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 }, + new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 }, + new User { Username = @"peppy", Id = 2, GlobalRank = 6251 }}; + + RoomInspector inspector; + Add(inspector = new RoomInspector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Room = room, + }); + + AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above"); + AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" }}); + AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); + AddStep(@"change beatmap", () => room.Beatmap.Value = null); + AddStep(@"change max participants", () => room.MaxParticipants.Value = null); + AddStep(@"change participants", () => room.Participants.Value = new[] + { + new User { Username = @"filsdelama", Id = 2831793, GlobalRank = 8542 }, + new User { Username = @"_index", Id = 652457, GlobalRank = 15024 } + }); + + AddStep(@"change room", () => + { + var newRoom = new Room(); + newRoom.Name.Value = @"My New, Better Than Ever Room"; + newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" }}; + newRoom.Status.Value = new RoomStatusOpen(); + newRoom.Beatmap.Value = new BeatmapInfo + { + StarDifficulty = 7.07, + Ruleset = rulesets.GetRuleset(0), + Metadata = new BeatmapMetadata + { + Title = @"xi", + Artist = @"FREEDOM DIVE", + Author = @"Nakagawa-Kanon", + }, + }; + newRoom.MaxParticipants.Value = 10; + newRoom.Participants.Value = new[] + { + new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 4 }, + new User { Username = @"HappyStick", Id = 256802, GlobalRank = 752 }, + new User { Username = @"-Konpaku-", Id = 2258797, GlobalRank = 571 } + }; + + inspector.Room = newRoom; + }); + } + + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets) + { + this.rulesets = rulesets; + } + } +} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index 5a532d7234..466c9336f0 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -224,6 +224,7 @@ + diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index c82025f902..fe3378f4a6 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -12,6 +12,8 @@ namespace osu.Game.Online.Multiplayer public Bindable Name = new Bindable(); public Bindable Host = new Bindable(); public Bindable Status = new Bindable(); - public Bindable Beatmap = new Bindable(); + public Bindable Beatmap = new Bindable(); + public Bindable MaxParticipants = new Bindable(); + public Bindable Participants = new Bindable(); } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index dd70289f7d..5f0ab3991d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -55,4 +55,4 @@ namespace osu.Game.Overlays.Toolbar DrawableIcon.TextSize *= 1.4f; } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index 7365963085..bbe279946a 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -227,13 +227,13 @@ namespace osu.Game.Screens.Multiplayer d.FadeColour(value.GetAppropriateColour(colours), 100); } - private void displayBeatmap(BeatmapMetadata value) + private void displayBeatmap(BeatmapInfo value) { if (value != null) { - beatmapTitle.Current = localisation.GetUnicodePreference(value.TitleUnicode, value.Title); + beatmapTitle.Current = localisation.GetUnicodePreference(value.Metadata.TitleUnicode, value.Metadata.Title); beatmapDash.Text = @" - "; - beatmapArtist.Current = localisation.GetUnicodePreference(value.ArtistUnicode, value.Artist); + beatmapArtist.Current = localisation.GetUnicodePreference(value.Metadata.ArtistUnicode, value.Metadata.Artist); } else { diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs new file mode 100644 index 0000000000..1471e2ed26 --- /dev/null +++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs @@ -0,0 +1,502 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Localisation; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Multiplayer; +using osu.Game.Users; + +namespace osu.Game.Screens.Multiplayer +{ + public class RoomInspector : Container + { + private readonly MarginPadding content_padding = new MarginPadding { Horizontal = 20, Vertical = 10 }; + + private readonly FillFlowContainer topFlow; + private readonly Box statusStrip; + private readonly OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor, host, levelRangeLower, levelRangeHigher; + private readonly Sprite cover; + private readonly FillFlowContainer levelRangeContainer; + private readonly ScrollContainer participantsScroll; + private readonly FillFlowContainer participantsFlow; + private readonly Container rulesetContainer; + private readonly Container flagContainer; + + private Bindable nameBind = new Bindable(); + private Bindable hostBind = new Bindable(); + private Bindable statusBind = new Bindable(); + private Bindable beatmapBind = new Bindable(); + private Bindable maxParticipantsBind = new Bindable(); + private Bindable participantsBind = new Bindable(); + + private OsuColour colours; + private LocalisationEngine localisation; + + private Room room; + public Room Room + { + get { return room; } + set + { + if (value == room) return; + room = value; + + nameBind.BindTo(Room.Name); + hostBind.BindTo(Room.Host); + statusBind.BindTo(Room.Status); + beatmapBind.BindTo(Room.Beatmap); + maxParticipantsBind.BindTo(Room.MaxParticipants); + participantsBind.BindTo(Room.Participants); + } + } + + public RoomInspector() + { + Width = 520; + RelativeSizeAxes = Axes.Y; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"343138"), + }, + topFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Height = 200, + Masking = true, + Children = new Drawable[] + { + cover = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + ColourInfo = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)), + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(20), + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + LayoutDuration = 100, + Children = new[] + { + participants = new OsuSpriteText + { + TextSize = 30, + Font = @"Exo2.0-Bold" + }, + participantsSlash = new OsuSpriteText + { + Text = @"/", + TextSize = 30, + Font = @"Exo2.0-Light" + }, + maxParticipants = new OsuSpriteText + { + TextSize = 30, + Font = @"Exo2.0-Light" + }, + }, + }, + name = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + TextSize = 30, + }, + }, + }, + }, + }, + statusStrip = new Box + { + RelativeSizeAxes = Axes.X, + Height = 5, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = content_padding, + Spacing = new Vector2(0f, 5f), + Children = new Drawable[] + { + status = new OsuSpriteText + { + TextSize = 14, + Font = @"Exo2.0-Bold", + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + LayoutDuration = 100, + Spacing = new Vector2(5f, 0f), + Children = new Drawable[] + { + rulesetContainer = new Container + { + Size = new Vector2(30f), + }, + new Container //todo: game type icon + { + Size = new Vector2(30f), + CornerRadius = 15f, + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"545454"), + }, + }, + }, + new Container + { + AutoSizeAxes = Axes.X, + Height = 30f, + Margin = new MarginPadding { Left = 5 }, + Children = new[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + beatmapTitle = new OsuSpriteText + { + Font = @"Exo2.0-BoldItalic", + }, + beatmapDash = new OsuSpriteText + { + Font = @"Exo2.0-BoldItalic", + }, + beatmapArtist = new OsuSpriteText + { + Font = @"Exo2.0-RegularItalic", + }, + }, + }, + beatmapAuthor = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + TextSize = 14, + }, + }, + }, + }, + }, + }, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = content_padding, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.X, + Height = 15f, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + Children = new Drawable[] + { + flagContainer = new Container + { + Width = 22f, + RelativeSizeAxes = Axes.Y, + }, + new Container + { + Width = 38f, + RelativeSizeAxes = Axes.Y, + CornerRadius = 2f, + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"ad387e"), + }, + }, + }, + new OsuSpriteText + { + Text = "hosted by", + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = 14, + }, + host = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = 14, + Font = @"Exo2.0-BoldItalic", + }, + }, + }, + levelRangeContainer = new FillFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + new OsuSpriteText + { + Text = "Level Range ", + TextSize = 14, + }, + new OsuSpriteText + { + Text = "#", + TextSize = 14, + }, + levelRangeLower = new OsuSpriteText + { + TextSize = 14, + Font = @"Exo2.0-Bold", + }, + new OsuSpriteText + { + Text = " - ", + TextSize = 14, + }, + new OsuSpriteText + { + Text = "#", + TextSize = 14, + }, + levelRangeHigher = new OsuSpriteText + { + Text = "6251", + TextSize = 14, + Font = @"Exo2.0-Bold", + }, + }, + }, + }, + }, + }, + }, + participantsScroll = new ScrollContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { Top = content_padding.Top, Left = 38, Right = 37 }, + Children = new[] + { + participantsFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + LayoutDuration = 100, + Spacing = new Vector2(5f), + }, + }, + }, + }; + + nameBind.ValueChanged += displayName; + hostBind.ValueChanged += displayUser; + maxParticipantsBind.ValueChanged += displayMaxParticipants; + participantsBind.ValueChanged += displayParticipants; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures, RulesetDatabase rulesets) + { + this.localisation = localisation; + this.colours = colours; + + beatmapAuthor.Colour = levelRangeContainer.Colour = colours.Gray9; + host.Colour = colours.Blue; + + cover.Texture = textures.Get(@"https://a.pomf.cat/mvduor.png"); + + rulesetContainer.Add(new DifficultyIcon(new BeatmapInfo + { + Ruleset = rulesets.GetRuleset(0), + StarDifficulty = 3.7, + }) { Size = new Vector2(30f) }); + + //binded here instead of ctor because dependencies are needed + statusBind.ValueChanged += displayStatus; + beatmapBind.ValueChanged += displayBeatmap; + + statusBind.TriggerChange(); + beatmapBind.TriggerChange(); + } + + protected override void Update() + { + base.Update(); + + participantsScroll.Height = DrawHeight - topFlow.DrawHeight; + } + + private void displayName(string value) + { + name.Text = value; + } + + private void displayUser(User value) + { + host.Text = value.Username; + flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName ?? @"__") { RelativeSizeAxes = Axes.Both } }; + } + + private void displayStatus(RoomStatus value) + { + if (value == null) return; + status.Text = value.Message; + + foreach (Drawable d in new Drawable[] { statusStrip, status }) + d.FadeColour(value.GetAppropriateColour(colours), 100); + } + + private void displayBeatmap(BeatmapInfo value) + { + if (value != null) + { + rulesetContainer.FadeIn(100); + rulesetContainer.Children = new[] + { + new DifficultyIcon(value) + { + Size = new Vector2(rulesetContainer.DrawHeight), + } + }; + + beatmapTitle.Current = localisation.GetUnicodePreference(value.Metadata.TitleUnicode, value.Metadata.Title); + beatmapDash.Text = @" - "; + beatmapArtist.Current = localisation.GetUnicodePreference(value.Metadata.ArtistUnicode, value.Metadata.Artist); + beatmapAuthor.Text = $"mapped by {value.Metadata.Author}"; + } + else + { + rulesetContainer.FadeOut(100); + + beatmapTitle.Current = null; + beatmapArtist.Current = null; + + beatmapTitle.Text = "Changing map"; + beatmapDash.Text = beatmapArtist.Text = beatmapAuthor.Text = string.Empty; + } + } + + private void displayMaxParticipants(int? value) + { + if (value == null) + { + participantsSlash.FadeOut(100); + maxParticipants.FadeOut(100); + } + else + { + participantsSlash.FadeIn(100); + maxParticipants.FadeIn(100); + maxParticipants.Text = value.ToString(); + } + } + + private void displayParticipants(User[] value) + { + participants.Text = value.Length.ToString(); + + var ranks = value.Select(u => u.GlobalRank); + levelRangeLower.Text = ranks.Min().ToString(); + levelRangeHigher.Text = ranks.Max().ToString(); + + participantsFlow.Children = value.Select(u => new UserTile(u)); + } + + private class UserTile : Container, IHasTooltip + { + private readonly User user; + + public string TooltipText => user.Username; + + public UserTile(User user) + { + this.user = user; + Size = new Vector2(70f); + CornerRadius = 5f; + Masking = true; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"27252d"), + }, + new UpdateableAvatar + { + RelativeSizeAxes = Axes.Both, + User = user, + }, + }; + } + } + } +} diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 93933c8fe9..8c5ab29736 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -22,6 +22,10 @@ namespace osu.Game.Users public Bindable Status = new Bindable(); + public int GlobalRank; + + public int CountryRank; + //public Team Team; [JsonProperty(@"profile_colour")] diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0ec0624978..d233d1e28b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -452,6 +452,7 @@ +