1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 13:33:52 +08:00

Merge remote-tracking branch 'upstream/master' into tournament-tools

# Conflicts:
#	osu.Game.Tournament.Tests/TestCaseDrawings.cs
#	osu.Game/osu.Game.csproj
This commit is contained in:
Dean Herbert 2019-02-17 17:25:09 +09:00
commit f0743ebecf
127 changed files with 1362 additions and 1197 deletions

3
.vscode/tasks.json vendored
View File

@ -70,7 +70,8 @@
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"restore" "restore",
"osu.sln"
], ],
"problemMatcher": [] "problemMatcher": []
} }

View File

@ -75,7 +75,7 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g
## Code analysis ## Code analysis
Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under windows due to [resharper cli shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternative, you can install resharper or use rider to get inline support in your IDE of choice. Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under windows due to [resharper cli shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install resharper or use rider to get inline support in your IDE of choice.
# Contributing # Contributing

View File

@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
base.SkinChanged(skin, allowFallback); base.SkinChanged(skin, allowFallback);
if (HitObject is IHasComboInformation combo) if (HitObject is IHasComboInformation combo)
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : Color4.White); AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
} }
private const float preempt = 1000; private const float preempt = 1000;

View File

@ -43,6 +43,6 @@ namespace osu.Game.Rulesets.Catch.Scoring
Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness;
} }
protected override HitWindows CreateHitWindows() => new CatchHitWindows(); public override HitWindows CreateHitWindows() => new CatchHitWindows();
} }
} }

View File

@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
difficultyHitObjects.AddRange(beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime)); difficultyHitObjects.AddRange(beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime));
if (!calculateStrainValues(difficultyHitObjects, timeRate)) if (!calculateStrainValues(difficultyHitObjects, timeRate))
return new DifficultyAttributes(mods, 0); return new ManiaDifficultyAttributes(mods, 0);
double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor;

View File

@ -159,6 +159,6 @@ namespace osu.Game.Rulesets.Mania.Scoring
} }
} }
protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); public override HitWindows CreateHitWindows() => new ManiaHitWindows();
} }
} }

View File

@ -0,0 +1,36 @@
// 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 NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Osu.Objects;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests
{
[TestFixture]
public class TestCaseHitCircleLongCombo : Game.Tests.Visual.TestCasePlayer
{
public TestCaseHitCircleLongCombo()
: base(new OsuRuleset())
{
}
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
Ruleset = ruleset.RulesetInfo
}
};
for (int i = 0; i < 512; i++)
beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 });
return beatmap;
}
}
}

View File

@ -143,7 +143,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime); var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime);
foreach (var time in scoringTimes) foreach (var time in scoringTimes)
computeVertex(time); computeVertex(time);
computeVertex(slider.EndTime);
} }
private Vector2 getEndCursorPosition(OsuHitObject hitObject) private Vector2 getEndCursorPosition(OsuHitObject hitObject)

View File

@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
base.SkinChanged(skin, allowFallback); base.SkinChanged(skin, allowFallback);
if (HitObject is IHasComboInformation combo) if (HitObject is IHasComboInformation combo)
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : Color4.White); AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
} }
protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn); protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn);

View File

@ -156,9 +156,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.SkinChanged(skin, allowFallback); base.SkinChanged(skin, allowFallback);
Body.AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : Body.AccentColour); Body.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour;
Body.BorderColour = skin.GetValue<SkinConfiguration, Color4>(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : Body.BorderColour); Body.BorderColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour;
Ball.AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : Ball.AccentColour); Ball.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour;
} }
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)

View File

@ -74,6 +74,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement);
protected override HitWindows CreateHitWindows() => new OsuHitWindows(); public override HitWindows CreateHitWindows() => new OsuHitWindows();
} }
} }

View File

@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config, IBindableBeatmap beatmap) private void load(OsuConfigManager config, IBindable<WorkingBeatmap> beatmap)
{ {
InternalChild = expandTarget = new Container InternalChild = expandTarget = new Container
{ {

View File

@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
if (!calculateStrainValues(difficultyHitObjects, timeRate)) if (!calculateStrainValues(difficultyHitObjects, timeRate))
return new DifficultyAttributes(mods, 0); return new TaikoDifficultyAttributes(mods, 0);
double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor;

View File

@ -67,6 +67,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring
Health.Value = 0; Health.Value = 0;
} }
protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); public override HitWindows CreateHitWindows() => new TaikoHitWindows();
} }
} }

View File

@ -0,0 +1,2 @@
[General]
Name: test skin

View File

@ -0,0 +1,8 @@
[General]
Name: test skin
[Colours]
Combo1 : 142,199,255
Combo2 : 255,128,128
Combo3 : 128,255,255
Combo7 : 100,100,100,100

View File

@ -0,0 +1,44 @@
// 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.IO;
using NUnit.Framework;
using osu.Game.Skinning;
using osu.Game.Tests.Resources;
using osuTK.Graphics;
namespace osu.Game.Tests.Skins
{
[TestFixture]
public class LegacySkinDecoderTest
{
[TestCase(true)]
[TestCase(false)]
public void TestDecodeSkinColours(bool hasColours)
{
var decoder = new LegacySkinDecoder();
using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini"))
using (var stream = new StreamReader(resStream))
{
var comboColors = decoder.Decode(stream).ComboColours;
List<Color4> expectedColors;
if (hasColours)
expectedColors = new List<Color4>
{
new Color4(142, 199, 255, 255),
new Color4(255, 128, 128, 255),
new Color4(128, 255, 255, 255),
new Color4(100, 100, 100, 100),
};
else
expectedColors = new DefaultSkin().Configuration.ComboColours;
Assert.AreEqual(expectedColors.Count, comboColors.Count);
for (int i = 0; i < expectedColors.Count; i++)
Assert.AreEqual(expectedColors[i], comboColors[i]);
}
}
}
}

View File

@ -2,27 +2,16 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseDisclaimer : OsuTestCase public class TestCaseDisclaimer : ScreenTestCase
{ {
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Children = new Drawable[] LoadScreen(new Disclaimer());
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
},
new Disclaimer()
};
} }
} }
} }

View File

@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IAdjustableClock adjustableClock, IBindableBeatmap beatmap) private void load(IAdjustableClock adjustableClock, IBindable<WorkingBeatmap> beatmap)
{ {
this.adjustableClock = adjustableClock; this.adjustableClock = adjustableClock;
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);

View File

@ -16,7 +16,7 @@ using osuTK.Graphics;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseLoungeRoomsContainer : OsuTestCase public class TestCaseLoungeRoomsContainer : MultiplayerTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] 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)); AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
AddStep("select first room", () => container.Rooms.First().Action?.Invoke()); 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()); AddStep("join first room", () => container.Rooms.First().Action?.Invoke());
AddAssert("first room joined", () => roomManager.Rooms.First().Status.Value is JoinedRoomStatus); AddAssert("first room joined", () => roomManager.Rooms.First().Status.Value is JoinedRoomStatus);
@ -71,7 +71,11 @@ namespace osu.Game.Tests.Visual
private class TestRoomManager : IRoomManager private class TestRoomManager : IRoomManager
{ {
public event Action RoomsUpdated; public event Action RoomsUpdated
{
add { }
remove { }
}
public readonly BindableList<Room> Rooms = new BindableList<Room>(); public readonly BindableList<Room> Rooms = new BindableList<Room>();
IBindableList<Room> IRoomManager.Rooms => Rooms; IBindableList<Room> IRoomManager.Rooms => Rooms;
@ -85,10 +89,6 @@ namespace osu.Game.Tests.Visual
public void PartRoom() public void PartRoom()
{ {
} }
public void Filter(FilterCriteria criteria)
{
}
} }
private class JoinedRoomStatus : RoomStatus private class JoinedRoomStatus : RoomStatus

View File

@ -12,7 +12,7 @@ using osu.Game.Screens.Multi.Match.Components;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseMatchHeader : OsuTestCase public class TestCaseMatchHeader : MultiplayerTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -21,11 +21,7 @@ namespace osu.Game.Tests.Visual
public TestCaseMatchHeader() public TestCaseMatchHeader()
{ {
var room = new Room(); Room.Playlist.Add(new PlaylistItem
var header = new Header(room);
room.Playlist.Add(new PlaylistItem
{ {
Beatmap = new BeatmapInfo 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();
} }
} }
} }

View File

@ -14,7 +14,7 @@ using osu.Game.Screens.Multi.Match.Components;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
[TestFixture] [TestFixture]
public class TestCaseMatchInfo : OsuTestCase public class TestCaseMatchInfo : MultiplayerTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -27,18 +27,15 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(RulesetStore rulesets) private void load(RulesetStore rulesets)
{ {
var room = new Room(); Add(new Info());
Info info = new Info(room); AddStep(@"set name", () => Room.Name.Value = @"Room Name?");
Add(info); 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", () => AddStep(@"set beatmap", () =>
{ {
room.Playlist.Clear(); Room.Playlist.Clear();
room.Playlist.Add(new PlaylistItem Room.Playlist.Add(new PlaylistItem
{ {
Beatmap = new BeatmapInfo Beatmap = new BeatmapInfo
{ {
@ -54,14 +51,14 @@ namespace osu.Game.Tests.Visual
}); });
}); });
AddStep(@"change name", () => room.Name.Value = @"Room Name!"); AddStep(@"change name", () => Room.Name.Value = @"Room Name!");
AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.InviteOnly); AddStep(@"change availability", () => Room.Availability.Value = RoomAvailability.InviteOnly);
AddStep(@"change status", () => room.Status.Value = new RoomStatusOpen()); AddStep(@"change status", () => Room.Status.Value = new RoomStatusOpen());
AddStep(@"null beatmap", () => room.Playlist.Clear()); AddStep(@"null beatmap", () => Room.Playlist.Clear());
AddStep(@"change beatmap", () => AddStep(@"change beatmap", () =>
{ {
room.Playlist.Clear(); Room.Playlist.Clear();
room.Playlist.Add(new PlaylistItem Room.Playlist.Add(new PlaylistItem
{ {
Beatmap = new BeatmapInfo Beatmap = new BeatmapInfo
{ {

View File

@ -6,24 +6,24 @@ using Newtonsoft.Json;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
using osu.Game.Users; using osu.Game.Users;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseMatchLeaderboard : OsuTestCase public class TestCaseMatchLeaderboard : MultiplayerTestCase
{ {
public TestCaseMatchLeaderboard() public TestCaseMatchLeaderboard()
{ {
Room.RoomID.Value = 3;
Add(new MatchLeaderboard Add(new MatchLeaderboard
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f), Size = new Vector2(550f, 450f),
Scope = MatchLeaderboardScope.Overall, Scope = MatchLeaderboardScope.Overall,
Room = new Room { RoomID = { Value = 3 } }
}); });
} }

View File

@ -1,9 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
using osu.Game.Users; using osu.Game.Users;
@ -11,22 +9,14 @@ using osu.Game.Users;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
[TestFixture] [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() public TestCaseMatchParticipants()
{ {
Participants participants; Add(new Participants { RelativeSizeAxes = Axes.Both });
Add(participants = new Participants { RelativeSizeAxes = Axes.Both }); AddStep(@"set max to null", () => Room.MaxParticipants.Value = null);
AddStep(@"set users", () => Room.Participants.Value = new[]
participants.MaxParticipants.BindTo(maxParticipants);
participants.Users.BindTo(users);
AddStep(@"set max to null", () => maxParticipants.Value = null);
AddStep(@"set users", () => users.Value = new[]
{ {
new User new User
{ {
@ -54,9 +44,9 @@ namespace osu.Game.Tests.Visual
}, },
}); });
AddStep(@"set max", () => maxParticipants.Value = 10); AddStep(@"set max", () => Room.MaxParticipants.Value = 10);
AddStep(@"clear users", () => users.Value = new User[] { }); AddStep(@"clear users", () => Room.Participants.Value = new User[] { });
AddStep(@"set max to null", () => maxParticipants.Value = null); AddStep(@"set max to null", () => Room.MaxParticipants.Value = null);
} }
} }
} }

View File

@ -8,7 +8,6 @@ using osu.Framework.Allocation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Multiplayer;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Multi.Ranking;
@ -19,7 +18,7 @@ using osu.Game.Users;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseMatchResults : OsuTestCase public class TestCaseMatchResults : MultiplayerTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -38,68 +37,52 @@ namespace osu.Game.Tests.Visual
if (beatmapInfo != null) if (beatmapInfo != null)
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
Child = new TestMatchResults(new ScoreInfo Room.RoomID.Value = 1;
Room.Name.Value = "an awesome room";
LoadScreen(new TestMatchResults(new ScoreInfo
{ {
User = new User { Id = 10 }, User = new User { Id = 10 },
}); }));
} }
private class TestMatchResults : MatchResults private class TestMatchResults : MatchResults
{ {
private readonly Room room;
public TestMatchResults(ScoreInfo score) public TestMatchResults(ScoreInfo score)
: this(score, new Room : base(score)
{
RoomID = { Value = 1 },
Name = { Value = "an awesome room" }
})
{ {
} }
public TestMatchResults(ScoreInfo score, Room room) protected override IEnumerable<IResultPageInfo> CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap.Value) };
: base(score, room)
{
this.room = room;
}
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap, room) };
} }
private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo
{ {
private readonly ScoreInfo score; private readonly ScoreInfo score;
private readonly WorkingBeatmap beatmap; private readonly WorkingBeatmap beatmap;
private readonly Room room;
public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room) public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
: base(score, beatmap, room) : base(score, beatmap)
{ {
this.score = score; this.score = score;
this.beatmap = beatmap; 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 private class TestRoomLeaderboardPage : RoomLeaderboardPage
{ {
public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap)
: base(score, beatmap, room) : base(score, beatmap)
{ {
} }
protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room); protected override MatchLeaderboard CreateLeaderboard() => new TestMatchLeaderboard();
} }
private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard
{ {
public TestMatchLeaderboard(Room room)
: base(room)
{
}
protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback) protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback)
{ {
var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray(); var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray();

View File

@ -13,12 +13,11 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi; using osu.Game.Screens.Multi;
using osu.Game.Screens.Multi.Lounge.Components;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseMatchSettingsOverlay : OsuTestCase public class TestCaseMatchSettingsOverlay : MultiplayerTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -28,14 +27,14 @@ namespace osu.Game.Tests.Visual
[Cached(Type = typeof(IRoomManager))] [Cached(Type = typeof(IRoomManager))]
private TestRoomManager roomManager = new TestRoomManager(); private TestRoomManager roomManager = new TestRoomManager();
private Room room;
private TestRoomSettings settings; private TestRoomSettings settings;
[SetUp] [SetUp]
public void Setup() => Schedule(() => public void Setup() => Schedule(() =>
{ {
room = new Room(); Room = new Room();
settings = new TestRoomSettings(room)
settings = new TestRoomSettings
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
State = Visibility.Visible State = Visibility.Visible
@ -49,19 +48,19 @@ namespace osu.Game.Tests.Visual
{ {
AddStep("clear name and beatmap", () => AddStep("clear name and beatmap", () =>
{ {
room.Name.Value = ""; Room.Name.Value = "";
room.Playlist.Clear(); Room.Playlist.Clear();
}); });
AddAssert("button disabled", () => !settings.ApplyButton.Enabled); 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); 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); AddAssert("button enabled", () => settings.ApplyButton.Enabled);
AddStep("clear name", () => room.Name.Value = ""); AddStep("clear name", () => Room.Name.Value = "");
AddAssert("button disabled", () => !settings.ApplyButton.Enabled); AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
} }
@ -117,17 +116,12 @@ namespace osu.Game.Tests.Visual
private class TestRoomSettings : MatchSettingsOverlay private class TestRoomSettings : MatchSettingsOverlay
{ {
public new TriangleButton ApplyButton => base.ApplyButton; public TriangleButton ApplyButton => Settings.ApplyButton;
public new OsuTextBox NameField => base.NameField; public OsuTextBox NameField => Settings.NameField;
public new OsuDropdown<TimeSpan> DurationField => base.DurationField; public OsuDropdown<TimeSpan> DurationField => Settings.DurationField;
public new OsuSpriteText ErrorText => base.ErrorText; public OsuSpriteText ErrorText => Settings.ErrorText;
public TestRoomSettings(Room room)
: base(room)
{
}
} }
private class TestRoomManager : IRoomManager private class TestRoomManager : IRoomManager
@ -136,7 +130,11 @@ namespace osu.Game.Tests.Visual
public Func<Room, bool> CreateRequested; public Func<Room, bool> CreateRequested;
public event Action RoomsUpdated; public event Action RoomsUpdated
{
add { }
remove { }
}
public IBindableList<Room> Rooms { get; } = null; 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 JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => throw new NotImplementedException();
public void PartRoom() => throw new NotImplementedException(); public void PartRoom() => throw new NotImplementedException();
public void Filter(FilterCriteria criteria) => throw new NotImplementedException();
} }
} }
} }

View File

@ -12,7 +12,7 @@ using osu.Game.Screens.Multi.Lounge.Components;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
[TestFixture] [TestFixture]
public class TestCaseMultiScreen : OsuTestCase public class TestCaseMultiScreen : ScreenTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual
{ {
Multiplayer multi = new Multiplayer(); Multiplayer multi = new Multiplayer();
AddStep(@"show", () => Add(multi)); AddStep(@"show", () => LoadScreen(multi));
AddWaitStep(5); AddWaitStep(5);
AddStep(@"exit", multi.Exit); AddStep(@"exit", multi.Exit);
} }

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Screens;
using osu.Game.Screens; using osu.Game.Screens;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osuTK.Graphics; using osuTK.Graphics;
@ -29,7 +30,10 @@ namespace osu.Game.Tests.Visual
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = Color4.Black, Colour = Color4.Black,
}, },
new Loader() new ScreenStack(new Loader())
{
RelativeSizeAxes = Axes.Both,
}
}; };
} }
} }

View File

@ -1,6 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Framework.Screens;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Backgrounds;
@ -14,7 +16,10 @@ namespace osu.Game.Tests.Visual
Add(parallax = new ParallaxContainer Add(parallax = new ParallaxContainer
{ {
Child = new BackgroundScreenDefault { Alpha = 0.8f } Child = new ScreenStack(new BackgroundScreenDefault { Alpha = 0.8f })
{
RelativeSizeAxes = Axes.Both,
}
}); });
AddStep("default parallax", () => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT); AddStep("default parallax", () => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT);

View File

@ -12,6 +12,7 @@ using osu.Framework.Configuration;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -25,7 +26,7 @@ using osu.Game.Screens.Select.Filter;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
[TestFixture] [TestFixture]
public class TestCasePlaySongSelect : OsuTestCase public class TestCasePlaySongSelect : ScreenTestCase
{ {
private BeatmapManager manager; private BeatmapManager manager;
@ -102,21 +103,16 @@ namespace osu.Game.Tests.Visual
} }
[SetUp] [SetUp]
public virtual void SetUp() public virtual void SetUp() =>
{ Schedule(() => { manager?.Delete(manager.GetAllUsableBeatmapSets()); });
Schedule(() =>
{
manager?.Delete(manager.GetAllUsableBeatmapSets());
Child = songSelect = new TestSongSelect();
});
}
[Test] [Test]
public void TestDummy() public void TestDummy()
{ {
createSongSelect();
AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap); AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap);
AddAssert("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap); AddUntilStep(() => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap, "dummy shown on wedge");
addManyTestMaps(); addManyTestMaps();
AddWaitStep(3); AddWaitStep(3);
@ -127,6 +123,7 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void TestSorting() public void TestSorting()
{ {
createSongSelect();
addManyTestMaps(); addManyTestMaps();
AddWaitStep(3); AddWaitStep(3);
@ -142,6 +139,7 @@ namespace osu.Game.Tests.Visual
[Ignore("needs fixing")] [Ignore("needs fixing")]
public void TestImportUnderDifferentRuleset() public void TestImportUnderDifferentRuleset()
{ {
createSongSelect();
changeRuleset(2); changeRuleset(2);
importForRuleset(0); importForRuleset(0);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection"); AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection");
@ -150,6 +148,7 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void TestImportUnderCurrentRuleset() public void TestImportUnderCurrentRuleset()
{ {
createSongSelect();
changeRuleset(2); changeRuleset(2);
importForRuleset(2); importForRuleset(2);
importForRuleset(1); importForRuleset(1);
@ -165,6 +164,7 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void TestRulesetChangeResetsMods() public void TestRulesetChangeResetsMods()
{ {
createSongSelect();
changeRuleset(0); changeRuleset(0);
changeMods(new OsuModHardRock()); changeMods(new OsuModHardRock());
@ -194,6 +194,7 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void TestStartAfterUnMatchingFilterDoesNotStart() public void TestStartAfterUnMatchingFilterDoesNotStart()
{ {
createSongSelect();
addManyTestMaps(); addManyTestMaps();
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap != null, "has selection"); AddUntilStep(() => songSelect.Carousel.SelectedBeatmap != null, "has selection");
@ -221,6 +222,12 @@ namespace osu.Game.Tests.Visual
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
private void createSongSelect()
{
AddStep("create song select", () => LoadScreen(songSelect = new TestSongSelect()));
AddUntilStep(() => songSelect.IsCurrentScreen(), "wait for present");
}
private void addManyTestMaps() private void addManyTestMaps()
{ {
AddStep("import test maps", () => AddStep("import test maps", () =>

View File

@ -3,6 +3,7 @@
using System.Threading; using System.Threading;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
@ -12,28 +13,37 @@ namespace osu.Game.Tests.Visual
public class TestCasePlayerLoader : ManualInputManagerTestCase public class TestCasePlayerLoader : ManualInputManagerTestCase
{ {
private PlayerLoader loader; private PlayerLoader loader;
private ScreenStack stack;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGameBase game) private void load(OsuGameBase game)
{ {
Beatmap.Value = new DummyWorkingBeatmap(game); Beatmap.Value = new DummyWorkingBeatmap(game);
AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(() => new Player InputManager.Add(stack = new ScreenStack { RelativeSizeAxes = Axes.Both });
AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player
{ {
AllowPause = false, AllowPause = false,
AllowLeadIn = false, AllowLeadIn = false,
AllowResults = false, AllowResults = false,
}))); })));
AddUntilStep(() => loader.IsCurrentScreen(), "wait for current");
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
AddUntilStep(() => !loader.IsCurrentScreen(), "wait for no longer current"); AddUntilStep(() => !loader.IsCurrentScreen(), "wait for no longer current");
AddStep("exit loader", () => loader.Exit());
AddUntilStep(() => !loader.IsAlive, "wait for no longer alive");
AddStep("load slow dummy beatmap", () => AddStep("load slow dummy beatmap", () =>
{ {
SlowLoadPlayer slow = null; SlowLoadPlayer slow = null;
Add(loader = new PlayerLoader(() => slow = new SlowLoadPlayer stack.Push(loader = new PlayerLoader(() => slow = new SlowLoadPlayer
{ {
AllowPause = false, AllowPause = false,
AllowLeadIn = false, AllowLeadIn = false,

View File

@ -16,7 +16,7 @@ using osu.Game.Users;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
[TestFixture] [TestFixture]
public class TestCaseResults : OsuTestCase public class TestCaseResults : ScreenTestCase
{ {
private BeatmapManager beatmaps; private BeatmapManager beatmaps;
@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual
if (beatmapInfo != null) if (beatmapInfo != null)
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
Add(new SoloResults(new ScoreInfo LoadScreen(new SoloResults(new ScoreInfo
{ {
TotalScore = 2845370, TotalScore = 2845370,
Accuracy = 0.98, Accuracy = 0.98,

View File

@ -9,11 +9,11 @@ using osu.Game.Tournament.Screens.Drawings.Components;
namespace osu.Game.Tournament.Tests namespace osu.Game.Tournament.Tests
{ {
public class TestCaseDrawings : OsuTestCase public class TestCaseDrawings : ScreenTestCase
{ {
public TestCaseDrawings() public TestCaseDrawings()
{ {
Add(new DrawingsScreen LoadScreen(new DrawingsScreen
{ {
TeamList = new TestTeamList(), TeamList = new TestTeamList(),
}); });

View File

@ -12,9 +12,9 @@ namespace osu.Game.Beatmaps
{ {
/// <summary> /// <summary>
/// A <see cref="Bindable{WorkingBeatmap}"/> for the <see cref="OsuGame"/> beatmap. /// A <see cref="Bindable{WorkingBeatmap}"/> for the <see cref="OsuGame"/> beatmap.
/// This should be used sparingly in-favour of <see cref="IBindableBeatmap"/>. /// This should be used sparingly in-favour of <see cref="IBindable<WorkingBeatmap>"/>.
/// </summary> /// </summary>
public abstract class BindableBeatmap : NonNullableBindable<WorkingBeatmap>, IBindableBeatmap public abstract class BindableBeatmap : NonNullableBindable<WorkingBeatmap>
{ {
private AudioManager audioManager; private AudioManager audioManager;
private WorkingBeatmap lastBeatmap; private WorkingBeatmap lastBeatmap;
@ -62,9 +62,6 @@ namespace osu.Game.Beatmaps
lastBeatmap = beatmap; lastBeatmap = beatmap;
} }
[NotNull]
IBindableBeatmap IBindableBeatmap.GetBoundCopy() => GetBoundCopy();
/// <summary> /// <summary>
/// Retrieve a new <see cref="BindableBeatmap"/> instance weakly bound to this <see cref="BindableBeatmap"/>. /// Retrieve a new <see cref="BindableBeatmap"/> instance weakly bound to this <see cref="BindableBeatmap"/>.
/// If you are further binding to events of the retrieved <see cref="BindableBeatmap"/>, ensure a local reference is held. /// If you are further binding to events of the retrieved <see cref="BindableBeatmap"/>, ensure a local reference is held.

View File

@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.Drawables
/// </summary> /// </summary>
public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable<BeatmapInfo> public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable<BeatmapInfo>
{ {
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>(); public readonly Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; }

View File

@ -1,19 +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 osu.Framework.Configuration;
namespace osu.Game.Beatmaps
{
/// <summary>
/// Read-only interface for the <see cref="OsuGame"/> beatmap.
/// </summary>
public interface IBindableBeatmap : IBindable<WorkingBeatmap>
{
/// <summary>
/// Retrieve a new <see cref="IBindableBeatmap"/> instance weakly bound to this <see cref="IBindableBeatmap"/>.
/// If you are further binding to events of the retrieved <see cref="IBindableBeatmap"/>, ensure a local reference is held.
/// </summary>
IBindableBeatmap GetBoundCopy();
}
}

View File

@ -74,7 +74,7 @@ namespace osu.Game.Graphics.Containers
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap) private void load(IBindable<WorkingBeatmap> beatmap)
{ {
Beatmap.BindTo(beatmap); Beatmap.BindTo(beatmap);
} }

View File

@ -9,12 +9,13 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Platform; using osu.Framework.Platform;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public class OsuPasswordTextBox : OsuTextBox public class OsuPasswordTextBox : OsuTextBox, ISuppressKeyEventLogging
{ {
protected override Drawable GetDrawableCharacter(char c) => new PasswordMaskChar(CalculatedTextSize); protected override Drawable GetDrawableCharacter(char c) => new PasswordMaskChar(CalculatedTextSize);

View File

@ -1,9 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.Configuration;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -37,10 +37,10 @@ namespace osu.Game.Online.Multiplayer
public RulesetInfo Ruleset { get; set; } public RulesetInfo Ruleset { get; set; }
[JsonIgnore] [JsonIgnore]
public readonly BindableList<Mod> AllowedMods = new BindableList<Mod>(); public readonly List<Mod> AllowedMods = new List<Mod>();
[JsonIgnore] [JsonIgnore]
public readonly BindableList<Mod> RequiredMods = new BindableList<Mod>(); public readonly List<Mod> RequiredMods = new List<Mod>();
[JsonProperty("beatmap")] [JsonProperty("beatmap")]
private APIBeatmap apiBeatmap { get; set; } private APIBeatmap apiBeatmap { get; set; }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.Allocation;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Online.Multiplayer.GameTypes;
using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Online.Multiplayer.RoomStatuses;
@ -14,44 +15,73 @@ namespace osu.Game.Online.Multiplayer
{ {
public class Room public class Room
{ {
[Cached]
[JsonProperty("id")] [JsonProperty("id")]
public Bindable<int?> RoomID { get; private set; } = new Bindable<int?>(); public Bindable<int?> RoomID { get; private set; } = new Bindable<int?>();
[Cached]
[JsonProperty("name")] [JsonProperty("name")]
public Bindable<string> Name { get; private set; } = new Bindable<string>(); public Bindable<string> Name { get; private set; } = new Bindable<string>();
[Cached]
[JsonProperty("host")] [JsonProperty("host")]
public Bindable<User> Host { get; private set; } = new Bindable<User>(); public Bindable<User> Host { get; private set; } = new Bindable<User>();
[Cached]
[JsonProperty("playlist")] [JsonProperty("playlist")]
public BindableList<PlaylistItem> Playlist { get; set; } = new BindableList<PlaylistItem>(); public BindableList<PlaylistItem> Playlist { get; private set; } = new BindableList<PlaylistItem>();
[Cached]
[JsonIgnore]
public Bindable<PlaylistItem> CurrentItem { get; private set; } = new Bindable<PlaylistItem>();
[Cached]
[JsonProperty("channel_id")] [JsonProperty("channel_id")]
public Bindable<int> ChannelId { get; private set; } = new Bindable<int>(); public Bindable<int> ChannelId { get; private set; } = new Bindable<int>();
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<TimeSpan> Duration { get; private set; } = new Bindable<TimeSpan>(TimeSpan.FromMinutes(30)); public Bindable<TimeSpan> Duration { get; private set; } = new Bindable<TimeSpan>(TimeSpan.FromMinutes(30));
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<int?> MaxAttempts { get; private set; } = new Bindable<int?>(); public Bindable<int?> MaxAttempts { get; private set; } = new Bindable<int?>();
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<RoomStatus> Status { get; private set; } = new Bindable<RoomStatus>(new RoomStatusOpen()); public Bindable<RoomStatus> Status { get; private set; } = new Bindable<RoomStatus>(new RoomStatusOpen());
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<RoomAvailability> Availability { get; private set; } = new Bindable<RoomAvailability>(); public Bindable<RoomAvailability> Availability { get; private set; } = new Bindable<RoomAvailability>();
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<GameType> Type { get; private set; } = new Bindable<GameType>(new GameTypeTimeshift()); public Bindable<GameType> Type { get; private set; } = new Bindable<GameType>(new GameTypeTimeshift());
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<int?> MaxParticipants { get; private set; } = new Bindable<int?>(); public Bindable<int?> MaxParticipants { get; private set; } = new Bindable<int?>();
[Cached]
[JsonIgnore] [JsonIgnore]
public Bindable<IEnumerable<User>> Participants { get; private set; } = new Bindable<IEnumerable<User>>(Enumerable.Empty<User>()); 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>(); public Bindable<int> ParticipantCount { get; private set; } = new Bindable<int>();
public Room()
{
Playlist.ItemsAdded += updateCurrent;
Playlist.ItemsRemoved += updateCurrent;
updateCurrent(Playlist);
}
private void updateCurrent(IEnumerable<PlaylistItem> playlist)
{
CurrentItem.Value = playlist.FirstOrDefault();
}
// todo: TEMPORARY // todo: TEMPORARY
[JsonProperty("participant_count")] [JsonProperty("participant_count")]
private int? participantCount private int? participantCount
@ -68,6 +98,7 @@ namespace osu.Game.Online.Multiplayer
} }
// Only supports retrieval for now // Only supports retrieval for now
[Cached]
[JsonProperty("ends_at")] [JsonProperty("ends_at")]
public Bindable<DateTimeOffset> EndDate { get; private set; } = new Bindable<DateTimeOffset>(); public Bindable<DateTimeOffset> EndDate { get; private set; } = new Bindable<DateTimeOffset>();
@ -83,7 +114,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. /// The position of this <see cref="Room"/> in the list. This is not read from or written to the API.
/// </summary> /// </summary>
[JsonIgnore] [JsonIgnore]
public int Position = -1; public Bindable<int> Position { get; private set; } = new Bindable<int>(-1);
public void CopyFrom(Room other) public void CopyFrom(Room other)
{ {

View File

@ -292,7 +292,7 @@ namespace osu.Game
return; return;
} }
if ((screenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange != true) if ((screenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false)
{ {
notifications.Post(new SimpleNotification notifications.Post(new SimpleNotification
{ {
@ -311,7 +311,7 @@ namespace osu.Game
void loadScore() void loadScore()
{ {
if (!menuScreen.IsCurrentScreen()) if (!menuScreen.IsCurrentScreen() || Beatmap.Disabled)
{ {
menuScreen.MakeCurrent(); menuScreen.MakeCurrent();
this.Delay(500).Schedule(loadScore, out scoreLoad); this.Delay(500).Schedule(loadScore, out scoreLoad);
@ -337,6 +337,11 @@ namespace osu.Game
{ {
base.LoadComplete(); base.LoadComplete();
// The next time this is updated is in UpdateAfterChildren, which occurs too late and results
// in the cursor being shown for a few frames during the intro.
// This prevents the cursor from showing until we have a screen with CursorVisible = true
MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false;
// todo: all archive managers should be able to be looped here. // todo: all archive managers should be able to be looped here.
SkinManager.PostNotification = n => notifications?.Post(n); SkinManager.PostNotification = n => notifications?.Post(n);
SkinManager.GetStableStorage = GetStorageForStableInstall; SkinManager.GetStableStorage = GetStorageForStableInstall;
@ -723,46 +728,13 @@ namespace osu.Game
{ {
base.UpdateAfterChildren(); base.UpdateAfterChildren();
// we only want to apply these restrictions when we are inside a screen stack.
// the use case for not applying is in visual/unit tests.
bool applyBeatmapRulesetRestrictions = !(screenStack.CurrentScreen as IOsuScreen)?.AllowBeatmapRulesetChange ?? false;
ruleset.Disabled = applyBeatmapRulesetRestrictions;
Beatmap.Disabled = applyBeatmapRulesetRestrictions;
screenContainer.Padding = new MarginPadding { Top = ToolbarOffset }; screenContainer.Padding = new MarginPadding { Top = ToolbarOffset };
overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; overlayContent.Padding = new MarginPadding { Top = ToolbarOffset };
MenuCursorContainer.CanShowCursor = (screenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; MenuCursorContainer.CanShowCursor = (screenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false;
} }
/// <summary> protected virtual void ScreenChanged(IScreen current, IScreen newScreen)
/// Sets <see cref="Beatmap"/> while ignoring any beatmap.
/// </summary>
/// <param name="beatmap">The beatmap to set.</param>
public void ForcefullySetBeatmap(WorkingBeatmap beatmap)
{
var beatmapDisabled = Beatmap.Disabled;
Beatmap.Disabled = false;
Beatmap.Value = beatmap;
Beatmap.Disabled = beatmapDisabled;
}
/// <summary>
/// Sets <see cref="Ruleset"/> while ignoring any ruleset restrictions.
/// </summary>
/// <param name="beatmap">The beatmap to set.</param>
public void ForcefullySetRuleset(RulesetInfo ruleset)
{
var rulesetDisabled = this.ruleset.Disabled;
this.ruleset.Disabled = false;
this.ruleset.Value = ruleset;
this.ruleset.Disabled = rulesetDisabled;
}
protected virtual void ScreenChanged(IScreen lastScreen, IScreen newScreen)
{ {
switch (newScreen) switch (newScreen)
{ {

View File

@ -69,8 +69,9 @@ namespace osu.Game
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private OsuBindableBeatmap beatmap; private Bindable<WorkingBeatmap> beatmap;
protected BindableBeatmap Beatmap => beatmap;
protected Bindable<WorkingBeatmap> Beatmap => beatmap;
private Bindable<bool> fpsDisplayVisible; private Bindable<bool> fpsDisplayVisible;
@ -155,7 +156,6 @@ namespace osu.Game
dependencies.CacheAs<IAPIProvider>(API); dependencies.CacheAs<IAPIProvider>(API);
var defaultBeatmap = new DummyWorkingBeatmap(this); var defaultBeatmap = new DummyWorkingBeatmap(this);
beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio);
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
@ -174,8 +174,10 @@ namespace osu.Game
// this adds a global reduction of track volume for the time being. // this adds a global reduction of track volume for the time being.
Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));
dependencies.CacheAs<BindableBeatmap>(beatmap); beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio);
dependencies.CacheAs<IBindableBeatmap>(beatmap);
dependencies.CacheAs<IBindable<WorkingBeatmap>>(beatmap);
dependencies.CacheAs(beatmap);
FileStore.Cleanup(); FileStore.Cleanup();

View File

@ -70,7 +70,10 @@ namespace osu.Game.Overlays
Colour = Color4.Black, Colour = Color4.Black,
Alpha = 0.9f, Alpha = 0.9f,
}, },
welcomeScreen = new ScreenWelcome(), new ScreenStack(welcomeScreen = new ScreenWelcome())
{
RelativeSizeAxes = Axes.Both,
},
} }
} }
} }

View File

@ -11,6 +11,9 @@ using osu.Game.Online.API.Requests;
namespace osu.Game.Overlays.Direct namespace osu.Game.Overlays.Direct
{ {
/// <summary>
/// A component which tracks a beatmap through potential download/import/deletion.
/// </summary>
public abstract class DownloadTrackingComposite : CompositeDrawable public abstract class DownloadTrackingComposite : CompositeDrawable
{ {
public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>(); public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>();
@ -51,6 +54,7 @@ namespace osu.Game.Overlays.Direct
}; };
beatmaps.ItemAdded += setAdded; beatmaps.ItemAdded += setAdded;
beatmaps.ItemRemoved += setRemoved;
} }
#region Disposal #region Disposal
@ -105,27 +109,22 @@ namespace osu.Game.Overlays.Direct
} }
} }
private void onRequestSuccess(string data) private void onRequestSuccess(string _) => Schedule(() => State.Value = DownloadState.Downloaded);
{
Schedule(() => State.Value = DownloadState.Downloaded);
}
private void onRequestProgress(float progress) private void onRequestProgress(float progress) => Schedule(() => Progress.Value = progress);
{
Schedule(() => Progress.Value = progress);
}
private void onRequestFailure(Exception e) private void onRequestFailure(Exception e) => Schedule(() => attachDownload(null));
{
Schedule(() => attachDownload(null));
}
private void setAdded(BeatmapSetInfo s, bool existing, bool silent) private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => setDownloadStateFromManager(s, DownloadState.LocallyAvailable);
private void setRemoved(BeatmapSetInfo s) => setDownloadStateFromManager(s, DownloadState.NotDownloaded);
private void setDownloadStateFromManager(BeatmapSetInfo s, DownloadState state) => Schedule(() =>
{ {
if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID) if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID)
return; return;
Schedule(() => State.Value = DownloadState.LocallyAvailable); State.Value = state;
} });
} }
} }

View File

@ -9,7 +9,7 @@ namespace osu.Game.Overlays.KeyBinding
{ {
public class GlobalKeyBindingsSection : SettingsSection public class GlobalKeyBindingsSection : SettingsSection
{ {
public override FontAwesome Icon => FontAwesome.fa_osu_hot; public override FontAwesome Icon => FontAwesome.fa_globe;
public override string Header => "Global"; public override string Header => "Global";
public GlobalKeyBindingsSection(GlobalActionContainer manager) public GlobalKeyBindingsSection(GlobalActionContainer manager)

View File

@ -9,7 +9,7 @@ namespace osu.Game.Overlays.KeyBinding
{ {
public class RulesetBindingsSection : SettingsSection public class RulesetBindingsSection : SettingsSection
{ {
public override FontAwesome Icon => FontAwesome.fa_osu_hot; public override FontAwesome Icon => (ruleset.CreateInstance().CreateIcon() as SpriteIcon)?.Icon ?? FontAwesome.fa_osu_hot;
public override string Header => ruleset.Name; public override string Header => ruleset.Name;
private readonly RulesetInfo ruleset; private readonly RulesetInfo ruleset;

View File

@ -3,10 +3,17 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Overlays.KeyBinding; using osu.Game.Overlays.KeyBinding;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Screens.Ranking;
using osuTK;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
@ -21,11 +28,85 @@ namespace osu.Game.Overlays
foreach (var ruleset in rulesets.AvailableRulesets) foreach (var ruleset in rulesets.AvailableRulesets)
AddSection(new RulesetBindingsSection(ruleset)); AddSection(new RulesetBindingsSection(ruleset));
AddInternal(new BackButton
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Action = Hide
});
} }
public KeyBindingOverlay() public KeyBindingOverlay()
: base(false) : base(true)
{ {
} }
private class BackButton : OsuClickableContainer, IKeyBindingHandler<GlobalAction>
{
private AspectContainer aspect;
[BackgroundDependencyLoader]
private void load()
{
Size = new Vector2(Sidebar.DEFAULT_WIDTH);
Children = new Drawable[]
{
aspect = new AspectContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = -15,
Size = new Vector2(15),
Shadow = true,
Icon = FontAwesome.fa_chevron_left
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = 15,
TextSize = 12,
Font = @"Exo2.0-Bold",
Text = @"back",
},
}
}
};
}
protected override bool OnMouseDown(MouseDownEvent e)
{
aspect.ScaleTo(0.75f, 2000, Easing.OutQuint);
return base.OnMouseDown(e);
}
protected override bool OnMouseUp(MouseUpEvent e)
{
aspect.ScaleTo(1, 1000, Easing.OutElastic);
return base.OnMouseUp(e);
}
public bool OnPressed(GlobalAction action)
{
switch (action)
{
case GlobalAction.Back:
Click();
return true;
}
return false;
}
public bool OnReleased(GlobalAction action) => false;
}
} }
} }

View File

@ -1,28 +1,19 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Input.Bindings;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Game.Overlays.Settings.Sections; using osu.Game.Overlays.Settings.Sections;
using osu.Game.Screens.Ranking;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using System.Collections.Generic;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
public class MainSettings : SettingsOverlay public class MainSettings : SettingsOverlay
{ {
private readonly KeyBindingOverlay keyBindingOverlay; private readonly KeyBindingOverlay keyBindingOverlay;
private BackButton backButton;
protected override IEnumerable<SettingsSection> CreateSections() => new SettingsSection[] protected override IEnumerable<SettingsSection> CreateSections() => new SettingsSection[]
{ {
@ -53,8 +44,6 @@ namespace osu.Game.Overlays
public override bool AcceptsFocus => keyBindingOverlay.State != Visibility.Visible; public override bool AcceptsFocus => keyBindingOverlay.State != Visibility.Visible;
private const float hidden_width = 120;
private void keyBindingOverlay_StateChanged(Visibility visibility) private void keyBindingOverlay_StateChanged(Visibility visibility)
{ {
switch (visibility) switch (visibility)
@ -64,9 +53,7 @@ namespace osu.Game.Overlays
Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint); Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint);
SectionsContainer.FadeOut(300, Easing.OutQuint); SectionsContainer.FadeOut(300, Easing.OutQuint);
ContentContainer.MoveToX(hidden_width - WIDTH, 500, Easing.OutQuint); ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint);
backButton.Delay(100).FadeIn(100);
break; break;
case Visibility.Hidden: case Visibility.Hidden:
Background.FadeTo(0.6f, 500, Easing.OutQuint); Background.FadeTo(0.6f, 500, Easing.OutQuint);
@ -74,94 +61,16 @@ namespace osu.Game.Overlays
SectionsContainer.FadeIn(500, Easing.OutQuint); SectionsContainer.FadeIn(500, Easing.OutQuint);
ContentContainer.MoveToX(0, 500, Easing.OutQuint); ContentContainer.MoveToX(0, 500, Easing.OutQuint);
backButton.FadeOut(100);
break; break;
} }
} }
protected override float ExpandedPosition => keyBindingOverlay.State == Visibility.Visible ? hidden_width - WIDTH : base.ExpandedPosition; protected override float ExpandedPosition => keyBindingOverlay.State == Visibility.Visible ? -WIDTH : base.ExpandedPosition;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
ContentContainer.Add(keyBindingOverlay); ContentContainer.Add(keyBindingOverlay);
ContentContainer.Add(backButton = new BackButton
{
Alpha = 0,
Width = hidden_width,
RelativeSizeAxes = Axes.Y,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Action = () => keyBindingOverlay.Hide()
});
}
private class BackButton : OsuClickableContainer, IKeyBindingHandler<GlobalAction>
{
private AspectContainer aspect;
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
aspect = new AspectContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = -15,
Size = new Vector2(15),
Shadow = true,
Icon = FontAwesome.fa_chevron_left
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = 15,
TextSize = 12,
Font = @"Exo2.0-Bold",
Text = @"back",
},
}
}
};
}
protected override bool OnMouseDown(MouseDownEvent e)
{
aspect.ScaleTo(0.75f, 2000, Easing.OutQuint);
return base.OnMouseDown(e);
}
protected override bool OnMouseUp(MouseUpEvent e)
{
aspect.ScaleTo(1, 1000, Easing.OutElastic);
return base.OnMouseUp(e);
}
public bool OnPressed(GlobalAction action)
{
switch (action)
{
case GlobalAction.Back:
Click();
return true;
}
return false;
}
public bool OnReleased(GlobalAction action) => false;
} }
} }
} }

View File

@ -169,6 +169,8 @@ namespace osu.Game.Overlays.Music
Alpha = 0f; Alpha = 0f;
Margin = new MarginPadding { Left = 5, Top = 2 }; Margin = new MarginPadding { Left = 5, Top = 2 };
} }
public override bool HandlePositionalInput => IsPresent;
} }
} }

View File

@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Music
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(BeatmapManager beatmaps, IBindableBeatmap beatmap) private void load(BeatmapManager beatmaps, IBindable<WorkingBeatmap> beatmap)
{ {
beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false, false)); beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false, false));
beatmaps.ItemAdded += addBeatmapSet; beatmaps.ItemAdded += addBeatmapSet;

View File

@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Music
private PlaylistList list; private PlaylistList list;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, BindableBeatmap beatmap, BeatmapManager beatmaps) private void load(OsuColour colours, Bindable<WorkingBeatmap> beatmap, BeatmapManager beatmaps)
{ {
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);
this.beatmaps = beatmaps; this.beatmaps = beatmaps;

View File

@ -66,7 +66,7 @@ namespace osu.Game.Overlays
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(BindableBeatmap beatmap, BeatmapManager beatmaps, OsuColour colours) private void load(Bindable<WorkingBeatmap> beatmap, BeatmapManager beatmaps, OsuColour colours)
{ {
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);
this.beatmaps = beatmaps; this.beatmaps = beatmaps;

View File

@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Edit
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap, IFrameBasedClock framedClock) private void load(IBindable<WorkingBeatmap> beatmap, IFrameBasedClock framedClock)
{ {
Beatmap.BindTo(beatmap); Beatmap.BindTo(beatmap);

View File

@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Edit
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap, IAdjustableClock clock) private void load(IBindable<WorkingBeatmap> beatmap, IAdjustableClock clock)
{ {
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);

View File

@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Scoring
/// <summary> /// <summary>
/// Create a <see cref="HitWindows"/> for this processor. /// Create a <see cref="HitWindows"/> for this processor.
/// </summary> /// </summary>
protected virtual HitWindows CreateHitWindows() => new HitWindows(); public virtual HitWindows CreateHitWindows() => new HitWindows();
/// <summary> /// <summary>
/// The current rank. /// The current rank.

View File

@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.UI
private WorkingBeatmap beatmap; private WorkingBeatmap beatmap;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap) private void load(IBindable<WorkingBeatmap> beatmap)
{ {
this.beatmap = beatmap.Value; this.beatmap = beatmap.Value;
} }

View File

@ -57,12 +57,32 @@ namespace osu.Game.Scoring.Legacy
var countKatu = (int)sr.ReadUInt16(); var countKatu = (int)sr.ReadUInt16();
var countMiss = (int)sr.ReadUInt16(); var countMiss = (int)sr.ReadUInt16();
score.ScoreInfo.Statistics[HitResult.Great] = count300; switch (currentRuleset.LegacyID)
score.ScoreInfo.Statistics[HitResult.Good] = count100; {
score.ScoreInfo.Statistics[HitResult.Meh] = count50; case 0:
score.ScoreInfo.Statistics[HitResult.Perfect] = countGeki; score.ScoreInfo.Statistics[HitResult.Great] = count300;
score.ScoreInfo.Statistics[HitResult.Ok] = countKatu; score.ScoreInfo.Statistics[HitResult.Good] = count100;
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; score.ScoreInfo.Statistics[HitResult.Meh] = count50;
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
break;
case 1:
score.ScoreInfo.Statistics[HitResult.Great] = count300;
score.ScoreInfo.Statistics[HitResult.Good] = count100;
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
break;
case 2:
score.ScoreInfo.Statistics[HitResult.Perfect] = count300;
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
break;
case 3:
score.ScoreInfo.Statistics[HitResult.Perfect] = countGeki;
score.ScoreInfo.Statistics[HitResult.Great] = count300;
score.ScoreInfo.Statistics[HitResult.Good] = countKatu;
score.ScoreInfo.Statistics[HitResult.Ok] = count100;
score.ScoreInfo.Statistics[HitResult.Meh] = count50;
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
break;
}
score.ScoreInfo.TotalScore = sr.ReadInt32(); score.ScoreInfo.TotalScore = sr.ReadInt32();
score.ScoreInfo.MaxCombo = sr.ReadUInt16(); score.ScoreInfo.MaxCombo = sr.ReadUInt16();
@ -116,12 +136,12 @@ namespace osu.Game.Scoring.Legacy
protected void CalculateAccuracy(ScoreInfo score) protected void CalculateAccuracy(ScoreInfo score)
{ {
int countMiss = score.Statistics[HitResult.Miss]; score.Statistics.TryGetValue(HitResult.Miss, out int countMiss);
int count50 = score.Statistics[HitResult.Meh]; score.Statistics.TryGetValue(HitResult.Meh, out int count50);
int count100 = score.Statistics[HitResult.Good]; score.Statistics.TryGetValue(HitResult.Good, out int count100);
int count300 = score.Statistics[HitResult.Great]; score.Statistics.TryGetValue(HitResult.Great, out int count300);
int countGeki = score.Statistics[HitResult.Perfect]; score.Statistics.TryGetValue(HitResult.Perfect, out int countGeki);
int countKatu = score.Statistics[HitResult.Ok]; score.Statistics.TryGetValue(HitResult.Ok, out int countKatu);
switch (score.Ruleset.ID) switch (score.Ruleset.ID)
{ {

View File

@ -14,6 +14,8 @@ namespace osu.Game.Screens
{ {
Scale = new Vector2(1.06f); Scale = new Vector2(1.06f);
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
} }
//public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; } //public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; }

View File

@ -42,7 +42,7 @@ namespace osu.Game.Screens.Edit.Components
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap, OsuColour colours) private void load(IBindable<WorkingBeatmap> beatmap, OsuColour colours)
{ {
Beatmap.BindTo(beatmap); Beatmap.BindTo(beatmap);
background.Colour = colours.Gray1; background.Colour = colours.Gray1;

View File

@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap) private void load(IBindable<WorkingBeatmap> beatmap)
{ {
Beatmap.BindTo(beatmap); Beatmap.BindTo(beatmap);
} }

View File

@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private WaveformGraph waveform; private WaveformGraph waveform;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap, IAdjustableClock adjustableClock, OsuColour colours) private void load(IBindable<WorkingBeatmap> beatmap, IAdjustableClock adjustableClock, OsuColour colours)
{ {
this.adjustableClock = adjustableClock; this.adjustableClock = adjustableClock;

View File

@ -29,7 +29,8 @@ namespace osu.Game.Screens.Edit
protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4");
public override bool HideOverlaysOnEnter => true; public override bool HideOverlaysOnEnter => true;
public override bool AllowBeatmapRulesetChange => false;
public override bool DisallowExternalBeatmapRulesetChanges => true;
private Box bottomBackground; private Box bottomBackground;
private Container screenContainer; private Container screenContainer;

View File

@ -29,7 +29,7 @@ namespace osu.Game.Screens.Edit
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap) private void load(IBindable<WorkingBeatmap> beatmap)
{ {
Beatmap.BindTo(beatmap); Beatmap.BindTo(beatmap);
} }

View File

@ -1,8 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Configuration;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Rulesets;
namespace osu.Game.Screens namespace osu.Game.Screens
{ {
@ -12,8 +15,12 @@ namespace osu.Game.Screens
/// Whether the beatmap or ruleset should be allowed to be changed by the user or game. /// Whether the beatmap or ruleset should be allowed to be changed by the user or game.
/// Used to mark exclusive areas where this is strongly prohibited, like gameplay. /// Used to mark exclusive areas where this is strongly prohibited, like gameplay.
/// </summary> /// </summary>
bool AllowBeatmapRulesetChange { get; } bool DisallowExternalBeatmapRulesetChanges { get; }
/// <summary>
/// Whether a top-level component should be allowed to exit the current screen to, for example,
/// complete an import.
/// </summary>
bool AllowExternalScreenChange { get; } bool AllowExternalScreenChange { get; }
/// <summary> /// <summary>
@ -35,5 +42,9 @@ namespace osu.Game.Screens
/// The amount of parallax to be applied while this screen is displayed. /// The amount of parallax to be applied while this screen is displayed.
/// </summary> /// </summary>
float BackgroundParallaxAmount { get; } float BackgroundParallaxAmount { get; }
Bindable<WorkingBeatmap> Beatmap { get; }
Bindable<RulesetInfo> Ruleset { get; }
} }
} }

View File

@ -21,6 +21,8 @@ namespace osu.Game.Screens
public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled;
public override bool CursorVisible => false;
protected override bool AllowBackButton => false; protected override bool AllowBackButton => false;
public Loader() public Loader()

View File

@ -28,8 +28,6 @@ namespace osu.Game.Screens.Menu
/// </summary> /// </summary>
public bool DidLoadMenu; public bool DidLoadMenu;
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
private MainMenu mainMenu; private MainMenu mainMenu;
private SampleChannel welcome; private SampleChannel welcome;
private SampleChannel seeya; private SampleChannel seeya;
@ -47,10 +45,8 @@ namespace osu.Game.Screens.Menu
private WorkingBeatmap introBeatmap; private WorkingBeatmap introBeatmap;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap) private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
{ {
this.beatmap.BindTo(beatmap);
menuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice); menuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice);
menuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic); menuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic);
@ -95,7 +91,7 @@ namespace osu.Game.Screens.Menu
if (!resuming) if (!resuming)
{ {
beatmap.Value = introBeatmap; Beatmap.Value = introBeatmap;
if (menuVoice) if (menuVoice)
welcome.Play(); welcome.Play();

View File

@ -74,7 +74,7 @@ namespace osu.Game.Screens.Menu
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ShaderManager shaders, IBindableBeatmap beatmap) private void load(ShaderManager shaders, IBindable<WorkingBeatmap> beatmap)
{ {
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED); shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);

View File

@ -42,7 +42,7 @@ namespace osu.Game.Screens.Menu
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindableBeatmap beatmap, OsuColour colours) private void load(IBindable<WorkingBeatmap> beatmap, OsuColour colours)
{ {
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);

View File

@ -2,11 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
@ -14,10 +11,8 @@ using osu.Game.Online.Chat;
namespace osu.Game.Screens.Multi.Components 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; private readonly LinkFlowContainer textFlow;
public BeatmapTitle() public BeatmapTitle()
@ -27,10 +22,10 @@ namespace osu.Game.Screens.Multi.Components
InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both }; InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both };
} }
protected override void LoadComplete() [BackgroundDependencyLoader]
private void load()
{ {
base.LoadComplete(); CurrentItem.BindValueChanged(v => updateText(), true);
Beatmap.BindValueChanged(v => updateText(), true);
} }
private float textSize = OsuSpriteText.FONT_SIZE; private float textSize = OsuSpriteText.FONT_SIZE;
@ -53,12 +48,14 @@ namespace osu.Game.Screens.Multi.Components
private void updateText() private void updateText()
{ {
if (!IsLoaded) if (LoadState < LoadState.Loading)
return; return;
textFlow.Clear(); textFlow.Clear();
if (Beatmap.Value == null) var beatmap = CurrentItem.Value?.Beatmap;
if (beatmap == null)
textFlow.AddText("No beatmap selected", s => textFlow.AddText("No beatmap selected", s =>
{ {
s.TextSize = TextSize; s.TextSize = TextSize;
@ -70,7 +67,7 @@ namespace osu.Game.Screens.Multi.Components
{ {
new OsuSpriteText new OsuSpriteText
{ {
Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)), Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)),
TextSize = TextSize, TextSize = TextSize,
}, },
new OsuSpriteText new OsuSpriteText
@ -80,10 +77,10 @@ namespace osu.Game.Screens.Multi.Components
}, },
new OsuSpriteText new OsuSpriteText
{ {
Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)), Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)),
TextSize = TextSize, TextSize = TextSize,
} }
}, null, LinkAction.OpenBeatmap, Beatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap"); }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap");
} }
} }
} }

View File

@ -1,31 +1,26 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // 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;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Online.Chat; using osu.Game.Online.Chat;
using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets;
using osuTK; using osuTK;
namespace osu.Game.Screens.Multi.Components 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() public BeatmapTypeInfo()
{ {
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
}
BeatmapTitle beatmapTitle; [BackgroundDependencyLoader]
ModeTypeInfo modeTypeInfo; private void load()
{
LinkFlowContainer beatmapAuthor; LinkFlowContainer beatmapAuthor;
InternalChild = new FillFlowContainer InternalChild = new FillFlowContainer
@ -36,7 +31,7 @@ namespace osu.Game.Screens.Multi.Components
Spacing = new Vector2(5, 0), Spacing = new Vector2(5, 0),
Children = new Drawable[] Children = new Drawable[]
{ {
modeTypeInfo = new ModeTypeInfo(), new ModeTypeInfo(),
new Container new Container
{ {
AutoSizeAxes = Axes.X, AutoSizeAxes = Axes.X,
@ -44,7 +39,7 @@ namespace osu.Game.Screens.Multi.Components
Margin = new MarginPadding { Left = 5 }, Margin = new MarginPadding { Left = 5 },
Children = new Drawable[] Children = new Drawable[]
{ {
beatmapTitle = new BeatmapTitle(), new BeatmapTitle(),
beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14) beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14)
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
@ -56,22 +51,18 @@ namespace osu.Game.Screens.Multi.Components
} }
}; };
modeTypeInfo.Beatmap.BindTo(Beatmap); CurrentItem.BindValueChanged(item =>
modeTypeInfo.Ruleset.BindTo(Ruleset);
modeTypeInfo.Type.BindTo(Type);
beatmapTitle.Beatmap.BindTo(Beatmap);
Beatmap.BindValueChanged(v =>
{ {
beatmapAuthor.Clear(); beatmapAuthor.Clear();
if (v != null) var beatmap = item?.Beatmap;
if (beatmap != null)
{ {
beatmapAuthor.AddText("mapped by ", s => s.Colour = OsuColour.Gray(0.8f)); 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"); beatmapAuthor.AddLink(beatmap.Metadata.Author.Username, null, LinkAction.OpenUserProfile, beatmap.Metadata.Author.Id.ToString(), "View Profile");
} }
}); }, true);
} }
} }
} }

View File

@ -1,32 +1,30 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // 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;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables; using osu.Game.Beatmaps.Drawables;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets;
using osuTK; using osuTK;
namespace osu.Game.Screens.Multi.Components namespace osu.Game.Screens.Multi.Components
{ {
public class ModeTypeInfo : CompositeDrawable public class ModeTypeInfo : MultiplayerComposite
{ {
private const float height = 30; private const float height = 30;
private const float transition_duration = 100; private const float transition_duration = 100;
private readonly Container rulesetContainer; private 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>();
public ModeTypeInfo() public ModeTypeInfo()
{ {
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
{
Container gameTypeContainer; Container gameTypeContainer;
InternalChild = new FillFlowContainer InternalChild = new FillFlowContainer
@ -48,17 +46,17 @@ namespace osu.Game.Screens.Multi.Components
}, },
}; };
Beatmap.BindValueChanged(updateBeatmap); CurrentItem.BindValueChanged(updateBeatmap, true);
Ruleset.BindValueChanged(_ => updateBeatmap(Beatmap.Value));
Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }); Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }, true);
} }
private void updateBeatmap(BeatmapInfo beatmap) private void updateBeatmap(PlaylistItem item)
{ {
if (beatmap != null) if (item?.Beatmap != null)
{ {
rulesetContainer.FadeIn(transition_duration); rulesetContainer.FadeIn(transition_duration);
rulesetContainer.Child = new DifficultyIcon(beatmap, Ruleset.Value) { Size = new Vector2(height) }; rulesetContainer.Child = new DifficultyIcon(item.Beatmap, item.Ruleset) { Size = new Vector2(height) };
} }
else else
rulesetContainer.FadeOut(transition_duration); rulesetContainer.FadeOut(transition_duration);

View File

@ -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();
CurrentItem.BindValueChanged(i => sprite.Beatmap.Value = i?.Beatmap, true);
}
protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both };
}
}

View File

@ -1,31 +1,28 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using osu.Framework.Allocation;
using System.Linq;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Users;
namespace osu.Game.Screens.Multi.Components namespace osu.Game.Screens.Multi.Components
{ {
public class ParticipantCountDisplay : CompositeDrawable public class ParticipantCountDisplay : MultiplayerComposite
{ {
private const float text_size = 30; private const float text_size = 30;
private const float transition_duration = 100; private const float transition_duration = 100;
private readonly OsuSpriteText slash, maxText; private 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?>();
public ParticipantCountDisplay() public ParticipantCountDisplay()
{ {
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
{
OsuSpriteText count; OsuSpriteText count;
InternalChild = new FillFlowContainer 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); MaxParticipants.BindValueChanged(_ => updateMax(), true);
ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0")); ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0"), true);
} }
private void updateMax() private void updateMax()

View File

@ -13,16 +13,16 @@ using osu.Game.Online.Multiplayer.RoomStatuses;
namespace osu.Game.Screens.Multi.Components namespace osu.Game.Screens.Multi.Components
{ {
public class RoomStatusInfo : CompositeDrawable public class RoomStatusInfo : MultiplayerComposite
{ {
private readonly RoomBindings bindings = new RoomBindings(); public RoomStatusInfo()
public RoomStatusInfo(Room room)
{ {
bindings.Room = room;
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
{
StatusPart statusPart; StatusPart statusPart;
EndDatePart endDatePart; EndDatePart endDatePart;
@ -41,10 +41,10 @@ namespace osu.Game.Screens.Multi.Components
} }
}; };
statusPart.EndDate.BindTo(bindings.EndDate); statusPart.EndDate.BindTo(EndDate);
statusPart.Status.BindTo(bindings.Status); statusPart.Status.BindTo(Status);
statusPart.Availability.BindTo(bindings.Availability); statusPart.Availability.BindTo(Availability);
endDatePart.EndDate.BindTo(bindings.EndDate); endDatePart.EndDate.BindTo(EndDate);
} }
private class EndDatePart : DrawableDate private class EndDatePart : DrawableDate

View 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);
}
}
}

View File

@ -4,7 +4,6 @@
using System; using System;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi.Lounge.Components;
namespace osu.Game.Screens.Multi namespace osu.Game.Screens.Multi
{ {
@ -40,11 +39,5 @@ namespace osu.Game.Screens.Multi
/// Parts the currently-joined <see cref="Room"/>. /// Parts the currently-joined <see cref="Room"/>.
/// </summary> /// </summary>
void PartRoom(); 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);
} }
} }

View File

@ -5,12 +5,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework; using osu.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
@ -34,12 +34,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components
public event Action<SelectionState> StateChanged; public event Action<SelectionState> StateChanged;
private readonly RoomBindings bindings = new RoomBindings();
private readonly Box selectionBox; private readonly Box selectionBox;
private UpdateableBeatmapBackgroundSprite background; private CachedModelDependencyContainer<Room> dependencies;
private BeatmapTitle beatmapTitle;
private ModeTypeInfo modeTypeInfo;
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; }
@ -80,7 +76,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components
public DrawableRoom(Room room) public DrawableRoom(Room room)
{ {
Room = room; Room = room;
bindings.Room = room;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = height + SELECTION_BORDER_WIDTH * 2; Height = height + SELECTION_BORDER_WIDTH * 2;
@ -98,13 +93,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
Box sideStrip;
ParticipantInfo participantInfo;
OsuSpriteText name;
Children = new Drawable[] Children = new Drawable[]
{ {
selectionBox, new StatusColouredContainer(transition_duration)
{
RelativeSizeAxes = Axes.Both,
Child = selectionBox
},
new Container new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -127,10 +122,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"212121"), Colour = OsuColour.FromHex(@"212121"),
}, },
sideStrip = new Box new StatusColouredContainer(transition_duration)
{ {
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Width = side_strip_width, Width = side_strip_width,
Child = new Box { RelativeSizeAxes = Axes.Both }
}, },
new Container new Container
{ {
@ -138,7 +134,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
Width = cover_width, Width = cover_width,
Masking = true, Masking = true,
Margin = new MarginPadding { Left = side_strip_width }, Margin = new MarginPadding { Left = side_strip_width },
Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } Child = new MultiplayerBackgroundSprite { RelativeSizeAxes = Axes.Both }
}, },
new Container new Container
{ {
@ -159,8 +155,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components
Spacing = new Vector2(5f), Spacing = new Vector2(5f),
Children = new Drawable[] Children = new Drawable[]
{ {
name = new OsuSpriteText { TextSize = 18 }, new RoomName { TextSize = 18 },
participantInfo = new ParticipantInfo(), new ParticipantInfo(),
}, },
}, },
new FillFlowContainer new FillFlowContainer
@ -173,11 +169,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components
Spacing = new Vector2(0, 5), Spacing = new Vector2(0, 5),
Children = new Drawable[] Children = new Drawable[]
{ {
new RoomStatusInfo(Room), new RoomStatusInfo(),
beatmapTitle = new BeatmapTitle { TextSize = 14 }, new BeatmapTitle { TextSize = 14 },
}, },
}, },
modeTypeInfo = new ModeTypeInfo new ModeTypeInfo
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
@ -188,22 +184,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
}, },
}, },
}; };
}
background.Beatmap.BindTo(bindings.CurrentBeatmap); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); {
modeTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
modeTypeInfo.Type.BindTo(bindings.Type); dependencies.Model.Value = Room;
beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap); return dependencies;
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 void LoadComplete() protected override void LoadComplete()
@ -211,5 +198,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components
base.LoadComplete(); base.LoadComplete();
this.FadeInFromZero(transition_duration); 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;
}
}
} }
} }

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.SearchableList;
using osuTK.Graphics; using osuTK.Graphics;
@ -15,17 +17,38 @@ namespace osu.Game.Screens.Multi.Lounge.Components
protected override float ContentHorizontalPadding => base.ContentHorizontalPadding + OsuScreen.HORIZONTAL_OVERFLOW_PADDING; protected override float ContentHorizontalPadding => base.ContentHorizontalPadding + OsuScreen.HORIZONTAL_OVERFLOW_PADDING;
[Resolved(CanBeNull = true)]
private Bindable<FilterCriteria> filter { get; set; }
public FilterControl() public FilterControl()
{ {
DisplayStyleControl.Hide(); DisplayStyleControl.Hide();
} }
public FilterCriteria CreateCriteria() => new FilterCriteria [BackgroundDependencyLoader]
private void load()
{ {
SearchString = Search.Current.Value ?? string.Empty, if (filter == null)
PrimaryFilter = Tabs.Current, filter = new Bindable<FilterCriteria>();
SecondaryFilter = DisplayStyleControl.Dropdown.Current }
};
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 public enum PrimaryFilter

View File

@ -1,10 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using Humanizer; using Humanizer;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -16,26 +14,24 @@ using osuTK;
namespace osu.Game.Screens.Multi.Lounge.Components 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() public ParticipantInfo()
{ {
OsuSpriteText summary;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = 15f; Height = 15f;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
OsuSpriteText summary;
OsuSpriteText levelRangeHigher; OsuSpriteText levelRangeHigher;
OsuSpriteText levelRangeLower; OsuSpriteText levelRangeLower;
Container flagContainer; Container flagContainer;
LinkFlowContainer hostText; LinkFlowContainer hostText;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
new FillFlowContainer new FillFlowContainer
{ {
@ -73,12 +69,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
} }
}, },
}, },
summaryContainer = new FillFlowContainer new FillFlowContainer
{ {
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
Colour = colours.Gray9,
Children = new[] Children = new[]
{ {
summary = new OsuSpriteText 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"); 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 }; 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 => /*Participants.BindValueChanged(v =>
{ {
@ -112,11 +109,5 @@ namespace osu.Game.Screens.Multi.Lounge.Components
levelRangeHigher.Text = ranks.Max().ToString(); levelRangeHigher.Text = ranks.Max().ToString();
});*/ });*/
} }
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
summaryContainer.Colour = colours.Gray9;
}
} }
} }

View File

@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API; using osu.Game.Online.API;
@ -24,34 +23,26 @@ using osuTK.Graphics;
namespace osu.Game.Screens.Multi.Lounge.Components namespace osu.Game.Screens.Multi.Lounge.Components
{ {
public class RoomInspector : Container public class RoomInspector : MultiplayerComposite
{ {
private const float transition_duration = 100; 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 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 ParticipantCountDisplay participantCount;
private OsuSpriteText name, status; private OsuSpriteText name;
private BeatmapTypeInfo beatmapTypeInfo; private BeatmapTypeInfo beatmapTypeInfo;
private ParticipantInfo participantInfo; private ParticipantInfo participantInfo;
private MatchParticipants participants;
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; }
private readonly Bindable<RoomStatus> status = new Bindable<RoomStatus>(new RoomStatusNoneSelected());
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
this.colours = colours; InternalChildren = new Drawable[]
Children = new Drawable[]
{ {
new Box new Box
{ {
@ -84,7 +75,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
Masking = true, Masking = true,
Children = new Drawable[] Children = new Drawable[]
{ {
background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, new MultiplayerBackgroundSprite { RelativeSizeAxes = Axes.Both },
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -106,15 +97,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
TextSize = 30, TextSize = 30,
Current = Name
}, },
}, },
}, },
}, },
}, },
statusStrip = new Box new StatusColouredContainer(transition_duration)
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 5, Height = 5,
Child = new Box { RelativeSizeAxes = Axes.Both }
}, },
new Container new Container
{ {
@ -137,10 +130,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components
Spacing = new Vector2(0f, 5f), Spacing = new Vector2(0f, 5f),
Children = new Drawable[] Children = new Drawable[]
{ {
status = new OsuSpriteText new StatusColouredContainer(transition_duration)
{ {
TextSize = 14, AutoSizeAxes = Axes.Both,
Font = @"Exo2.0-Bold", Child = new StatusText
{
TextSize = 14,
Font = @"Exo2.0-Bold",
}
}, },
beatmapTypeInfo = new BeatmapTypeInfo(), beatmapTypeInfo = new BeatmapTypeInfo(),
}, },
@ -162,7 +159,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
}, },
new Drawable[] new Drawable[]
{ {
participants = new MatchParticipants new MatchParticipants
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
} }
@ -171,51 +168,37 @@ namespace osu.Game.Screens.Multi.Lounge.Components
} }
}; };
participantInfo.Host.BindTo(bindings.Host); Status.BindValueChanged(_ => updateStatus(), true);
participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); RoomID.BindValueChanged(_ => updateStatus(), true);
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);
} }
private void updateRoom(Room room) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{ {
bindings.Room = room; var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
participants.Room = room; 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); participantCount.FadeIn(transition_duration);
beatmapTypeInfo.FadeIn(transition_duration); beatmapTypeInfo.FadeIn(transition_duration);
name.FadeIn(transition_duration); name.FadeIn(transition_duration);
participantInfo.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 private class RoomStatusNoneSelected : RoomStatus
@ -224,23 +207,21 @@ namespace osu.Game.Screens.Multi.Lounge.Components
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray8; public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray8;
} }
private class MatchParticipants : CompositeDrawable private class StatusText : OsuSpriteText
{ {
private Room room; [Resolved(typeof(Room), nameof(Room.Status))]
private readonly FillFlowContainer fill; private Bindable<RoomStatus> status { get; set; }
public Room Room [BackgroundDependencyLoader]
private void load()
{ {
get { return room; } status.BindValueChanged(s => Text = s.Message, true);
set
{
if (room == value)
return;
room = value;
updateParticipants();
}
} }
}
private class MatchParticipants : MultiplayerComposite
{
private readonly FillFlowContainer fill;
public MatchParticipants() public MatchParticipants()
{ {
@ -259,6 +240,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components
}; };
} }
[BackgroundDependencyLoader]
private void load()
{
RoomID.BindValueChanged(_ => updateParticipants(), true);
}
[Resolved] [Resolved]
private APIAccess api { get; set; } private APIAccess api { get; set; }
@ -266,7 +253,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
private void updateParticipants() private void updateParticipants()
{ {
var roomId = room?.RoomID.Value ?? 0; var roomId = RoomID.Value ?? 0;
request?.Cancel(); request?.Cancel();
@ -284,7 +271,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
request = new GetRoomScoresRequest(roomId); request = new GetRoomScoresRequest(roomId);
request.Success += scores => request.Success += scores =>
{ {
if (roomId != room.RoomID.Value) if (roomId != RoomID.Value)
return; return;
fill.Clear(); fill.Clear();

View File

@ -19,14 +19,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components
{ {
public Action<Room> JoinRequested; 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 IBindableList<Room> rooms = new BindableList<Room>();
private readonly FillFlowContainer<DrawableRoom> roomFlow; private readonly FillFlowContainer<DrawableRoom> roomFlow;
public IReadOnlyList<DrawableRoom> Rooms => roomFlow; public IReadOnlyList<DrawableRoom> Rooms => roomFlow;
[Resolved]
private Bindable<Room> currentRoom { get; set; }
[Resolved] [Resolved]
private IRoomManager roomManager { get; set; } private IRoomManager roomManager { get; set; }
@ -121,7 +121,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
else else
roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected); 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) protected override void Dispose(bool isDisposing)

View File

@ -1,7 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // 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;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
@ -21,16 +22,13 @@ namespace osu.Game.Screens.Multi.Lounge
protected readonly FilterControl Filter; protected readonly FilterControl Filter;
private readonly Container content; private readonly Container content;
private readonly RoomsContainer rooms;
private readonly Action<Screen> pushGameplayScreen;
private readonly ProcessingOverlay processingOverlay; private readonly ProcessingOverlay processingOverlay;
public LoungeSubScreen(Action<Screen> pushGameplayScreen) [Resolved]
private Bindable<Room> currentRoom { get; set; }
public LoungeSubScreen()
{ {
this.pushGameplayScreen = pushGameplayScreen;
RoomInspector inspector;
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
Filter = new FilterControl { Depth = -1 }, Filter = new FilterControl { Depth = -1 },
@ -54,13 +52,13 @@ namespace osu.Game.Screens.Multi.Lounge
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Child = rooms = new RoomsContainer { JoinRequested = joinRequested } Child = new RoomsContainer { JoinRequested = joinRequested }
}, },
}, },
processingOverlay = new ProcessingOverlay { Alpha = 0 } processingOverlay = new ProcessingOverlay { Alpha = 0 }
} }
}, },
inspector = new RoomInspector new RoomInspector
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
@ -71,10 +69,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; Filter.Search.Exit += this.Exit;
} }
@ -85,8 +79,8 @@ namespace osu.Game.Screens.Multi.Lounge
content.Padding = new MarginPadding content.Padding = new MarginPadding
{ {
Top = Filter.DrawHeight, Top = Filter.DrawHeight,
Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH + OsuScreen.HORIZONTAL_OVERFLOW_PADDING, Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH + HORIZONTAL_OVERFLOW_PADDING,
Right = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING, Right = SearchableListOverlay.WIDTH_PADDING + HORIZONTAL_OVERFLOW_PADDING,
}; };
} }
@ -113,18 +107,12 @@ namespace osu.Game.Screens.Multi.Lounge
Filter.Search.HoldFocus = false; Filter.Search.HoldFocus = false;
} }
private void filterRooms()
{
rooms.Filter(Filter.CreateCriteria());
Manager?.Filter(Filter.CreateCriteria());
}
private void joinRequested(Room room) private void joinRequested(Room room)
{ {
processingOverlay.Show(); processingOverlay.Show();
Manager?.JoinRoom(room, r => RoomManager?.JoinRoom(room, r =>
{ {
Push(room); Open(room);
processingOverlay.Hide(); processingOverlay.Hide();
}, _ => processingOverlay.Hide()); }, _ => processingOverlay.Hide());
} }
@ -132,13 +120,15 @@ namespace osu.Game.Screens.Multi.Lounge
/// <summary> /// <summary>
/// Push a room as a new subscreen. /// Push a room as a new subscreen.
/// </summary> /// </summary>
public void Push(Room room) public void Open(Room room)
{ {
// Handles the case where a room is clicked 3 times in quick succession // Handles the case where a room is clicked 3 times in quick succession
if (!this.IsCurrentScreen()) if (!this.IsCurrentScreen())
return; return;
this.Push(new MatchSubScreen(room, s => pushGameplayScreen?.Invoke(s))); currentRoom.Value = room;
this.Push(new MatchSubScreen(room));
} }
} }
} }

View File

@ -20,31 +20,27 @@ using osuTK.Graphics;
namespace osu.Game.Screens.Multi.Match.Components namespace osu.Game.Screens.Multi.Match.Components
{ {
public class Header : Container public class Header : MultiplayerComposite
{ {
public const float HEIGHT = 200; 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 Header()
public Action OnRequestSelectBeatmap;
public Header(Room room)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = HEIGHT; Height = HEIGHT;
}
bindings.Room = room; [BackgroundDependencyLoader]
private void load(OsuColour colours)
BeatmapTypeInfo beatmapTypeInfo; {
BeatmapSelectButton beatmapButton; BeatmapSelectButton beatmapButton;
UpdateableBeatmapBackgroundSprite background;
ModDisplay modDisplay; ModDisplay modDisplay;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
new Container new Container
{ {
@ -52,7 +48,7 @@ namespace osu.Game.Screens.Multi.Match.Components
Masking = true, Masking = true,
Children = new Drawable[] Children = new Drawable[]
{ {
background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, new HeaderBackgroundSprite { RelativeSizeAxes = Axes.Both },
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -60,12 +56,13 @@ namespace osu.Game.Screens.Multi.Match.Components
}, },
} }
}, },
tabStrip = new Box new Box
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 1, Height = 1,
Colour = colours.Yellow
}, },
new Container new Container
{ {
@ -80,7 +77,7 @@ namespace osu.Game.Screens.Multi.Match.Components
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
beatmapTypeInfo = new BeatmapTypeInfo(), new BeatmapTypeInfo(),
modDisplay = new ModDisplay modDisplay = new ModDisplay
{ {
Scale = new Vector2(0.75f), Scale = new Vector2(0.75f),
@ -95,13 +92,13 @@ namespace osu.Game.Screens.Multi.Match.Components
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Width = 200, Width = 200,
Padding = new MarginPadding { Vertical = 10 }, Padding = new MarginPadding { Vertical = 10 },
Child = beatmapButton = new BeatmapSelectButton(room) Child = beatmapButton = new BeatmapSelectButton
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 1, Height = 1,
}, },
}, },
Tabs = new MatchTabControl(room) Tabs = new MatchTabControl
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
@ -111,37 +108,36 @@ namespace osu.Game.Screens.Multi.Match.Components
}, },
}; };
beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); CurrentItem.BindValueChanged(i => modDisplay.Current.Value = i?.RequiredMods, true);
beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset);
beatmapTypeInfo.Type.BindTo(bindings.Type);
background.Beatmap.BindTo(bindings.CurrentBeatmap);
bindings.CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true);
beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); beatmapButton.Action = () => RequestBeatmapSelection?.Invoke();
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
tabStrip.Colour = colours.Yellow;
} }
private class BeatmapSelectButton : HeaderButton 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"; Text = "Select beatmap";
}
roomIDBind.BindTo(room.RoomID); [BackgroundDependencyLoader]
roomIDBind.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true); 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;
}
} }
} }
} }

View File

@ -2,35 +2,37 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.Multiplayer;
using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.SearchableList;
using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Components;
using osuTK; using osuTK;
namespace osu.Game.Screens.Multi.Match.Components namespace osu.Game.Screens.Multi.Match.Components
{ {
public class Info : Container public class Info : MultiplayerComposite
{ {
public Action OnStart; public Action OnStart;
private readonly RoomBindings bindings = new RoomBindings(); public Info()
public Info(Room room)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
}
[BackgroundDependencyLoader]
private void load()
{
ReadyButton readyButton; ReadyButton readyButton;
ViewBeatmapButton viewBeatmapButton; ViewBeatmapButton viewBeatmapButton;
HostInfo hostInfo; HostInfo hostInfo;
RoomStatusInfo statusInfo; RoomStatusInfo statusInfo;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
new Box new Box
{ {
@ -61,9 +63,9 @@ namespace osu.Game.Screens.Multi.Match.Components
new OsuSpriteText new OsuSpriteText
{ {
TextSize = 30, TextSize = 30,
Current = bindings.Name Current = Name
}, },
new RoomStatusInfo(room), new RoomStatusInfo(),
} }
}, },
hostInfo = new HostInfo(), hostInfo = new HostInfo(),
@ -80,7 +82,7 @@ namespace osu.Game.Screens.Multi.Match.Components
Children = new Drawable[] Children = new Drawable[]
{ {
viewBeatmapButton = new ViewBeatmapButton(), viewBeatmapButton = new ViewBeatmapButton(),
readyButton = new ReadyButton(room) readyButton = new ReadyButton
{ {
Action = () => OnStart?.Invoke() Action = () => OnStart?.Invoke()
} }
@ -90,11 +92,13 @@ namespace osu.Game.Screens.Multi.Match.Components
}, },
}; };
viewBeatmapButton.Beatmap.BindTo(bindings.CurrentBeatmap); CurrentItem.BindValueChanged(item =>
readyButton.Beatmap.BindTo(bindings.CurrentBeatmap); {
hostInfo.Host.BindTo(bindings.Host); viewBeatmapButton.Beatmap.Value = item?.Beatmap;
readyButton.Beatmap.Value = item?.Beatmap;
}, true);
bindings.Room = room; hostInfo.Host.BindTo(Host);
} }
} }
} }

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Game.Online.Chat; using osu.Game.Online.Chat;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
@ -9,28 +10,31 @@ namespace osu.Game.Screens.Multi.Match.Components
{ {
public class MatchChatDisplay : StandAloneChatDisplay 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)] [Resolved(CanBeNull = true)]
private ChannelManager channelManager { get; set; } private ChannelManager channelManager { get; set; }
public MatchChatDisplay(Room room) public MatchChatDisplay()
: base(true) : base(true)
{ {
this.room = room;
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
room.RoomID.BindValueChanged(v => updateChannel(), true); roomId.BindValueChanged(v => updateChannel(), true);
} }
private void updateChannel() private void updateChannel()
{ {
if (room.RoomID.Value != null) if (roomId.Value != null)
Channel.Value = channelManager?.JoinChannel(new Channel { Id = room.ChannelId, Type = ChannelType.Multiplayer, Name = $"#mp_{room.RoomID}" }); Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId, Type = ChannelType.Multiplayer, Name = $"#mp_{roomId.Value}" });
} }
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
@ -16,18 +17,13 @@ namespace osu.Game.Screens.Multi.Match.Components
{ {
public Action<IEnumerable<APIRoomScoreInfo>> ScoresLoaded; public Action<IEnumerable<APIRoomScoreInfo>> ScoresLoaded;
public Room Room [Resolved(typeof(Room), nameof(Room.RoomID))]
{ private Bindable<int?> roomId { get; set; }
get => bindings.Room;
set => bindings.Room = value;
}
private readonly RoomBindings bindings = new RoomBindings();
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
bindings.RoomID.BindValueChanged(id => roomId.BindValueChanged(id =>
{ {
if (id == null) if (id == null)
return; return;
@ -39,10 +35,10 @@ namespace osu.Game.Screens.Multi.Match.Components
protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback) protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback)
{ {
if (bindings.RoomID.Value == null) if (roomId.Value == null)
return null; return null;
var req = new GetRoomScoresRequest(bindings.RoomID.Value ?? 0); var req = new GetRoomScoresRequest(roomId.Value ?? 0);
req.Success += r => req.Success += r =>
{ {

View File

@ -4,6 +4,7 @@
using System; using System;
using Humanizer; using Humanizer;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; 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 transition_duration = 350;
private const float field_padding = 45; 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; [BackgroundDependencyLoader]
private void load()
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)
{ {
this.room = room;
bindings.Room = room;
Masking = true; Masking = true;
Child = content = new Container Child = Settings = new MatchSettings
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Y, RelativePositionAxes = Axes.Y
Children = new Drawable[] };
}
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 new Box
{ {
@ -111,7 +125,10 @@ namespace osu.Game.Screens.Multi.Match.Components
new Section("Room visibility") new Section("Room visibility")
{ {
Alpha = disabled_alpha, Alpha = disabled_alpha,
Child = AvailabilityPicker = new RoomAvailabilityPicker(), Child = AvailabilityPicker = new RoomAvailabilityPicker
{
Enabled = { Value = false }
},
}, },
new Section("Game type") new Section("Game type")
{ {
@ -127,10 +144,12 @@ namespace osu.Game.Screens.Multi.Match.Components
TypePicker = new GameTypePicker TypePicker = new GameTypePicker
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Enabled = { Value = false }
}, },
typeLabel = new OsuSpriteText typeLabel = new OsuSpriteText
{ {
TextSize = 14, TextSize = 14,
Colour = colours.Yellow
}, },
}, },
}, },
@ -151,7 +170,8 @@ namespace osu.Game.Screens.Multi.Match.Components
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
TabbableContentContainer = this, TabbableContentContainer = this,
OnCommit = (sender, text) => apply(), ReadOnly = true,
OnCommit = (sender, text) => apply()
}, },
}, },
new Section("Duration") new Section("Duration")
@ -177,10 +197,11 @@ namespace osu.Game.Screens.Multi.Match.Components
new Section("Password (optional)") new Section("Password (optional)")
{ {
Alpha = disabled_alpha, Alpha = disabled_alpha,
Child = PasswordField = new SettingsPasswordTextBox Child = new SettingsPasswordTextBox
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
TabbableContentContainer = this, TabbableContentContainer = this,
ReadOnly = true,
OnCommit = (sender, text) => apply() OnCommit = (sender, text) => apply()
}, },
}, },
@ -222,6 +243,7 @@ namespace osu.Game.Screens.Multi.Match.Components
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
Size = new Vector2(230, 55), Size = new Vector2(230, 55),
Enabled = { Value = false },
Action = apply, Action = apply,
}, },
ErrorText = new OsuSpriteText ErrorText = new OsuSpriteText
@ -229,7 +251,8 @@ namespace osu.Game.Screens.Multi.Match.Components
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
Alpha = 0, 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 } 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); protected override void Update()
bindings.Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true); {
bindings.Type.BindValueChanged(t => TypePicker.Current.Value = t, true); base.Update();
bindings.MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true);
bindings.Duration.BindValueChanged(d => DurationField.Current.Value = d, true);
}
[BackgroundDependencyLoader] ApplyButton.Enabled.Value = hasValidSettings;
private void load(OsuColour colours) }
{
typeLabel.Colour = colours.Yellow;
ErrorText.Colour = colours.RedDark;
MaxParticipantsField.ReadOnly = true; private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0;
PasswordField.ReadOnly = true;
AvailabilityPicker.Enabled.Value = false;
TypePicker.Enabled.Value = false;
ApplyButton.Enabled.Value = false;
}
protected override void Update() private void apply()
{ {
base.Update(); 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() Duration.Value = DurationField.Current.Value;
{
content.MoveToY(0, transition_duration, Easing.OutQuint);
}
protected override void PopOut() manager?.CreateRoom(currentRoom, onSuccess, onError);
{
content.MoveToY(-1, transition_duration, Easing.InSine);
}
private void apply() processingOverlay.Show();
{ }
hideError();
bindings.Name.Value = NameField.Text; private void hideError() => ErrorText.FadeOut(50);
bindings.Availability.Value = AvailabilityPicker.Current.Value;
bindings.Type.Value = TypePicker.Current.Value;
if (int.TryParse(MaxParticipantsField.Text, out int max)) private void onSuccess(Room room) => processingOverlay.Hide();
bindings.MaxParticipants.Value = max;
else
bindings.MaxParticipants.Value = null;
bindings.Duration.Value = DurationField.Current.Value; private void onError(string text)
{
ErrorText.Text = text;
ErrorText.FadeIn(50);
manager?.CreateRoom(room, onSuccess, onError); processingOverlay.Hide();
}
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();
} }
private class SettingsTextBox : OsuTextBox private class SettingsTextBox : OsuTextBox

View File

@ -14,12 +14,11 @@ namespace osu.Game.Screens.Multi.Match.Components
{ {
public class MatchTabControl : PageTabControl<MatchPage> 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 RoomMatchPage());
AddItem(new SettingsMatchPage()); AddItem(new SettingsMatchPage());
} }
@ -27,7 +26,7 @@ namespace osu.Game.Screens.Multi.Match.Components
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
roomIdBind.BindValueChanged(v => roomId.BindValueChanged(v =>
{ {
if (v.HasValue) if (v.HasValue)
{ {

View File

@ -1,9 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Configuration; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.SearchableList;
@ -13,16 +12,12 @@ using osuTK;
namespace osu.Game.Screens.Multi.Match.Components 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>>(); [BackgroundDependencyLoader]
public readonly IBindable<int> ParticipantCount = new Bindable<int>(); private void load()
public readonly IBindable<int?> MaxParticipants = new Bindable<int?>();
public Participants()
{ {
FillFlowContainer<UserPanel> usersFlow; FillFlowContainer<UserPanel> usersFlow;
ParticipantCountDisplay count;
InternalChild = new Container InternalChild = new Container
{ {
@ -36,7 +31,7 @@ namespace osu.Game.Screens.Multi.Match.Components
Padding = new MarginPadding { Top = 10 }, Padding = new MarginPadding { Top = 10 },
Children = new Drawable[] Children = new Drawable[]
{ {
count = new ParticipantCountDisplay new ParticipantCountDisplay
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
@ -55,11 +50,7 @@ namespace osu.Game.Screens.Multi.Match.Components
}, },
}; };
count.Participants.BindTo(Users); Participants.BindValueChanged(v =>
count.ParticipantCount.BindTo(ParticipantCount);
count.MaxParticipants.BindTo(MaxParticipants);
Users.BindValueChanged(v =>
{ {
usersFlow.Children = v.Select(u => new UserPanel(u) usersFlow.Children = v.Select(u => new UserPanel(u)
{ {
@ -68,7 +59,7 @@ namespace osu.Game.Screens.Multi.Match.Components
Width = 300, Width = 300,
OnLoadComplete = d => d.FadeInFromZero(60), OnLoadComplete = d => d.FadeInFromZero(60),
}).ToList(); }).ToList();
}); }, true);
} }
} }
} }

View File

@ -14,21 +14,21 @@ namespace osu.Game.Screens.Multi.Match.Components
{ {
public class ReadyButton : HeaderButton public class ReadyButton : HeaderButton
{ {
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>(); public readonly Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
private readonly Room room; [Resolved(typeof(Room), nameof(Room.EndDate))]
private Bindable<DateTimeOffset> endDate { get; set; }
[Resolved] [Resolved]
private IBindableBeatmap gameBeatmap { get; set; } private IBindable<WorkingBeatmap> gameBeatmap { get; set; }
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; }
private bool hasBeatmap; private bool hasBeatmap;
public ReadyButton(Room room) public ReadyButton()
{ {
this.room = room;
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
Size = new Vector2(200, 1); Size = new Vector2(200, 1);
@ -55,6 +55,9 @@ namespace osu.Game.Screens.Multi.Match.Components
private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent)
{ {
if (Beatmap.Value == null)
return;
if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID)) if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID))
Schedule(() => hasBeatmap = true); Schedule(() => hasBeatmap = true);
} }
@ -74,7 +77,7 @@ namespace osu.Game.Screens.Multi.Match.Components
return; 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; Enabled.Value = hasBeatmap && hasEnoughTime;
} }

View File

@ -11,7 +11,7 @@ namespace osu.Game.Screens.Multi.Match.Components
{ {
public class ViewBeatmapButton : HeaderButton public class ViewBeatmapButton : HeaderButton
{ {
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>(); public readonly Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
private OsuGame osuGame { get; set; } private OsuGame osuGame { get; set; }

View File

@ -1,49 +1,66 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Online.Multiplayer.GameTypes;
using osu.Game.Rulesets; using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
using osu.Game.Screens.Multi.Play; using osu.Game.Screens.Multi.Play;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem;
namespace osu.Game.Screens.Multi.Match namespace osu.Game.Screens.Multi.Match
{ {
public class MatchSubScreen : MultiplayerSubScreen public class MatchSubScreen : MultiplayerSubScreen
{ {
public override bool AllowBeatmapRulesetChange => false; public override bool DisallowExternalBeatmapRulesetChanges => true;
public override string Title { get; }
public override string Title => room.RoomID.Value == null ? "New room" : room.Name.Value;
public override string ShortTitle => "room"; 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; [Resolved(typeof(Room), nameof(Room.Type))]
private Bindable<GameType> type { get; set; }
[Cached] [Resolved(typeof(Room))]
private readonly Room room; protected BindableList<PlaylistItem> Playlist { get; private set; }
[Resolved(typeof(Room))]
protected Bindable<PlaylistItem> CurrentItem { get; private set; }
[Resolved]
protected Bindable<IEnumerable<Mod>> CurrentMods { get; private set; }
[Resolved] [Resolved]
private BeatmapManager beatmapManager { get; set; } private BeatmapManager beatmapManager { get; set; }
public MatchSubScreen(Room room, Action<Screen> pushGameplayScreen) [Resolved(CanBeNull = true)]
private OsuGame game { get; set; }
private MatchLeaderboard leaderboard;
public MatchSubScreen(Room room)
{ {
this.room = room; Title = room.RoomID.Value == null ? "New room" : room.Name;
this.pushGameplayScreen = pushGameplayScreen; }
bindings.Room = room;
[BackgroundDependencyLoader]
private void load()
{
MatchChatDisplay chat; MatchChatDisplay chat;
Components.Header header; Components.Header header;
Info info; Info info;
@ -57,8 +74,25 @@ namespace osu.Game.Screens.Multi.Match
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Content = new[] Content = new[]
{ {
new Drawable[] { header = new Components.Header(room) { Depth = -1 } }, new Drawable[]
new Drawable[] { info = new Info(room) { OnStart = onStart } }, {
header = new Components.Header
{
Depth = -1,
RequestBeatmapSelection = () =>
{
this.Push(new MatchSongSelect
{
Selected = item =>
{
Playlist.Clear();
Playlist.Add(item);
}
});
}
}
},
new Drawable[] { info = new Info { OnStart = onStart } },
new Drawable[] new Drawable[]
{ {
bottomRow = new GridContainer bottomRow = new GridContainer
@ -72,23 +106,22 @@ namespace osu.Game.Screens.Multi.Match
{ {
Padding = new MarginPadding Padding = new MarginPadding
{ {
Left = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING, Left = 10 + HORIZONTAL_OVERFLOW_PADDING,
Right = 10, Right = 10,
Vertical = 10, Vertical = 10,
}, },
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both
Room = room
}, },
new Container new Container
{ {
Padding = new MarginPadding Padding = new MarginPadding
{ {
Left = 10, Left = 10,
Right = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING, Right = 10 + HORIZONTAL_OVERFLOW_PADDING,
Vertical = 10, Vertical = 10,
}, },
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = chat = new MatchChatDisplay(room) Child = chat = new MatchChatDisplay
{ {
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
} }
@ -109,16 +142,11 @@ namespace osu.Game.Screens.Multi.Match
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = Components.Header.HEIGHT }, Padding = new MarginPadding { Top = Components.Header.HEIGHT },
Child = settings = new MatchSettingsOverlay(room) { RelativeSizeAxes = Axes.Both }, Child = settings = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both },
}, },
}; };
header.OnRequestSelectBeatmap = () => this.Push(new MatchSongSelect header.Tabs.Current.BindValueChanged(t =>
{
Selected = addPlaylistItem,
});
header.Tabs.Current.ValueChanged += t =>
{ {
const float fade_duration = 500; const float fade_duration = 500;
if (t is SettingsMatchPage) if (t is SettingsMatchPage)
@ -133,84 +161,77 @@ namespace osu.Game.Screens.Multi.Match
info.FadeIn(fade_duration, Easing.OutQuint); info.FadeIn(fade_duration, Easing.OutQuint);
bottomRow.FadeIn(fade_duration, Easing.OutQuint); bottomRow.FadeIn(fade_duration, Easing.OutQuint);
} }
}; }, true);
chat.Exit += () => chat.Exit += () =>
{ {
if (this.IsCurrentScreen()) if (this.IsCurrentScreen())
this.Exit(); this.Exit();
}; };
}
[BackgroundDependencyLoader]
private void load()
{
beatmapManager.ItemAdded += beatmapAdded; beatmapManager.ItemAdded += beatmapAdded;
} }
public override bool OnExiting(IScreen next)
{
Manager?.PartRoom();
return base.OnExiting(next);
}
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
bindings.CurrentBeatmap.BindValueChanged(setBeatmap, true); CurrentItem.BindValueChanged(currentItemChanged, true);
bindings.CurrentRuleset.BindValueChanged(setRuleset, true);
} }
private void setBeatmap(BeatmapInfo beatmap) public override bool OnExiting(IScreen next)
{
RoomManager?.PartRoom();
return base.OnExiting(next);
}
/// <summary>
/// Handles propagation of the current playlist item's content to game-wide mechanisms.
/// </summary>
private void currentItemChanged(PlaylistItem item)
{ {
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info // 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); var localBeatmap = item?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.Beatmap.OnlineBeatmapID);
Game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
} CurrentMods.Value = item?.RequiredMods ?? Enumerable.Empty<Mod>();
if (item?.Ruleset != null)
private void setRuleset(RulesetInfo ruleset) Ruleset.Value = item.Ruleset;
{
if (ruleset == null)
return;
Game?.ForcefullySetRuleset(ruleset);
} }
/// <summary>
/// Handle the case where a beatmap is imported (and can be used by this match).
/// </summary>
private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() => private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() =>
{ {
if (Beatmap.Value != beatmapManager.DefaultBeatmap) if (Beatmap.Value != beatmapManager.DefaultBeatmap)
return; return;
if (bindings.CurrentBeatmap.Value == null) if (Beatmap.Value == null)
return; return;
// Try to retrieve the corresponding local beatmap // Try to retrieve the corresponding local beatmap
var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == bindings.CurrentBeatmap.Value.OnlineBeatmapID); var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == CurrentItem.Value.Beatmap.OnlineBeatmapID);
if (localBeatmap != null) if (localBeatmap != null)
Game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
}); });
private void addPlaylistItem(PlaylistItem item) [Resolved(canBeNull: true)]
{ private Multiplayer multiplayer { get; set; }
bindings.Playlist.Clear();
bindings.Playlist.Add(item);
}
private void onStart() private void onStart()
{ {
Beatmap.Value.Mods.Value = bindings.CurrentMods.Value.ToArray(); Beatmap.Value.Mods.Value = CurrentMods.Value.ToArray();
switch (bindings.Type.Value) switch (type.Value)
{ {
default: default:
case GameTypeTimeshift _: case GameTypeTimeshift _:
pushGameplayScreen?.Invoke(new PlayerLoader(() => new TimeshiftPlayer(room, room.Playlist.First().ID) multiplayer?.Start(() => new TimeshiftPlayer(CurrentItem)
{ {
Exited = () => leaderboard.RefreshScores() Exited = () => leaderboard.RefreshScores()
})); });
break; break;
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -8,7 +9,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
@ -16,31 +16,22 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Input; using osu.Game.Input;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Overlays.BeatmapSet.Buttons;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osu.Game.Screens.Multi.Lounge; using osu.Game.Screens.Multi.Lounge;
using osu.Game.Screens.Multi.Lounge.Components;
using osu.Game.Screens.Multi.Match; using osu.Game.Screens.Multi.Match;
using osu.Game.Screens.Play;
using osuTK; using osuTK;
namespace osu.Game.Screens.Multi namespace osu.Game.Screens.Multi
{ {
[Cached] [Cached]
public class Multiplayer : CompositeDrawable, IOsuScreen, IOnlineComponent public class Multiplayer : OsuScreen, IOnlineComponent
{ {
public bool AllowBeatmapRulesetChange => (screenStack.CurrentScreen as IMultiplayerSubScreen)?.AllowBeatmapRulesetChange ?? true; public override bool CursorVisible => (screenStack.CurrentScreen as IMultiplayerSubScreen)?.CursorVisible ?? true;
public bool AllowExternalScreenChange => (screenStack.CurrentScreen as IMultiplayerSubScreen)?.AllowExternalScreenChange ?? true;
public bool CursorVisible => (screenStack.CurrentScreen as IMultiplayerSubScreen)?.AllowExternalScreenChange ?? true;
public bool HideOverlaysOnEnter => false; public override bool DisallowExternalBeatmapRulesetChanges => true;
public OverlayActivation InitialOverlayActivationMode => OverlayActivation.All;
public float BackgroundParallaxAmount => 1;
public bool ValidForResume { get; set; } = true;
public bool ValidForPush { get; set; } = true;
public override bool RemoveWhenNotAlive => false;
private readonly MultiplayerWaveContainer waves; private readonly MultiplayerWaveContainer waves;
@ -48,12 +39,17 @@ namespace osu.Game.Screens.Multi
private readonly LoungeSubScreen loungeSubScreen; private readonly LoungeSubScreen loungeSubScreen;
private readonly ScreenStack screenStack; 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>(new FilterCriteria());
[Cached(Type = typeof(IRoomManager))] [Cached(Type = typeof(IRoomManager))]
private RoomManager roomManager; private RoomManager roomManager;
[Resolved]
private IBindableBeatmap beatmap { get; set; }
[Resolved] [Resolved]
private OsuGameBase game { get; set; } private OsuGameBase game { get; set; }
@ -68,70 +64,65 @@ namespace osu.Game.Screens.Multi
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Padding = new MarginPadding { Horizontal = -HORIZONTAL_OVERFLOW_PADDING };
InternalChild = waves = new MultiplayerWaveContainer InternalChild = waves = new MultiplayerWaveContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"3e3a44"),
},
new Triangles
{
RelativeSizeAxes = Axes.Both,
ColourLight = OsuColour.FromHex(@"3c3842"),
ColourDark = OsuColour.FromHex(@"393540"),
TriangleScale = 5,
},
},
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = Header.HEIGHT },
Child = screenStack = new ScreenStack(loungeSubScreen = new LoungeSubScreen()) { RelativeSizeAxes = Axes.Both }
},
new Header(screenStack),
createButton = new HeaderButton
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.None,
Size = new Vector2(150, Header.HEIGHT - 20),
Margin = new MarginPadding
{
Top = 10,
Right = 10 + HORIZONTAL_OVERFLOW_PADDING,
},
Text = "Create room",
Action = () => loungeSubScreen.Open(new Room
{
Name = { Value = $"{api.LocalUser}'s awesome room" }
}),
},
roomManager = new RoomManager()
}
}; };
screenStack = new ScreenStack(loungeSubScreen = new LoungeSubScreen(this.Push)) { RelativeSizeAxes = Axes.Both };
Padding = new MarginPadding { Horizontal = -OsuScreen.HORIZONTAL_OVERFLOW_PADDING };
waves.AddRange(new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex(@"3e3a44"),
},
new Triangles
{
RelativeSizeAxes = Axes.Both,
ColourLight = OsuColour.FromHex(@"3c3842"),
ColourDark = OsuColour.FromHex(@"393540"),
TriangleScale = 5,
},
},
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = Header.HEIGHT },
Child = screenStack
},
new Header(screenStack),
createButton = new HeaderButton
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
RelativeSizeAxes = Axes.None,
Size = new Vector2(150, Header.HEIGHT - 20),
Margin = new MarginPadding
{
Top = 10,
Right = 10 + OsuScreen.HORIZONTAL_OVERFLOW_PADDING,
},
Text = "Create room",
Action = () => loungeSubScreen.Push(new Room
{
Name = { Value = $"{api.LocalUser}'s awesome room" }
}),
},
roomManager = new RoomManager()
});
screenStack.ScreenPushed += screenPushed; screenStack.ScreenPushed += screenPushed;
screenStack.ScreenExited += screenExited; screenStack.ScreenExited += screenExited;
} }
private readonly IBindable<bool> isIdle = new BindableBool();
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(IdleTracker idleTracker) private void load(IdleTracker idleTracker)
{ {
@ -147,12 +138,31 @@ namespace osu.Game.Screens.Multi
isIdle.BindValueChanged(updatePollingRate, true); isIdle.BindValueChanged(updatePollingRate, true);
} }
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
dependencies.Model.BindTo(currentRoom);
return dependencies;
}
private void updatePollingRate(bool idle) private void updatePollingRate(bool idle)
{ {
roomManager.TimeBetweenPolls = !this.IsCurrentScreen() || !(screenStack.CurrentScreen is LoungeSubScreen) ? 0 : (idle ? 120000 : 15000); roomManager.TimeBetweenPolls = !this.IsCurrentScreen() || !(screenStack.CurrentScreen is LoungeSubScreen) ? 0 : (idle ? 120000 : 15000);
Logger.Log($"Polling adjusted to {roomManager.TimeBetweenPolls}"); Logger.Log($"Polling adjusted to {roomManager.TimeBetweenPolls}");
} }
/// <summary>
/// Push a <see cref="Player"/> to the main screen stack to begin gameplay.
/// Generally called from a <see cref="MatchSubScreen"/> via DI resolution.
/// </summary>
public void Start(Func<Player> player)
{
if (!this.IsCurrentScreen())
return;
this.Push(new PlayerLoader(player));
}
public void APIStateChanged(APIAccess api, APIState state) public void APIStateChanged(APIAccess api, APIState state)
{ {
if (state != APIState.Online) if (state != APIState.Online)
@ -171,14 +181,13 @@ namespace osu.Game.Screens.Multi
} }
} }
public void OnEntering(IScreen last) public override void OnEntering(IScreen last)
{ {
this.FadeIn(); this.FadeIn();
waves.Show(); waves.Show();
} }
public bool OnExiting(IScreen next) public override bool OnExiting(IScreen next)
{ {
waves.Hide(); waves.Hide();
@ -191,23 +200,29 @@ namespace osu.Game.Screens.Multi
updatePollingRate(isIdle.Value); updatePollingRate(isIdle.Value);
// the wave overlay transition takes longer than expected to run. base.OnExiting(next);
logo?.AppendAnimatingAction(() => logo.Delay(WaveContainer.DISAPPEAR_DURATION / 2).FadeOut(), false);
return false; return false;
} }
public void OnResuming(IScreen last) protected override void LogoExiting(OsuLogo logo)
{
base.LogoExiting(logo);
// the wave overlay transition takes longer than expected to run.
logo.Delay(WaveContainer.DISAPPEAR_DURATION / 2).FadeOut();
}
public override void OnResuming(IScreen last)
{ {
this.FadeIn(250); this.FadeIn(250);
this.ScaleTo(1, 250, Easing.OutSine); this.ScaleTo(1, 250, Easing.OutSine);
logo?.AppendAnimatingAction(() => OsuScreen.ApplyLogoArrivingDefaults(logo), true); base.OnResuming(last);
updatePollingRate(isIdle.Value); updatePollingRate(isIdle.Value);
} }
public void OnSuspending(IScreen next) public override void OnSuspending(IScreen next)
{ {
this.ScaleTo(1.1f, 250, Easing.InSine); this.ScaleTo(1.1f, 250, Easing.InSine);
this.FadeOut(250); this.FadeOut(250);
@ -218,7 +233,8 @@ namespace osu.Game.Screens.Multi
private void cancelLooping() private void cancelLooping()
{ {
var track = beatmap.Value.Track; var track = Beatmap?.Value?.Track;
if (track != null) if (track != null)
track.Looping = false; track.Looping = false;
} }
@ -231,7 +247,7 @@ namespace osu.Game.Screens.Multi
if (screenStack.CurrentScreen is MatchSubScreen) if (screenStack.CurrentScreen is MatchSubScreen)
{ {
var track = beatmap.Value.Track; var track = Beatmap.Value.Track;
if (track != null) if (track != null)
{ {
track.Looping = true; track.Looping = true;
@ -239,7 +255,7 @@ namespace osu.Game.Screens.Multi
if (!track.IsRunning) if (!track.IsRunning)
{ {
game.Audio.AddItemToList(track); game.Audio.AddItemToList(track);
track.Seek(beatmap.Value.Metadata.PreviewTime); track.Seek(Beatmap.Value.Metadata.PreviewTime);
track.Start(); track.Start();
} }
} }

View File

@ -0,0 +1,55 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Multiplayer;
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<PlaylistItem> CurrentItem { 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; }
}
}

View File

@ -3,43 +3,26 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Overlays;
namespace osu.Game.Screens.Multi namespace osu.Game.Screens.Multi
{ {
public abstract class MultiplayerSubScreen : CompositeDrawable, IMultiplayerSubScreen, IKeyBindingHandler<GlobalAction> public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen, IKeyBindingHandler<GlobalAction>
{ {
public virtual bool AllowBeatmapRulesetChange => true; public override bool DisallowExternalBeatmapRulesetChanges => false;
public bool AllowExternalScreenChange => true;
public bool CursorVisible => true;
public bool HideOverlaysOnEnter => false;
public OverlayActivation InitialOverlayActivationMode => OverlayActivation.All;
public float BackgroundParallaxAmount => 1;
public bool ValidForResume { get; set; } = true;
public bool ValidForPush { get; set; } = true;
public override bool RemoveWhenNotAlive => false; public override bool RemoveWhenNotAlive => false;
public abstract string Title { get; }
public virtual string ShortTitle => Title; public virtual string ShortTitle => Title;
[Resolved]
protected IBindableBeatmap Beatmap { get; private set; }
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
protected OsuGame Game { get; private set; } protected OsuGame Game { get; private set; }
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
protected IRoomManager Manager { get; private set; } protected IRoomManager RoomManager { get; private set; }
protected MultiplayerSubScreen() protected MultiplayerSubScreen()
{ {
@ -48,14 +31,14 @@ namespace osu.Game.Screens.Multi
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
} }
public virtual void OnEntering(IScreen last) public override void OnEntering(IScreen last)
{ {
this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
this.MoveToX(200).MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); this.MoveToX(200).MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
} }
public virtual bool OnExiting(IScreen next) public override bool OnExiting(IScreen next)
{ {
this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint);
this.MoveToX(200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); this.MoveToX(200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint);
@ -63,19 +46,19 @@ namespace osu.Game.Screens.Multi
return false; return false;
} }
public virtual void OnResuming(IScreen last) public override void OnResuming(IScreen last)
{ {
this.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); this.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
this.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); this.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
} }
public virtual void OnSuspending(IScreen next) public override void OnSuspending(IScreen next)
{ {
this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint);
this.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); this.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint);
} }
public virtual bool OnPressed(GlobalAction action) public override bool OnPressed(GlobalAction action)
{ {
if (!this.IsCurrentScreen()) return false; if (!this.IsCurrentScreen()) return false;

View File

@ -5,6 +5,7 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Online.API; using osu.Game.Online.API;
@ -21,16 +22,17 @@ namespace osu.Game.Screens.Multi.Play
{ {
public Action Exited; public Action Exited;
private readonly Room room; [Resolved(typeof(Room), nameof(Room.RoomID))]
private readonly int playlistItemId; private Bindable<int?> roomId { get; set; }
private readonly PlaylistItem playlistItem;
[Resolved] [Resolved]
private APIAccess api { get; set; } private APIAccess api { get; set; }
public TimeshiftPlayer(Room room, int playlistItemId) public TimeshiftPlayer(PlaylistItem playlistItem)
{ {
this.room = room; this.playlistItem = playlistItem;
this.playlistItemId = playlistItemId;
} }
private int? token; private int? token;
@ -42,7 +44,7 @@ namespace osu.Game.Screens.Multi.Play
bool failed = false; 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.Success += r => token = r.ID;
req.Failure += e => req.Failure += e =>
{ {
@ -87,7 +89,7 @@ namespace osu.Game.Screens.Multi.Play
Debug.Assert(token != null); 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"); request.Failure += e => Logger.Error(e, "Failed to submit score");
api.Queue(request); api.Queue(request);
} }
@ -99,6 +101,6 @@ namespace osu.Game.Screens.Multi.Play
Exited = null; Exited = null;
} }
protected override Results CreateResults(ScoreInfo score) => new MatchResults(score, room); protected override Results CreateResults(ScoreInfo score) => new MatchResults(score);
} }
} }

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Online.Multiplayer;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Multi.Ranking.Types; using osu.Game.Screens.Multi.Ranking.Types;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
@ -12,19 +11,16 @@ namespace osu.Game.Screens.Multi.Ranking
{ {
public class MatchResults : Results public class MatchResults : Results
{ {
private readonly Room room; public MatchResults(ScoreInfo score)
public MatchResults(ScoreInfo score, Room room)
: base(score) : base(score)
{ {
this.room = room;
} }
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[] protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
{ {
new ScoreOverviewPageInfo(Score, Beatmap), new ScoreOverviewPageInfo(Score, Beatmap),
new LocalLeaderboardPageInfo(Score, Beatmap), new LocalLeaderboardPageInfo(Score, Beatmap),
new RoomLeaderboardPageInfo(Score, Beatmap, room), new RoomLeaderboardPageInfo(Score, Beatmap),
}; };
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -23,16 +24,15 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
{ {
public class RoomLeaderboardPage : ResultsPage public class RoomLeaderboardPage : ResultsPage
{ {
private readonly Room room;
private OsuColour colours; private OsuColour colours;
private TextFlowContainer rankText; 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) : base(score, beatmap)
{ {
this.room = room;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -53,7 +53,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
BackgroundColour = colours.Gray6, BackgroundColour = colours.Gray6,
Child = leaderboard = CreateLeaderboard(room) Child = leaderboard = CreateLeaderboard()
}, },
rankText = new TextFlowContainer rankText = new TextFlowContainer
{ {
@ -84,7 +84,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
s.Colour = colours.GrayF; s.Colour = colours.GrayF;
}; };
rankText.AddText(room.Name + "\n", white); rankText.AddText(name + "\n", white);
rankText.AddText("You are placed ", gray); 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))); 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); 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 class ResultsMatchLeaderboard : MatchLeaderboard
{ {
public ResultsMatchLeaderboard(Room room)
{
Room = room;
}
protected override bool FadeTop => true; protected override bool FadeTop => true;
protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index)

View File

@ -3,7 +3,6 @@
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Online.Multiplayer;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Multi.Ranking.Pages; using osu.Game.Screens.Multi.Ranking.Pages;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
@ -14,19 +13,17 @@ namespace osu.Game.Screens.Multi.Ranking.Types
{ {
private readonly ScoreInfo score; private readonly ScoreInfo score;
private readonly WorkingBeatmap beatmap; 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.score = score;
this.beatmap = beatmap; this.beatmap = beatmap;
this.room = room;
} }
public FontAwesome Icon => FontAwesome.fa_users; public FontAwesome Icon => FontAwesome.fa_users;
public string Name => "Room Leaderboard"; public string Name => "Room Leaderboard";
public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap, room); public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap);
} }
} }

Some files were not shown because too many files have changed in this diff Show More