diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 8fd8880fd6..bcebf0a8d9 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index e0e6332ef0..c1253e4f5c 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -10,8 +8,9 @@ using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Multi.Components; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; using osuTK.Input; @@ -20,12 +19,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseLounge : ManualInputManagerTestCase { - private TestLounge lounge; + private TestLoungeScreen loungeScreen; [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - lounge = new TestLounge(); + loungeScreen = new TestLoungeScreen(); Room[] rooms = { @@ -159,52 +158,45 @@ namespace osu.Game.Tests.Visual }, }; - AddStep(@"show", () => Add(lounge)); - AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddStep(@"show", () => Add(loungeScreen)); selectAssert(0); - AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); - AddAssert(@"no room selected", () => lounge.SelectedRoom == null); - AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddAssert(@"no room selected", () => loungeScreen.SelectedRoom == null); selectAssert(1); AddStep(@"open room 1", () => clickRoom(1)); - AddUntilStep(() => lounge.ChildScreen?.IsCurrentScreen == true, "wait until room current"); - AddStep(@"make lounge current", lounge.MakeCurrent); + AddUntilStep(() => loungeScreen.ChildScreen?.IsCurrentScreen == true, "wait until room current"); + AddStep(@"make lounge current", loungeScreen.MakeCurrent); filterAssert(@"THE FINAL", LoungeTab.Public, 1); filterAssert(string.Empty, LoungeTab.Public, 2); filterAssert(string.Empty, LoungeTab.Private, 1); filterAssert(string.Empty, LoungeTab.Public, 2); filterAssert(@"no matches", LoungeTab.Public, 0); - AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); - AddStep(@"set rooms", () => lounge.Rooms = rooms); - AddAssert(@"no matches after clear", () => !lounge.ChildRooms.Any()); filterAssert(string.Empty, LoungeTab.Public, 2); - AddStep(@"exit", lounge.Exit); + AddStep(@"exit", loungeScreen.Exit); } private void clickRoom(int n) { - InputManager.MoveMouseTo(lounge.ChildRooms.ElementAt(n)); InputManager.Click(MouseButton.Left); } private void selectAssert(int n) { AddStep($@"select room {n}", () => clickRoom(n)); - AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms.ElementAt(n).Room); } private void filterAssert(string filter, LoungeTab tab, int endCount) { - AddStep($@"filter '{filter}', {tab}", () => lounge.SetFilter(filter, tab)); - AddAssert(@"filtered correctly", () => lounge.ChildRooms.Count() == endCount); + AddStep($@"filter '{filter}', {tab}", () => loungeScreen.SetFilter(filter, tab)); } - private class TestLounge : Lounge + private class TestLoungeScreen : LoungeScreen { protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); - public IEnumerable ChildRooms => RoomsContainer.Children.Where(r => r.MatchingFilter); - public Room SelectedRoom => Inspector.Room; + [Resolved] + private RoomManager manager { get; set; } + + public Room SelectedRoom => manager.Current.Value; public void SetFilter(string filter, LoungeTab tab) { diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index bb22358425..fd4806ac90 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -1,12 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -14,6 +17,13 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseMatch : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TestCaseMatch), + typeof(GameTypePicker), + typeof(RoomSettingsOverlay) + }; + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { @@ -86,9 +96,9 @@ namespace osu.Game.Tests.Visual }, }; - Match match = new Match(room); + MatchScreen matchScreen = new MatchScreen(room); - AddStep(@"show", () => Add(match)); + AddStep(@"show", () => Add(matchScreen)); AddStep(@"null beatmap", () => room.Beatmap.Value = null); AddStep(@"change name", () => room.Name.Value = @"Two Awesome Rooms"); AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); @@ -136,7 +146,7 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"exit", match.Exit); + AddStep(@"exit", matchScreen.Exit); } } } diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs deleted file mode 100644 index 34f98f97c2..0000000000 --- a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Screens.Multi.Screens.Match; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseMatchHeader : OsuTestCase - { - public TestCaseMatchHeader() - { - Header header = new Header(); - Add(header); - - AddStep(@"set beatmap set", () => header.BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/760757/covers/cover.jpg?1526944540", - }, - }, - }); - - AddStep(@"change beatmap set", () => header.BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/761883/covers/cover.jpg?1525557400", - }, - }, - }); - - AddStep(@"null beatmap set", () => header.BeatmapSet = null); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 205da6932f..37b3f6030d 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -6,7 +6,7 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match.Components; namespace osu.Game.Tests.Visual { @@ -19,10 +19,10 @@ namespace osu.Game.Tests.Visual Info info = new Info(); Add(info); - AddStep(@"set name", () => info.Name = @"Room Name?"); - AddStep(@"set availability", () => info.Availability = RoomAvailability.FriendsOnly); - AddStep(@"set status", () => info.Status = new RoomStatusPlaying()); - AddStep(@"set beatmap", () => info.Beatmap = new BeatmapInfo + AddStep(@"set name", () => info.Name.Value = @"Room Name?"); + AddStep(@"set availability", () => info.Availability.Value = RoomAvailability.FriendsOnly); + AddStep(@"set status", () => info.Status.Value = new RoomStatusPlaying()); + AddStep(@"set beatmap", () => info.Beatmap.Value = new BeatmapInfo { StarDifficulty = 2.4, Ruleset = rulesets.GetRuleset(0), @@ -34,14 +34,14 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set type", () => info.Type = new GameTypeTagTeam()); + AddStep(@"set type", () => info.Type.Value = new GameTypeTagTeam()); - AddStep(@"change name", () => info.Name = @"Room Name!"); - AddStep(@"change availability", () => info.Availability = RoomAvailability.InviteOnly); - AddStep(@"change status", () => info.Status = new RoomStatusOpen()); - AddStep(@"null beatmap", () => info.Beatmap = null); - AddStep(@"change type", () => info.Type = new GameTypeTeamVersus()); - AddStep(@"change beatmap", () => info.Beatmap = new BeatmapInfo + AddStep(@"change name", () => info.Name.Value = @"Room Name!"); + AddStep(@"change availability", () => info.Availability.Value = RoomAvailability.InviteOnly); + AddStep(@"change status", () => info.Status.Value = new RoomStatusOpen()); + AddStep(@"null beatmap", () => info.Beatmap.Value = null); + AddStep(@"change type", () => info.Type.Value = new GameTypeTeamVersus()); + AddStep(@"change beatmap", () => info.Beatmap.Value = new BeatmapInfo { StarDifficulty = 4.2, Ruleset = rulesets.GetRuleset(3), diff --git a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs index d6ae07252b..67a56e525f 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -19,8 +19,8 @@ namespace osu.Game.Tests.Visual RelativeSizeAxes = Axes.Both, }); - AddStep(@"set max to null", () => participants.Max = null); - AddStep(@"set users", () => participants.Users = new[] + AddStep(@"set max to null", () => participants.MaxParticipants.Value = null); + AddStep(@"set users", () => participants.Users.Value = new[] { new User { @@ -48,9 +48,9 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set max", () => participants.Max = 10); - AddStep(@"clear users", () => participants.Users = new User[] { }); - AddStep(@"set max to null", () => participants.Max = null); + AddStep(@"set max", () => participants.MaxParticipants.Value = 10); + AddStep(@"clear users", () => participants.Users.Value = new User[] { }); + AddStep(@"set max to null", () => participants.MaxParticipants.Value = null); } } } diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index d27a447077..e416000f31 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi.Lounge; namespace osu.Game.Tests.Visual { @@ -13,14 +13,14 @@ namespace osu.Game.Tests.Visual { public TestCaseMultiHeader() { - Lounge lounge; + LoungeScreen loungeScreen; Children = new Drawable[] { - lounge = new Lounge + loungeScreen = new LoungeScreen { Padding = new MarginPadding { Top = Header.HEIGHT }, }, - new Header(lounge), + new Header(loungeScreen), }; } } diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs index 6c22fb020f..c65ab4e3e3 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -1,14 +1,25 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Tests.Visual { [TestFixture] public class TestCaseMultiScreen : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Multiplayer), + typeof(LoungeScreen), + typeof(FilterControl) + }; + public TestCaseMultiScreen() { Multiplayer multi = new Multiplayer(); diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 06b9c4a6f9..9f6eea68e7 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -66,8 +66,7 @@ namespace osu.Game.Tests.Visual } }; - RoomInspector inspector; - Add(inspector = new RoomInspector + Add(new RoomInspector { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -75,9 +74,6 @@ namespace osu.Game.Tests.Visual Width = 0.5f, }); - AddStep(@"set room", () => inspector.Room = room); - AddStep(@"null room", () => inspector.Room = null); - AddStep(@"set room", () => inspector.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()); @@ -133,8 +129,6 @@ namespace osu.Game.Tests.Visual } } }; - - inspector.Room = newRoom; }); } diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index 40742ce709..19e27ddefe 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -1,11 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing.Input; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Screens.Match.Settings; +using osu.Game.Screens.Multi.Match.Components; using osuTK.Input; namespace osu.Game.Tests.Visual @@ -13,6 +16,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseRoomSettings : ManualInputManagerTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RoomSettingsOverlay), + typeof(GameTypePicker) + }; + private readonly Room room; private readonly TestRoomSettingsOverlay overlay; @@ -26,13 +35,13 @@ namespace osu.Game.Tests.Visual MaxParticipants = { Value = 10 }, }; - Add(overlay = new TestRoomSettingsOverlay(room) + Add(overlay = new TestRoomSettingsOverlay { RelativeSizeAxes = Axes.Both, Height = 0.75f, + State = Visibility.Visible }); - AddStep(@"show", overlay.Show); assertAll(); AddStep(@"set name", () => overlay.CurrentName = @"Two Testing Room"); AddStep(@"set max", () => overlay.CurrentMaxParticipants = null); @@ -105,10 +114,6 @@ namespace osu.Game.Tests.Visual set => TypePicker.Current.Value = value; } - public TestRoomSettingsOverlay(Room room) : base(room) - { - } - public void ClickApplyButton(ManualInputManager inputManager) { inputManager.MoveMouseTo(ApplyButton); diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs new file mode 100644 index 0000000000..5ced21e436 --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Beatmaps.Drawables +{ + public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable + { + public readonly IBindable Beatmap = new Bindable(); + + [Resolved] + private OsuGameBase game { get; set; } + + public UpdateableBeatmapBackgroundSprite() + { + Beatmap.BindValueChanged(b => Schedule(() => Model = b)); + } + + protected override Drawable CreateDrawable(WorkingBeatmap model) + { + Drawable drawable = model == null ? (Drawable)new DefaultSprite() : new BeatmapBackgroundSprite(model); + + drawable.RelativeSizeAxes = Axes.Both; + drawable.Anchor = Anchor.Centre; + drawable.Origin = Anchor.Centre; + drawable.FillMode = FillMode.Fill; + + return drawable; + } + + protected override double FadeDuration => 400; + + private class DefaultSprite : Sprite + { + [Resolved] + private IBindableBeatmap gameBeatmap { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + Texture = gameBeatmap.Default.Background; + } + } + } +} diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 54a2ea47f9..795fe7caf4 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -62,7 +62,7 @@ namespace osu.Game.Graphics.Containers public void AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) { - AddInternal(new DrawableLinkCompiler(AddText(text, creationParameters).ToList()) + AddInternal(new DrawableLinkCompiler(AddText(text, creationParameters).OfType().ToList()) { TooltipText = tooltipText ?? (url != text ? url : string.Empty), Action = () => diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs index 8d39e8f59d..8c9d635eea 100644 --- a/osu.Game/Online/Multiplayer/GameType.cs +++ b/osu.Game/Online/Multiplayer/GameType.cs @@ -13,6 +13,7 @@ namespace osu.Game.Online.Multiplayer public abstract class GameType { public abstract string Name { get; } + public abstract Drawable GetIcon(OsuColour colours, float size); public override int GetHashCode() => GetType().GetHashCode(); @@ -22,6 +23,7 @@ namespace osu.Game.Online.Multiplayer public class GameTypeTag : GameType { public override string Name => "Tag"; + public override Drawable GetIcon(OsuColour colours, float size) { return new SpriteIcon @@ -39,6 +41,7 @@ namespace osu.Game.Online.Multiplayer 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) @@ -52,6 +55,7 @@ namespace osu.Game.Online.Multiplayer public class GameTypeTagTeam : GameType { public override string Name => "Tag Team"; + public override Drawable GetIcon(OsuColour colours, float size) { return new FillFlowContainer @@ -85,6 +89,7 @@ namespace osu.Game.Online.Multiplayer public class GameTypeTeamVersus : GameType { public override string Name => "Team Versus"; + public override Drawable GetIcon(OsuColour colours, float size) { return new FillFlowContainer @@ -146,4 +151,20 @@ namespace osu.Game.Online.Multiplayer }; } } + + public class GameTypeTimeshift : GameType + { + public override string Name => "Timeshift"; + + public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.fa_osu_charts, + X = -2, // The icon is off-centre + Size = new Vector2(size), + Colour = colours.Blue, + Shadow = false + }; + } } diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index b076afbcdb..67ddb60823 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Users; @@ -10,13 +11,15 @@ namespace osu.Game.Online.Multiplayer { public class Room { - public Bindable Name = new Bindable(); + public Bindable Name = new Bindable("My awesome room!"); public Bindable Host = new Bindable(); - public Bindable Status = new Bindable(); + public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); - public Bindable Type = new Bindable(); + public Bindable Type = new Bindable(new GameTypeTimeshift()); public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); - public Bindable> Participants = new Bindable>(); + public Bindable> Participants = new Bindable>(Enumerable.Empty()); + + public Bindable Created = new Bindable(); } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 2729676504..28d5c557bc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -259,7 +259,7 @@ namespace osu.Game RegisterAudioManager(audioManager); } - private OsuBindableBeatmap(WorkingBeatmap defaultValue) + public OsuBindableBeatmap(WorkingBeatmap defaultValue) : base(defaultValue) { } diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 40a395535d..b4828e41f6 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -110,7 +111,7 @@ namespace osu.Game.Overlays.Music { sprite.TextSize = 16; sprite.Font = @"Exo2.0-Regular"; - }); + }).OfType(); text.AddText(artistBind.Value, sprite => { diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index ae1f27610b..943dfa53af 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -17,7 +17,9 @@ using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Input; using osu.Game.Input.Bindings; +using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -90,7 +92,7 @@ namespace osu.Game.Screens.Menu buttonArea.Flow.CentreTarget = iconFacade; buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.fa_user, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P)); - buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), () => OnMulti?.Invoke(), 0, Key.M)); + buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), onMulti, 0, Key.M)); buttonsPlay.Add(new Button(@"chart", @"button-generic-select", FontAwesome.fa_osu_charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke())); buttonsPlay.ForEach(b => b.VisibleState = ButtonSystemState.Play); @@ -103,19 +105,40 @@ namespace osu.Game.Screens.Menu buttonArea.AddRange(buttonsTopLevel); } - private OsuGame game; + [Resolved] + private OsuGame game { get; set; } + + [Resolved] + private APIAccess api { get; set; } + + [Resolved] + private NotificationOverlay notifications { get; set; } [BackgroundDependencyLoader(true)] - private void load(AudioManager audio, OsuGame game, IdleTracker idleTracker) + private void load(AudioManager audio, IdleTracker idleTracker) { - this.game = game; - isIdle.ValueChanged += updateIdleState; + if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); sampleBack = audio.Sample.Get(@"Menu/button-back-select"); } + private void onMulti() + { + if (!api.IsLoggedIn) + { + notifications.Post(new SimpleNotification + { + Text = "You gotta be logged in to multi 'yo!", + Icon = FontAwesome.fa_globe + }); + + return; + } + OnMulti?.Invoke(); + } + private void updateIdleState(bool isIdle) { if (isIdle && State != ButtonSystemState.Exit) diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index 6dc59f5cac..e3ef5eb401 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; @@ -9,7 +10,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Multi.Components { - public class BeatmapTitle : FillFlowContainer + public class BeatmapTitle : CompositeDrawable { private readonly OsuSpriteText beatmapTitle, beatmapDash, beatmapArtist; @@ -18,31 +19,25 @@ namespace osu.Game.Screens.Multi.Components set { beatmapTitle.TextSize = beatmapDash.TextSize = beatmapArtist.TextSize = value; } } - private BeatmapInfo beatmap; - - public BeatmapInfo Beatmap - { - set - { - if (value == beatmap) return; - beatmap = value; - - if (IsLoaded) - updateText(); - } - } + public readonly Bindable Beatmap = new Bindable(); public BeatmapTitle() { AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - Children = new[] + InternalChild = new FillFlowContainer { - beatmapTitle = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, - beatmapDash = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, - beatmapArtist = new OsuSpriteText { Font = @"Exo2.0-RegularItalic", }, + 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", }, + } }; + + Beatmap.BindValueChanged(v => updateText()); } protected override void LoadComplete() @@ -53,16 +48,19 @@ namespace osu.Game.Screens.Multi.Components private void updateText() { - if (beatmap == null) + if (!IsLoaded) + return; + + if (Beatmap.Value == null) { beatmapTitle.Text = "Changing map"; beatmapDash.Text = beatmapArtist.Text = string.Empty; } else { - beatmapTitle.Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)); + beatmapTitle.Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)); beatmapDash.Text = @" - "; - beatmapArtist.Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)); + beatmapArtist.Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)); } } } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index a22e171275..2bd7b19a0a 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -12,53 +13,55 @@ using osuTK; namespace osu.Game.Screens.Multi.Components { - public class BeatmapTypeInfo : FillFlowContainer + public class BeatmapTypeInfo : CompositeDrawable { - private readonly ModeTypeInfo modeTypeInfo; - private readonly BeatmapTitle beatmapTitle; private readonly OsuSpriteText beatmapAuthor; - public BeatmapInfo Beatmap - { - set - { - modeTypeInfo.Beatmap = beatmapTitle.Beatmap = value; - beatmapAuthor.Text = value == null ? string.Empty : $"mapped by {value.Metadata.Author}"; - } - } + public readonly Bindable Beatmap = new Bindable(); - public GameType Type - { - set { modeTypeInfo.Type = value; } - } + public readonly Bindable Type = new Bindable(); public BeatmapTypeInfo() { AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - LayoutDuration = 100; - Spacing = new Vector2(5f, 0f); - Children = new Drawable[] + BeatmapTitle beatmapTitle; + ModeTypeInfo modeTypeInfo; + + InternalChild = new FillFlowContainer { - modeTypeInfo = new ModeTypeInfo(), - new Container + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + LayoutDuration = 100, + Spacing = new Vector2(5, 0), + Children = new Drawable[] { - AutoSizeAxes = Axes.X, - Height = 30, - Margin = new MarginPadding { Left = 5 }, - Children = new Drawable[] + modeTypeInfo = new ModeTypeInfo(), + new Container { - beatmapTitle = new BeatmapTitle(), - beatmapAuthor = new OsuSpriteText + AutoSizeAxes = Axes.X, + Height = 30, + Margin = new MarginPadding { Left = 5 }, + Children = new Drawable[] { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - TextSize = 14, + beatmapTitle = new BeatmapTitle(), + beatmapAuthor = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + TextSize = 14, + }, }, }, - }, + } }; + + modeTypeInfo.Beatmap.BindTo(Beatmap); + modeTypeInfo.Type.BindTo(Type); + + beatmapTitle.Beatmap.BindTo(Beatmap); + + Beatmap.BindValueChanged(v => beatmapAuthor.Text = v == null ? string.Empty : $"mapped by {v.Metadata.Author}"); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs new file mode 100644 index 0000000000..fdc2fd578d --- /dev/null +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osuTK.Graphics; + +namespace osu.Game.Screens.Multi.Components +{ + public abstract class DisableableTabControl : TabControl + { + public readonly BindableBool ReadOnly = new BindableBool(); + + protected override void AddTabItem(TabItem tab, bool addToDropdown = true) + { + if (tab is DisableableTabItem disableable) + disableable.ReadOnly.BindTo(ReadOnly); + base.AddTabItem(tab, addToDropdown); + } + + protected abstract class DisableableTabItem : TabItem + { + public readonly BindableBool ReadOnly = new BindableBool(); + + protected DisableableTabItem(T value) + : base(value) + { + ReadOnly.BindValueChanged(updateReadOnly); + } + + private void updateReadOnly(bool readOnly) + { + Colour = readOnly ? Color4.Gray : Color4.White; + } + + protected override bool OnClick(ClickEvent e) + { + if (ReadOnly) + return true; + return base.OnClick(e); + } + } + } +} diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 95f0c2153d..87d150c5a4 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -10,74 +11,54 @@ using osuTK; namespace osu.Game.Screens.Multi.Components { - public class ModeTypeInfo : Container + public class ModeTypeInfo : CompositeDrawable { private const float height = 30; private const float transition_duration = 100; - private readonly Container rulesetContainer, gameTypeContainer; + private readonly Container rulesetContainer; - public BeatmapInfo Beatmap - { - set - { - if (value != null) - { - rulesetContainer.FadeIn(transition_duration); - rulesetContainer.Children = new[] - { - new DifficultyIcon(value) - { - Size = new Vector2(height), - }, - }; - } - else - { - rulesetContainer.FadeOut(transition_duration); - } - } - } - - public GameType Type - { - set - { - gameTypeContainer.Children = new[] - { - new DrawableGameType(value) - { - Size = new Vector2(height), - }, - }; - } - } + public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Type = new Bindable(); public ModeTypeInfo() { AutoSizeAxes = Axes.Both; - Children = new[] + Container gameTypeContainer; + + InternalChild = new FillFlowContainer { - new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + LayoutDuration = 100, + Children = new[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - LayoutDuration = 100, - Children = new[] + rulesetContainer = new Container { - rulesetContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, - gameTypeContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, + AutoSizeAxes = Axes.Both, + }, + gameTypeContainer = new Container + { + AutoSizeAxes = Axes.Both, }, }, }; + + Beatmap.BindValueChanged(updateBeatmap); + Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }); + } + + private void updateBeatmap(BeatmapInfo beatmap) + { + if (beatmap != null) + { + rulesetContainer.FadeIn(transition_duration); + rulesetContainer.Child = new DifficultyIcon(beatmap) { Size = new Vector2(height) }; + } + else + rulesetContainer.FadeOut(transition_duration); } } } diff --git a/osu.Game/Screens/Multi/Components/ParticipantCount.cs b/osu.Game/Screens/Multi/Components/ParticipantCount.cs index e7183cbd92..66f13ed683 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantCount.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantCount.cs @@ -1,69 +1,65 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Users; namespace osu.Game.Screens.Multi.Components { - public class ParticipantCount : FillFlowContainer + public class ParticipantCount : CompositeDrawable { private const float text_size = 30; private const float transition_duration = 100; - private readonly OsuSpriteText count, slash, maxText; + private readonly OsuSpriteText slash, maxText; - public int Count - { - set => count.Text = value.ToString(); - } - - private int? max; - public int? Max - { - get => max; - set - { - if (value == max) return; - max = value; - - updateMax(); - } - } + public readonly Bindable> Participants = new Bindable>(); + public readonly Bindable MaxParticipants = new Bindable(); public ParticipantCount() { AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - LayoutDuration = transition_duration; - Children = new[] + OsuSpriteText count; + + InternalChild = new FillFlowContainer { - count = new OsuSpriteText + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + LayoutDuration = transition_duration, + Children = new[] { - TextSize = text_size, - Font = @"Exo2.0-Bold" - }, - slash = new OsuSpriteText - { - Text = @"/", - TextSize = text_size, - Font = @"Exo2.0-Light" - }, - maxText = new OsuSpriteText - { - TextSize = text_size, - Font = @"Exo2.0-Light" - }, + count = new OsuSpriteText + { + TextSize = text_size, + Font = @"Exo2.0-Bold" + }, + slash = new OsuSpriteText + { + Text = @"/", + TextSize = text_size, + Font = @"Exo2.0-Light" + }, + maxText = new OsuSpriteText + { + TextSize = text_size, + Font = @"Exo2.0-Light" + }, + } }; - updateMax(); + Participants.BindValueChanged(v => count.Text = v.Count().ToString()); + MaxParticipants.BindValueChanged(_ => updateMax(), true); } private void updateMax() { - if (Max == null) + if (MaxParticipants.Value == null) { slash.FadeOut(transition_duration); maxText.FadeOut(transition_duration); @@ -71,7 +67,7 @@ namespace osu.Game.Screens.Multi.Components else { slash.FadeIn(transition_duration); - maxText.Text = Max.ToString(); + maxText.Text = MaxParticipants.Value.ToString(); maxText.FadeIn(transition_duration); } } diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 6bd300eadc..8e5a7381e9 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -10,7 +10,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Screens; using osuTK; using osuTK.Graphics; @@ -86,7 +85,7 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type.ToLowerInvariant(); + breadcrumbs.Current.ValueChanged += s => screenType.Text = ((IMultiplayerScreen)s).ShortTitle.ToLowerInvariant(); breadcrumbs.Current.TriggerChange(); } diff --git a/osu.Game/Screens/Multi/IMultiplayerScreen.cs b/osu.Game/Screens/Multi/IMultiplayerScreen.cs new file mode 100644 index 0000000000..c1f43fa30d --- /dev/null +++ b/osu.Game/Screens/Multi/IMultiplayerScreen.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Screens.Multi +{ + public interface IMultiplayerScreen + { + string ShortTitle { get; } + } +} diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs similarity index 86% rename from osu.Game/Screens/Multi/Components/DrawableRoom.cs rename to osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 05ec2f0fac..57ce9fc0b9 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -10,7 +10,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; @@ -18,11 +17,12 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Lounge.Components { public class DrawableRoom : OsuClickableContainer, IStateful, IFilterable { @@ -34,15 +34,22 @@ namespace osu.Game.Screens.Multi.Components private const float side_strip_width = 5; private const float cover_width = 145; + public event Action StateChanged; + private readonly Box selectionBox; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly Bindable beatmap = new Bindable(); + + [Resolved] + private BeatmapManager beatmaps { get; set; } + public readonly Room Room; private SelectionState state; @@ -76,19 +83,6 @@ namespace osu.Game.Screens.Multi.Components } } - private Action action; - public new Action Action - { - get { return action; } - set - { - action = value; - Enabled.Value = action != null; - } - } - - public event Action StateChanged; - public DrawableRoom(Room room) { Room = room; @@ -110,11 +104,12 @@ namespace osu.Game.Screens.Multi.Components private void load(OsuColour colours) { Box sideStrip; - UpdateableBeatmapSetCover cover; - OsuSpriteText name, status; + UpdateableBeatmapBackgroundSprite background; + OsuSpriteText status; ParticipantInfo participantInfo; BeatmapTitle beatmapTitle; ModeTypeInfo modeTypeInfo; + OsuSpriteText name; Children = new Drawable[] { @@ -146,12 +141,13 @@ namespace osu.Game.Screens.Multi.Components RelativeSizeAxes = Axes.Y, Width = side_strip_width, }, - cover = new UpdateableBeatmapSetCover + new Container { - Width = cover_width, RelativeSizeAxes = Axes.Y, + Width = cover_width, Masking = true, Margin = new MarginPadding { Left = side_strip_width }, + Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } }, new Container { @@ -172,10 +168,7 @@ namespace osu.Game.Screens.Multi.Components Spacing = new Vector2(5f), Children = new Drawable[] { - name = new OsuSpriteText - { - TextSize = 18, - }, + name = new OsuSpriteText { TextSize = 18 }, participantInfo = new ParticipantInfo(), }, }, @@ -212,11 +205,6 @@ namespace osu.Game.Screens.Multi.Components }, }; - nameBind.ValueChanged += n => name.Text = n; - hostBind.ValueChanged += h => participantInfo.Host = h; - typeBind.ValueChanged += m => modeTypeInfo.Type = m; - participantsBind.ValueChanged += p => participantInfo.Participants = p; - statusBind.ValueChanged += s => { status.Text = s.Message; @@ -225,12 +213,10 @@ namespace osu.Game.Screens.Multi.Components d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }; - beatmapBind.ValueChanged += b => - { - cover.BeatmapSet = b?.BeatmapSet; - beatmapTitle.Beatmap = b; - modeTypeInfo.Beatmap = b; - }; + background.Beatmap.BindTo(beatmap); + + beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); + nameBind.BindValueChanged(n => name.Text = n); nameBind.BindTo(Room.Name); hostBind.BindTo(Room.Host); @@ -238,6 +224,14 @@ namespace osu.Game.Screens.Multi.Components typeBind.BindTo(Room.Type); beatmapBind.BindTo(Room.Beatmap); participantsBind.BindTo(Room.Participants); + + modeTypeInfo.Beatmap.BindTo(beatmapBind); + modeTypeInfo.Type.BindTo(typeBind); + + participantInfo.Host.BindTo(hostBind); + participantInfo.Participants.BindTo(participantsBind); + + beatmapTitle.Beatmap.BindTo(beatmapBind); } protected override void LoadComplete() @@ -245,16 +239,5 @@ namespace osu.Game.Screens.Multi.Components base.LoadComplete(); this.FadeInFromZero(transition_duration); } - - protected override bool OnClick(ClickEvent e) - { - if (Enabled.Value) - { - Action?.Invoke(this); - State = SelectionState.Selected; - } - - return true; - } } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs similarity index 51% rename from osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs rename to osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 69cb6ad349..ddab9c197e 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -6,7 +6,7 @@ using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Lounge +namespace osu.Game.Screens.Multi.Lounge.Components { public class FilterControl : SearchableListFilterControl { @@ -17,11 +17,29 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { DisplayStyleControl.Hide(); } + + public FilterCriteria CreateCriteria() => new FilterCriteria { Availability = availability }; + + private RoomAvailability availability + { + get + { + switch (Tabs.Current.Value) + { + default: + case LoungeTab.Public: + return RoomAvailability.Public; + case LoungeTab.Private: + return RoomAvailability.FriendsOnly; + } + } + } } public enum LoungeTab { - Public = RoomAvailability.Public, - Private = RoomAvailability.FriendsOnly, + Create, + Public, + Private, } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs new file mode 100644 index 0000000000..ec62ef1bdf --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public class FilterCriteria + { + public RoomAvailability Availability; + } +} diff --git a/osu.Game/Screens/Multi/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs similarity index 86% rename from osu.Game/Screens/Multi/Components/ParticipantInfo.cs rename to osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index b1c77a04af..3bc20b58c5 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -12,40 +13,25 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Lounge.Components { public class ParticipantInfo : Container { - private readonly Container flagContainer; private readonly OsuSpriteText host; private readonly FillFlowContainer levelRangeContainer; - private readonly OsuSpriteText levelRangeLower; - private readonly OsuSpriteText levelRangeHigher; - public User Host - { - set - { - host.Text = value.Username; - flagContainer.Children = new[] { new DrawableFlag(value.Country) { RelativeSizeAxes = Axes.Both } }; - } - } - - public IEnumerable Participants - { - set - { - var ranks = value.Select(u => u.Statistics.Ranks.Global); - levelRangeLower.Text = ranks.Min().ToString(); - levelRangeHigher.Text = ranks.Max().ToString(); - } - } + public readonly Bindable Host = new Bindable(); + public readonly Bindable> Participants = new Bindable>(); public ParticipantInfo(string rankPrefix = null) { RelativeSizeAxes = Axes.X; Height = 15f; + OsuSpriteText levelRangeHigher; + OsuSpriteText levelRangeLower; + Container flagContainer; + Children = new Drawable[] { new FillFlowContainer @@ -133,6 +119,19 @@ namespace osu.Game.Screens.Multi.Components }, }, }; + + Host.BindValueChanged(v => + { + host.Text = v.Username; + flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; + }); + + Participants.BindValueChanged(v => + { + var ranks = v.Select(u => u.Statistics.Ranks.Global); + levelRangeLower.Text = ranks.Min().ToString(); + levelRangeHigher.Text = ranks.Max().ToString(); + }); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs similarity index 80% rename from osu.Game/Screens/Multi/Components/RoomInspector.cs rename to osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 1ec509d5a8..e8de201b8f 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -17,28 +17,33 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Lounge.Components { public class RoomInspector : Container { private const float transition_duration = 100; + public readonly Bindable Room = new Bindable(); + private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly Bindable beatmap = new Bindable(); + private OsuColour colours; private Box statusStrip; - private UpdateableBeatmapSetCover cover; + private UpdateableBeatmapBackgroundSprite background; private ParticipantCount participantCount; private FillFlowContainer topFlow, participantsFlow; private OsuSpriteText name, status; @@ -46,37 +51,8 @@ namespace osu.Game.Screens.Multi.Components private ScrollContainer participantsScroll; private ParticipantInfo participantInfo; - private Room room; - public Room Room - { - get { return room; } - set - { - if (value == room) return; - room = value; - - nameBind.UnbindBindings(); - hostBind.UnbindBindings(); - statusBind.UnbindBindings(); - typeBind.UnbindBindings(); - beatmapBind.UnbindBindings(); - maxParticipantsBind.UnbindBindings(); - participantsBind.UnbindBindings(); - - if (room != null) - { - nameBind.BindTo(room.Name); - hostBind.BindTo(room.Host); - statusBind.BindTo(room.Status); - typeBind.BindTo(room.Type); - beatmapBind.BindTo(room.Beatmap); - maxParticipantsBind.BindTo(room.MaxParticipants); - participantsBind.BindTo(room.Participants); - } - - updateState(); - } - } + [Resolved] + private BeatmapManager beatmaps { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -104,10 +80,7 @@ namespace osu.Game.Screens.Multi.Components Masking = true, Children = new Drawable[] { - cover = new UpdateableBeatmapSetCover - { - RelativeSizeAxes = Axes.Both, - }, + background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, new Box { RelativeSizeAxes = Axes.Both, @@ -201,26 +174,69 @@ namespace osu.Game.Screens.Multi.Components }, }; - nameBind.ValueChanged += n => name.Text = n; - hostBind.ValueChanged += h => participantInfo.Host = h; - typeBind.ValueChanged += t => beatmapTypeInfo.Type = t; - maxParticipantsBind.ValueChanged += m => participantCount.Max = m; - statusBind.ValueChanged += displayStatus; + statusBind.BindValueChanged(displayStatus); + beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); + participantsBind.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); - beatmapBind.ValueChanged += b => + nameBind.BindValueChanged(n => name.Text = n); + + background.Beatmap.BindTo(beatmap); + + participantInfo.Host.BindTo(hostBind); + participantInfo.Participants.BindTo(participantsBind); + + participantCount.Participants.BindTo(participantsBind); + participantCount.MaxParticipants.BindTo(maxParticipantsBind); + + beatmapTypeInfo.Type.BindTo(typeBind); + beatmapTypeInfo.Beatmap.BindTo(beatmapBind); + + Room.BindValueChanged(updateRoom, true); + } + + private Room lastRoom; + + private void updateRoom(Room newRoom) + { + if (lastRoom != null) { - cover.BeatmapSet = b?.BeatmapSet; - beatmapTypeInfo.Beatmap = b; - }; + nameBind.UnbindFrom(lastRoom.Name); + hostBind.UnbindFrom(lastRoom.Host); + statusBind.UnbindFrom(lastRoom.Status); + typeBind.UnbindFrom(lastRoom.Type); + beatmapBind.UnbindFrom(lastRoom.Beatmap); + maxParticipantsBind.UnbindFrom(lastRoom.MaxParticipants); + participantsBind.UnbindFrom(lastRoom.Participants); + } - participantsBind.ValueChanged += p => + if (newRoom != null) { - participantCount.Count = p.Count(); - participantInfo.Participants = p; - participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); - }; + nameBind.BindTo(newRoom.Name); + hostBind.BindTo(newRoom.Host); + statusBind.BindTo(newRoom.Status); + typeBind.BindTo(newRoom.Type); + beatmapBind.BindTo(newRoom.Beatmap); + maxParticipantsBind.BindTo(newRoom.MaxParticipants); + participantsBind.BindTo(newRoom.Participants); - updateState(); + participantsFlow.FadeIn(transition_duration); + participantCount.FadeIn(transition_duration); + beatmapTypeInfo.FadeIn(transition_duration); + name.FadeIn(transition_duration); + participantInfo.FadeIn(transition_duration); + } + else + { + participantsFlow.FadeOut(transition_duration); + participantCount.FadeOut(transition_duration); + beatmapTypeInfo.FadeOut(transition_duration); + name.FadeOut(transition_duration); + participantInfo.FadeOut(transition_duration); + + displayStatus(new RoomStatusNoneSelected()); + } + + lastRoom = newRoom; } protected override void UpdateAfterChildren() @@ -239,32 +255,6 @@ namespace osu.Game.Screens.Multi.Components status.FadeColour(c, transition_duration); } - private void updateState() - { - if (Room == null) - { - cover.BeatmapSet = null; - participantsFlow.FadeOut(transition_duration); - participantCount.FadeOut(transition_duration); - beatmapTypeInfo.FadeOut(transition_duration); - name.FadeOut(transition_duration); - participantInfo.FadeOut(transition_duration); - - displayStatus(new RoomStatusNoneSelected()); - } - else - { - participantsFlow.FadeIn(transition_duration); - participantCount.FadeIn(transition_duration); - beatmapTypeInfo.FadeIn(transition_duration); - name.FadeIn(transition_duration); - participantInfo.FadeIn(transition_duration); - - statusBind.TriggerChange(); - beatmapBind.TriggerChange(); - } - } - private class UserTile : Container, IHasTooltip { private readonly User user; diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs new file mode 100644 index 0000000000..072a892954 --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -0,0 +1,104 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osuTK; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public class RoomsContainer : CompositeDrawable, IHasFilterableChildren + { + public Action OpenRequested; + + private readonly IBindableCollection rooms = new BindableCollection(); + private readonly Bindable currentRoom = new Bindable(); + + private readonly FillFlowContainer roomFlow; + + [Resolved] + private RoomManager manager { get; set; } + + public RoomsContainer() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChild = roomFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2), + }; + } + + [BackgroundDependencyLoader] + private void load() + { + currentRoom.BindTo(manager.Current); + rooms.BindTo(manager.Rooms); + + rooms.ItemsAdded += addRooms; + rooms.ItemsRemoved += removeRooms; + + addRooms(rooms); + + currentRoom.BindValueChanged(selectRoom, true); + } + + private FilterCriteria currentFilter; + + public void Filter(FilterCriteria criteria) + { + roomFlow.Children.ForEach(r => r.MatchingFilter = criteria == null || r.Room.Availability == criteria.Availability); + currentFilter = criteria; + } + + private void addRooms(IEnumerable rooms) + { + foreach (var r in rooms) + roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); + + Filter(currentFilter); + } + + private void removeRooms(IEnumerable rooms) + { + foreach (var r in rooms) + { + var toRemove = roomFlow.Single(d => d.Room == r); + toRemove.Action = null; + + roomFlow.Remove(toRemove); + } + } + + private void selectRoom(Room room) + { + var drawable = roomFlow.FirstOrDefault(r => r.Room == room); + + if (drawable != null && drawable.State == SelectionState.Selected) + OpenRequested?.Invoke(room); + else + { + currentRoom.Value = room; + roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected); + } + } + + public IEnumerable FilterTerms => Enumerable.Empty(); + + public IEnumerable FilterableChildren => InternalChildren.OfType(); + + public bool MatchingFilter { set { } } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs similarity index 53% rename from osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs rename to osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 0af941a668..1b49e0c1b3 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -1,62 +1,40 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Screens; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Components; -using osuTK; +using osu.Game.Screens.Multi.Lounge.Components; +using osu.Game.Screens.Multi.Match; -namespace osu.Game.Screens.Multi.Screens.Lounge +namespace osu.Game.Screens.Multi.Lounge { - public class Lounge : MultiplayerScreen + public class LoungeScreen : MultiplayerScreen { + protected readonly FilterControl Filter; + private readonly Container content; private readonly SearchContainer search; + private readonly RoomsContainer rooms; - protected readonly FilterControl Filter; - protected readonly FillFlowContainer RoomsContainer; - protected readonly RoomInspector Inspector; + [Cached] + private readonly RoomManager manager; public override string Title => "Lounge"; - protected override Container TransitionContent => content; + protected override Drawable TransitionContent => content; - private IEnumerable rooms; - public IEnumerable Rooms + public LoungeScreen() { - get { return rooms; } - set - { - if (Equals(value, rooms)) return; - rooms = value; + RoomInspector inspector; - var enumerable = rooms.ToList(); - - RoomsContainer.Children = enumerable.Select(r => new DrawableRoom(r) - { - Action = didSelect, - }).ToList(); - - if (!enumerable.Contains(Inspector.Room)) - Inspector.Room = null; - - filterRooms(); - } - } - - public Lounge() - { Children = new Drawable[] { - Filter = new FilterControl(), + Filter = new FilterControl { Depth = -1 }, content = new Container { RelativeSizeAxes = Axes.Both, @@ -75,16 +53,10 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = RoomsContainer = new RoomsFilterContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(10 - DrawableRoom.SELECTION_BORDER_WIDTH * 2), - }, + Child = rooms = new RoomsContainer { OpenRequested = openRoom } }, }, - Inspector = new RoomInspector + inspector = new RoomInspector { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -93,8 +65,11 @@ namespace osu.Game.Screens.Multi.Screens.Lounge }, }, }, + manager = new RoomManager() }; + inspector.Room.BindTo(manager.Current); + Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; @@ -132,6 +107,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override void OnResuming(Screen last) { base.OnResuming(last); + Filter.Search.HoldFocus = true; } @@ -143,49 +119,24 @@ namespace osu.Game.Screens.Multi.Screens.Lounge private void filterRooms() { + if (Filter.Tabs.Current.Value == LoungeTab.Create) + { + Filter.Tabs.Current.Value = LoungeTab.Public; + Push(new MatchScreen(new Room())); + } + search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; - foreach (DrawableRoom r in RoomsContainer.Children) - { - r.MatchingFilter = r.MatchingFilter && - r.Room.Availability.Value == (RoomAvailability)Filter.Tabs.Current.Value; - } + rooms.Filter(Filter.CreateCriteria()); } - private void didSelect(DrawableRoom room) + private void openRoom(Room room) { - RoomsContainer.Children.ForEach(c => - { - if (c != room) - c.State = SelectionState.NotSelected; - }); + // Handles the case where a room is clicked 3 times in quick succession + if (!IsCurrentScreen) + return; - Inspector.Room = room.Room; - - // open the room if its selected and is clicked again - if (room.State == SelectionState.Selected) - Push(new Match.Match(room.Room)); - } - - private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren - { - public IEnumerable FilterTerms => new string[] { }; - public IEnumerable FilterableChildren => Children; - - public bool MatchingFilter - { - set - { - if (value) - InvalidateLayout(); - } - } - - public RoomsFilterContainer() - { - LayoutDuration = 200; - LayoutEasing = Easing.OutQuint; - } + Push(new MatchScreen(room)); } } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Settings/GameTypePicker.cs b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs similarity index 91% rename from osu.Game/Screens/Multi/Screens/Match/Settings/GameTypePicker.cs rename to osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs index cd8b081b4e..aec26a751e 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Settings/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs @@ -12,14 +12,15 @@ using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Match.Settings +namespace osu.Game.Screens.Multi.Match.Components { - public class GameTypePicker : TabControl + 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 Dropdown CreateDropdown() => null; public GameTypePicker() @@ -31,15 +32,17 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings AddItem(new GameTypeVersus()); AddItem(new GameTypeTagTeam()); AddItem(new GameTypeTeamVersus()); + AddItem(new GameTypeTimeshift()); } - private class GameTypePickerItem : TabItem + private class GameTypePickerItem : DisableableTabItem { private const float transition_duration = 200; private readonly CircularContainer hover, selection; - public GameTypePickerItem(GameType value) : base(value) + public GameTypePickerItem(GameType value) + : base(value) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs similarity index 50% rename from osu.Game/Screens/Multi/Screens/Match/Header.cs rename to osu.Game/Screens/Multi/Match/Components/Header.cs index c2de50fa65..9c72403806 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -3,36 +3,31 @@ using System; 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.Shapes; -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; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class Header : Container { public const float HEIGHT = 200; + public readonly IBindable Beatmap = new Bindable(); + private readonly Box tabStrip; - private readonly UpdateableBeatmapSetCover cover; - public readonly PageTabControl Tabs; - - public BeatmapSetInfo BeatmapSet - { - set => cover.BeatmapSet = value; - } + public readonly MatchTabControl Tabs; public Action OnRequestSelectBeatmap; @@ -42,12 +37,14 @@ namespace osu.Game.Screens.Multi.Screens.Match Height = HEIGHT; BeatmapSelectButton beatmapButton; + UpdateableBeatmapBackgroundSprite background; Children = new Drawable[] { - cover = new UpdateableBeatmapSetCover + new Container { RelativeSizeAxes = Axes.Both, Masking = true, + Child = background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } }, new Box { @@ -77,19 +74,22 @@ namespace osu.Game.Screens.Multi.Screens.Match Child = beatmapButton = new BeatmapSelectButton { RelativeSizeAxes = Axes.Both, + Height = 1 }, }, - Tabs = new PageTabControl + Tabs = new MatchTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, + RelativeSizeAxes = Axes.X }, }, }, }; beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); + + background.Beatmap.BindTo(Beatmap); } [BackgroundDependencyLoader] @@ -98,87 +98,29 @@ namespace osu.Game.Screens.Multi.Screens.Match tabStrip.Colour = colours.Yellow; } - private class BeatmapSelectButton : OsuClickableContainer + private class BeatmapSelectButton : TriangleButton { - private const float corner_radius = 5; - private const float bg_opacity = 0.5f; - private const float transition_duration = 100; + private readonly IBindable createdBind = new Bindable(); - private readonly Box bg; - private readonly Container border; + [Resolved] + private Room room { get; set; } public BeatmapSelectButton() { - Masking = true; - CornerRadius = corner_radius; - - Children = new Drawable[] - { - bg = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = bg_opacity, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = @"Exo2.0-Bold", - Text = "Select Beatmap", - }, - border = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = corner_radius, - BorderThickness = 4, - Alpha = 0, - Child = new Box // needs a child to show the border - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - }, - }, - }; + Text = "Select beatmap"; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - border.BorderColour = colours.Yellow; - } - - protected override bool OnHover(HoverEvent e) - { - border.FadeIn(transition_duration); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - border.FadeOut(transition_duration); - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - bg.FadeTo(0.75f, 1000, Easing.Out); - return base.OnMouseDown(e); - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - bg.FadeTo(bg_opacity, transition_duration); - return base.OnMouseUp(e); + createdBind.BindTo(room.Created); + createdBind.BindValueChanged(v => Enabled.Value = !v, true); } } - } - public enum MatchHeaderPage - { - Settings, - Room, + private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double FadeDuration => 0; + } } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs similarity index 76% rename from osu.Game/Screens/Multi/Screens/Match/Info.cs rename to osu.Game/Screens/Multi/Match/Components/Info.cs index a2c056c8bd..b3de5abf67 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -17,66 +17,33 @@ using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Components; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class Info : Container { public const float HEIGHT = 128; - private readonly OsuSpriteText name, availabilityStatus; - private readonly BeatmapTypeInfo beatmapTypeInfo; + private readonly OsuSpriteText availabilityStatus; private readonly ReadyButton readyButton; private OsuColour colours; public Bindable Ready => readyButton.Ready; - public string Name - { - set { name.Text = value; } - } - - private RoomAvailability availability; - public RoomAvailability Availability - { - set - { - if (value == availability) return; - availability = value; - - if (IsLoaded) - updateAvailabilityStatus(); - } - } - - private RoomStatus status; - public RoomStatus Status - { - set - { - if (value == status) return; - status = value; - - if (IsLoaded) - updateAvailabilityStatus(); - } - } - - public BeatmapInfo Beatmap - { - set { beatmapTypeInfo.Beatmap = value; } - } - - public GameType Type - { - set { beatmapTypeInfo.Type = value; } - } + public readonly Bindable Name = new Bindable(); + public readonly Bindable Availability = new Bindable(); + public readonly Bindable Status = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Type = new Bindable(); public Info() { RelativeSizeAxes = Axes.X; Height = HEIGHT; + BeatmapTypeInfo beatmapTypeInfo; + OsuSpriteText name; + Children = new Drawable[] { new Box @@ -103,14 +70,8 @@ namespace osu.Game.Screens.Multi.Screens.Match Direction = FillDirection.Vertical, Children = new Drawable[] { - name = new OsuSpriteText - { - TextSize = 30, - }, - availabilityStatus = new OsuSpriteText - { - TextSize = 14, - }, + name = new OsuSpriteText { TextSize = 30 }, + availabilityStatus = new OsuSpriteText { TextSize = 14 }, }, }, beatmapTypeInfo = new BeatmapTypeInfo @@ -131,6 +92,13 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }, }; + + beatmapTypeInfo.Beatmap.BindTo(Beatmap); + beatmapTypeInfo.Type.BindTo(Type); + + Availability.BindValueChanged(_ => updateAvailabilityStatus()); + Status.BindValueChanged(_ => updateAvailabilityStatus()); + Name.BindValueChanged(n => name.Text = n); } [BackgroundDependencyLoader] @@ -148,10 +116,13 @@ namespace osu.Game.Screens.Multi.Screens.Match private void updateAvailabilityStatus() { - if (status != null) + if (!IsLoaded) + return; + + if (Status.Value != null) { - availabilityStatus.FadeColour(status.GetAppropriateColour(colours), 100); - availabilityStatus.Text = $"{availability.GetDescription()}, {status.Message}"; + availabilityStatus.FadeColour(Status.Value.GetAppropriateColour(colours), 100); + availabilityStatus.Text = $"{Availability.Value.GetDescription()}, {Status.Value.Message}"; } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs new file mode 100644 index 0000000000..54ba345934 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public abstract class MatchPage + { + public abstract string Name { get; } + + public readonly BindableBool Enabled = new BindableBool(true); + + public override string ToString() => Name; + public override int GetHashCode() => GetType().GetHashCode(); + public override bool Equals(object obj) => GetType() == obj?.GetType(); + } + + public class SettingsMatchPage : MatchPage + { + public override string Name => "Settings"; + } + + public class RoomMatchPage : MatchPage + { + public override string Name => "Room"; + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs new file mode 100644 index 0000000000..51698fa50f --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osuTK.Graphics; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class MatchTabControl : PageTabControl + { + private readonly IBindable created = new Bindable(); + + [Resolved] + private Room room { get; set; } + + public MatchTabControl() + { + AddItem(new SettingsMatchPage()); + AddItem(new RoomMatchPage()); + } + + [BackgroundDependencyLoader] + private void load() + { + created.BindTo(room.Created); + created.BindValueChanged(v => + { + if (v) + { + Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage)); + Current.Value = new RoomMatchPage(); + } + else + { + Items.ForEach(t => t.Enabled.Value = t is SettingsMatchPage); + Current.Value = new SettingsMatchPage(); + } + }, true); + } + + protected override TabItem CreateTabItem(MatchPage value) => new TabItem(value); + + private class TabItem : PageTabItem + { + private readonly IBindable enabled = new BindableBool(); + + public TabItem(MatchPage value) + : base(value) + { + enabled.BindTo(value.Enabled); + enabled.BindValueChanged(v => Colour = v ? Color4.White : Color4.Gray); + } + + protected override bool OnClick(ClickEvent e) + { + if (!enabled.Value) + return true; + return base.OnClick(e); + } + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs similarity index 71% rename from osu.Game/Screens/Multi/Screens/Match/Participants.cs rename to osu.Game/Screens/Multi/Match/Components/Participants.cs index 55541a1acd..92732dc045 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.SearchableList; @@ -10,36 +11,25 @@ using osu.Game.Screens.Multi.Components; using osu.Game.Users; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { - public class Participants : Container + public class Participants : CompositeDrawable { - private readonly ParticipantCount count; - private readonly FillFlowContainer usersFlow; + public readonly Bindable> Users = new Bindable>(); + public readonly Bindable MaxParticipants = new Bindable(); - public IEnumerable Users + public new MarginPadding Padding { - set { - usersFlow.Children = value.Select(u => new UserPanel(u) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 300, - OnLoadComplete = d => d.FadeInFromZero(60), - }).ToList(); - - count.Count = value.Count(); - } - } - - public int? Max - { - set => count.Max = value; + get => base.Padding; + set => base.Padding = value; } public Participants() { - Child = new Container + FillFlowContainer usersFlow; + ParticipantCount count; + + InternalChild = new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, @@ -69,6 +59,20 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }, }; + + count.Participants.BindTo(Users); + count.MaxParticipants.BindTo(MaxParticipants); + + Users.BindValueChanged(v => + { + usersFlow.Children = v.Select(u => new UserPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 300, + OnLoadComplete = d => d.FadeInFromZero(60), + }).ToList(); + }); } } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs similarity index 91% rename from osu.Game/Screens/Multi/Screens/Match/Settings/RoomAvailabilityPicker.cs rename to osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs index 251bd062ec..4ddc9b30e9 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs @@ -10,12 +10,13 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match.Settings +namespace osu.Game.Screens.Multi.Match.Components { - public class RoomAvailabilityPicker : TabControl + public class RoomAvailabilityPicker : DisableableTabControl { protected override TabItem CreateTabItem(RoomAvailability value) => new RoomAvailabilityPickerItem(value); protected override Dropdown CreateDropdown() => null; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings AddItem(RoomAvailability.InviteOnly); } - private class RoomAvailabilityPickerItem : TabItem + private class RoomAvailabilityPickerItem : DisableableTabItem { private const float transition_duration = 200; @@ -41,7 +42,7 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings public RoomAvailabilityPickerItem(RoomAvailability value) : base(value) { RelativeSizeAxes = Axes.Y; - Width = 120; + Width = 102; Masking = true; CornerRadius = 5; diff --git a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs similarity index 90% rename from osu.Game/Screens/Multi/Screens/Match/Settings/RoomSettingsOverlay.cs rename to osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index d45ba48f0e..e4eb2046b2 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -6,6 +6,7 @@ using osu.Framework.Configuration; 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.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -14,7 +15,7 @@ using osu.Game.Overlays.SearchableList; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match.Settings +namespace osu.Game.Screens.Multi.Match.Components { public class RoomSettingsOverlay : FocusedOverlayContainer { @@ -22,19 +23,28 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings private const float field_padding = 45; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Container content; + private readonly OsuSpriteText typeLabel; protected readonly OsuTextBox NameField, MaxParticipantsField; protected readonly RoomAvailabilityPicker AvailabilityPicker; protected readonly GameTypePicker TypePicker; protected readonly TriangleButton ApplyButton; + protected readonly OsuPasswordTextBox PasswordField; - public RoomSettingsOverlay(Room room) + [Resolved] + private RoomManager manager { get; set; } + + [Resolved] + private Room room { get; set; } + + public RoomSettingsOverlay() { Masking = true; @@ -114,11 +124,11 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings }, new Section("PASSWORD (OPTIONAL)") { - Child = new SettingsPasswordTextBox + Child = PasswordField = new SettingsPasswordTextBox { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), + OnCommit = (sender, text) => apply() }, }, }, @@ -142,19 +152,35 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings availabilityBind.ValueChanged += a => AvailabilityPicker.Current.Value = a; typeBind.ValueChanged += t => TypePicker.Current.Value = t; maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); - - nameBind.BindTo(room.Name); - availabilityBind.BindTo(room.Availability); - typeBind.BindTo(room.Type); - maxParticipantsBind.BindTo(room.MaxParticipants); } [BackgroundDependencyLoader] private void load(OsuColour colours) { typeLabel.Colour = colours.Yellow; + + nameBind.BindTo(room.Name); + beatmapBind.BindTo(room.Beatmap); + availabilityBind.BindTo(room.Availability); + typeBind.BindTo(room.Type); + maxParticipantsBind.BindTo(room.MaxParticipants); + + MaxParticipantsField.ReadOnly = true; + PasswordField.ReadOnly = true; + AvailabilityPicker.ReadOnly.Value = true; + TypePicker.ReadOnly.Value = true; + ApplyButton.Enabled.Value = false; } + protected override void Update() + { + base.Update(); + + ApplyButton.Enabled.Value = hasValidSettings; + } + + private bool hasValidSettings => NameField.Text.Length > 0 && beatmapBind.Value != null; + protected override void PopIn() { // reapply the rooms values if the overlay was completely closed @@ -185,7 +211,7 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings else maxParticipantsBind.Value = null; - Hide(); + manager.CreateRoom(room); } private class SettingsTextBox : OsuTextBox diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs similarity index 59% rename from osu.Game/Screens/Multi/Screens/Match/Match.cs rename to osu.Game/Screens/Multi/Match/MatchScreen.cs index f7d98df60e..755b071f30 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -2,62 +2,82 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Screens.Match.Settings; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Select; using osu.Game.Users; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match { - public class Match : MultiplayerScreen + public class MatchScreen : MultiplayerScreen { - private readonly Room room; private readonly Participants participants; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); - protected override Container TransitionContent => participants; + protected override Drawable TransitionContent => participants; - public override string Type => "room"; public override string Title => room.Name.Value; - public Match(Room room) + public override string ShortTitle => "room"; + + [Cached] + private readonly Room room; + + [Resolved] + private BeatmapManager beatmapManager { get; set; } + + [Resolved] + private APIAccess api { get; set; } + + public MatchScreen(Room room) { this.room = room; - Header header; + + nameBind.BindTo(room.Name); + beatmapBind.BindTo(room.Beatmap); + statusBind.BindTo(room.Status); + availabilityBind.BindTo(room.Availability); + typeBind.BindTo(room.Type); + participantsBind.BindTo(room.Participants); + maxParticipantsBind.BindTo(room.MaxParticipants); + + Components.Header header; RoomSettingsOverlay settings; Info info; Children = new Drawable[] { - header = new Header + header = new Components.Header { Depth = -1, }, info = new Info { - Margin = new MarginPadding { Top = Header.HEIGHT }, + Margin = new MarginPadding { Top = Components.Header.HEIGHT }, }, participants = new Participants { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Header.HEIGHT + Info.HEIGHT }, + Padding = new MarginPadding { Top = Components.Header.HEIGHT + Info.HEIGHT }, }, new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = settings = new RoomSettingsOverlay(room) + Padding = new MarginPadding { Top = Components.Header.HEIGHT }, + Child = settings = new RoomSettingsOverlay { RelativeSizeAxes = Axes.Both, Height = 0.9f, @@ -66,45 +86,32 @@ namespace osu.Game.Screens.Multi.Screens.Match }; header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect()); - - beatmapBind.BindTo(room.Beatmap); - beatmapBind.BindValueChanged(b => - { - header.BeatmapSet = b?.BeatmapSet; - info.Beatmap = b; - }, true); + header.Beatmap.BindTo(Beatmap); header.Tabs.Current.ValueChanged += t => { - if (t == MatchHeaderPage.Settings) + if (t is SettingsMatchPage) settings.Show(); else settings.Hide(); }; - settings.StateChanged += s => - { - if (s == Visibility.Hidden) - header.Tabs.Current.Value = MatchHeaderPage.Room; - }; + info.Beatmap.BindTo(beatmapBind); + info.Name.BindTo(nameBind); + info.Status.BindTo(statusBind); + info.Availability.BindTo(availabilityBind); + info.Type.BindTo(typeBind); - nameBind.BindTo(room.Name); - nameBind.BindValueChanged(n => info.Name = n, true); + participants.Users.BindTo(participantsBind); + participants.MaxParticipants.BindTo(maxParticipantsBind); + } - statusBind.BindTo(room.Status); - statusBind.BindValueChanged(s => info.Status = s, true); - - availabilityBind.BindTo(room.Availability); - availabilityBind.BindValueChanged(a => info.Availability = a, true); - - typeBind.BindTo(room.Type); - typeBind.BindValueChanged(t => info.Type = t, true); - - maxParticipantsBind.BindTo(room.MaxParticipants); - maxParticipantsBind.BindValueChanged(m => { participants.Max = m; }, true); - - participantsBind.BindTo(room.Participants); - participantsBind.BindValueChanged(p => participants.Users = p, true); + [BackgroundDependencyLoader] + private void load() + { + beatmapBind.BindTo(room.Beatmap); + beatmapBind.BindValueChanged(b => Beatmap.Value = beatmapManager.GetWorkingBeatmap(room.Beatmap.Value), true); + Beatmap.BindValueChanged(b => beatmapBind.Value = b.BeatmapInfo); } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 7822fa68dc..aba83753cb 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Screens.Menu; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi.Lounge; namespace osu.Game.Screens.Multi { @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both, }; - Lounge lounge; + LoungeScreen loungeScreen; Children = new Drawable[] { new Container @@ -53,12 +53,12 @@ namespace osu.Game.Screens.Multi { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = lounge = new Lounge(), + Child = loungeScreen = new LoungeScreen(), }, - new Header(lounge), + new Header(loungeScreen) }; - lounge.Exited += s => Exit(); + loungeScreen.Exited += s => Exit(); } protected override void OnEntering(Screen last) diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/MultiplayerScreen.cs similarity index 80% rename from osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs rename to osu.Game/Screens/Multi/MultiplayerScreen.cs index 00c2613d54..da9a2b3051 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerScreen.cs @@ -2,20 +2,16 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Graphics.Containers; -namespace osu.Game.Screens.Multi.Screens +namespace osu.Game.Screens.Multi { - public abstract class MultiplayerScreen : OsuScreen + public abstract class MultiplayerScreen : OsuScreen, IMultiplayerScreen { - protected virtual Container TransitionContent => Content; + protected virtual Drawable TransitionContent => Content; - /// - /// The type to display in the title of the . - /// - public virtual string Type => Title; + public virtual string ShortTitle => Title; protected override void OnEntering(Screen last) { diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs new file mode 100644 index 0000000000..9e233f278b --- /dev/null +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi +{ + public class RoomManager : Component + { + public IBindableCollection Rooms => rooms; + private readonly BindableCollection rooms = new BindableCollection(); + + public readonly Bindable Current = new Bindable(); + + [Resolved] + private APIAccess api { get; set; } + + public void CreateRoom(Room room) + { + room.Host.Value = api.LocalUser; + + // Todo: Perform API request + + room.Created.Value = true; + rooms.Add(room); + } + } +} diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 339392d5cf..94ac951159 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Screens.Multi; + namespace osu.Game.Screens.Select { - public class MatchSongSelect : SongSelect + public class MatchSongSelect : SongSelect, IMultiplayerScreen { + public string ShortTitle => "song selection"; + protected override bool OnStart() { if (IsCurrentScreen) Exit(); diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 67a13bd850..80c9b2ab47 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -29,6 +29,9 @@ namespace osu.Game.Tests.Visual { Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures + beatmap.Default = new DummyWorkingBeatmap(Dependencies.Get()); + Dependencies.CacheAs(beatmap); Dependencies.CacheAs(beatmap); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ed0e6c8417..1be75ebccc 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - +