mirror of
https://github.com/ppy/osu.git
synced 2024-12-16 19:33:01 +08:00
Merge branch 'master' into notify_track_completion_failure
This commit is contained in:
commit
f08d5f058c
@ -16,7 +16,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseLoungeRoomsContainer : OsuTestCase
|
||||
public class TestCaseLoungeRoomsContainer : MultiplayerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual
|
||||
AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
|
||||
|
||||
AddStep("select first room", () => container.Rooms.First().Action?.Invoke());
|
||||
AddAssert("first room selected", () => container.SelectedRoom.Value == roomManager.Rooms.First());
|
||||
AddAssert("first room selected", () => Room == roomManager.Rooms.First());
|
||||
|
||||
AddStep("join first room", () => container.Rooms.First().Action?.Invoke());
|
||||
AddAssert("first room joined", () => roomManager.Rooms.First().Status.Value is JoinedRoomStatus);
|
||||
@ -71,7 +71,11 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
private class TestRoomManager : IRoomManager
|
||||
{
|
||||
public event Action RoomsUpdated;
|
||||
public event Action RoomsUpdated
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public readonly BindableList<Room> Rooms = new BindableList<Room>();
|
||||
IBindableList<Room> IRoomManager.Rooms => Rooms;
|
||||
@ -85,10 +89,6 @@ namespace osu.Game.Tests.Visual
|
||||
public void PartRoom()
|
||||
{
|
||||
}
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class JoinedRoomStatus : RoomStatus
|
||||
|
@ -12,7 +12,7 @@ using osu.Game.Screens.Multi.Match.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchHeader : OsuTestCase
|
||||
public class TestCaseMatchHeader : MultiplayerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -21,11 +21,7 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
public TestCaseMatchHeader()
|
||||
{
|
||||
var room = new Room();
|
||||
|
||||
var header = new Header(room);
|
||||
|
||||
room.Playlist.Add(new PlaylistItem
|
||||
Room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
Beatmap = new BeatmapInfo
|
||||
{
|
||||
@ -46,9 +42,9 @@ namespace osu.Game.Tests.Visual
|
||||
}
|
||||
});
|
||||
|
||||
room.Type.Value = new GameTypeTimeshift();
|
||||
Room.Type.Value = new GameTypeTimeshift();
|
||||
|
||||
Child = header;
|
||||
Child = new Header();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ using osu.Game.Screens.Multi.Match.Components;
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseMatchInfo : OsuTestCase
|
||||
public class TestCaseMatchInfo : MultiplayerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -27,18 +27,15 @@ namespace osu.Game.Tests.Visual
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
var room = new Room();
|
||||
Add(new Info());
|
||||
|
||||
Info info = new Info(room);
|
||||
Add(info);
|
||||
|
||||
AddStep(@"set name", () => room.Name.Value = @"Room Name?");
|
||||
AddStep(@"set availability", () => room.Availability.Value = RoomAvailability.FriendsOnly);
|
||||
AddStep(@"set status", () => room.Status.Value = new RoomStatusPlaying());
|
||||
AddStep(@"set name", () => Room.Name.Value = @"Room Name?");
|
||||
AddStep(@"set availability", () => Room.Availability.Value = RoomAvailability.FriendsOnly);
|
||||
AddStep(@"set status", () => Room.Status.Value = new RoomStatusPlaying());
|
||||
AddStep(@"set beatmap", () =>
|
||||
{
|
||||
room.Playlist.Clear();
|
||||
room.Playlist.Add(new PlaylistItem
|
||||
Room.Playlist.Clear();
|
||||
Room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
Beatmap = new BeatmapInfo
|
||||
{
|
||||
@ -54,14 +51,14 @@ namespace osu.Game.Tests.Visual
|
||||
});
|
||||
});
|
||||
|
||||
AddStep(@"change name", () => room.Name.Value = @"Room Name!");
|
||||
AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.InviteOnly);
|
||||
AddStep(@"change status", () => room.Status.Value = new RoomStatusOpen());
|
||||
AddStep(@"null beatmap", () => room.Playlist.Clear());
|
||||
AddStep(@"change name", () => Room.Name.Value = @"Room Name!");
|
||||
AddStep(@"change availability", () => Room.Availability.Value = RoomAvailability.InviteOnly);
|
||||
AddStep(@"change status", () => Room.Status.Value = new RoomStatusOpen());
|
||||
AddStep(@"null beatmap", () => Room.Playlist.Clear());
|
||||
AddStep(@"change beatmap", () =>
|
||||
{
|
||||
room.Playlist.Clear();
|
||||
room.Playlist.Add(new PlaylistItem
|
||||
Room.Playlist.Clear();
|
||||
Room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
Beatmap = new BeatmapInfo
|
||||
{
|
||||
|
@ -6,24 +6,24 @@ using Newtonsoft.Json;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchLeaderboard : OsuTestCase
|
||||
public class TestCaseMatchLeaderboard : MultiplayerTestCase
|
||||
{
|
||||
public TestCaseMatchLeaderboard()
|
||||
{
|
||||
Room.RoomID.Value = 3;
|
||||
|
||||
Add(new MatchLeaderboard
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(550f, 450f),
|
||||
Scope = MatchLeaderboardScope.Overall,
|
||||
Room = new Room { RoomID = { Value = 3 } }
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Users;
|
||||
@ -11,22 +9,14 @@ using osu.Game.Users;
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseMatchParticipants : OsuTestCase
|
||||
public class TestCaseMatchParticipants : MultiplayerTestCase
|
||||
{
|
||||
private readonly Bindable<int?> maxParticipants = new Bindable<int?>();
|
||||
private readonly Bindable<IEnumerable<User>> users = new Bindable<IEnumerable<User>>();
|
||||
|
||||
public TestCaseMatchParticipants()
|
||||
{
|
||||
Participants participants;
|
||||
Add(new Participants { RelativeSizeAxes = Axes.Both });
|
||||
|
||||
Add(participants = new Participants { RelativeSizeAxes = Axes.Both });
|
||||
|
||||
participants.MaxParticipants.BindTo(maxParticipants);
|
||||
participants.Users.BindTo(users);
|
||||
|
||||
AddStep(@"set max to null", () => maxParticipants.Value = null);
|
||||
AddStep(@"set users", () => users.Value = new[]
|
||||
AddStep(@"set max to null", () => Room.MaxParticipants.Value = null);
|
||||
AddStep(@"set users", () => Room.Participants.Value = new[]
|
||||
{
|
||||
new User
|
||||
{
|
||||
@ -54,9 +44,9 @@ namespace osu.Game.Tests.Visual
|
||||
},
|
||||
});
|
||||
|
||||
AddStep(@"set max", () => maxParticipants.Value = 10);
|
||||
AddStep(@"clear users", () => users.Value = new User[] { });
|
||||
AddStep(@"set max to null", () => maxParticipants.Value = null);
|
||||
AddStep(@"set max", () => Room.MaxParticipants.Value = 10);
|
||||
AddStep(@"clear users", () => Room.Participants.Value = new User[] { });
|
||||
AddStep(@"set max to null", () => Room.MaxParticipants.Value = null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Screens.Multi.Ranking;
|
||||
@ -19,7 +18,7 @@ using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchResults : OsuTestCase
|
||||
public class TestCaseMatchResults : MultiplayerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -38,6 +37,9 @@ namespace osu.Game.Tests.Visual
|
||||
if (beatmapInfo != null)
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
|
||||
|
||||
Room.RoomID.Value = 1;
|
||||
Room.Name.Value = "an awesome room";
|
||||
|
||||
Child = new TestMatchResults(new ScoreInfo
|
||||
{
|
||||
User = new User { Id = 10 },
|
||||
@ -46,60 +48,41 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
private class TestMatchResults : MatchResults
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
public TestMatchResults(ScoreInfo score)
|
||||
: this(score, new Room
|
||||
{
|
||||
RoomID = { Value = 1 },
|
||||
Name = { Value = "an awesome room" }
|
||||
})
|
||||
: base(score)
|
||||
{
|
||||
}
|
||||
|
||||
public TestMatchResults(ScoreInfo score, Room room)
|
||||
: base(score, room)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap, room) };
|
||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap) };
|
||||
}
|
||||
|
||||
private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo
|
||||
{
|
||||
private readonly ScoreInfo score;
|
||||
private readonly WorkingBeatmap beatmap;
|
||||
private readonly Room room;
|
||||
|
||||
public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
: base(score, beatmap, room)
|
||||
public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
|
||||
: base(score, beatmap)
|
||||
{
|
||||
this.score = score;
|
||||
this.beatmap = beatmap;
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap, room);
|
||||
public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap);
|
||||
}
|
||||
|
||||
private class TestRoomLeaderboardPage : RoomLeaderboardPage
|
||||
{
|
||||
public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
: base(score, beatmap, room)
|
||||
public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap)
|
||||
: base(score, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room);
|
||||
protected override MatchLeaderboard CreateLeaderboard() => new TestMatchLeaderboard();
|
||||
}
|
||||
|
||||
private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard
|
||||
{
|
||||
public TestMatchLeaderboard(Room room)
|
||||
: base(room)
|
||||
{
|
||||
}
|
||||
|
||||
protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback)
|
||||
{
|
||||
var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray();
|
||||
|
@ -13,12 +13,11 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchSettingsOverlay : OsuTestCase
|
||||
public class TestCaseMatchSettingsOverlay : MultiplayerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -28,14 +27,14 @@ namespace osu.Game.Tests.Visual
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private TestRoomManager roomManager = new TestRoomManager();
|
||||
|
||||
private Room room;
|
||||
private TestRoomSettings settings;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
room = new Room();
|
||||
settings = new TestRoomSettings(room)
|
||||
Room = new Room();
|
||||
|
||||
settings = new TestRoomSettings
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = Visibility.Visible
|
||||
@ -49,19 +48,19 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("clear name and beatmap", () =>
|
||||
{
|
||||
room.Name.Value = "";
|
||||
room.Playlist.Clear();
|
||||
Room.Name.Value = "";
|
||||
Room.Playlist.Clear();
|
||||
});
|
||||
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
|
||||
|
||||
AddStep("set name", () => room.Name.Value = "Room name");
|
||||
AddStep("set name", () => Room.Name.Value = "Room name");
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
|
||||
|
||||
AddStep("set beatmap", () => room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo }));
|
||||
AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo }));
|
||||
AddAssert("button enabled", () => settings.ApplyButton.Enabled);
|
||||
|
||||
AddStep("clear name", () => room.Name.Value = "");
|
||||
AddStep("clear name", () => Room.Name.Value = "");
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
|
||||
}
|
||||
|
||||
@ -117,17 +116,12 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
private class TestRoomSettings : MatchSettingsOverlay
|
||||
{
|
||||
public new TriangleButton ApplyButton => base.ApplyButton;
|
||||
public TriangleButton ApplyButton => Settings.ApplyButton;
|
||||
|
||||
public new OsuTextBox NameField => base.NameField;
|
||||
public new OsuDropdown<TimeSpan> DurationField => base.DurationField;
|
||||
public OsuTextBox NameField => Settings.NameField;
|
||||
public OsuDropdown<TimeSpan> DurationField => Settings.DurationField;
|
||||
|
||||
public new OsuSpriteText ErrorText => base.ErrorText;
|
||||
|
||||
public TestRoomSettings(Room room)
|
||||
: base(room)
|
||||
{
|
||||
}
|
||||
public OsuSpriteText ErrorText => Settings.ErrorText;
|
||||
}
|
||||
|
||||
private class TestRoomManager : IRoomManager
|
||||
@ -136,7 +130,11 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
public Func<Room, bool> CreateRequested;
|
||||
|
||||
public event Action RoomsUpdated;
|
||||
public event Action RoomsUpdated
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public IBindableList<Room> Rooms { get; } = null;
|
||||
|
||||
@ -154,8 +152,6 @@ namespace osu.Game.Tests.Visual
|
||||
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => throw new NotImplementedException();
|
||||
|
||||
public void PartRoom() => throw new NotImplementedException();
|
||||
|
||||
public void Filter(FilterCriteria criteria) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Online.Multiplayer.GameTypes;
|
||||
using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
@ -14,42 +15,55 @@ namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
public class Room
|
||||
{
|
||||
[Cached]
|
||||
[JsonProperty("id")]
|
||||
public Bindable<int?> RoomID { get; private set; } = new Bindable<int?>();
|
||||
|
||||
[Cached]
|
||||
[JsonProperty("name")]
|
||||
public Bindable<string> Name { get; private set; } = new Bindable<string>();
|
||||
|
||||
[Cached]
|
||||
[JsonProperty("host")]
|
||||
public Bindable<User> Host { get; private set; } = new Bindable<User>();
|
||||
|
||||
[Cached]
|
||||
[JsonProperty("playlist")]
|
||||
public BindableList<PlaylistItem> Playlist { get; set; } = new BindableList<PlaylistItem>();
|
||||
public BindableList<PlaylistItem> Playlist { get; private set; } = new BindableList<PlaylistItem>();
|
||||
|
||||
[Cached]
|
||||
[JsonProperty("channel_id")]
|
||||
public Bindable<int> ChannelId { get; private set; } = new Bindable<int>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<TimeSpan> Duration { get; private set; } = new Bindable<TimeSpan>(TimeSpan.FromMinutes(30));
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<int?> MaxAttempts { get; private set; } = new Bindable<int?>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<RoomStatus> Status { get; private set; } = new Bindable<RoomStatus>(new RoomStatusOpen());
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<RoomAvailability> Availability { get; private set; } = new Bindable<RoomAvailability>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<GameType> Type { get; private set; } = new Bindable<GameType>(new GameTypeTimeshift());
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<int?> MaxParticipants { get; private set; } = new Bindable<int?>();
|
||||
|
||||
[Cached]
|
||||
[JsonIgnore]
|
||||
public Bindable<IEnumerable<User>> Participants { get; private set; } = new Bindable<IEnumerable<User>>(Enumerable.Empty<User>());
|
||||
|
||||
[Cached]
|
||||
public Bindable<int> ParticipantCount { get; private set; } = new Bindable<int>();
|
||||
|
||||
// todo: TEMPORARY
|
||||
@ -68,6 +82,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
}
|
||||
|
||||
// Only supports retrieval for now
|
||||
[Cached]
|
||||
[JsonProperty("ends_at")]
|
||||
public Bindable<DateTimeOffset> EndDate { get; private set; } = new Bindable<DateTimeOffset>();
|
||||
|
||||
@ -83,7 +98,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
/// The position of this <see cref="Room"/> in the list. This is not read from or written to the API.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public int Position = -1;
|
||||
public Bindable<int> Position { get; private set; } = new Bindable<int>(-1);
|
||||
|
||||
public void CopyFrom(Room other)
|
||||
{
|
||||
|
@ -2,11 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
@ -14,10 +11,8 @@ using osu.Game.Online.Chat;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class BeatmapTitle : CompositeDrawable
|
||||
public class BeatmapTitle : MultiplayerComposite
|
||||
{
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
|
||||
private readonly LinkFlowContainer textFlow;
|
||||
|
||||
public BeatmapTitle()
|
||||
@ -27,10 +22,10 @@ namespace osu.Game.Screens.Multi.Components
|
||||
InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both };
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Beatmap.BindValueChanged(v => updateText(), true);
|
||||
CurrentBeatmap.BindValueChanged(v => updateText(), true);
|
||||
}
|
||||
|
||||
private float textSize = OsuSpriteText.FONT_SIZE;
|
||||
@ -58,7 +53,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
|
||||
textFlow.Clear();
|
||||
|
||||
if (Beatmap.Value == null)
|
||||
if (CurrentBeatmap.Value == null)
|
||||
textFlow.AddText("No beatmap selected", s =>
|
||||
{
|
||||
s.TextSize = TextSize;
|
||||
@ -70,7 +65,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)),
|
||||
Text = new LocalisedString((CurrentBeatmap.Value.Metadata.ArtistUnicode, CurrentBeatmap.Value.Metadata.Artist)),
|
||||
TextSize = TextSize,
|
||||
},
|
||||
new OsuSpriteText
|
||||
@ -80,10 +75,10 @@ namespace osu.Game.Screens.Multi.Components
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)),
|
||||
Text = new LocalisedString((CurrentBeatmap.Value.Metadata.TitleUnicode, CurrentBeatmap.Value.Metadata.Title)),
|
||||
TextSize = TextSize,
|
||||
}
|
||||
}, null, LinkAction.OpenBeatmap, Beatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap");
|
||||
}, null, LinkAction.OpenBeatmap, CurrentBeatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,26 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class BeatmapTypeInfo : CompositeDrawable
|
||||
public class BeatmapTypeInfo : MultiplayerComposite
|
||||
{
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
public readonly IBindable<GameType> Type = new Bindable<GameType>();
|
||||
|
||||
public BeatmapTypeInfo()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
BeatmapTitle beatmapTitle;
|
||||
ModeTypeInfo modeTypeInfo;
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LinkFlowContainer beatmapAuthor;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
@ -36,7 +31,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
modeTypeInfo = new ModeTypeInfo(),
|
||||
new ModeTypeInfo(),
|
||||
new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
@ -44,7 +39,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
Margin = new MarginPadding { Left = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
beatmapTitle = new BeatmapTitle(),
|
||||
new BeatmapTitle(),
|
||||
beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
@ -56,13 +51,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
}
|
||||
};
|
||||
|
||||
modeTypeInfo.Beatmap.BindTo(Beatmap);
|
||||
modeTypeInfo.Ruleset.BindTo(Ruleset);
|
||||
modeTypeInfo.Type.BindTo(Type);
|
||||
|
||||
beatmapTitle.Beatmap.BindTo(Beatmap);
|
||||
|
||||
Beatmap.BindValueChanged(v =>
|
||||
CurrentBeatmap.BindValueChanged(v =>
|
||||
{
|
||||
beatmapAuthor.Clear();
|
||||
|
||||
@ -71,7 +60,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
beatmapAuthor.AddText("mapped by ", s => s.Colour = OsuColour.Gray(0.8f));
|
||||
beatmapAuthor.AddLink(v.Metadata.Author.Username, null, LinkAction.OpenUserProfile, v.Metadata.Author.Id.ToString(), "View Profile");
|
||||
}
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,29 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class ModeTypeInfo : CompositeDrawable
|
||||
public class ModeTypeInfo : MultiplayerComposite
|
||||
{
|
||||
private const float height = 30;
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly Container rulesetContainer;
|
||||
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
public readonly IBindable<GameType> Type = new Bindable<GameType>();
|
||||
private Container rulesetContainer;
|
||||
|
||||
public ModeTypeInfo()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Container gameTypeContainer;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
@ -48,17 +45,17 @@ namespace osu.Game.Screens.Multi.Components
|
||||
},
|
||||
};
|
||||
|
||||
Beatmap.BindValueChanged(updateBeatmap);
|
||||
Ruleset.BindValueChanged(_ => updateBeatmap(Beatmap.Value));
|
||||
Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) });
|
||||
CurrentBeatmap.BindValueChanged(_ => updateBeatmap());
|
||||
CurrentRuleset.BindValueChanged(_ => updateBeatmap(), true);
|
||||
Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }, true);
|
||||
}
|
||||
|
||||
private void updateBeatmap(BeatmapInfo beatmap)
|
||||
private void updateBeatmap()
|
||||
{
|
||||
if (beatmap != null)
|
||||
if (CurrentBeatmap.Value != null)
|
||||
{
|
||||
rulesetContainer.FadeIn(transition_duration);
|
||||
rulesetContainer.Child = new DifficultyIcon(beatmap, Ruleset.Value) { Size = new Vector2(height) };
|
||||
rulesetContainer.Child = new DifficultyIcon(CurrentBeatmap.Value, CurrentRuleset.Value) { Size = new Vector2(height) };
|
||||
}
|
||||
else
|
||||
rulesetContainer.FadeOut(transition_duration);
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class MultiplayerBackgroundSprite : MultiplayerComposite
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
UpdateableBeatmapBackgroundSprite sprite;
|
||||
|
||||
InternalChild = sprite = CreateBackgroundSprite();
|
||||
|
||||
sprite.Beatmap.BindTo(CurrentBeatmap);
|
||||
}
|
||||
|
||||
protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
}
|
@ -1,31 +1,28 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Allocation;
|
||||
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 ParticipantCountDisplay : CompositeDrawable
|
||||
public class ParticipantCountDisplay : MultiplayerComposite
|
||||
{
|
||||
private const float text_size = 30;
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly OsuSpriteText slash, maxText;
|
||||
|
||||
public readonly IBindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
public readonly IBindable<int> ParticipantCount = new Bindable<int>();
|
||||
public readonly IBindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
private OsuSpriteText slash, maxText;
|
||||
|
||||
public ParticipantCountDisplay()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
OsuSpriteText count;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
@ -54,9 +51,8 @@ namespace osu.Game.Screens.Multi.Components
|
||||
}
|
||||
};
|
||||
|
||||
Participants.BindValueChanged(v => count.Text = v.Count().ToString());
|
||||
MaxParticipants.BindValueChanged(_ => updateMax(), true);
|
||||
ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0"));
|
||||
ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0"), true);
|
||||
}
|
||||
|
||||
private void updateMax()
|
||||
|
@ -13,16 +13,16 @@ using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class RoomStatusInfo : CompositeDrawable
|
||||
public class RoomStatusInfo : MultiplayerComposite
|
||||
{
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
public RoomStatusInfo(Room room)
|
||||
public RoomStatusInfo()
|
||||
{
|
||||
bindings.Room = room;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
StatusPart statusPart;
|
||||
EndDatePart endDatePart;
|
||||
|
||||
@ -41,10 +41,10 @@ namespace osu.Game.Screens.Multi.Components
|
||||
}
|
||||
};
|
||||
|
||||
statusPart.EndDate.BindTo(bindings.EndDate);
|
||||
statusPart.Status.BindTo(bindings.Status);
|
||||
statusPart.Availability.BindTo(bindings.Availability);
|
||||
endDatePart.EndDate.BindTo(bindings.EndDate);
|
||||
statusPart.EndDate.BindTo(EndDate);
|
||||
statusPart.Status.BindTo(Status);
|
||||
statusPart.Availability.BindTo(Availability);
|
||||
endDatePart.EndDate.BindTo(EndDate);
|
||||
}
|
||||
|
||||
private class EndDatePart : DrawableDate
|
||||
|
31
osu.Game/Screens/Multi/Components/StatusColouredContainer.cs
Normal file
31
osu.Game/Screens/Multi/Components/StatusColouredContainer.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class StatusColouredContainer : Container
|
||||
{
|
||||
private readonly double transitionDuration;
|
||||
|
||||
[Resolved(typeof(Room), nameof(Room.Status))]
|
||||
private Bindable<RoomStatus> status { get; set; }
|
||||
|
||||
public StatusColouredContainer(double transitionDuration = 100)
|
||||
{
|
||||
this.transitionDuration = transitionDuration;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
status.BindValueChanged(s => this.FadeColour(s.GetAppropriateColour(colours), transitionDuration), true);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
@ -40,11 +39,5 @@ namespace osu.Game.Screens.Multi
|
||||
/// Parts the currently-joined <see cref="Room"/>.
|
||||
/// </summary>
|
||||
void PartRoom();
|
||||
|
||||
/// <summary>
|
||||
/// Queries for <see cref="Room"/>s matching a new <see cref="FilterCriteria"/>.
|
||||
/// </summary>
|
||||
/// <param name="criteria">The <see cref="FilterCriteria"/> to match.</param>
|
||||
void Filter(FilterCriteria criteria);
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
@ -34,12 +34,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
|
||||
public event Action<SelectionState> StateChanged;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private readonly Box selectionBox;
|
||||
private UpdateableBeatmapBackgroundSprite background;
|
||||
private BeatmapTitle beatmapTitle;
|
||||
private ModeTypeInfo modeTypeInfo;
|
||||
private CachedModelDependencyContainer<Room> dependencies;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
@ -80,7 +76,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
public DrawableRoom(Room room)
|
||||
{
|
||||
Room = room;
|
||||
bindings.Room = room;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = height + SELECTION_BORDER_WIDTH * 2;
|
||||
@ -98,13 +93,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Box sideStrip;
|
||||
ParticipantInfo participantInfo;
|
||||
OsuSpriteText name;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
selectionBox,
|
||||
new StatusColouredContainer(transition_duration)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = selectionBox
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -127,10 +122,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"212121"),
|
||||
},
|
||||
sideStrip = new Box
|
||||
new StatusColouredContainer(transition_duration)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = side_strip_width,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -138,7 +134,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
Width = cover_width,
|
||||
Masking = true,
|
||||
Margin = new MarginPadding { Left = side_strip_width },
|
||||
Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }
|
||||
Child = new MultiplayerBackgroundSprite { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -159,8 +155,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
Spacing = new Vector2(5f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
name = new OsuSpriteText { TextSize = 18 },
|
||||
participantInfo = new ParticipantInfo(),
|
||||
new RoomName { TextSize = 18 },
|
||||
new ParticipantInfo(),
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
@ -173,11 +169,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new RoomStatusInfo(Room),
|
||||
beatmapTitle = new BeatmapTitle { TextSize = 14 },
|
||||
new RoomStatusInfo(),
|
||||
new BeatmapTitle { TextSize = 14 },
|
||||
},
|
||||
},
|
||||
modeTypeInfo = new ModeTypeInfo
|
||||
new ModeTypeInfo
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
@ -188,22 +184,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
background.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
modeTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset);
|
||||
modeTypeInfo.Type.BindTo(bindings.Type);
|
||||
beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
participantInfo.Host.BindTo(bindings.Host);
|
||||
participantInfo.Participants.BindTo(bindings.Participants);
|
||||
participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount);
|
||||
|
||||
bindings.Name.BindValueChanged(n => name.Text = n, true);
|
||||
bindings.Status.BindValueChanged(s =>
|
||||
{
|
||||
foreach (Drawable d in new Drawable[] { selectionBox, sideStrip })
|
||||
d.FadeColour(s.GetAppropriateColour(colours), transition_duration);
|
||||
}, true);
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
|
||||
dependencies.Model.Value = Room;
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -211,5 +198,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
base.LoadComplete();
|
||||
this.FadeInFromZero(transition_duration);
|
||||
}
|
||||
|
||||
private class RoomName : OsuSpriteText
|
||||
{
|
||||
[Resolved(typeof(Room), nameof(Online.Multiplayer.Room.Name))]
|
||||
private Bindable<string> name { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Current = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osuTK.Graphics;
|
||||
@ -15,17 +17,38 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
|
||||
protected override float ContentHorizontalPadding => base.ContentHorizontalPadding + OsuScreen.HORIZONTAL_OVERFLOW_PADDING;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private Bindable<FilterCriteria> filter { get; set; }
|
||||
|
||||
public FilterControl()
|
||||
{
|
||||
DisplayStyleControl.Hide();
|
||||
}
|
||||
|
||||
public FilterCriteria CreateCriteria() => new FilterCriteria
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SearchString = Search.Current.Value ?? string.Empty,
|
||||
PrimaryFilter = Tabs.Current,
|
||||
SecondaryFilter = DisplayStyleControl.Dropdown.Current
|
||||
};
|
||||
if (filter == null)
|
||||
filter = new Bindable<FilterCriteria>();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Search.Current.BindValueChanged(_ => updateFilter());
|
||||
Tabs.Current.BindValueChanged(_ => updateFilter(), true);
|
||||
}
|
||||
|
||||
private void updateFilter()
|
||||
{
|
||||
filter.Value = new FilterCriteria
|
||||
{
|
||||
SearchString = Search.Current.Value ?? string.Empty,
|
||||
PrimaryFilter = Tabs.Current,
|
||||
SecondaryFilter = DisplayStyleControl.Dropdown.Current
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum PrimaryFilter
|
||||
|
@ -1,10 +1,8 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
@ -16,26 +14,24 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class ParticipantInfo : Container
|
||||
public class ParticipantInfo : MultiplayerComposite
|
||||
{
|
||||
private readonly FillFlowContainer summaryContainer;
|
||||
|
||||
public readonly IBindable<User> Host = new Bindable<User>();
|
||||
public readonly IBindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
public readonly IBindable<int> ParticipantCount = new Bindable<int>();
|
||||
|
||||
public ParticipantInfo()
|
||||
{
|
||||
OsuSpriteText summary;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 15f;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
OsuSpriteText summary;
|
||||
OsuSpriteText levelRangeHigher;
|
||||
OsuSpriteText levelRangeLower;
|
||||
Container flagContainer;
|
||||
LinkFlowContainer hostText;
|
||||
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
@ -73,12 +69,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
}
|
||||
},
|
||||
},
|
||||
summaryContainer = new FillFlowContainer
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Colour = colours.Gray9,
|
||||
Children = new[]
|
||||
{
|
||||
summary = new OsuSpriteText
|
||||
@ -101,9 +98,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
hostText.AddLink(v.Username, null, LinkAction.OpenUserProfile, v.Id.ToString(), "Open profile", s => s.Font = "Exo2.0-BoldItalic");
|
||||
flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
});
|
||||
}, true);
|
||||
|
||||
ParticipantCount.BindValueChanged(v => summary.Text = $"{v:#,0}{" participant".Pluralize(v == 1)}");
|
||||
ParticipantCount.BindValueChanged(v => summary.Text = $"{v:#,0}{" participant".Pluralize(v == 1)}", true);
|
||||
|
||||
/*Participants.BindValueChanged(v =>
|
||||
{
|
||||
@ -112,11 +109,5 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
levelRangeHigher.Text = ranks.Max().ToString();
|
||||
});*/
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
summaryContainer.Colour = colours.Gray9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API;
|
||||
@ -24,34 +23,26 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class RoomInspector : Container
|
||||
public class RoomInspector : MultiplayerComposite
|
||||
{
|
||||
private const float transition_duration = 100;
|
||||
|
||||
public readonly IBindable<Room> Room = new Bindable<Room>();
|
||||
|
||||
private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 };
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private OsuColour colours;
|
||||
private Box statusStrip;
|
||||
private UpdateableBeatmapBackgroundSprite background;
|
||||
private ParticipantCountDisplay participantCount;
|
||||
private OsuSpriteText name, status;
|
||||
private OsuSpriteText name;
|
||||
private BeatmapTypeInfo beatmapTypeInfo;
|
||||
private ParticipantInfo participantInfo;
|
||||
private MatchParticipants participants;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
private readonly Bindable<RoomStatus> status = new Bindable<RoomStatus>(new RoomStatusNoneSelected());
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
this.colours = colours;
|
||||
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
@ -84,7 +75,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both },
|
||||
new MultiplayerBackgroundSprite { RelativeSizeAxes = Axes.Both },
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -106,15 +97,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
TextSize = 30,
|
||||
Current = Name
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
statusStrip = new Box
|
||||
new StatusColouredContainer(transition_duration)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 5,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -137,10 +130,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
Spacing = new Vector2(0f, 5f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
status = new OsuSpriteText
|
||||
new StatusColouredContainer(transition_duration)
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Child = new StatusText
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
}
|
||||
},
|
||||
beatmapTypeInfo = new BeatmapTypeInfo(),
|
||||
},
|
||||
@ -162,7 +159,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
participants = new MatchParticipants
|
||||
new MatchParticipants
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
@ -171,51 +168,37 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
}
|
||||
};
|
||||
|
||||
participantInfo.Host.BindTo(bindings.Host);
|
||||
participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount);
|
||||
participantInfo.Participants.BindTo(bindings.Participants);
|
||||
participantCount.Participants.BindTo(bindings.Participants);
|
||||
participantCount.ParticipantCount.BindTo(bindings.ParticipantCount);
|
||||
participantCount.MaxParticipants.BindTo(bindings.MaxParticipants);
|
||||
beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset);
|
||||
beatmapTypeInfo.Type.BindTo(bindings.Type);
|
||||
background.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
bindings.Status.BindValueChanged(displayStatus);
|
||||
bindings.Name.BindValueChanged(n => name.Text = n);
|
||||
Room.BindValueChanged(updateRoom, true);
|
||||
Status.BindValueChanged(_ => updateStatus(), true);
|
||||
RoomID.BindValueChanged(_ => updateStatus(), true);
|
||||
}
|
||||
|
||||
private void updateRoom(Room room)
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
bindings.Room = room;
|
||||
participants.Room = room;
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
dependencies.CacheAs(status, new CacheInfo(nameof(Room.Status), typeof(Room)));
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
if (room != null)
|
||||
private void updateStatus()
|
||||
{
|
||||
if (RoomID.Value == null)
|
||||
{
|
||||
status.Value = new RoomStatusNoneSelected();
|
||||
|
||||
participantCount.FadeOut(transition_duration);
|
||||
beatmapTypeInfo.FadeOut(transition_duration);
|
||||
name.FadeOut(transition_duration);
|
||||
participantInfo.FadeOut(transition_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
status.Value = Status;
|
||||
|
||||
participantCount.FadeIn(transition_duration);
|
||||
beatmapTypeInfo.FadeIn(transition_duration);
|
||||
name.FadeIn(transition_duration);
|
||||
participantInfo.FadeIn(transition_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
participantCount.FadeOut(transition_duration);
|
||||
beatmapTypeInfo.FadeOut(transition_duration);
|
||||
name.FadeOut(transition_duration);
|
||||
participantInfo.FadeOut(transition_duration);
|
||||
|
||||
displayStatus(new RoomStatusNoneSelected());
|
||||
}
|
||||
}
|
||||
|
||||
private void displayStatus(RoomStatus s)
|
||||
{
|
||||
status.Text = s.Message;
|
||||
|
||||
Color4 c = s.GetAppropriateColour(colours);
|
||||
statusStrip.FadeColour(c, transition_duration);
|
||||
status.FadeColour(c, transition_duration);
|
||||
}
|
||||
|
||||
private class RoomStatusNoneSelected : RoomStatus
|
||||
@ -224,23 +207,21 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray8;
|
||||
}
|
||||
|
||||
private class MatchParticipants : CompositeDrawable
|
||||
private class StatusText : OsuSpriteText
|
||||
{
|
||||
private Room room;
|
||||
private readonly FillFlowContainer fill;
|
||||
[Resolved(typeof(Room), nameof(Room.Status))]
|
||||
private Bindable<RoomStatus> status { get; set; }
|
||||
|
||||
public Room Room
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
get { return room; }
|
||||
set
|
||||
{
|
||||
if (room == value)
|
||||
return;
|
||||
|
||||
room = value;
|
||||
updateParticipants();
|
||||
}
|
||||
status.BindValueChanged(s => Text = s.Message, true);
|
||||
}
|
||||
}
|
||||
|
||||
private class MatchParticipants : MultiplayerComposite
|
||||
{
|
||||
private readonly FillFlowContainer fill;
|
||||
|
||||
public MatchParticipants()
|
||||
{
|
||||
@ -259,6 +240,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RoomID.BindValueChanged(_ => updateParticipants(), true);
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
@ -266,7 +253,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
|
||||
private void updateParticipants()
|
||||
{
|
||||
var roomId = room?.RoomID.Value ?? 0;
|
||||
var roomId = RoomID.Value ?? 0;
|
||||
|
||||
request?.Cancel();
|
||||
|
||||
@ -284,7 +271,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
request = new GetRoomScoresRequest(roomId);
|
||||
request.Success += scores =>
|
||||
{
|
||||
if (roomId != room.RoomID.Value)
|
||||
if (roomId != RoomID.Value)
|
||||
return;
|
||||
|
||||
fill.Clear();
|
||||
|
@ -19,14 +19,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public Action<Room> JoinRequested;
|
||||
|
||||
private readonly Bindable<Room> selectedRoom = new Bindable<Room>();
|
||||
public IBindable<Room> SelectedRoom => selectedRoom;
|
||||
|
||||
private readonly IBindableList<Room> rooms = new BindableList<Room>();
|
||||
|
||||
private readonly FillFlowContainer<DrawableRoom> roomFlow;
|
||||
public IReadOnlyList<DrawableRoom> Rooms => roomFlow;
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> currentRoom { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IRoomManager roomManager { get; set; }
|
||||
|
||||
@ -121,7 +121,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
else
|
||||
roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected);
|
||||
|
||||
selectedRoom.Value = room;
|
||||
currentRoom.Value = room;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
|
@ -2,6 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
@ -21,16 +23,16 @@ namespace osu.Game.Screens.Multi.Lounge
|
||||
protected readonly FilterControl Filter;
|
||||
|
||||
private readonly Container content;
|
||||
private readonly RoomsContainer rooms;
|
||||
private readonly Action<Screen> pushGameplayScreen;
|
||||
private readonly ProcessingOverlay processingOverlay;
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> currentRoom { get; set; }
|
||||
|
||||
public LoungeSubScreen(Action<Screen> pushGameplayScreen)
|
||||
{
|
||||
this.pushGameplayScreen = pushGameplayScreen;
|
||||
|
||||
RoomInspector inspector;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
Filter = new FilterControl { Depth = -1 },
|
||||
@ -54,13 +56,13 @@ namespace osu.Game.Screens.Multi.Lounge
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = rooms = new RoomsContainer { JoinRequested = joinRequested }
|
||||
Child = new RoomsContainer { JoinRequested = joinRequested }
|
||||
},
|
||||
},
|
||||
processingOverlay = new ProcessingOverlay { Alpha = 0 }
|
||||
}
|
||||
},
|
||||
inspector = new RoomInspector
|
||||
new RoomInspector
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
@ -71,10 +73,6 @@ namespace osu.Game.Screens.Multi.Lounge
|
||||
},
|
||||
};
|
||||
|
||||
inspector.Room.BindTo(rooms.SelectedRoom);
|
||||
|
||||
Filter.Search.Current.ValueChanged += s => filterRooms();
|
||||
Filter.Tabs.Current.ValueChanged += t => filterRooms();
|
||||
Filter.Search.Exit += this.Exit;
|
||||
}
|
||||
|
||||
@ -113,18 +111,12 @@ namespace osu.Game.Screens.Multi.Lounge
|
||||
Filter.Search.HoldFocus = false;
|
||||
}
|
||||
|
||||
private void filterRooms()
|
||||
{
|
||||
rooms.Filter(Filter.CreateCriteria());
|
||||
Manager?.Filter(Filter.CreateCriteria());
|
||||
}
|
||||
|
||||
private void joinRequested(Room room)
|
||||
{
|
||||
processingOverlay.Show();
|
||||
Manager?.JoinRoom(room, r =>
|
||||
{
|
||||
Push(room);
|
||||
Open(room);
|
||||
processingOverlay.Hide();
|
||||
}, _ => processingOverlay.Hide());
|
||||
}
|
||||
@ -132,12 +124,14 @@ namespace osu.Game.Screens.Multi.Lounge
|
||||
/// <summary>
|
||||
/// Push a room as a new subscreen.
|
||||
/// </summary>
|
||||
public void Push(Room room)
|
||||
public void Open(Room room)
|
||||
{
|
||||
// Handles the case where a room is clicked 3 times in quick succession
|
||||
if (!this.IsCurrentScreen())
|
||||
return;
|
||||
|
||||
currentRoom.Value = room;
|
||||
|
||||
this.Push(new MatchSubScreen(room, s => pushGameplayScreen?.Invoke(s)));
|
||||
}
|
||||
}
|
||||
|
@ -20,31 +20,27 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class Header : Container
|
||||
public class Header : MultiplayerComposite
|
||||
{
|
||||
public const float HEIGHT = 200;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
public MatchTabControl Tabs;
|
||||
|
||||
private readonly Box tabStrip;
|
||||
public Action RequestBeatmapSelection;
|
||||
|
||||
public readonly MatchTabControl Tabs;
|
||||
|
||||
public Action OnRequestSelectBeatmap;
|
||||
|
||||
public Header(Room room)
|
||||
public Header()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
}
|
||||
|
||||
bindings.Room = room;
|
||||
|
||||
BeatmapTypeInfo beatmapTypeInfo;
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BeatmapSelectButton beatmapButton;
|
||||
UpdateableBeatmapBackgroundSprite background;
|
||||
ModDisplay modDisplay;
|
||||
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
@ -52,7 +48,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both },
|
||||
new HeaderBackgroundSprite { RelativeSizeAxes = Axes.Both },
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -60,12 +56,13 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
},
|
||||
}
|
||||
},
|
||||
tabStrip = new Box
|
||||
new Box
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Colour = colours.Yellow
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -80,7 +77,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
beatmapTypeInfo = new BeatmapTypeInfo(),
|
||||
new BeatmapTypeInfo(),
|
||||
modDisplay = new ModDisplay
|
||||
{
|
||||
Scale = new Vector2(0.75f),
|
||||
@ -95,13 +92,13 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 200,
|
||||
Padding = new MarginPadding { Vertical = 10 },
|
||||
Child = beatmapButton = new BeatmapSelectButton(room)
|
||||
Child = beatmapButton = new BeatmapSelectButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 1,
|
||||
},
|
||||
},
|
||||
Tabs = new MatchTabControl(room)
|
||||
Tabs = new MatchTabControl
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
@ -111,37 +108,36 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
},
|
||||
};
|
||||
|
||||
beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset);
|
||||
beatmapTypeInfo.Type.BindTo(bindings.Type);
|
||||
background.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
bindings.CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true);
|
||||
CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true);
|
||||
|
||||
beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
tabStrip.Colour = colours.Yellow;
|
||||
beatmapButton.Action = () => RequestBeatmapSelection?.Invoke();
|
||||
}
|
||||
|
||||
private class BeatmapSelectButton : HeaderButton
|
||||
{
|
||||
private readonly IBindable<int?> roomIDBind = new Bindable<int?>();
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
|
||||
public BeatmapSelectButton(Room room)
|
||||
public BeatmapSelectButton()
|
||||
{
|
||||
Text = "Select beatmap";
|
||||
}
|
||||
|
||||
roomIDBind.BindTo(room.RoomID);
|
||||
roomIDBind.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true);
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
roomId.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true);
|
||||
}
|
||||
}
|
||||
|
||||
private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite
|
||||
private class HeaderBackgroundSprite : MultiplayerBackgroundSprite
|
||||
{
|
||||
protected override double FadeDuration => 200;
|
||||
protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
private class BackgroundSprite : UpdateableBeatmapBackgroundSprite
|
||||
{
|
||||
protected override double FadeDuration => 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,35 +2,37 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class Info : Container
|
||||
public class Info : MultiplayerComposite
|
||||
{
|
||||
public Action OnStart;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
public Info(Room room)
|
||||
public Info()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ReadyButton readyButton;
|
||||
ViewBeatmapButton viewBeatmapButton;
|
||||
HostInfo hostInfo;
|
||||
RoomStatusInfo statusInfo;
|
||||
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
@ -61,9 +63,9 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
new OsuSpriteText
|
||||
{
|
||||
TextSize = 30,
|
||||
Current = bindings.Name
|
||||
Current = Name
|
||||
},
|
||||
new RoomStatusInfo(room),
|
||||
new RoomStatusInfo(),
|
||||
}
|
||||
},
|
||||
hostInfo = new HostInfo(),
|
||||
@ -80,7 +82,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Children = new Drawable[]
|
||||
{
|
||||
viewBeatmapButton = new ViewBeatmapButton(),
|
||||
readyButton = new ReadyButton(room)
|
||||
readyButton = new ReadyButton
|
||||
{
|
||||
Action = () => OnStart?.Invoke()
|
||||
}
|
||||
@ -90,11 +92,9 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
},
|
||||
};
|
||||
|
||||
viewBeatmapButton.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
readyButton.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
hostInfo.Host.BindTo(bindings.Host);
|
||||
|
||||
bindings.Room = room;
|
||||
viewBeatmapButton.Beatmap.BindTo(CurrentBeatmap);
|
||||
readyButton.Beatmap.BindTo(CurrentBeatmap);
|
||||
hostInfo.Host.BindTo(Host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
@ -9,28 +10,31 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
private readonly Room room;
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
|
||||
[Resolved(typeof(Room), nameof(Room.ChannelId))]
|
||||
private Bindable<int> channelId { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private ChannelManager channelManager { get; set; }
|
||||
|
||||
public MatchChatDisplay(Room room)
|
||||
public MatchChatDisplay()
|
||||
: base(true)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
room.RoomID.BindValueChanged(v => updateChannel(), true);
|
||||
roomId.BindValueChanged(v => updateChannel(), true);
|
||||
}
|
||||
|
||||
private void updateChannel()
|
||||
{
|
||||
if (room.RoomID.Value != null)
|
||||
Channel.Value = channelManager?.JoinChannel(new Channel { Id = room.ChannelId, Type = ChannelType.Multiplayer, Name = $"#mp_{room.RoomID}" });
|
||||
if (roomId.Value != null)
|
||||
Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId, Type = ChannelType.Multiplayer, Name = $"#mp_{roomId.Value}" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
@ -16,18 +17,13 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public Action<IEnumerable<APIRoomScoreInfo>> ScoresLoaded;
|
||||
|
||||
public Room Room
|
||||
{
|
||||
get => bindings.Room;
|
||||
set => bindings.Room = value;
|
||||
}
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
bindings.RoomID.BindValueChanged(id =>
|
||||
roomId.BindValueChanged(id =>
|
||||
{
|
||||
if (id == null)
|
||||
return;
|
||||
@ -39,10 +35,10 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
|
||||
protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback)
|
||||
{
|
||||
if (bindings.RoomID.Value == null)
|
||||
if (roomId.Value == null)
|
||||
return null;
|
||||
|
||||
var req = new GetRoomScoresRequest(bindings.RoomID.Value ?? 0);
|
||||
var req = new GetRoomScoresRequest(roomId.Value ?? 0);
|
||||
|
||||
req.Success += r =>
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -22,43 +23,56 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
private const float transition_duration = 350;
|
||||
private const float field_padding = 45;
|
||||
private const float disabled_alpha = 0.2f;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
protected MatchSettings Settings { get; private set; }
|
||||
|
||||
private readonly Container content;
|
||||
|
||||
private readonly OsuSpriteText typeLabel;
|
||||
|
||||
protected readonly OsuTextBox NameField, MaxParticipantsField;
|
||||
protected readonly OsuDropdown<TimeSpan> DurationField;
|
||||
protected readonly RoomAvailabilityPicker AvailabilityPicker;
|
||||
protected readonly GameTypePicker TypePicker;
|
||||
protected readonly TriangleButton ApplyButton;
|
||||
protected readonly OsuPasswordTextBox PasswordField;
|
||||
|
||||
protected readonly OsuSpriteText ErrorText;
|
||||
|
||||
private readonly ProcessingOverlay processingOverlay;
|
||||
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IRoomManager manager { get; set; }
|
||||
|
||||
public MatchSettingsOverlay(Room room)
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
this.room = room;
|
||||
|
||||
bindings.Room = room;
|
||||
|
||||
Masking = true;
|
||||
|
||||
Child = content = new Container
|
||||
Child = Settings = new MatchSettings
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
RelativePositionAxes = Axes.Y
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
Settings.MoveToY(0, transition_duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
Settings.MoveToY(-1, transition_duration, Easing.InSine);
|
||||
}
|
||||
|
||||
protected class MatchSettings : MultiplayerComposite
|
||||
{
|
||||
private const float disabled_alpha = 0.2f;
|
||||
|
||||
public OsuTextBox NameField, MaxParticipantsField;
|
||||
public OsuDropdown<TimeSpan> DurationField;
|
||||
public RoomAvailabilityPicker AvailabilityPicker;
|
||||
public GameTypePicker TypePicker;
|
||||
public TriangleButton ApplyButton;
|
||||
|
||||
public OsuSpriteText ErrorText;
|
||||
|
||||
private OsuSpriteText typeLabel;
|
||||
private ProcessingOverlay processingOverlay;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IRoomManager manager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Room> currentRoom { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
@ -111,7 +125,10 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
new Section("Room visibility")
|
||||
{
|
||||
Alpha = disabled_alpha,
|
||||
Child = AvailabilityPicker = new RoomAvailabilityPicker(),
|
||||
Child = AvailabilityPicker = new RoomAvailabilityPicker
|
||||
{
|
||||
Enabled = { Value = false }
|
||||
},
|
||||
},
|
||||
new Section("Game type")
|
||||
{
|
||||
@ -127,10 +144,12 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
TypePicker = new GameTypePicker
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Enabled = { Value = false }
|
||||
},
|
||||
typeLabel = new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Colour = colours.Yellow
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -151,7 +170,8 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
TabbableContentContainer = this,
|
||||
OnCommit = (sender, text) => apply(),
|
||||
ReadOnly = true,
|
||||
OnCommit = (sender, text) => apply()
|
||||
},
|
||||
},
|
||||
new Section("Duration")
|
||||
@ -177,10 +197,11 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
new Section("Password (optional)")
|
||||
{
|
||||
Alpha = disabled_alpha,
|
||||
Child = PasswordField = new SettingsPasswordTextBox
|
||||
Child = new SettingsPasswordTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
TabbableContentContainer = this,
|
||||
ReadOnly = true,
|
||||
OnCommit = (sender, text) => apply()
|
||||
},
|
||||
},
|
||||
@ -222,6 +243,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Size = new Vector2(230, 55),
|
||||
Enabled = { Value = false },
|
||||
Action = apply,
|
||||
},
|
||||
ErrorText = new OsuSpriteText
|
||||
@ -229,7 +251,8 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Alpha = 0,
|
||||
Depth = 1
|
||||
Depth = 1,
|
||||
Colour = colours.RedDark
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -239,80 +262,56 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
}
|
||||
},
|
||||
processingOverlay = new ProcessingOverlay { Alpha = 0 }
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
TypePicker.Current.ValueChanged += t => typeLabel.Text = t.Name;
|
||||
TypePicker.Current.BindValueChanged(t => typeLabel.Text = t?.Name ?? string.Empty, true);
|
||||
Name.BindValueChanged(n => NameField.Text = n, true);
|
||||
Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true);
|
||||
Type.BindValueChanged(t => TypePicker.Current.Value = t, true);
|
||||
MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true);
|
||||
Duration.BindValueChanged(d => DurationField.Current.Value = d, true);
|
||||
}
|
||||
|
||||
bindings.Name.BindValueChanged(n => NameField.Text = n, true);
|
||||
bindings.Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true);
|
||||
bindings.Type.BindValueChanged(t => TypePicker.Current.Value = t, true);
|
||||
bindings.MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true);
|
||||
bindings.Duration.BindValueChanged(d => DurationField.Current.Value = d, true);
|
||||
}
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
typeLabel.Colour = colours.Yellow;
|
||||
ErrorText.Colour = colours.RedDark;
|
||||
ApplyButton.Enabled.Value = hasValidSettings;
|
||||
}
|
||||
|
||||
MaxParticipantsField.ReadOnly = true;
|
||||
PasswordField.ReadOnly = true;
|
||||
AvailabilityPicker.Enabled.Value = false;
|
||||
TypePicker.Enabled.Value = false;
|
||||
ApplyButton.Enabled.Value = false;
|
||||
}
|
||||
private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
private void apply()
|
||||
{
|
||||
hideError();
|
||||
|
||||
ApplyButton.Enabled.Value = hasValidSettings;
|
||||
}
|
||||
Name.Value = NameField.Text;
|
||||
Availability.Value = AvailabilityPicker.Current.Value;
|
||||
Type.Value = TypePicker.Current.Value;
|
||||
|
||||
private bool hasValidSettings => bindings.Room.RoomID.Value == null && NameField.Text.Length > 0 && bindings.Playlist.Count > 0;
|
||||
if (int.TryParse(MaxParticipantsField.Text, out int max))
|
||||
MaxParticipants.Value = max;
|
||||
else
|
||||
MaxParticipants.Value = null;
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
content.MoveToY(0, transition_duration, Easing.OutQuint);
|
||||
}
|
||||
Duration.Value = DurationField.Current.Value;
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
content.MoveToY(-1, transition_duration, Easing.InSine);
|
||||
}
|
||||
manager?.CreateRoom(currentRoom, onSuccess, onError);
|
||||
|
||||
private void apply()
|
||||
{
|
||||
hideError();
|
||||
processingOverlay.Show();
|
||||
}
|
||||
|
||||
bindings.Name.Value = NameField.Text;
|
||||
bindings.Availability.Value = AvailabilityPicker.Current.Value;
|
||||
bindings.Type.Value = TypePicker.Current.Value;
|
||||
private void hideError() => ErrorText.FadeOut(50);
|
||||
|
||||
if (int.TryParse(MaxParticipantsField.Text, out int max))
|
||||
bindings.MaxParticipants.Value = max;
|
||||
else
|
||||
bindings.MaxParticipants.Value = null;
|
||||
private void onSuccess(Room room) => processingOverlay.Hide();
|
||||
|
||||
bindings.Duration.Value = DurationField.Current.Value;
|
||||
private void onError(string text)
|
||||
{
|
||||
ErrorText.Text = text;
|
||||
ErrorText.FadeIn(50);
|
||||
|
||||
manager?.CreateRoom(room, onSuccess, onError);
|
||||
|
||||
processingOverlay.Show();
|
||||
}
|
||||
|
||||
private void hideError() => ErrorText.FadeOut(50);
|
||||
|
||||
private void onSuccess(Room room) => processingOverlay.Hide();
|
||||
|
||||
private void onError(string text)
|
||||
{
|
||||
ErrorText.Text = text;
|
||||
ErrorText.FadeIn(50);
|
||||
|
||||
processingOverlay.Hide();
|
||||
processingOverlay.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsTextBox : OsuTextBox
|
||||
|
@ -14,12 +14,11 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchTabControl : PageTabControl<MatchPage>
|
||||
{
|
||||
private readonly IBindable<int?> roomIdBind = new Bindable<int?>();
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
|
||||
public MatchTabControl(Room room)
|
||||
public MatchTabControl()
|
||||
{
|
||||
roomIdBind.BindTo(room.RoomID);
|
||||
|
||||
AddItem(new RoomMatchPage());
|
||||
AddItem(new SettingsMatchPage());
|
||||
}
|
||||
@ -27,7 +26,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
roomIdBind.BindValueChanged(v =>
|
||||
roomId.BindValueChanged(v =>
|
||||
{
|
||||
if (v.HasValue)
|
||||
{
|
||||
|
@ -1,9 +1,8 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
@ -13,16 +12,12 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class Participants : CompositeDrawable
|
||||
public class Participants : MultiplayerComposite
|
||||
{
|
||||
public readonly IBindable<IEnumerable<User>> Users = new Bindable<IEnumerable<User>>();
|
||||
public readonly IBindable<int> ParticipantCount = new Bindable<int>();
|
||||
public readonly IBindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
|
||||
public Participants()
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
FillFlowContainer<UserPanel> usersFlow;
|
||||
ParticipantCountDisplay count;
|
||||
|
||||
InternalChild = new Container
|
||||
{
|
||||
@ -36,7 +31,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Padding = new MarginPadding { Top = 10 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
count = new ParticipantCountDisplay
|
||||
new ParticipantCountDisplay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
@ -55,11 +50,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
},
|
||||
};
|
||||
|
||||
count.Participants.BindTo(Users);
|
||||
count.ParticipantCount.BindTo(ParticipantCount);
|
||||
count.MaxParticipants.BindTo(MaxParticipants);
|
||||
|
||||
Users.BindValueChanged(v =>
|
||||
Participants.BindValueChanged(v =>
|
||||
{
|
||||
usersFlow.Children = v.Select(u => new UserPanel(u)
|
||||
{
|
||||
@ -68,7 +59,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
Width = 300,
|
||||
OnLoadComplete = d => d.FadeInFromZero(60),
|
||||
}).ToList();
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
|
||||
private readonly Room room;
|
||||
[Resolved(typeof(Room), nameof(Room.EndDate))]
|
||||
private Bindable<DateTimeOffset> endDate { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IBindableBeatmap gameBeatmap { get; set; }
|
||||
@ -26,9 +27,8 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
|
||||
private bool hasBeatmap;
|
||||
|
||||
public ReadyButton(Room room)
|
||||
public ReadyButton()
|
||||
{
|
||||
this.room = room;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Size = new Vector2(200, 1);
|
||||
|
||||
@ -77,7 +77,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < room.EndDate;
|
||||
bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate;
|
||||
|
||||
Enabled.Value = hasBeatmap && hasEnoughTime;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
@ -22,130 +23,40 @@ namespace osu.Game.Screens.Multi.Match
|
||||
{
|
||||
public override bool AllowBeatmapRulesetChange => false;
|
||||
|
||||
public override string Title => room.RoomID.Value == null ? "New room" : room.Name.Value;
|
||||
public override string Title { get; }
|
||||
|
||||
public override string ShortTitle => "room";
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
|
||||
private readonly MatchLeaderboard leaderboard;
|
||||
[Resolved(typeof(Room), nameof(Room.Name))]
|
||||
private Bindable<string> name { get; set; }
|
||||
|
||||
private readonly Action<Screen> pushGameplayScreen;
|
||||
|
||||
[Cached]
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
[Resolved(typeof(Room), nameof(Room.Playlist))]
|
||||
private BindableList<PlaylistItem> playlist { get; set; }
|
||||
|
||||
public MatchSubScreen(Room room, Action<Screen> pushGameplayScreen)
|
||||
{
|
||||
this.room = room;
|
||||
this.pushGameplayScreen = pushGameplayScreen;
|
||||
Title = room.RoomID.Value == null ? "New room" : room.Name;
|
||||
|
||||
bindings.Room = room;
|
||||
|
||||
MatchChatDisplay chat;
|
||||
Components.Header header;
|
||||
Info info;
|
||||
GridContainer bottomRow;
|
||||
MatchSettingsOverlay settings;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
InternalChild = new Match(pushGameplayScreen)
|
||||
{
|
||||
new GridContainer
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RequestBeatmapSelection = () => this.Push(new MatchSongSelect
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
Selected = item =>
|
||||
{
|
||||
new Drawable[] { header = new Components.Header(room) { Depth = -1 } },
|
||||
new Drawable[] { info = new Info(room) { OnStart = onStart } },
|
||||
new Drawable[]
|
||||
{
|
||||
bottomRow = new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
leaderboard = new MatchLeaderboard
|
||||
{
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Left = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
|
||||
Right = 10,
|
||||
Vertical = 10,
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Room = room
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Left = 10,
|
||||
Right = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
|
||||
Vertical = 10,
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = chat = new MatchChatDisplay(room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
playlist.Clear();
|
||||
playlist.Add(item);
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.Distributed),
|
||||
}
|
||||
},
|
||||
new Container
|
||||
}),
|
||||
RequestExit = () =>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = Components.Header.HEIGHT },
|
||||
Child = settings = new MatchSettingsOverlay(room) { RelativeSizeAxes = Axes.Both },
|
||||
},
|
||||
};
|
||||
|
||||
header.OnRequestSelectBeatmap = () => this.Push(new MatchSongSelect
|
||||
{
|
||||
Selected = addPlaylistItem,
|
||||
});
|
||||
|
||||
header.Tabs.Current.ValueChanged += t =>
|
||||
{
|
||||
const float fade_duration = 500;
|
||||
if (t is SettingsMatchPage)
|
||||
{
|
||||
settings.Show();
|
||||
info.FadeOut(fade_duration, Easing.OutQuint);
|
||||
bottomRow.FadeOut(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.Hide();
|
||||
info.FadeIn(fade_duration, Easing.OutQuint);
|
||||
bottomRow.FadeIn(fade_duration, Easing.OutQuint);
|
||||
if (this.IsCurrentScreen())
|
||||
this.Exit();
|
||||
}
|
||||
};
|
||||
|
||||
chat.Exit += () =>
|
||||
{
|
||||
if (this.IsCurrentScreen())
|
||||
this.Exit();
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
beatmapManager.ItemAdded += beatmapAdded;
|
||||
}
|
||||
|
||||
public override bool OnExiting(IScreen next)
|
||||
@ -154,73 +65,191 @@ namespace osu.Game.Screens.Multi.Match
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
private class Match : MultiplayerComposite
|
||||
{
|
||||
base.LoadComplete();
|
||||
public Action RequestBeatmapSelection;
|
||||
public Action RequestExit;
|
||||
|
||||
bindings.CurrentBeatmap.BindValueChanged(setBeatmap, true);
|
||||
bindings.CurrentRuleset.BindValueChanged(setRuleset, true);
|
||||
}
|
||||
private readonly Action<Screen> pushGameplayScreen;
|
||||
|
||||
private void setBeatmap(BeatmapInfo beatmap)
|
||||
{
|
||||
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
|
||||
var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID);
|
||||
private MatchLeaderboard leaderboard;
|
||||
|
||||
Game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap));
|
||||
}
|
||||
[Resolved]
|
||||
private IBindableBeatmap gameBeatmap { get; set; }
|
||||
|
||||
private void setRuleset(RulesetInfo ruleset)
|
||||
{
|
||||
if (ruleset == null)
|
||||
return;
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
Game?.ForcefullySetRuleset(ruleset);
|
||||
}
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuGame game { get; set; }
|
||||
|
||||
private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() =>
|
||||
{
|
||||
if (Beatmap.Value != beatmapManager.DefaultBeatmap)
|
||||
return;
|
||||
|
||||
if (bindings.CurrentBeatmap.Value == null)
|
||||
return;
|
||||
|
||||
// Try to retrieve the corresponding local beatmap
|
||||
var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == bindings.CurrentBeatmap.Value.OnlineBeatmapID);
|
||||
|
||||
if (localBeatmap != null)
|
||||
Game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap));
|
||||
});
|
||||
|
||||
private void addPlaylistItem(PlaylistItem item)
|
||||
{
|
||||
bindings.Playlist.Clear();
|
||||
bindings.Playlist.Add(item);
|
||||
}
|
||||
|
||||
private void onStart()
|
||||
{
|
||||
Beatmap.Value.Mods.Value = bindings.CurrentMods.Value.ToArray();
|
||||
|
||||
switch (bindings.Type.Value)
|
||||
public Match(Action<Screen> pushGameplayScreen)
|
||||
{
|
||||
default:
|
||||
case GameTypeTimeshift _:
|
||||
pushGameplayScreen?.Invoke(new PlayerLoader(() => new TimeshiftPlayer(room, room.Playlist.First().ID)
|
||||
{
|
||||
Exited = () => leaderboard.RefreshScores()
|
||||
}));
|
||||
break;
|
||||
this.pushGameplayScreen = pushGameplayScreen;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
MatchChatDisplay chat;
|
||||
Components.Header header;
|
||||
Info info;
|
||||
GridContainer bottomRow;
|
||||
MatchSettingsOverlay settings;
|
||||
|
||||
if (beatmapManager != null)
|
||||
beatmapManager.ItemAdded -= beatmapAdded;
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
header = new Components.Header
|
||||
{
|
||||
Depth = -1,
|
||||
RequestBeatmapSelection = () => RequestBeatmapSelection?.Invoke()
|
||||
}
|
||||
},
|
||||
new Drawable[] { info = new Info { OnStart = onStart } },
|
||||
new Drawable[]
|
||||
{
|
||||
bottomRow = new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
leaderboard = new MatchLeaderboard
|
||||
{
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Left = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
|
||||
Right = 10,
|
||||
Vertical = 10,
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Left = 10,
|
||||
Right = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
|
||||
Vertical = 10,
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = chat = new MatchChatDisplay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.Distributed),
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = Components.Header.HEIGHT },
|
||||
Child = settings = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both },
|
||||
},
|
||||
};
|
||||
|
||||
header.Tabs.Current.BindValueChanged(t =>
|
||||
{
|
||||
const float fade_duration = 500;
|
||||
if (t is SettingsMatchPage)
|
||||
{
|
||||
settings.Show();
|
||||
info.FadeOut(fade_duration, Easing.OutQuint);
|
||||
bottomRow.FadeOut(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.Hide();
|
||||
info.FadeIn(fade_duration, Easing.OutQuint);
|
||||
bottomRow.FadeIn(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
}, true);
|
||||
|
||||
chat.Exit += () => RequestExit?.Invoke();
|
||||
|
||||
beatmapManager.ItemAdded += beatmapAdded;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
CurrentBeatmap.BindValueChanged(setBeatmap, true);
|
||||
CurrentRuleset.BindValueChanged(setRuleset, true);
|
||||
}
|
||||
|
||||
private void setBeatmap(BeatmapInfo beatmap)
|
||||
{
|
||||
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
|
||||
var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID);
|
||||
|
||||
game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap));
|
||||
}
|
||||
|
||||
private void setRuleset(RulesetInfo ruleset)
|
||||
{
|
||||
if (ruleset == null)
|
||||
return;
|
||||
|
||||
game?.ForcefullySetRuleset(ruleset);
|
||||
}
|
||||
|
||||
private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() =>
|
||||
{
|
||||
if (gameBeatmap.Value != beatmapManager.DefaultBeatmap)
|
||||
return;
|
||||
|
||||
if (CurrentBeatmap.Value == null)
|
||||
return;
|
||||
|
||||
// Try to retrieve the corresponding local beatmap
|
||||
var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == CurrentBeatmap.Value.OnlineBeatmapID);
|
||||
|
||||
if (localBeatmap != null)
|
||||
game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap));
|
||||
});
|
||||
|
||||
private void onStart()
|
||||
{
|
||||
gameBeatmap.Value.Mods.Value = CurrentMods.Value.ToArray();
|
||||
|
||||
switch (Type.Value)
|
||||
{
|
||||
default:
|
||||
case GameTypeTimeshift _:
|
||||
pushGameplayScreen?.Invoke(new PlayerLoader(() => new TimeshiftPlayer(Playlist.First())
|
||||
{
|
||||
Exited = () => leaderboard.RefreshScores()
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (beatmapManager != null)
|
||||
beatmapManager.ItemAdded -= beatmapAdded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapSet.Buttons;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Multi.Lounge;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
using osu.Game.Screens.Multi.Match;
|
||||
using osuTK;
|
||||
|
||||
@ -48,6 +49,14 @@ namespace osu.Game.Screens.Multi
|
||||
private readonly LoungeSubScreen loungeSubScreen;
|
||||
private readonly ScreenStack screenStack;
|
||||
|
||||
private readonly IBindable<bool> isIdle = new BindableBool();
|
||||
|
||||
[Cached]
|
||||
private readonly Bindable<Room> currentRoom = new Bindable<Room>();
|
||||
|
||||
[Cached]
|
||||
private readonly Bindable<FilterCriteria> currentFilter = new Bindable<FilterCriteria>();
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private RoomManager roomManager;
|
||||
|
||||
@ -74,7 +83,7 @@ namespace osu.Game.Screens.Multi
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
|
||||
screenStack = new ScreenStack(loungeSubScreen = new LoungeSubScreen(this.Push)) { RelativeSizeAxes = Axes.Both };
|
||||
screenStack = new ScreenStack(loungeSubScreen = new LoungeSubScreen(pushGameplayScreen)) { RelativeSizeAxes = Axes.Both };
|
||||
Padding = new MarginPadding { Horizontal = -OsuScreen.HORIZONTAL_OVERFLOW_PADDING };
|
||||
|
||||
waves.AddRange(new Drawable[]
|
||||
@ -118,7 +127,7 @@ namespace osu.Game.Screens.Multi
|
||||
Right = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
|
||||
},
|
||||
Text = "Create room",
|
||||
Action = () => loungeSubScreen.Push(new Room
|
||||
Action = () => loungeSubScreen.Open(new Room
|
||||
{
|
||||
Name = { Value = $"{api.LocalUser}'s awesome room" }
|
||||
}),
|
||||
@ -130,8 +139,6 @@ namespace osu.Game.Screens.Multi
|
||||
screenStack.ScreenExited += screenExited;
|
||||
}
|
||||
|
||||
private readonly IBindable<bool> isIdle = new BindableBool();
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(IdleTracker idleTracker)
|
||||
{
|
||||
@ -147,12 +154,29 @@ namespace osu.Game.Screens.Multi
|
||||
isIdle.BindValueChanged(updatePollingRate, true);
|
||||
}
|
||||
|
||||
private CachedModelDependencyContainer<Room> dependencies;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
|
||||
dependencies.Model.BindTo(currentRoom);
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private void updatePollingRate(bool idle)
|
||||
{
|
||||
roomManager.TimeBetweenPolls = !this.IsCurrentScreen() || !(screenStack.CurrentScreen is LoungeSubScreen) ? 0 : (idle ? 120000 : 15000);
|
||||
Logger.Log($"Polling adjusted to {roomManager.TimeBetweenPolls}");
|
||||
}
|
||||
|
||||
private void pushGameplayScreen(IScreen gameplayScreen)
|
||||
{
|
||||
if (!this.IsCurrentScreen())
|
||||
return;
|
||||
|
||||
this.Push(gameplayScreen);
|
||||
}
|
||||
|
||||
public void APIStateChanged(APIAccess api, APIState state)
|
||||
{
|
||||
if (state != APIState.Online)
|
||||
|
86
osu.Game/Screens/Multi/MultiplayerComposite.cs
Normal file
86
osu.Game/Screens/Multi/MultiplayerComposite.cs
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public class MultiplayerComposite : CompositeDrawable
|
||||
{
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<int?> RoomID { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<string> Name { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<User> Host { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<RoomStatus> Status { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<GameType> Type { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected BindableList<PlaylistItem> Playlist { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<IEnumerable<User>> Participants { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<int> ParticipantCount { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<int?> MaxParticipants { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<DateTimeOffset> EndDate { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<RoomAvailability> Availability { get; private set; }
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected Bindable<TimeSpan> Duration { get; private set; }
|
||||
|
||||
private readonly Bindable<BeatmapInfo> currentBeatmap = new Bindable<BeatmapInfo>();
|
||||
protected IBindable<BeatmapInfo> CurrentBeatmap => currentBeatmap;
|
||||
|
||||
private readonly Bindable<IEnumerable<Mod>> currentMods = new Bindable<IEnumerable<Mod>>();
|
||||
protected IBindable<IEnumerable<Mod>> CurrentMods => currentMods;
|
||||
|
||||
private readonly Bindable<RulesetInfo> currentRuleset = new Bindable<RulesetInfo>();
|
||||
protected IBindable<RulesetInfo> CurrentRuleset => currentRuleset;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Playlist.ItemsAdded += _ => updatePlaylist();
|
||||
Playlist.ItemsRemoved += _ => updatePlaylist();
|
||||
|
||||
updatePlaylist();
|
||||
}
|
||||
|
||||
private void updatePlaylist()
|
||||
{
|
||||
// Todo: We only ever have one playlist item for now. In the future, this will be user-settable
|
||||
|
||||
var playlistItem = Playlist.FirstOrDefault();
|
||||
|
||||
currentBeatmap.Value = playlistItem?.Beatmap;
|
||||
currentMods.Value = playlistItem?.RequiredMods ?? Enumerable.Empty<Mod>();
|
||||
currentRuleset.Value = playlistItem?.Ruleset;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Online.API;
|
||||
@ -21,16 +22,17 @@ namespace osu.Game.Screens.Multi.Play
|
||||
{
|
||||
public Action Exited;
|
||||
|
||||
private readonly Room room;
|
||||
private readonly int playlistItemId;
|
||||
[Resolved(typeof(Room), nameof(Room.RoomID))]
|
||||
private Bindable<int?> roomId { get; set; }
|
||||
|
||||
private readonly PlaylistItem playlistItem;
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
public TimeshiftPlayer(Room room, int playlistItemId)
|
||||
public TimeshiftPlayer(PlaylistItem playlistItem)
|
||||
{
|
||||
this.room = room;
|
||||
this.playlistItemId = playlistItemId;
|
||||
this.playlistItem = playlistItem;
|
||||
}
|
||||
|
||||
private int? token;
|
||||
@ -42,7 +44,7 @@ namespace osu.Game.Screens.Multi.Play
|
||||
|
||||
bool failed = false;
|
||||
|
||||
var req = new CreateRoomScoreRequest(room.RoomID.Value ?? 0, playlistItemId);
|
||||
var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID);
|
||||
req.Success += r => token = r.ID;
|
||||
req.Failure += e =>
|
||||
{
|
||||
@ -87,7 +89,7 @@ namespace osu.Game.Screens.Multi.Play
|
||||
|
||||
Debug.Assert(token != null);
|
||||
|
||||
var request = new SubmitRoomScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score);
|
||||
var request = new SubmitRoomScoreRequest(token.Value, roomId.Value ?? 0, playlistItem.ID, score);
|
||||
request.Failure += e => Logger.Error(e, "Failed to submit score");
|
||||
api.Queue(request);
|
||||
}
|
||||
@ -99,6 +101,6 @@ namespace osu.Game.Screens.Multi.Play
|
||||
Exited = null;
|
||||
}
|
||||
|
||||
protected override Results CreateResults(ScoreInfo score) => new MatchResults(score, room);
|
||||
protected override Results CreateResults(ScoreInfo score) => new MatchResults(score);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Ranking.Types;
|
||||
using osu.Game.Screens.Ranking;
|
||||
@ -12,19 +11,16 @@ namespace osu.Game.Screens.Multi.Ranking
|
||||
{
|
||||
public class MatchResults : Results
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
public MatchResults(ScoreInfo score, Room room)
|
||||
public MatchResults(ScoreInfo score)
|
||||
: base(score)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
|
||||
{
|
||||
new ScoreOverviewPageInfo(Score, Beatmap),
|
||||
new LocalLeaderboardPageInfo(Score, Beatmap),
|
||||
new RoomLeaderboardPageInfo(Score, Beatmap, room),
|
||||
new RoomLeaderboardPageInfo(Score, Beatmap),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -23,16 +24,15 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
|
||||
{
|
||||
public class RoomLeaderboardPage : ResultsPage
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
private OsuColour colours;
|
||||
|
||||
private TextFlowContainer rankText;
|
||||
|
||||
public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
[Resolved(typeof(Room), nameof(Room.Name))]
|
||||
private Bindable<string> name { get; set; }
|
||||
|
||||
public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap)
|
||||
: base(score, beatmap)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -53,7 +53,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BackgroundColour = colours.Gray6,
|
||||
Child = leaderboard = CreateLeaderboard(room)
|
||||
Child = leaderboard = CreateLeaderboard()
|
||||
},
|
||||
rankText = new TextFlowContainer
|
||||
{
|
||||
@ -84,7 +84,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
|
||||
s.Colour = colours.GrayF;
|
||||
};
|
||||
|
||||
rankText.AddText(room.Name + "\n", white);
|
||||
rankText.AddText(name + "\n", white);
|
||||
rankText.AddText("You are placed ", gray);
|
||||
|
||||
int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer<APIRoomScoreInfo>((s1, s2) => s1.User.Id.Equals(s2.User.Id)));
|
||||
@ -98,15 +98,10 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
|
||||
rankText.AddText("in the room!", gray);
|
||||
}
|
||||
|
||||
protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new ResultsMatchLeaderboard(room);
|
||||
protected virtual MatchLeaderboard CreateLeaderboard() => new ResultsMatchLeaderboard();
|
||||
|
||||
public class ResultsMatchLeaderboard : MatchLeaderboard
|
||||
{
|
||||
public ResultsMatchLeaderboard(Room room)
|
||||
{
|
||||
Room = room;
|
||||
}
|
||||
|
||||
protected override bool FadeTop => true;
|
||||
|
||||
protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index)
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Ranking.Pages;
|
||||
using osu.Game.Screens.Ranking;
|
||||
@ -14,19 +13,17 @@ namespace osu.Game.Screens.Multi.Ranking.Types
|
||||
{
|
||||
private readonly ScoreInfo score;
|
||||
private readonly WorkingBeatmap beatmap;
|
||||
private readonly Room room;
|
||||
|
||||
public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
|
||||
{
|
||||
this.score = score;
|
||||
this.beatmap = beatmap;
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public FontAwesome Icon => FontAwesome.fa_users;
|
||||
|
||||
public string Name => "Room Leaderboard";
|
||||
|
||||
public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap, room);
|
||||
public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -1,106 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class which binds to values from a <see cref="Room"/>.
|
||||
/// </summary>
|
||||
public class RoomBindings
|
||||
{
|
||||
public RoomBindings()
|
||||
{
|
||||
Playlist.ItemsAdded += _ => updatePlaylist();
|
||||
Playlist.ItemsRemoved += _ => updatePlaylist();
|
||||
}
|
||||
|
||||
private Room room;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Room"/> to bind to.
|
||||
/// </summary>
|
||||
public Room Room
|
||||
{
|
||||
get => room;
|
||||
set
|
||||
{
|
||||
if (room == value)
|
||||
return;
|
||||
|
||||
if (room != null)
|
||||
{
|
||||
RoomID.UnbindFrom(room.RoomID);
|
||||
Name.UnbindFrom(room.Name);
|
||||
Host.UnbindFrom(room.Host);
|
||||
Status.UnbindFrom(room.Status);
|
||||
Type.UnbindFrom(room.Type);
|
||||
Playlist.UnbindFrom(room.Playlist);
|
||||
Participants.UnbindFrom(room.Participants);
|
||||
ParticipantCount.UnbindFrom(room.ParticipantCount);
|
||||
MaxParticipants.UnbindFrom(room.MaxParticipants);
|
||||
EndDate.UnbindFrom(room.EndDate);
|
||||
Availability.UnbindFrom(room.Availability);
|
||||
Duration.UnbindFrom(room.Duration);
|
||||
}
|
||||
|
||||
room = value ?? new Room();
|
||||
|
||||
RoomID.BindTo(room.RoomID);
|
||||
Name.BindTo(room.Name);
|
||||
Host.BindTo(room.Host);
|
||||
Status.BindTo(room.Status);
|
||||
Type.BindTo(room.Type);
|
||||
Playlist.BindTo(room.Playlist);
|
||||
Participants.BindTo(room.Participants);
|
||||
ParticipantCount.BindTo(room.ParticipantCount);
|
||||
MaxParticipants.BindTo(room.MaxParticipants);
|
||||
EndDate.BindTo(room.EndDate);
|
||||
Availability.BindTo(room.Availability);
|
||||
Duration.BindTo(room.Duration);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePlaylist()
|
||||
{
|
||||
// Todo: We only ever have one playlist item for now. In the future, this will be user-settable
|
||||
|
||||
var playlistItem = Playlist.FirstOrDefault();
|
||||
|
||||
currentBeatmap.Value = playlistItem?.Beatmap;
|
||||
currentMods.Value = playlistItem?.RequiredMods ?? Enumerable.Empty<Mod>();
|
||||
currentRuleset.Value = playlistItem?.Ruleset;
|
||||
}
|
||||
|
||||
public readonly Bindable<int?> RoomID = new Bindable<int?>();
|
||||
public readonly Bindable<string> Name = new Bindable<string>();
|
||||
public readonly Bindable<User> Host = new Bindable<User>();
|
||||
public readonly Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
|
||||
public readonly Bindable<GameType> Type = new Bindable<GameType>();
|
||||
public readonly BindableList<PlaylistItem> Playlist = new BindableList<PlaylistItem>();
|
||||
public readonly Bindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
public readonly Bindable<int> ParticipantCount = new Bindable<int>();
|
||||
public readonly Bindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
public readonly Bindable<DateTimeOffset> EndDate = new Bindable<DateTimeOffset>();
|
||||
public readonly Bindable<RoomAvailability> Availability = new Bindable<RoomAvailability>();
|
||||
public readonly Bindable<TimeSpan> Duration = new Bindable<TimeSpan>();
|
||||
|
||||
private readonly Bindable<BeatmapInfo> currentBeatmap = new Bindable<BeatmapInfo>();
|
||||
public IBindable<BeatmapInfo> CurrentBeatmap => currentBeatmap;
|
||||
|
||||
private readonly Bindable<IEnumerable<Mod>> currentMods = new Bindable<IEnumerable<Mod>>();
|
||||
public IBindable<IEnumerable<Mod>> CurrentMods => currentMods;
|
||||
|
||||
private readonly Bindable<RulesetInfo> currentRuleset = new Bindable<RulesetInfo>();
|
||||
public IBindable<RulesetInfo> CurrentRuleset => currentRuleset;
|
||||
}
|
||||
}
|
@ -24,9 +24,10 @@ namespace osu.Game.Screens.Multi
|
||||
private readonly BindableList<Room> rooms = new BindableList<Room>();
|
||||
public IBindableList<Room> Rooms => rooms;
|
||||
|
||||
private Room currentRoom;
|
||||
private Room joinedRoom;
|
||||
|
||||
private FilterCriteria currentFilter = new FilterCriteria();
|
||||
[Resolved]
|
||||
private Bindable<FilterCriteria> currentFilter { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
@ -37,6 +38,16 @@ namespace osu.Game.Screens.Multi
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
currentFilter.BindValueChanged(_ =>
|
||||
{
|
||||
if (IsLoaded)
|
||||
PollImmediately();
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
@ -51,11 +62,12 @@ namespace osu.Game.Screens.Multi
|
||||
|
||||
req.Success += result =>
|
||||
{
|
||||
joinedRoom = room;
|
||||
|
||||
update(room, result);
|
||||
addRoom(room);
|
||||
|
||||
RoomsUpdated?.Invoke();
|
||||
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
@ -80,7 +92,7 @@ namespace osu.Game.Screens.Multi
|
||||
currentJoinRoomRequest = new JoinRoomRequest(room, api.LocalUser.Value);
|
||||
currentJoinRoomRequest.Success += () =>
|
||||
{
|
||||
currentRoom = room;
|
||||
joinedRoom = room;
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
@ -95,17 +107,11 @@ namespace osu.Game.Screens.Multi
|
||||
|
||||
public void PartRoom()
|
||||
{
|
||||
if (currentRoom == null)
|
||||
if (joinedRoom == null)
|
||||
return;
|
||||
|
||||
api.Queue(new PartRoomRequest(currentRoom, api.LocalUser.Value));
|
||||
currentRoom = null;
|
||||
}
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
{
|
||||
currentFilter = criteria;
|
||||
PollImmediately();
|
||||
api.Queue(new PartRoomRequest(joinedRoom, api.LocalUser.Value));
|
||||
joinedRoom = null;
|
||||
}
|
||||
|
||||
private GetRoomsRequest pollReq;
|
||||
@ -118,7 +124,7 @@ namespace osu.Game.Screens.Multi
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
pollReq?.Cancel();
|
||||
pollReq = new GetRoomsRequest(currentFilter.PrimaryFilter);
|
||||
pollReq = new GetRoomsRequest(currentFilter.Value.PrimaryFilter);
|
||||
|
||||
pollReq.Success += result =>
|
||||
{
|
||||
@ -132,14 +138,13 @@ namespace osu.Game.Screens.Multi
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
var r = result[i];
|
||||
r.Position = i;
|
||||
r.Position.Value = i;
|
||||
|
||||
update(r, r);
|
||||
addRoom(r);
|
||||
}
|
||||
|
||||
RoomsUpdated?.Invoke();
|
||||
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
|
||||
|
30
osu.Game/Tests/Visual/MultiplayerTestCase.cs
Normal file
30
osu.Game/Tests/Visual/MultiplayerTestCase.cs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class MultiplayerTestCase : OsuTestCase
|
||||
{
|
||||
[Cached]
|
||||
private readonly Bindable<Room> currentRoom = new Bindable<Room>(new Room());
|
||||
|
||||
protected Room Room
|
||||
{
|
||||
get => currentRoom;
|
||||
set => currentRoom.Value = value;
|
||||
}
|
||||
|
||||
private CachedModelDependencyContainer<Room> dependencies;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
|
||||
dependencies.Model.BindTo(currentRoom);
|
||||
return dependencies;
|
||||
}
|
||||
}
|
||||
}
|
@ -105,12 +105,12 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.128.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2019.131.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.131.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2019.208.1" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.208.1" />
|
||||
<PackageReference Include="SharpCompress" Version="0.22.0" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2019.110.0" ExcludeAssets="all" />
|
||||
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2019.208.0" ExcludeAssets="all" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user