mirror of
https://github.com/ppy/osu.git
synced 2025-01-26 16:12:54 +08:00
commit
7ecd96e329
@ -1,135 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseDrawableRoom : OsuTestCase
|
||||
{
|
||||
private RulesetStore rulesets;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
DrawableRoom first;
|
||||
Add(new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Width = 580f,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
first = new DrawableRoom(new Room
|
||||
{
|
||||
Name = { Value = @"Great Room Right Here" },
|
||||
Host = { Value = new User { Username = @"Naeferith", Id = 9492835, Country = new Country { FlagName = @"FR" } } },
|
||||
Status = { Value = new RoomStatusOpen() },
|
||||
Type = { Value = new GameTypeTeamVersus() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 4.65,
|
||||
Ruleset = rulesets.GetRuleset(3),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Critical Crystal",
|
||||
Artist = @"Seiryu",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh//beatmaps/376340/covers/cover.jpg?1456478455",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1355 } } },
|
||||
new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 8756 } } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
new DrawableRoom(new Room
|
||||
{
|
||||
Name = { Value = @"Relax It's The Weekend" },
|
||||
Host = { Value = new User { Username = @"peppy", Id = 2, Country = new Country { FlagName = @"AU" } } },
|
||||
Status = { Value = new RoomStatusPlaying() },
|
||||
Type = { Value = new GameTypeTagTeam() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 1.96,
|
||||
Ruleset = rulesets.GetRuleset(0),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Serendipity",
|
||||
Artist = @"ZAQ",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh//beatmaps/526839/covers/cover.jpg?1493815706",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 578975 } } },
|
||||
new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24554 } } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
AddStep(@"select", () => first.State = SelectionState.Selected);
|
||||
AddStep(@"change title", () => first.Room.Name.Value = @"I Changed Name");
|
||||
AddStep(@"change host", () => first.Room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } });
|
||||
AddStep(@"change status", () => first.Room.Status.Value = new RoomStatusPlaying());
|
||||
AddStep(@"change type", () => first.Room.Type.Value = new GameTypeVersus());
|
||||
AddStep(@"change beatmap", () => first.Room.Beatmap.Value = null);
|
||||
AddStep(@"change participants", () => first.Room.Participants.Value = new[]
|
||||
{
|
||||
new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1254 } } },
|
||||
new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 123189 } } },
|
||||
});
|
||||
AddStep(@"deselect", () => first.State = SelectionState.NotSelected);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osu.Game.Screens.Multi.Screens.Lounge;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseLounge : ManualInputManagerTestCase
|
||||
{
|
||||
private TestLounge lounge;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
lounge = new TestLounge();
|
||||
|
||||
Room[] rooms =
|
||||
{
|
||||
new Room
|
||||
{
|
||||
Name = { Value = @"Just Another Room" },
|
||||
Host = { Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } } },
|
||||
Status = { Value = new RoomStatusPlaying() },
|
||||
Availability = { Value = RoomAvailability.Public },
|
||||
Type = { Value = new GameTypeTagTeam() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 5.65,
|
||||
Ruleset = rulesets.GetRuleset(0),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Sidetracked Day (Short Ver.)",
|
||||
Artist = @"VINXIS",
|
||||
AuthorString = @"Hobbes2",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/767600/covers/cover.jpg?1526243446",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
MaxParticipants = { Value = 10 },
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } },
|
||||
new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } },
|
||||
new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } },
|
||||
new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } },
|
||||
new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } },
|
||||
new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } },
|
||||
}
|
||||
}
|
||||
},
|
||||
new Room
|
||||
{
|
||||
Name = { Value = @"Not Just Any Room" },
|
||||
Host = { Value = new User { Username = @"Monstrata", Id = 2706438, Country = new Country { FlagName = @"CA" } } },
|
||||
Status = { Value = new RoomStatusOpen() },
|
||||
Availability = { Value = RoomAvailability.FriendsOnly },
|
||||
Type = { Value = new GameTypeTeamVersus() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 2.73,
|
||||
Ruleset = rulesets.GetRuleset(0),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"lit(var)",
|
||||
Artist = @"kensuke ushio",
|
||||
AuthorString = @"Monstrata",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/623972/covers/cover.jpg?1521167183",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Username = @"Jeby", Id = 3136279, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 3497 } } },
|
||||
new User { Username = @"DualAkira", Id = 5220933, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 643 } } },
|
||||
new User { Username = @"Datenshi Yohane", Id = 7171857, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10555 } } },
|
||||
}
|
||||
}
|
||||
},
|
||||
new Room
|
||||
{
|
||||
Name = { Value = @"room THE FINAL" },
|
||||
Host = { Value = new User { Username = @"Delis", Id = 1603923, Country = new Country { FlagName = @"JP" } } },
|
||||
Status = { Value = new RoomStatusPlaying() },
|
||||
Availability = { Value = RoomAvailability.Public },
|
||||
Type = { Value = new GameTypeTagTeam() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 4.48,
|
||||
Ruleset = rulesets.GetRuleset(3),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"ONIGIRI FREEWAY",
|
||||
Artist = @"OISHII",
|
||||
AuthorString = @"Mentholzzz",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/663098/covers/cover.jpg?1521898837",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
MaxParticipants = { Value = 30 },
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Username = @"KizuA", Id = 6510442, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 5372 } } },
|
||||
new User { Username = @"Colored", Id = 827563, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 810 } } },
|
||||
new User { Username = @"Beryl", Id = 3817591, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10096 } } },
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
AddStep(@"show", () => Add(lounge));
|
||||
AddStep(@"set rooms", () => lounge.Rooms = rooms);
|
||||
selectAssert(0);
|
||||
AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {});
|
||||
AddAssert(@"no room selected", () => lounge.SelectedRoom == null);
|
||||
AddStep(@"set rooms", () => lounge.Rooms = rooms);
|
||||
selectAssert(1);
|
||||
AddStep(@"open room 1", () => clickRoom(1));
|
||||
AddUntilStep(() => lounge.ChildScreen?.IsCurrentScreen == true, "wait until room current");
|
||||
AddStep(@"make lounge current", lounge.MakeCurrent);
|
||||
filterAssert(@"THE FINAL", LoungeTab.Public, 1);
|
||||
filterAssert(string.Empty, LoungeTab.Public, 2);
|
||||
filterAssert(string.Empty, LoungeTab.Private, 1);
|
||||
filterAssert(string.Empty, LoungeTab.Public, 2);
|
||||
filterAssert(@"no matches", LoungeTab.Public, 0);
|
||||
AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {});
|
||||
AddStep(@"set rooms", () => lounge.Rooms = rooms);
|
||||
AddAssert(@"no matches after clear", () => !lounge.ChildRooms.Any());
|
||||
filterAssert(string.Empty, LoungeTab.Public, 2);
|
||||
AddStep(@"exit", lounge.Exit);
|
||||
}
|
||||
|
||||
private void clickRoom(int n)
|
||||
{
|
||||
InputManager.MoveMouseTo(lounge.ChildRooms.ElementAt(n));
|
||||
InputManager.Click(MouseButton.Left);
|
||||
}
|
||||
|
||||
private void selectAssert(int n)
|
||||
{
|
||||
AddStep($@"select room {n}", () => clickRoom(n));
|
||||
AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms.ElementAt(n).Room);
|
||||
}
|
||||
|
||||
private void filterAssert(string filter, LoungeTab tab, int endCount)
|
||||
{
|
||||
AddStep($@"filter '{filter}', {tab}", () => lounge.SetFilter(filter, tab));
|
||||
AddAssert(@"filtered correctly", () => lounge.ChildRooms.Count() == endCount);
|
||||
}
|
||||
|
||||
private class TestLounge : Lounge
|
||||
{
|
||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault();
|
||||
|
||||
public IEnumerable<DrawableRoom> ChildRooms => RoomsContainer.Children.Where(r => r.MatchingFilter);
|
||||
public Room SelectedRoom => Inspector.Room;
|
||||
|
||||
public void SetFilter(string filter, LoungeTab tab)
|
||||
{
|
||||
Filter.Search.Current.Value = filter;
|
||||
Filter.Tabs.Current.Value = tab;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
99
osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs
Normal file
99
osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseLoungeRoomsContainer : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(RoomsContainer),
|
||||
typeof(DrawableRoom)
|
||||
};
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private TestRoomManager roomManager = new TestRoomManager();
|
||||
|
||||
public TestCaseLoungeRoomsContainer()
|
||||
{
|
||||
RoomsContainer container;
|
||||
|
||||
Child = container = new RoomsContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 0.5f,
|
||||
JoinRequested = joinRequested
|
||||
};
|
||||
|
||||
AddStep("clear rooms", () => roomManager.Rooms.Clear());
|
||||
|
||||
AddStep("add rooms", () =>
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
roomManager.Rooms.Add(new Room
|
||||
{
|
||||
RoomID = { Value = i },
|
||||
Name = { Value = $"Room {i}" },
|
||||
Host = { Value = new User { Username = "Host" } },
|
||||
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
AddAssert("has 2 rooms", () => container.Rooms.Count == 3);
|
||||
AddStep("remove first room", () => roomManager.Rooms.Remove(roomManager.Rooms.FirstOrDefault()));
|
||||
AddAssert("has 2 rooms", () => container.Rooms.Count == 2);
|
||||
AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0));
|
||||
|
||||
AddStep("select first room", () => container.Rooms.First().Action?.Invoke());
|
||||
AddAssert("first room selected", () => container.SelectedRoom.Value == roomManager.Rooms.First());
|
||||
|
||||
AddStep("join first room", () => container.Rooms.First().Action?.Invoke());
|
||||
AddAssert("first room joined", () => roomManager.Rooms.First().Status.Value is JoinedRoomStatus);
|
||||
}
|
||||
|
||||
private void joinRequested(Room room) => room.Status.Value = new JoinedRoomStatus();
|
||||
|
||||
private class TestRoomManager : IRoomManager
|
||||
{
|
||||
public readonly BindableCollection<Room> Rooms = new BindableCollection<Room>();
|
||||
IBindableCollection<Room> IRoomManager.Rooms => Rooms;
|
||||
|
||||
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => Rooms.Add(room);
|
||||
|
||||
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
}
|
||||
|
||||
public void PartRoom()
|
||||
{
|
||||
}
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class JoinedRoomStatus : RoomStatus
|
||||
{
|
||||
public override string Message => "Joined";
|
||||
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Yellow;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Multi.Screens.Match;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseMatch : OsuTestCase
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
Room room = new Room
|
||||
{
|
||||
Name = { Value = @"One Awesome Room" },
|
||||
Status = { Value = new RoomStatusOpen() },
|
||||
Availability = { Value = RoomAvailability.Public },
|
||||
Type = { Value = new GameTypeTeamVersus() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 5.02,
|
||||
Ruleset = rulesets.GetRuleset(1),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Paradigm Shift",
|
||||
Artist = @"Morimori Atsushi",
|
||||
AuthorString = @"eiri-",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/765055/covers/cover.jpg?1526955337",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MaxParticipants = { Value = 5 },
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User
|
||||
{
|
||||
Username = @"eiri-",
|
||||
Id = 3388410,
|
||||
Country = new Country { FlagName = @"US" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/3388410/00a8486a247831e1cc4375db519f611ac970bda8bc0057d78b0f540ea38c3e58.jpeg",
|
||||
IsSupporter = true,
|
||||
},
|
||||
new User
|
||||
{
|
||||
Username = @"Nepuri",
|
||||
Id = 6637817,
|
||||
Country = new Country { FlagName = @"DE" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/6637817/9085fc60248b6b5327a72c1dcdecf2dbedba810ae0ab6bcf7224e46b1339632a.jpeg",
|
||||
IsSupporter = true,
|
||||
},
|
||||
new User
|
||||
{
|
||||
Username = @"goheegy",
|
||||
Id = 8057655,
|
||||
Country = new Country { FlagName = @"GB" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8057655/21cec27c25a11dc197a4ec6a74253dbabb495949b0e0697113352f12007018c5.jpeg",
|
||||
},
|
||||
new User
|
||||
{
|
||||
Username = @"Alumetri",
|
||||
Id = 5371497,
|
||||
Country = new Country { FlagName = @"RU" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/5371497/e023b8c7fbe3613e64bd4856703517ea50fbed8a5805dc9acda9efe9897c67e2.jpeg",
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Match match = new Match(room);
|
||||
|
||||
AddStep(@"show", () => Add(match));
|
||||
AddStep(@"null beatmap", () => room.Beatmap.Value = null);
|
||||
AddStep(@"change name", () => room.Name.Value = @"Two Awesome Rooms");
|
||||
AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying());
|
||||
AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.FriendsOnly);
|
||||
AddStep(@"change type", () => room.Type.Value = new GameTypeTag());
|
||||
AddStep(@"change beatmap", () => room.Beatmap.Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 4.33,
|
||||
Ruleset = rulesets.GetRuleset(2),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Yasashisa no Riyuu",
|
||||
Artist = @"ChouCho",
|
||||
AuthorString = @"celerih",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/685391/covers/cover.jpg?1524597970",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
AddStep(@"null max participants", () => room.MaxParticipants.Value = null);
|
||||
AddStep(@"change participants", () => room.Participants.Value = new[]
|
||||
{
|
||||
new User
|
||||
{
|
||||
Username = @"Spectator",
|
||||
Id = 702598,
|
||||
Country = new Country { FlagName = @"KR" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/702598/3bbf4cb8b8d2cf8b03145000a975ff27e191ab99b0920832e7dd67386280e288.jpeg",
|
||||
IsSupporter = true,
|
||||
},
|
||||
new User
|
||||
{
|
||||
Username = @"celerih",
|
||||
Id = 4696296,
|
||||
Country = new Country { FlagName = @"CA" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/4696296/7f8500731d0ac66d5472569d146a7be07d9460273361913f22c038867baddaef.jpeg",
|
||||
},
|
||||
});
|
||||
|
||||
AddStep(@"exit", match.Exit);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +1,54 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Multi.Screens.Match;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.GameTypes;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseMatchHeader : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(Header)
|
||||
};
|
||||
|
||||
public TestCaseMatchHeader()
|
||||
{
|
||||
Header header = new Header();
|
||||
Add(header);
|
||||
var room = new Room();
|
||||
|
||||
AddStep(@"set beatmap set", () => header.BeatmapSet = new BeatmapSetInfo
|
||||
var header = new Header(room);
|
||||
|
||||
room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
Beatmap = new BeatmapInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/760757/covers/cover.jpg?1526944540",
|
||||
Title = "Title",
|
||||
Artist = "Artist",
|
||||
AuthorString = "Author",
|
||||
},
|
||||
Version = "Version",
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
},
|
||||
RequiredMods =
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModNoFail(),
|
||||
new OsuModRelax(),
|
||||
}
|
||||
});
|
||||
|
||||
AddStep(@"change beatmap set", () => header.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/761883/covers/cover.jpg?1525557400",
|
||||
},
|
||||
},
|
||||
});
|
||||
room.Type.Value = new GameTypeTimeshift();
|
||||
|
||||
AddStep(@"null beatmap set", () => header.BeatmapSet = null);
|
||||
Child = header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs
Normal file
35
osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchHostInfo : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(HostInfo)
|
||||
};
|
||||
|
||||
private readonly Bindable<User> host = new Bindable<User>(new User { Username = "SomeHost" });
|
||||
|
||||
public TestCaseMatchHostInfo()
|
||||
{
|
||||
HostInfo hostInfo;
|
||||
|
||||
Child = hostInfo = new HostInfo
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
};
|
||||
|
||||
hostInfo.Host.BindTo(host);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +1,80 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Multi.Screens.Match;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseMatchInfo : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(Info),
|
||||
typeof(HeaderButton),
|
||||
typeof(ReadyButton),
|
||||
typeof(ViewBeatmapButton)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
Info info = new Info();
|
||||
var room = new Room();
|
||||
|
||||
Info info = new Info(room);
|
||||
Add(info);
|
||||
|
||||
AddStep(@"set name", () => info.Name = @"Room Name?");
|
||||
AddStep(@"set availability", () => info.Availability = RoomAvailability.FriendsOnly);
|
||||
AddStep(@"set status", () => info.Status = new RoomStatusPlaying());
|
||||
AddStep(@"set beatmap", () => info.Beatmap = new BeatmapInfo
|
||||
AddStep(@"set name", () => room.Name.Value = @"Room Name?");
|
||||
AddStep(@"set availability", () => room.Availability.Value = RoomAvailability.FriendsOnly);
|
||||
AddStep(@"set status", () => room.Status.Value = new RoomStatusPlaying());
|
||||
AddStep(@"set beatmap", () =>
|
||||
{
|
||||
StarDifficulty = 2.4,
|
||||
Ruleset = rulesets.GetRuleset(0),
|
||||
Metadata = new BeatmapMetadata
|
||||
room.Playlist.Clear();
|
||||
room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
Title = @"My Song",
|
||||
Artist = @"VisualTests",
|
||||
AuthorString = @"osu!lazer",
|
||||
},
|
||||
Beatmap = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 2.4,
|
||||
Ruleset = rulesets.GetRuleset(0),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"My Song",
|
||||
Artist = @"VisualTests",
|
||||
AuthorString = @"osu!lazer",
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
AddStep(@"set type", () => info.Type = new GameTypeTagTeam());
|
||||
|
||||
AddStep(@"change name", () => info.Name = @"Room Name!");
|
||||
AddStep(@"change availability", () => info.Availability = RoomAvailability.InviteOnly);
|
||||
AddStep(@"change status", () => info.Status = new RoomStatusOpen());
|
||||
AddStep(@"null beatmap", () => info.Beatmap = null);
|
||||
AddStep(@"change type", () => info.Type = new GameTypeTeamVersus());
|
||||
AddStep(@"change beatmap", () => info.Beatmap = new BeatmapInfo
|
||||
AddStep(@"change name", () => room.Name.Value = @"Room Name!");
|
||||
AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.InviteOnly);
|
||||
AddStep(@"change status", () => room.Status.Value = new RoomStatusOpen());
|
||||
AddStep(@"null beatmap", () => room.Playlist.Clear());
|
||||
AddStep(@"change beatmap", () =>
|
||||
{
|
||||
StarDifficulty = 4.2,
|
||||
Ruleset = rulesets.GetRuleset(3),
|
||||
Metadata = new BeatmapMetadata
|
||||
room.Playlist.Clear();
|
||||
room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
Title = @"Your Song",
|
||||
Artist = @"Tester",
|
||||
AuthorString = @"Someone",
|
||||
},
|
||||
Beatmap = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 4.2,
|
||||
Ruleset = rulesets.GetRuleset(3),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Your Song",
|
||||
Artist = @"Tester",
|
||||
AuthorString = @"Someone",
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
68
osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs
Normal file
68
osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchLeaderboard : OsuTestCase
|
||||
{
|
||||
public TestCaseMatchLeaderboard()
|
||||
{
|
||||
Add(new MatchLeaderboard(new Room { RoomID = { Value = 3 } })
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(550f, 450f),
|
||||
Scope = MatchLeaderboardScope.Overall,
|
||||
});
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var req = new GetRoomScoresRequest();
|
||||
req.Success += v => { };
|
||||
req.Failure += _ => { };
|
||||
|
||||
api.Queue(req);
|
||||
}
|
||||
|
||||
private class GetRoomScoresRequest : APIRequest<List<RoomScore>>
|
||||
{
|
||||
protected override string Target => "rooms/3/leaderboard";
|
||||
}
|
||||
|
||||
private class RoomScore
|
||||
{
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
|
||||
[JsonProperty("accuracy")]
|
||||
public double Accuracy { get; set; }
|
||||
|
||||
[JsonProperty("total_score")]
|
||||
public int TotalScore { get; set; }
|
||||
|
||||
[JsonProperty("pp")]
|
||||
public double PP { get; set; }
|
||||
|
||||
[JsonProperty("attempts")]
|
||||
public int TotalAttempts { get; set; }
|
||||
|
||||
[JsonProperty("completed")]
|
||||
public int CompletedAttempts { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.Multi.Screens.Match;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
@ -11,16 +13,20 @@ namespace osu.Game.Tests.Visual
|
||||
[TestFixture]
|
||||
public class TestCaseMatchParticipants : OsuTestCase
|
||||
{
|
||||
private readonly Bindable<int?> maxParticipants = new Bindable<int?>();
|
||||
private readonly Bindable<IEnumerable<User>> users = new Bindable<IEnumerable<User>>();
|
||||
|
||||
public TestCaseMatchParticipants()
|
||||
{
|
||||
Participants participants;
|
||||
Add(participants = new Participants
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
|
||||
AddStep(@"set max to null", () => participants.Max = null);
|
||||
AddStep(@"set users", () => participants.Users = new[]
|
||||
Add(participants = new Participants { RelativeSizeAxes = Axes.Both });
|
||||
|
||||
participants.MaxParticipants.BindTo(maxParticipants);
|
||||
participants.Users.BindTo(users);
|
||||
|
||||
AddStep(@"set max to null", () => maxParticipants.Value = null);
|
||||
AddStep(@"set users", () => users.Value = new[]
|
||||
{
|
||||
new User
|
||||
{
|
||||
@ -48,9 +54,9 @@ namespace osu.Game.Tests.Visual
|
||||
},
|
||||
});
|
||||
|
||||
AddStep(@"set max", () => participants.Max = 10);
|
||||
AddStep(@"clear users", () => participants.Users = new User[] { });
|
||||
AddStep(@"set max to null", () => participants.Max = null);
|
||||
AddStep(@"set max", () => maxParticipants.Value = 10);
|
||||
AddStep(@"clear users", () => users.Value = new User[] { });
|
||||
AddStep(@"set max to null", () => maxParticipants.Value = null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
123
osu.Game.Tests/Visual/TestCaseMatchResults.cs
Normal file
123
osu.Game.Tests/Visual/TestCaseMatchResults.cs
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Screens.Multi.Ranking;
|
||||
using osu.Game.Screens.Multi.Ranking.Pages;
|
||||
using osu.Game.Screens.Multi.Ranking.Types;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchResults : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(MatchResults),
|
||||
typeof(RoomLeaderboardPageInfo),
|
||||
typeof(RoomLeaderboardPage)
|
||||
};
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0);
|
||||
if (beatmapInfo != null)
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
|
||||
|
||||
Child = new TestMatchResults(new ScoreInfo
|
||||
{
|
||||
User = new User { Id = 10 },
|
||||
});
|
||||
}
|
||||
|
||||
private class TestMatchResults : MatchResults
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
public TestMatchResults(ScoreInfo score)
|
||||
: this(score, new Room
|
||||
{
|
||||
RoomID = { Value = 1 },
|
||||
Name = { Value = "an awesome room" }
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TestMatchResults(ScoreInfo score, Room room)
|
||||
: base(score, room)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap, room) };
|
||||
}
|
||||
|
||||
private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo
|
||||
{
|
||||
private readonly ScoreInfo score;
|
||||
private readonly WorkingBeatmap beatmap;
|
||||
private readonly Room room;
|
||||
|
||||
public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
: base(score, beatmap, room)
|
||||
{
|
||||
this.score = score;
|
||||
this.beatmap = beatmap;
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap, room);
|
||||
}
|
||||
|
||||
private class TestRoomLeaderboardPage : RoomLeaderboardPage
|
||||
{
|
||||
public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
: base(score, beatmap, room)
|
||||
{
|
||||
}
|
||||
|
||||
protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room);
|
||||
}
|
||||
|
||||
private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard
|
||||
{
|
||||
public TestMatchLeaderboard(Room room)
|
||||
: base(room)
|
||||
{
|
||||
}
|
||||
|
||||
protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback)
|
||||
{
|
||||
var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray();
|
||||
|
||||
scoresCallback?.Invoke(scores);
|
||||
ScoresLoaded?.Invoke(scores);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private APIRoomScoreInfo createRoomScore(int id) => new APIRoomScoreInfo
|
||||
{
|
||||
User = new User { Id = id, Username = $"User {id}" },
|
||||
Accuracy = 0.98,
|
||||
TotalScore = 987654,
|
||||
TotalAttempts = 13,
|
||||
CompletedBeatmaps = 5
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
159
osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs
Normal file
159
osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs
Normal file
@ -0,0 +1,159 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseMatchSettingsOverlay : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(MatchSettingsOverlay)
|
||||
};
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private TestRoomManager roomManager = new TestRoomManager();
|
||||
|
||||
private Room room;
|
||||
private TestRoomSettings settings;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
room = new Room();
|
||||
settings = new TestRoomSettings(room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = Visibility.Visible
|
||||
};
|
||||
|
||||
Child = settings;
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestButtonEnabledOnlyWithNameAndBeatmap()
|
||||
{
|
||||
AddStep("clear name and beatmap", () =>
|
||||
{
|
||||
room.Name.Value = "";
|
||||
room.Playlist.Clear();
|
||||
});
|
||||
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
|
||||
|
||||
AddStep("set name", () => room.Name.Value = "Room name");
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
|
||||
|
||||
AddStep("set beatmap", () => room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo }));
|
||||
AddAssert("button enabled", () => settings.ApplyButton.Enabled);
|
||||
|
||||
AddStep("clear name", () => room.Name.Value = "");
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCorrectSettingsApplied()
|
||||
{
|
||||
const string expected_name = "expected name";
|
||||
TimeSpan expectedDuration = TimeSpan.FromMinutes(15);
|
||||
|
||||
Room createdRoom = null;
|
||||
|
||||
AddStep("setup", () =>
|
||||
{
|
||||
settings.NameField.Current.Value = expected_name;
|
||||
settings.DurationField.Current.Value = expectedDuration;
|
||||
|
||||
roomManager.CreateRequested = r =>
|
||||
{
|
||||
createdRoom = r;
|
||||
return true;
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("create room", () => settings.ApplyButton.Action.Invoke());
|
||||
AddAssert("has correct name", () => createdRoom.Name.Value == expected_name);
|
||||
AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCreationFailureDisplaysError()
|
||||
{
|
||||
bool fail;
|
||||
|
||||
AddStep("setup", () =>
|
||||
{
|
||||
fail = true;
|
||||
roomManager.CreateRequested = _ => !fail;
|
||||
});
|
||||
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
|
||||
|
||||
AddStep("create room", () => settings.ApplyButton.Action.Invoke());
|
||||
AddAssert("error displayed", () => settings.ErrorText.IsPresent);
|
||||
AddAssert("error has correct text", () => settings.ErrorText.Text == TestRoomManager.FAILED_TEXT);
|
||||
|
||||
AddStep("create room no fail", () =>
|
||||
{
|
||||
fail = false;
|
||||
settings.ApplyButton.Action.Invoke();
|
||||
});
|
||||
|
||||
AddUntilStep(() => !settings.ErrorText.IsPresent, "error not displayed");
|
||||
}
|
||||
|
||||
private class TestRoomSettings : MatchSettingsOverlay
|
||||
{
|
||||
public new TriangleButton ApplyButton => base.ApplyButton;
|
||||
|
||||
public new OsuTextBox NameField => base.NameField;
|
||||
public new OsuDropdown<TimeSpan> DurationField => base.DurationField;
|
||||
|
||||
public new OsuSpriteText ErrorText => base.ErrorText;
|
||||
|
||||
public TestRoomSettings(Room room)
|
||||
: base(room)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestRoomManager : IRoomManager
|
||||
{
|
||||
public const string FAILED_TEXT = "failed";
|
||||
|
||||
public Func<Room, bool> CreateRequested;
|
||||
|
||||
public IBindableCollection<Room> Rooms { get; } = null;
|
||||
|
||||
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
if (CreateRequested == null)
|
||||
return;
|
||||
|
||||
if (!CreateRequested.Invoke(room))
|
||||
onError?.Invoke(FAILED_TEXT);
|
||||
else
|
||||
onSuccess?.Invoke(room);
|
||||
}
|
||||
|
||||
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => throw new NotImplementedException();
|
||||
|
||||
public void PartRoom() => throw new NotImplementedException();
|
||||
|
||||
public void Filter(FilterCriteria criteria) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Multi;
|
||||
using osu.Game.Screens.Multi.Screens.Lounge;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
@ -13,15 +13,31 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public TestCaseMultiHeader()
|
||||
{
|
||||
Lounge lounge;
|
||||
int index = 0;
|
||||
|
||||
OsuScreen currentScreen = new TestMultiplayerSubScreen(index);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
lounge = new Lounge
|
||||
{
|
||||
Padding = new MarginPadding { Top = Header.HEIGHT },
|
||||
},
|
||||
new Header(lounge),
|
||||
currentScreen,
|
||||
new Header(currentScreen)
|
||||
};
|
||||
|
||||
AddStep("push multi screen", () => currentScreen.Push(currentScreen = new TestMultiplayerSubScreen(++index)));
|
||||
}
|
||||
|
||||
private class TestMultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen
|
||||
{
|
||||
private readonly int index;
|
||||
|
||||
public string ShortTitle => $"Screen {index}";
|
||||
|
||||
public TestMultiplayerSubScreen(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public override string ToString() => ShortTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,25 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Screens.Multi;
|
||||
using osu.Game.Screens.Multi.Lounge;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseMultiScreen : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(Multiplayer),
|
||||
typeof(LoungeSubScreen),
|
||||
typeof(FilterControl)
|
||||
};
|
||||
|
||||
public TestCaseMultiScreen()
|
||||
{
|
||||
Multiplayer multi = new Multiplayer();
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
Beatmap.Value = new DummyWorkingBeatmap(game);
|
||||
|
||||
AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(new Player
|
||||
AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(() => new Player
|
||||
{
|
||||
AllowPause = false,
|
||||
AllowLeadIn = false,
|
||||
@ -30,9 +30,9 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
AddStep("load slow dummy beatmap", () =>
|
||||
{
|
||||
SlowLoadPlayer slow;
|
||||
SlowLoadPlayer slow = null;
|
||||
|
||||
Add(loader = new PlayerLoader(slow = new SlowLoadPlayer
|
||||
Add(loader = new PlayerLoader(() => slow = new SlowLoadPlayer
|
||||
{
|
||||
AllowPause = false,
|
||||
AllowLeadIn = false,
|
||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual
|
||||
typeof(Results),
|
||||
typeof(ResultsPage),
|
||||
typeof(ScoreResultsPage),
|
||||
typeof(RankingResultsPage)
|
||||
typeof(LocalLeaderboardPage)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -1,147 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseRoomInspector : OsuTestCase
|
||||
{
|
||||
private RulesetStore rulesets;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Room room = new Room
|
||||
{
|
||||
Name = { Value = @"My Awesome Room" },
|
||||
Host = { Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" } } },
|
||||
Status = { Value = new RoomStatusOpen() },
|
||||
Type = { Value = new GameTypeTeamVersus() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 3.7,
|
||||
Ruleset = rulesets.GetRuleset(3),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Platina",
|
||||
Artist = @"Maaya Sakamoto",
|
||||
AuthorString = @"uwutm8",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/560573/covers/cover.jpg?1492722343",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
MaxParticipants = { Value = 200 },
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } },
|
||||
new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } },
|
||||
new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } },
|
||||
new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } },
|
||||
new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } },
|
||||
new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RoomInspector inspector;
|
||||
Add(inspector = new RoomInspector
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
});
|
||||
|
||||
AddStep(@"set room", () => inspector.Room = room);
|
||||
AddStep(@"null room", () => inspector.Room = null);
|
||||
AddStep(@"set room", () => inspector.Room = room);
|
||||
AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above");
|
||||
AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } });
|
||||
AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying());
|
||||
AddStep(@"change type", () => room.Type.Value = new GameTypeTag());
|
||||
AddStep(@"change beatmap", () => room.Beatmap.Value = null);
|
||||
AddStep(@"change max participants", () => room.MaxParticipants.Value = null);
|
||||
AddStep(@"change participants", () => room.Participants.Value = new[]
|
||||
{
|
||||
new User { Username = @"filsdelama", Id = 2831793, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 854 } } },
|
||||
new User { Username = @"_index", Id = 652457, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 150 } } }
|
||||
});
|
||||
|
||||
AddStep(@"change room", () =>
|
||||
{
|
||||
Room newRoom = new Room
|
||||
{
|
||||
Name = { Value = @"My New, Better Than Ever Room" },
|
||||
Host = { Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" } } },
|
||||
Status = { Value = new RoomStatusOpen() },
|
||||
Type = { Value = new GameTypeTagTeam() },
|
||||
Beatmap =
|
||||
{
|
||||
Value = new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 7.07,
|
||||
Ruleset = rulesets.GetRuleset(0),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"FREEDOM DIVE",
|
||||
Artist = @"xi",
|
||||
AuthorString = @"Nakagawa-Kanon",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/39804/covers/cover.jpg?1456506845",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MaxParticipants = { Value = 10 },
|
||||
Participants =
|
||||
{
|
||||
Value = new[]
|
||||
{
|
||||
new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 4 } } },
|
||||
new User { Username = @"HappyStick", Id = 256802, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 752 } } },
|
||||
new User { Username = @"-Konpaku-", Id = 2258797, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 571 } } }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inspector.Room = newRoom;
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing.Input;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Screens.Match.Settings;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseRoomSettings : ManualInputManagerTestCase
|
||||
{
|
||||
private readonly Room room;
|
||||
private readonly TestRoomSettingsOverlay overlay;
|
||||
|
||||
public TestCaseRoomSettings()
|
||||
{
|
||||
room = new Room
|
||||
{
|
||||
Name = { Value = "One Testing Room" },
|
||||
Availability = { Value = RoomAvailability.Public },
|
||||
Type = { Value = new GameTypeTeamVersus() },
|
||||
MaxParticipants = { Value = 10 },
|
||||
};
|
||||
|
||||
Add(overlay = new TestRoomSettingsOverlay(room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.75f,
|
||||
});
|
||||
|
||||
AddStep(@"show", overlay.Show);
|
||||
assertAll();
|
||||
AddStep(@"set name", () => overlay.CurrentName = @"Two Testing Room");
|
||||
AddStep(@"set max", () => overlay.CurrentMaxParticipants = null);
|
||||
AddStep(@"set availability", () => overlay.CurrentAvailability = RoomAvailability.InviteOnly);
|
||||
AddStep(@"set type", () => overlay.CurrentType = new GameTypeTagTeam());
|
||||
apply();
|
||||
assertAll();
|
||||
AddStep(@"show", overlay.Show);
|
||||
AddStep(@"set room name", () => room.Name.Value = @"Room Changed Name!");
|
||||
AddStep(@"set room availability", () => room.Availability.Value = RoomAvailability.Public);
|
||||
AddStep(@"set room type", () => room.Type.Value = new GameTypeTag());
|
||||
AddStep(@"set room max", () => room.MaxParticipants.Value = 100);
|
||||
assertAll();
|
||||
AddStep(@"set name", () => overlay.CurrentName = @"Unsaved Testing Room");
|
||||
AddStep(@"set max", () => overlay.CurrentMaxParticipants = 20);
|
||||
AddStep(@"set availability", () => overlay.CurrentAvailability = RoomAvailability.FriendsOnly);
|
||||
AddStep(@"set type", () => overlay.CurrentType = new GameTypeVersus());
|
||||
AddStep(@"hide", overlay.Hide);
|
||||
AddWaitStep(5);
|
||||
AddStep(@"show", overlay.Show);
|
||||
assertAll();
|
||||
AddStep(@"hide", overlay.Hide);
|
||||
}
|
||||
|
||||
private void apply()
|
||||
{
|
||||
AddStep(@"apply", () =>
|
||||
{
|
||||
overlay.ClickApplyButton(InputManager);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertAll()
|
||||
{
|
||||
AddAssert(@"name == room name", () => overlay.CurrentName == room.Name.Value);
|
||||
AddAssert(@"max == room max", () => overlay.CurrentMaxParticipants == room.MaxParticipants.Value);
|
||||
AddAssert(@"availability == room availability", () => overlay.CurrentAvailability == room.Availability.Value);
|
||||
AddAssert(@"type == room type", () => Equals(overlay.CurrentType, room.Type.Value));
|
||||
}
|
||||
|
||||
private class TestRoomSettingsOverlay : RoomSettingsOverlay
|
||||
{
|
||||
public string CurrentName
|
||||
{
|
||||
get => NameField.Text;
|
||||
set => NameField.Text = value;
|
||||
}
|
||||
|
||||
public int? CurrentMaxParticipants
|
||||
{
|
||||
get
|
||||
{
|
||||
if (int.TryParse(MaxParticipantsField.Text, out int max))
|
||||
return max;
|
||||
|
||||
return null;
|
||||
}
|
||||
set => MaxParticipantsField.Text = value?.ToString();
|
||||
}
|
||||
|
||||
public RoomAvailability CurrentAvailability
|
||||
{
|
||||
get => AvailabilityPicker.Current.Value;
|
||||
set => AvailabilityPicker.Current.Value = value;
|
||||
}
|
||||
|
||||
public GameType CurrentType
|
||||
{
|
||||
get => TypePicker.Current.Value;
|
||||
set => TypePicker.Current.Value = value;
|
||||
}
|
||||
|
||||
public TestRoomSettingsOverlay(Room room) : base(room)
|
||||
{
|
||||
}
|
||||
|
||||
public void ClickApplyButton(ManualInputManager inputManager)
|
||||
{
|
||||
inputManager.MoveMouseTo(ApplyButton);
|
||||
inputManager.Click(MouseButton.Left);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
osu.Game.Tests/Visual/TestCaseRoomStatus.cs
Normal file
50
osu.Game.Tests/Visual/TestCaseRoomStatus.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseRoomStatus : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(RoomStatusEnded),
|
||||
typeof(RoomStatusOpen),
|
||||
typeof(RoomStatusPlaying)
|
||||
};
|
||||
|
||||
public TestCaseRoomStatus()
|
||||
{
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new DrawableRoom(new Room
|
||||
{
|
||||
Name = { Value = "Room 1" },
|
||||
Status = { Value = new RoomStatusOpen() }
|
||||
}),
|
||||
new DrawableRoom(new Room
|
||||
{
|
||||
Name = { Value = "Room 2" },
|
||||
Status = { Value = new RoomStatusPlaying() }
|
||||
}),
|
||||
new DrawableRoom(new Room
|
||||
{
|
||||
Name = { Value = "Room 3" },
|
||||
Status = { Value = new RoomStatusEnded() }
|
||||
}),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -16,15 +17,16 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
public class DifficultyIcon : DifficultyColouredContainer
|
||||
{
|
||||
private readonly BeatmapInfo beatmap;
|
||||
private readonly RulesetInfo ruleset;
|
||||
|
||||
public DifficultyIcon(BeatmapInfo beatmap)
|
||||
public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null)
|
||||
: base(beatmap)
|
||||
{
|
||||
if (beatmap == null)
|
||||
throw new ArgumentNullException(nameof(beatmap));
|
||||
|
||||
this.beatmap = beatmap;
|
||||
this.ruleset = ruleset ?? beatmap.Ruleset;
|
||||
|
||||
Size = new Vector2(20);
|
||||
}
|
||||
|
||||
@ -58,7 +60,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment)
|
||||
Icon = beatmap.Ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o }
|
||||
Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
|
||||
public UpdateableBeatmapBackgroundSprite()
|
||||
{
|
||||
Beatmap.BindValueChanged(b => Schedule(() => Model = b));
|
||||
Beatmap.BindValueChanged(b => Model = b);
|
||||
}
|
||||
|
||||
protected override Drawable CreateDrawable(BeatmapInfo model)
|
||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Online.API
|
||||
/// </summary>
|
||||
public abstract class APIRequest
|
||||
{
|
||||
protected virtual string Target => string.Empty;
|
||||
protected abstract string Target { get; }
|
||||
|
||||
protected virtual WebRequest CreateWebRequest() => new WebRequest(Uri);
|
||||
|
||||
|
35
osu.Game/Online/API/Requests/CreateRoomRequest.cs
Normal file
35
osu.Game/Online/API/Requests/CreateRoomRequest.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.IO.Network;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class CreateRoomRequest : APIRequest<APICreatedRoom>
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
public CreateRoomRequest(Room room)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
{
|
||||
var req = base.CreateWebRequest();
|
||||
|
||||
req.ContentType = "application/json";
|
||||
req.Method = HttpMethod.Post;
|
||||
|
||||
req.AddRaw(JsonConvert.SerializeObject(room));
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override string Target => "rooms";
|
||||
}
|
||||
}
|
30
osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs
Normal file
30
osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Net.Http;
|
||||
using osu.Framework.IO.Network;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class CreateRoomScoreRequest : APIRequest<APIScoreToken>
|
||||
{
|
||||
private readonly int roomId;
|
||||
private readonly int playlistItemId;
|
||||
|
||||
public CreateRoomScoreRequest(int roomId, int playlistItemId)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
this.playlistItemId = playlistItemId;
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
{
|
||||
var req = base.CreateWebRequest();
|
||||
req.Method = HttpMethod.Post;
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores";
|
||||
}
|
||||
}
|
20
osu.Game/Online/API/Requests/GetRoomScoresRequest.cs
Normal file
20
osu.Game/Online/API/Requests/GetRoomScoresRequest.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class GetRoomScoresRequest : APIRequest<List<APIRoomScoreInfo>>
|
||||
{
|
||||
private readonly int roomId;
|
||||
|
||||
public GetRoomScoresRequest(int roomId)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
}
|
||||
|
||||
protected override string Target => $@"rooms/{roomId}/leaderboard";
|
||||
}
|
||||
}
|
44
osu.Game/Online/API/Requests/GetRoomsRequest.cs
Normal file
44
osu.Game/Online/API/Requests/GetRoomsRequest.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class GetRoomsRequest : APIRequest<List<Room>>
|
||||
{
|
||||
private readonly PrimaryFilter primaryFilter;
|
||||
|
||||
public GetRoomsRequest(PrimaryFilter primaryFilter)
|
||||
{
|
||||
this.primaryFilter = primaryFilter;
|
||||
}
|
||||
|
||||
protected override string Target
|
||||
{
|
||||
get
|
||||
{
|
||||
string target = "rooms";
|
||||
|
||||
switch (primaryFilter)
|
||||
{
|
||||
case PrimaryFilter.Open:
|
||||
break;
|
||||
case PrimaryFilter.Owned:
|
||||
target += "/owned";
|
||||
break;
|
||||
case PrimaryFilter.Participated:
|
||||
target += "/participated";
|
||||
break;
|
||||
case PrimaryFilter.RecentlyEnded:
|
||||
target += "/ended";
|
||||
break;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
osu.Game/Online/API/Requests/JoinRoomRequest.cs
Normal file
31
osu.Game/Online/API/Requests/JoinRoomRequest.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Net.Http;
|
||||
using osu.Framework.IO.Network;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class JoinRoomRequest : APIRequest
|
||||
{
|
||||
private readonly Room room;
|
||||
private readonly User user;
|
||||
|
||||
public JoinRoomRequest(Room room, User user)
|
||||
{
|
||||
this.room = room;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
{
|
||||
var req = base.CreateWebRequest();
|
||||
req.Method = HttpMethod.Put;
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}";
|
||||
}
|
||||
}
|
31
osu.Game/Online/API/Requests/PartRoomRequest.cs
Normal file
31
osu.Game/Online/API/Requests/PartRoomRequest.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Net.Http;
|
||||
using osu.Framework.IO.Network;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class PartRoomRequest : APIRequest
|
||||
{
|
||||
private readonly Room room;
|
||||
private readonly User user;
|
||||
|
||||
public PartRoomRequest(Room room, User user)
|
||||
{
|
||||
this.room = room;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
{
|
||||
var req = base.CreateWebRequest();
|
||||
req.Method = HttpMethod.Delete;
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}";
|
||||
}
|
||||
}
|
@ -59,19 +59,17 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
|
||||
public BeatmapInfo ToBeatmap(RulesetStore rulesets)
|
||||
{
|
||||
var set = BeatmapSet?.ToBeatmapSet(rulesets);
|
||||
|
||||
return new BeatmapInfo
|
||||
{
|
||||
Metadata = this,
|
||||
Metadata = set?.Metadata ?? this,
|
||||
Ruleset = rulesets.GetRuleset(ruleset),
|
||||
StarDifficulty = starDifficulty,
|
||||
OnlineBeatmapID = OnlineBeatmapID,
|
||||
Version = version,
|
||||
Status = Status,
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = OnlineBeatmapSetID,
|
||||
Status = BeatmapSet?.Status ?? BeatmapSetOnlineStatus.None
|
||||
},
|
||||
BeatmapSet = set,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
DrainRate = drainRate,
|
||||
|
14
osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs
Normal file
14
osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APICreatedRoom : Room
|
||||
{
|
||||
[JsonProperty("error")]
|
||||
public string Error { get; set; }
|
||||
}
|
||||
}
|
12
osu.Game/Online/API/Requests/Responses/APIMod.cs
Normal file
12
osu.Game/Online/API/Requests/Responses/APIMod.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIMod : IMod
|
||||
{
|
||||
public string Acronym { get; set; }
|
||||
}
|
||||
}
|
17
osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs
Normal file
17
osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIRoomScoreInfo : ScoreInfo
|
||||
{
|
||||
[JsonProperty("attempts")]
|
||||
public int TotalAttempts { get; set; }
|
||||
|
||||
[JsonProperty("completed")]
|
||||
public int CompletedBeatmaps { get; set; }
|
||||
}
|
||||
}
|
13
osu.Game/Online/API/Requests/Responses/APIScoreToken.cs
Normal file
13
osu.Game/Online/API/Requests/Responses/APIScoreToken.cs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
public class APIScoreToken
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ID { get; set; }
|
||||
}
|
||||
}
|
40
osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs
Normal file
40
osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.IO.Network;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
{
|
||||
public class SubmitRoomScoreRequest : APIRequest
|
||||
{
|
||||
private readonly int scoreId;
|
||||
private readonly int roomId;
|
||||
private readonly int playlistItemId;
|
||||
private readonly ScoreInfo scoreInfo;
|
||||
|
||||
public SubmitRoomScoreRequest(int scoreId, int roomId, int playlistItemId, ScoreInfo scoreInfo)
|
||||
{
|
||||
this.scoreId = scoreId;
|
||||
this.roomId = roomId;
|
||||
this.playlistItemId = playlistItemId;
|
||||
this.scoreInfo = scoreInfo;
|
||||
}
|
||||
|
||||
protected override WebRequest CreateWebRequest()
|
||||
{
|
||||
var req = base.CreateWebRequest();
|
||||
|
||||
req.ContentType = "application/json";
|
||||
req.Method = HttpMethod.Put;
|
||||
|
||||
req.AddRaw(JsonConvert.SerializeObject(scoreInfo));
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores/{scoreId}";
|
||||
}
|
||||
}
|
@ -19,10 +19,10 @@ namespace osu.Game.Online.Chat
|
||||
/// </summary>
|
||||
public class StandAloneChatDisplay : CompositeDrawable
|
||||
{
|
||||
private readonly bool postingTextbox;
|
||||
|
||||
public readonly Bindable<Channel> Channel = new Bindable<Channel>();
|
||||
|
||||
public Action Exit;
|
||||
|
||||
private readonly FocusedTextBox textbox;
|
||||
|
||||
protected ChannelManager ChannelManager;
|
||||
@ -31,6 +31,8 @@ namespace osu.Game.Online.Chat
|
||||
|
||||
private DrawableChannel drawableChannel;
|
||||
|
||||
private readonly bool postingTextbox;
|
||||
|
||||
private const float textbox_height = 30;
|
||||
|
||||
/// <summary>
|
||||
@ -66,6 +68,8 @@ namespace osu.Game.Online.Chat
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
});
|
||||
|
||||
textbox.Exit += () => Exit?.Invoke();
|
||||
}
|
||||
|
||||
Channel.BindValueChanged(channelChanged);
|
||||
|
@ -18,7 +18,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
public abstract class Leaderboard<TScope, ScoreInfo> : Container
|
||||
public abstract class Leaderboard<TScope, ScoreInfo> : Container, IOnlineComponent
|
||||
{
|
||||
private const double fade_duration = 300;
|
||||
|
||||
@ -55,14 +55,8 @@ namespace osu.Game.Online.Leaderboards
|
||||
// ensure placeholder is hidden when displaying scores
|
||||
PlaceholderState = PlaceholderState.Successful;
|
||||
|
||||
var flow = scrollFlow = new FillFlowContainer<LeaderboardScore>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 5f),
|
||||
Padding = new MarginPadding { Top = 10, Bottom = 5 },
|
||||
ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1))
|
||||
};
|
||||
scrollFlow = CreateScoreFlow();
|
||||
scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
|
||||
|
||||
// schedule because we may not be loaded yet (LoadComponentAsync complains).
|
||||
showScoresDelegate?.Cancel();
|
||||
@ -71,12 +65,12 @@ namespace osu.Game.Online.Leaderboards
|
||||
else
|
||||
showScores();
|
||||
|
||||
void showScores() => LoadComponentAsync(flow, _ =>
|
||||
void showScores() => LoadComponentAsync(scrollFlow, _ =>
|
||||
{
|
||||
scrollContainer.Add(flow);
|
||||
scrollContainer.Add(scrollFlow);
|
||||
|
||||
int i = 0;
|
||||
foreach (var s in flow.Children)
|
||||
foreach (var s in scrollFlow.Children)
|
||||
{
|
||||
using (s.BeginDelayedSequence(i++ * 50, true))
|
||||
s.Show();
|
||||
@ -87,6 +81,15 @@ namespace osu.Game.Online.Leaderboards
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual FillFlowContainer<LeaderboardScore> CreateScoreFlow()
|
||||
=> new FillFlowContainer<LeaderboardScore>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 5f),
|
||||
Padding = new MarginPadding { Top = 10, Bottom = 5 },
|
||||
};
|
||||
|
||||
private TScope scope;
|
||||
|
||||
public TScope Scope
|
||||
@ -175,26 +178,22 @@ namespace osu.Game.Online.Leaderboards
|
||||
private void load(APIAccess api)
|
||||
{
|
||||
this.api = api;
|
||||
|
||||
if (api != null)
|
||||
api.OnStateChange += handleApiStateChange;
|
||||
api?.Register(this);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (api != null)
|
||||
api.OnStateChange -= handleApiStateChange;
|
||||
api?.Unregister(this);
|
||||
}
|
||||
|
||||
public void RefreshScores() => UpdateScores();
|
||||
|
||||
private APIRequest getScoresRequest;
|
||||
|
||||
private void handleApiStateChange(APIState oldState, APIState newState)
|
||||
public void APIStateChanged(APIAccess api, APIState state)
|
||||
{
|
||||
if (newState == APIState.Online)
|
||||
if (state == APIState.Online)
|
||||
UpdateScores();
|
||||
}
|
||||
|
||||
@ -265,14 +264,18 @@ namespace osu.Game.Online.Leaderboards
|
||||
currentPlaceholder = placeholder;
|
||||
}
|
||||
|
||||
protected virtual bool FadeBottom => true;
|
||||
protected virtual bool FadeTop => false;
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
var fadeStart = scrollContainer.Current + scrollContainer.DrawHeight;
|
||||
var fadeBottom = scrollContainer.Current + scrollContainer.DrawHeight;
|
||||
var fadeTop = scrollContainer.Current + LeaderboardScore.HEIGHT;
|
||||
|
||||
if (!scrollContainer.IsScrolledToEnd())
|
||||
fadeStart -= LeaderboardScore.HEIGHT;
|
||||
fadeBottom -= LeaderboardScore.HEIGHT;
|
||||
|
||||
if (scrollFlow == null)
|
||||
return;
|
||||
@ -282,15 +285,23 @@ namespace osu.Game.Online.Leaderboards
|
||||
var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y;
|
||||
var bottomY = topY + LeaderboardScore.HEIGHT;
|
||||
|
||||
if (bottomY < fadeStart)
|
||||
bool requireTopFade = FadeTop && topY <= fadeTop;
|
||||
bool requireBottomFade = FadeBottom && bottomY >= fadeBottom;
|
||||
|
||||
if (!requireTopFade && !requireBottomFade)
|
||||
c.Colour = Color4.White;
|
||||
else if (topY > fadeStart + LeaderboardScore.HEIGHT)
|
||||
else if (topY > fadeBottom + LeaderboardScore.HEIGHT || bottomY < fadeTop - LeaderboardScore.HEIGHT)
|
||||
c.Colour = Color4.Transparent;
|
||||
else
|
||||
{
|
||||
c.Colour = ColourInfo.GradientVertical(
|
||||
Color4.White.Opacity(Math.Min(1 - (topY - fadeStart) / LeaderboardScore.HEIGHT, 1)),
|
||||
Color4.White.Opacity(Math.Min(1 - (bottomY - fadeStart) / LeaderboardScore.HEIGHT, 1)));
|
||||
if (bottomY - fadeBottom > 0 && FadeBottom)
|
||||
c.Colour = ColourInfo.GradientVertical(
|
||||
Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / LeaderboardScore.HEIGHT, 1)),
|
||||
Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / LeaderboardScore.HEIGHT, 1)));
|
||||
else if (FadeTop)
|
||||
c.Colour = ColourInfo.GradientVertical(
|
||||
Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / LeaderboardScore.HEIGHT, 1)),
|
||||
Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / LeaderboardScore.HEIGHT, 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,8 +73,8 @@ namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = @"Exo2.0-MediumItalic",
|
||||
TextSize = 22,
|
||||
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
|
||||
|
@ -1,11 +1,7 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer
|
||||
@ -13,137 +9,10 @@ namespace osu.Game.Online.Multiplayer
|
||||
public abstract class GameType
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public abstract Drawable GetIcon(OsuColour colours, float size);
|
||||
|
||||
public override int GetHashCode() => GetType().GetHashCode();
|
||||
public override bool Equals(object obj) => GetType() == obj?.GetType();
|
||||
}
|
||||
|
||||
public class GameTypeTag : GameType
|
||||
{
|
||||
public override string Name => "Tag";
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Icon = FontAwesome.fa_refresh,
|
||||
Size = new Vector2(size),
|
||||
Colour = colours.Blue,
|
||||
Shadow = false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class GameTypeVersus : GameType
|
||||
{
|
||||
public override string Name => "Versus";
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new VersusRow(colours.Blue, colours.Blue, size * 0.6f)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class GameTypeTagTeam : GameType
|
||||
{
|
||||
public override string Name => "Tag Team";
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(2f),
|
||||
Children = new[]
|
||||
{
|
||||
new SpriteIcon
|
||||
{
|
||||
Icon = FontAwesome.fa_refresh,
|
||||
Size = new Vector2(size * 0.75f),
|
||||
Colour = colours.Blue,
|
||||
Shadow = false,
|
||||
},
|
||||
new SpriteIcon
|
||||
{
|
||||
Icon = FontAwesome.fa_refresh,
|
||||
Size = new Vector2(size * 0.75f),
|
||||
Colour = colours.Pink,
|
||||
Shadow = false,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class GameTypeTeamVersus : GameType
|
||||
{
|
||||
public override string Name => "Team Versus";
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(2f),
|
||||
Children = new[]
|
||||
{
|
||||
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
|
||||
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class VersusRow : FillFlowContainer
|
||||
{
|
||||
public VersusRow(Color4 first, Color4 second, float size)
|
||||
{
|
||||
var triangleSize = new Vector2(size);
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Spacing = new Vector2(2f, 0f);
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Size = triangleSize,
|
||||
Colour = first,
|
||||
Children = new[]
|
||||
{
|
||||
new EquilateralTriangle
|
||||
{
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Rotation = 90,
|
||||
EdgeSmoothness = new Vector2(1f),
|
||||
},
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Size = triangleSize,
|
||||
Colour = second,
|
||||
Children = new[]
|
||||
{
|
||||
new EquilateralTriangle
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Rotation = -90,
|
||||
EdgeSmoothness = new Vector2(1f),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs
Normal file
27
osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.GameTypes
|
||||
{
|
||||
public class GameTypeTag : GameType
|
||||
{
|
||||
public override string Name => "Tag";
|
||||
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Icon = FontAwesome.fa_refresh,
|
||||
Size = new Vector2(size),
|
||||
Colour = colours.Blue,
|
||||
Shadow = false,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
44
osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs
Normal file
44
osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.GameTypes
|
||||
{
|
||||
public class GameTypeTagTeam : GameType
|
||||
{
|
||||
public override string Name => "Tag Team";
|
||||
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(2f),
|
||||
Children = new[]
|
||||
{
|
||||
new SpriteIcon
|
||||
{
|
||||
Icon = FontAwesome.fa_refresh,
|
||||
Size = new Vector2(size * 0.75f),
|
||||
Colour = colours.Blue,
|
||||
Shadow = false,
|
||||
},
|
||||
new SpriteIcon
|
||||
{
|
||||
Icon = FontAwesome.fa_refresh,
|
||||
Size = new Vector2(size * 0.75f),
|
||||
Colour = colours.Pink,
|
||||
Shadow = false,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
32
osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs
Normal file
32
osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.GameTypes
|
||||
{
|
||||
public class GameTypeTeamVersus : GameType
|
||||
{
|
||||
public override string Name => "Team Versus";
|
||||
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(2f),
|
||||
Children = new[]
|
||||
{
|
||||
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
|
||||
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
24
osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs
Normal file
24
osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.GameTypes
|
||||
{
|
||||
public class GameTypeTimeshift : GameType
|
||||
{
|
||||
public override string Name => "Timeshift";
|
||||
|
||||
public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Icon = FontAwesome.fa_clock_o,
|
||||
Size = new Vector2(size),
|
||||
Colour = colours.Blue,
|
||||
Shadow = false
|
||||
};
|
||||
}
|
||||
}
|
22
osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs
Normal file
22
osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.GameTypes
|
||||
{
|
||||
public class GameTypeVersus : GameType
|
||||
{
|
||||
public override string Name => "Versus";
|
||||
|
||||
public override Drawable GetIcon(OsuColour colours, float size)
|
||||
{
|
||||
return new VersusRow(colours.Blue, colours.Blue, size * 0.6f)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
55
osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs
Normal file
55
osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.GameTypes
|
||||
{
|
||||
public class VersusRow : FillFlowContainer
|
||||
{
|
||||
public VersusRow(Color4 first, Color4 second, float size)
|
||||
{
|
||||
var triangleSize = new Vector2(size);
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Spacing = new Vector2(2f, 0f);
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Size = triangleSize,
|
||||
Colour = first,
|
||||
Children = new[]
|
||||
{
|
||||
new EquilateralTriangle
|
||||
{
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Rotation = 90,
|
||||
EdgeSmoothness = new Vector2(1f),
|
||||
},
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Size = triangleSize,
|
||||
Colour = second,
|
||||
Children = new[]
|
||||
{
|
||||
new EquilateralTriangle
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Rotation = -90,
|
||||
EdgeSmoothness = new Vector2(1f),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
93
osu.Game/Online/Multiplayer/PlaylistItem.cs
Normal file
93
osu.Game/Online/Multiplayer/PlaylistItem.cs
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
public class PlaylistItem
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ID { get; set; }
|
||||
|
||||
[JsonProperty("beatmap_id")]
|
||||
public int BeatmapID { get; set; }
|
||||
|
||||
[JsonProperty("ruleset_id")]
|
||||
public int RulesetID { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
get => beatmap;
|
||||
set
|
||||
{
|
||||
beatmap = value;
|
||||
BeatmapID = value?.OnlineBeatmapID ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public RulesetInfo Ruleset { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly BindableCollection<Mod> AllowedMods = new BindableCollection<Mod>();
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly BindableCollection<Mod> RequiredMods = new BindableCollection<Mod>();
|
||||
|
||||
[JsonProperty("beatmap")]
|
||||
private APIBeatmap apiBeatmap { get; set; }
|
||||
|
||||
[JsonProperty("allowed_mods")]
|
||||
private APIMod[] allowedMods
|
||||
{
|
||||
get => AllowedMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray();
|
||||
set => _allowedMods = value;
|
||||
}
|
||||
|
||||
[JsonProperty("required_mods")]
|
||||
private APIMod[] requiredMods
|
||||
{
|
||||
get => RequiredMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray();
|
||||
set => _requiredMods = value;
|
||||
}
|
||||
|
||||
private BeatmapInfo beatmap;
|
||||
private APIMod[] _allowedMods;
|
||||
private APIMod[] _requiredMods;
|
||||
|
||||
public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets)
|
||||
{
|
||||
// If we don't have an api beatmap, the request occurred as a result of room creation, so we can query the local beatmap instead
|
||||
// Todo: Is this a bug? Room creation only returns the beatmap ID
|
||||
Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets);
|
||||
Ruleset = rulesets.GetRuleset(RulesetID);
|
||||
|
||||
if (_allowedMods != null)
|
||||
{
|
||||
AllowedMods.Clear();
|
||||
AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym)));
|
||||
|
||||
_allowedMods = null;
|
||||
}
|
||||
|
||||
if (_requiredMods != null)
|
||||
{
|
||||
RequiredMods.Clear();
|
||||
RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym)));
|
||||
|
||||
_requiredMods = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShouldSerializeID() => false;
|
||||
public bool ShouldSerializeapiBeatmap() => false;
|
||||
}
|
||||
}
|
@ -1,22 +1,112 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer.GameTypes;
|
||||
using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
public class Room
|
||||
{
|
||||
public Bindable<string> Name = new Bindable<string>();
|
||||
public Bindable<User> Host = new Bindable<User>();
|
||||
public Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
|
||||
public Bindable<RoomAvailability> Availability = new Bindable<RoomAvailability>();
|
||||
public Bindable<GameType> Type = new Bindable<GameType>();
|
||||
public Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
public Bindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
public Bindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
[JsonProperty("id")]
|
||||
public Bindable<int?> RoomID { get; private set; } = new Bindable<int?>();
|
||||
|
||||
[JsonProperty("name")]
|
||||
public Bindable<string> Name { get; private set; } = new Bindable<string>();
|
||||
|
||||
[JsonProperty("host")]
|
||||
public Bindable<User> Host { get; private set; } = new Bindable<User>();
|
||||
|
||||
[JsonProperty("playlist")]
|
||||
public BindableCollection<PlaylistItem> Playlist { get; set; } = new BindableCollection<PlaylistItem>();
|
||||
|
||||
[JsonProperty("channel_id")]
|
||||
public Bindable<int> ChannelId { get; private set; } = new Bindable<int>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<TimeSpan> Duration { get; private set; } = new Bindable<TimeSpan>(TimeSpan.FromMinutes(30));
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<int?> MaxAttempts { get; private set; } = new Bindable<int?>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<RoomStatus> Status { get; private set; } = new Bindable<RoomStatus>(new RoomStatusOpen());
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<RoomAvailability> Availability { get; private set; } = new Bindable<RoomAvailability>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<GameType> Type { get; private set; } = new Bindable<GameType>(new GameTypeTimeshift());
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<int?> MaxParticipants { get; private set; } = new Bindable<int?>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<IEnumerable<User>> Participants { get; private set; } = new Bindable<IEnumerable<User>>(Enumerable.Empty<User>());
|
||||
|
||||
public Bindable<int> ParticipantCount { get; private set; } = new Bindable<int>();
|
||||
|
||||
// todo: TEMPORARY
|
||||
[JsonProperty("participant_count")]
|
||||
private int? participantCount
|
||||
{
|
||||
get => ParticipantCount;
|
||||
set => ParticipantCount.Value = value ?? 0;
|
||||
}
|
||||
|
||||
[JsonProperty("duration")]
|
||||
private int duration
|
||||
{
|
||||
get => (int)Duration.Value.TotalMinutes;
|
||||
set => Duration.Value = TimeSpan.FromMinutes(value);
|
||||
}
|
||||
|
||||
// Only supports retrieval for now
|
||||
[JsonProperty("ends_at")]
|
||||
public Bindable<DateTimeOffset> EndDate { get; private set; } = new Bindable<DateTimeOffset>();
|
||||
|
||||
// Todo: Find a better way to do this (https://github.com/ppy/osu-framework/issues/1930)
|
||||
[JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
private int? maxAttempts
|
||||
{
|
||||
get => MaxAttempts;
|
||||
set => MaxAttempts.Value = value;
|
||||
}
|
||||
|
||||
public void CopyFrom(Room other)
|
||||
{
|
||||
RoomID.Value = other.RoomID;
|
||||
Name.Value = other.Name;
|
||||
|
||||
if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id)
|
||||
Host.Value = other.Host;
|
||||
|
||||
Status.Value = other.Status;
|
||||
Availability.Value = other.Availability;
|
||||
Type.Value = other.Type;
|
||||
MaxParticipants.Value = other.MaxParticipants;
|
||||
ParticipantCount.Value = other.ParticipantCount.Value;
|
||||
Participants.Value = other.Participants.Value.ToArray();
|
||||
EndDate.Value = other.EndDate;
|
||||
|
||||
if (DateTimeOffset.Now >= EndDate.Value)
|
||||
Status.Value = new RoomStatusEnded();
|
||||
|
||||
// Todo: Temporary, should only remove/add new items (requires framework changes)
|
||||
if (Playlist.Count == 0)
|
||||
Playlist.AddRange(other.Playlist);
|
||||
else if (other.Playlist.Count > 0)
|
||||
Playlist.First().ID = other.Playlist.First().ID;
|
||||
}
|
||||
|
||||
public bool ShouldSerializeRoomID() => false;
|
||||
public bool ShouldSerializeHost() => false;
|
||||
public bool ShouldSerializeEndDate() => false;
|
||||
}
|
||||
}
|
||||
|
@ -10,17 +10,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
public abstract string Message { get; }
|
||||
public abstract Color4 GetAppropriateColour(OsuColour colours);
|
||||
}
|
||||
|
||||
public class RoomStatusOpen : RoomStatus
|
||||
{
|
||||
public override string Message => @"Welcoming Players";
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight;
|
||||
}
|
||||
|
||||
public class RoomStatusPlaying : RoomStatus
|
||||
{
|
||||
public override string Message => @"Now Playing";
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple;
|
||||
public override int GetHashCode() => GetType().GetHashCode();
|
||||
public override bool Equals(object obj) => GetType() == obj?.GetType();
|
||||
}
|
||||
}
|
||||
|
14
osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs
Normal file
14
osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.RoomStatuses
|
||||
{
|
||||
public class RoomStatusEnded : RoomStatus
|
||||
{
|
||||
public override string Message => @"Ended";
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.YellowDarker;
|
||||
}
|
||||
}
|
14
osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs
Normal file
14
osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.RoomStatuses
|
||||
{
|
||||
public class RoomStatusOpen : RoomStatus
|
||||
{
|
||||
public override string Message => @"Welcoming Players";
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Online.Multiplayer.RoomStatuses
|
||||
{
|
||||
public class RoomStatusPlaying : RoomStatus
|
||||
{
|
||||
public override string Message => @"Now Playing";
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple;
|
||||
}
|
||||
}
|
@ -87,13 +87,22 @@ namespace osu.Game.Online
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform the polling in this method. Call <see cref="pollComplete"/> when done.
|
||||
/// Performs a poll. Implement but do not call this.
|
||||
/// </summary>
|
||||
protected virtual Task Poll()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Immediately performs a <see cref="Poll"/>.
|
||||
/// </summary>
|
||||
public void PollImmediately()
|
||||
{
|
||||
lastTimePolled = Time.Current - timeBetweenPolls;
|
||||
scheduleNextPoll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call when a poll operation has completed.
|
||||
/// </summary>
|
||||
|
@ -317,7 +317,7 @@ namespace osu.Game
|
||||
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap);
|
||||
Beatmap.Value.Mods.Value = databasedScoreInfo.Mods;
|
||||
|
||||
currentScreen.Push(new PlayerLoader(new ReplayPlayer(databasedScore)));
|
||||
currentScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,6 +690,32 @@ namespace osu.Game
|
||||
MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
}
|
||||
|
||||
private void screenAdded(Screen newScreen)
|
||||
{
|
||||
currentScreen = (OsuScreen)newScreen;
|
||||
|
@ -260,7 +260,7 @@ namespace osu.Game
|
||||
RegisterAudioManager(audioManager);
|
||||
}
|
||||
|
||||
private OsuBindableBeatmap(WorkingBeatmap defaultValue)
|
||||
public OsuBindableBeatmap(WorkingBeatmap defaultValue)
|
||||
: base(defaultValue)
|
||||
{
|
||||
}
|
||||
|
@ -3,10 +3,12 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -110,7 +112,7 @@ namespace osu.Game.Overlays.Music
|
||||
{
|
||||
sprite.TextSize = 16;
|
||||
sprite.Font = @"Exo2.0-Regular";
|
||||
});
|
||||
}).OfType<SpriteText>();
|
||||
|
||||
text.AddText(artistBind.Value, sprite =>
|
||||
{
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public interface IMod
|
||||
@ -8,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// <summary>
|
||||
/// The shortened name of this mod.
|
||||
/// </summary>
|
||||
[JsonProperty("acronym")]
|
||||
string Acronym { get; }
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Rulesets;
|
||||
@ -19,25 +20,39 @@ namespace osu.Game.Scoring
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
[JsonProperty("rank")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public ScoreRank Rank { get; set; }
|
||||
|
||||
[JsonProperty("total_score")]
|
||||
public int TotalScore { get; set; }
|
||||
|
||||
[JsonProperty("accuracy")]
|
||||
[Column(TypeName="DECIMAL(1,4)")]
|
||||
public double Accuracy { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public double? PP { get; set; }
|
||||
|
||||
[JsonProperty("max_combo")]
|
||||
public int MaxCombo { get; set; }
|
||||
|
||||
public int Combo { get; set; }
|
||||
[JsonIgnore]
|
||||
public int Combo { get; set; } // Todo: Shouldn't exist in here
|
||||
|
||||
[JsonIgnore]
|
||||
public int RulesetID { get; set; }
|
||||
|
||||
[JsonProperty("passed")]
|
||||
[NotMapped]
|
||||
public bool Passed { get; set; } = true;
|
||||
|
||||
[JsonIgnore]
|
||||
public virtual RulesetInfo Ruleset { get; set; }
|
||||
|
||||
private Mod[] mods;
|
||||
|
||||
[JsonProperty("mods")]
|
||||
[NotMapped]
|
||||
public Mod[] Mods
|
||||
{
|
||||
@ -62,6 +77,7 @@ namespace osu.Game.Scoring
|
||||
|
||||
private string modsJson;
|
||||
|
||||
[JsonIgnore]
|
||||
[Column("Mods")]
|
||||
public string ModsJson
|
||||
{
|
||||
@ -84,9 +100,11 @@ namespace osu.Game.Scoring
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public User User;
|
||||
[NotMapped]
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[Column("User")]
|
||||
public string UserString
|
||||
{
|
||||
@ -97,15 +115,19 @@ namespace osu.Game.Scoring
|
||||
[JsonIgnore]
|
||||
public int BeatmapInfoID { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public virtual BeatmapInfo Beatmap { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public long? OnlineScoreID { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public DateTimeOffset Date { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[JsonProperty("statistics")]
|
||||
public Dictionary<HitResult, int> Statistics = new Dictionary<HitResult, int>();
|
||||
|
||||
[JsonIgnore]
|
||||
[Column("Statistics")]
|
||||
public string StatisticsJson
|
||||
{
|
||||
@ -125,8 +147,10 @@ namespace osu.Game.Scoring
|
||||
[JsonIgnore]
|
||||
public List<ScoreFileInfo> Files { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string Hash { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool DeletePending { get; set; }
|
||||
|
||||
[Serializable]
|
||||
|
@ -17,7 +17,9 @@ using osu.Framework.Threading;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
@ -90,7 +92,7 @@ namespace osu.Game.Screens.Menu
|
||||
buttonArea.Flow.CentreTarget = iconFacade;
|
||||
|
||||
buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.fa_user, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P));
|
||||
buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), () => OnMulti?.Invoke(), 0, Key.M));
|
||||
buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), onMulti, 0, Key.M));
|
||||
buttonsPlay.Add(new Button(@"chart", @"button-generic-select", FontAwesome.fa_osu_charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke()));
|
||||
buttonsPlay.ForEach(b => b.VisibleState = ButtonSystemState.Play);
|
||||
|
||||
@ -103,19 +105,41 @@ namespace osu.Game.Screens.Menu
|
||||
buttonArea.AddRange(buttonsTopLevel);
|
||||
}
|
||||
|
||||
private OsuGame game;
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuGame game { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private NotificationOverlay notifications { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(AudioManager audio, OsuGame game, IdleTracker idleTracker)
|
||||
private void load(AudioManager audio, IdleTracker idleTracker)
|
||||
{
|
||||
this.game = game;
|
||||
|
||||
isIdle.ValueChanged += updateIdleState;
|
||||
|
||||
if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle);
|
||||
|
||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||
}
|
||||
|
||||
private void onMulti()
|
||||
{
|
||||
if (!api.IsLoggedIn)
|
||||
{
|
||||
notifications?.Post(new SimpleNotification
|
||||
{
|
||||
Text = "You gotta be logged in to multi 'yo!",
|
||||
Icon = FontAwesome.fa_globe
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
OnMulti?.Invoke();
|
||||
}
|
||||
|
||||
private void updateIdleState(bool isIdle)
|
||||
{
|
||||
if (isIdle && State != ButtonSystemState.Exit)
|
||||
|
@ -1,68 +1,89 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Chat;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class BeatmapTitle : FillFlowContainer<OsuSpriteText>
|
||||
public class BeatmapTitle : CompositeDrawable
|
||||
{
|
||||
private readonly OsuSpriteText beatmapTitle, beatmapDash, beatmapArtist;
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
|
||||
public float TextSize
|
||||
{
|
||||
set { beatmapTitle.TextSize = beatmapDash.TextSize = beatmapArtist.TextSize = value; }
|
||||
}
|
||||
|
||||
private BeatmapInfo beatmap;
|
||||
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == beatmap) return;
|
||||
beatmap = value;
|
||||
|
||||
if (IsLoaded)
|
||||
updateText();
|
||||
}
|
||||
}
|
||||
private readonly LinkFlowContainer textFlow;
|
||||
|
||||
public BeatmapTitle()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Horizontal;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
beatmapTitle = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", },
|
||||
beatmapDash = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", },
|
||||
beatmapArtist = new OsuSpriteText { Font = @"Exo2.0-RegularItalic", },
|
||||
};
|
||||
InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both };
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateText();
|
||||
Beatmap.BindValueChanged(v => updateText(), true);
|
||||
}
|
||||
|
||||
private float textSize = OsuSpriteText.FONT_SIZE;
|
||||
|
||||
public float TextSize
|
||||
{
|
||||
get => textSize;
|
||||
set
|
||||
{
|
||||
if (textSize == value)
|
||||
return;
|
||||
textSize = value;
|
||||
|
||||
updateText();
|
||||
}
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; }
|
||||
|
||||
private void updateText()
|
||||
{
|
||||
if (beatmap == null)
|
||||
{
|
||||
beatmapTitle.Text = "Changing map";
|
||||
beatmapDash.Text = beatmapArtist.Text = string.Empty;
|
||||
}
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
textFlow.Clear();
|
||||
|
||||
if (Beatmap.Value == null)
|
||||
textFlow.AddText("No beatmap selected", s =>
|
||||
{
|
||||
s.TextSize = TextSize;
|
||||
s.Colour = colours.PinkLight;
|
||||
});
|
||||
else
|
||||
{
|
||||
beatmapTitle.Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title));
|
||||
beatmapDash.Text = @" - ";
|
||||
beatmapArtist.Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist));
|
||||
textFlow.AddLink(new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)),
|
||||
TextSize = TextSize,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = " - ",
|
||||
TextSize = TextSize,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)),
|
||||
TextSize = TextSize,
|
||||
}
|
||||
}, null, LinkAction.OpenBeatmap, Beatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,77 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class BeatmapTypeInfo : FillFlowContainer
|
||||
public class BeatmapTypeInfo : CompositeDrawable
|
||||
{
|
||||
private readonly ModeTypeInfo modeTypeInfo;
|
||||
private readonly BeatmapTitle beatmapTitle;
|
||||
private readonly OsuSpriteText beatmapAuthor;
|
||||
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
set
|
||||
{
|
||||
modeTypeInfo.Beatmap = beatmapTitle.Beatmap = value;
|
||||
beatmapAuthor.Text = value == null ? string.Empty : $"mapped by {value.Metadata.Author}";
|
||||
}
|
||||
}
|
||||
|
||||
public GameType Type
|
||||
{
|
||||
set { modeTypeInfo.Type = value; }
|
||||
}
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
public readonly IBindable<GameType> Type = new Bindable<GameType>();
|
||||
|
||||
public BeatmapTypeInfo()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Horizontal;
|
||||
LayoutDuration = 100;
|
||||
Spacing = new Vector2(5f, 0f);
|
||||
|
||||
Children = new Drawable[]
|
||||
BeatmapTitle beatmapTitle;
|
||||
ModeTypeInfo modeTypeInfo;
|
||||
LinkFlowContainer beatmapAuthor;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
modeTypeInfo = new ModeTypeInfo(),
|
||||
new Container
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
LayoutDuration = 100,
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = 30,
|
||||
Margin = new MarginPadding { Left = 5 },
|
||||
Children = new Drawable[]
|
||||
modeTypeInfo = new ModeTypeInfo(),
|
||||
new Container
|
||||
{
|
||||
beatmapTitle = new BeatmapTitle(),
|
||||
beatmapAuthor = new OsuSpriteText
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = 30,
|
||||
Margin = new MarginPadding { Left = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
TextSize = 14,
|
||||
beatmapTitle = new BeatmapTitle(),
|
||||
beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
AutoSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
beatmapAuthor.Colour = colours.Gray9;
|
||||
modeTypeInfo.Beatmap.BindTo(Beatmap);
|
||||
modeTypeInfo.Ruleset.BindTo(Ruleset);
|
||||
modeTypeInfo.Type.BindTo(Type);
|
||||
|
||||
beatmapTitle.Beatmap.BindTo(Beatmap);
|
||||
|
||||
Beatmap.BindValueChanged(v =>
|
||||
{
|
||||
beatmapAuthor.Clear();
|
||||
|
||||
if (v != null)
|
||||
{
|
||||
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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
38
osu.Game/Screens/Multi/Components/DisableableTabControl.cs
Normal file
38
osu.Game/Screens/Multi/Components/DisableableTabControl.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public abstract class DisableableTabControl<T> : TabControl<T>
|
||||
{
|
||||
public readonly BindableBool Enabled = new BindableBool();
|
||||
|
||||
protected override void AddTabItem(TabItem<T> tab, bool addToDropdown = true)
|
||||
{
|
||||
if (tab is DisableableTabItem<T> disableable)
|
||||
disableable.Enabled.BindTo(Enabled);
|
||||
base.AddTabItem(tab, addToDropdown);
|
||||
}
|
||||
|
||||
protected abstract class DisableableTabItem<T> : TabItem<T>
|
||||
{
|
||||
public readonly BindableBool Enabled = new BindableBool();
|
||||
|
||||
protected DisableableTabItem(T value)
|
||||
: base(value)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (!Enabled)
|
||||
return true;
|
||||
return base.OnClick(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,83 +1,67 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class ModeTypeInfo : Container
|
||||
public class ModeTypeInfo : CompositeDrawable
|
||||
{
|
||||
private const float height = 30;
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly Container rulesetContainer, gameTypeContainer;
|
||||
private readonly Container rulesetContainer;
|
||||
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
rulesetContainer.FadeIn(transition_duration);
|
||||
rulesetContainer.Children = new[]
|
||||
{
|
||||
new DifficultyIcon(value)
|
||||
{
|
||||
Size = new Vector2(height),
|
||||
},
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
rulesetContainer.FadeOut(transition_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GameType Type
|
||||
{
|
||||
set
|
||||
{
|
||||
gameTypeContainer.Children = new[]
|
||||
{
|
||||
new DrawableGameType(value)
|
||||
{
|
||||
Size = new Vector2(height),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
public readonly IBindable<GameType> Type = new Bindable<GameType>();
|
||||
|
||||
public ModeTypeInfo()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new[]
|
||||
Container gameTypeContainer;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
new FillFlowContainer
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5f, 0f),
|
||||
LayoutDuration = 100,
|
||||
Children = new[]
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5f, 0f),
|
||||
LayoutDuration = 100,
|
||||
Children = new[]
|
||||
rulesetContainer = new Container
|
||||
{
|
||||
rulesetContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
gameTypeContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
gameTypeContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Beatmap.BindValueChanged(updateBeatmap);
|
||||
Ruleset.BindValueChanged(_ => updateBeatmap(Beatmap.Value));
|
||||
Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) });
|
||||
}
|
||||
|
||||
private void updateBeatmap(BeatmapInfo beatmap)
|
||||
{
|
||||
if (beatmap != null)
|
||||
{
|
||||
rulesetContainer.FadeIn(transition_duration);
|
||||
rulesetContainer.Child = new DifficultyIcon(beatmap, Ruleset.Value) { Size = new Vector2(height) };
|
||||
}
|
||||
else
|
||||
rulesetContainer.FadeOut(transition_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +1,67 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class ParticipantCount : FillFlowContainer
|
||||
public class ParticipantCountDisplay : CompositeDrawable
|
||||
{
|
||||
private const float text_size = 30;
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly OsuSpriteText count, slash, maxText;
|
||||
private readonly OsuSpriteText slash, maxText;
|
||||
|
||||
public int Count
|
||||
{
|
||||
set => count.Text = value.ToString();
|
||||
}
|
||||
public readonly IBindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
public readonly IBindable<int> ParticipantCount = new Bindable<int>();
|
||||
public readonly IBindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
|
||||
private int? max;
|
||||
public int? Max
|
||||
{
|
||||
get => max;
|
||||
set
|
||||
{
|
||||
if (value == max) return;
|
||||
max = value;
|
||||
|
||||
updateMax();
|
||||
}
|
||||
}
|
||||
|
||||
public ParticipantCount()
|
||||
public ParticipantCountDisplay()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Horizontal;
|
||||
LayoutDuration = transition_duration;
|
||||
|
||||
Children = new[]
|
||||
OsuSpriteText count;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
count = new OsuSpriteText
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
LayoutDuration = transition_duration,
|
||||
Children = new[]
|
||||
{
|
||||
TextSize = text_size,
|
||||
Font = @"Exo2.0-Bold"
|
||||
},
|
||||
slash = new OsuSpriteText
|
||||
{
|
||||
Text = @"/",
|
||||
TextSize = text_size,
|
||||
Font = @"Exo2.0-Light"
|
||||
},
|
||||
maxText = new OsuSpriteText
|
||||
{
|
||||
TextSize = text_size,
|
||||
Font = @"Exo2.0-Light"
|
||||
},
|
||||
count = new OsuSpriteText
|
||||
{
|
||||
TextSize = text_size,
|
||||
Font = @"Exo2.0-Bold"
|
||||
},
|
||||
slash = new OsuSpriteText
|
||||
{
|
||||
Text = @"/",
|
||||
TextSize = text_size,
|
||||
Font = @"Exo2.0-Light"
|
||||
},
|
||||
maxText = new OsuSpriteText
|
||||
{
|
||||
TextSize = text_size,
|
||||
Font = @"Exo2.0-Light"
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
updateMax();
|
||||
Participants.BindValueChanged(v => count.Text = v.Count().ToString());
|
||||
MaxParticipants.BindValueChanged(_ => updateMax(), true);
|
||||
ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0"));
|
||||
}
|
||||
|
||||
private void updateMax()
|
||||
{
|
||||
if (Max == null)
|
||||
if (MaxParticipants.Value == null)
|
||||
{
|
||||
slash.FadeOut(transition_duration);
|
||||
maxText.FadeOut(transition_duration);
|
||||
@ -71,7 +69,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
else
|
||||
{
|
||||
slash.FadeIn(transition_duration);
|
||||
maxText.Text = Max.ToString();
|
||||
maxText.Text = MaxParticipants.Value.ToString();
|
||||
maxText.FadeIn(transition_duration);
|
||||
}
|
||||
}
|
||||
|
@ -1,145 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class ParticipantInfo : Container
|
||||
{
|
||||
private readonly Container flagContainer;
|
||||
private readonly OsuSpriteText host;
|
||||
private readonly FillFlowContainer levelRangeContainer;
|
||||
private readonly OsuSpriteText levelRangeLower;
|
||||
private readonly OsuSpriteText levelRangeHigher;
|
||||
|
||||
public User Host
|
||||
{
|
||||
set
|
||||
{
|
||||
host.Text = value.Username;
|
||||
flagContainer.Children = new[] { new DrawableFlag(value.Country) { RelativeSizeAxes = Axes.Both } };
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<User> Participants
|
||||
{
|
||||
set
|
||||
{
|
||||
var ranks = value.Select(u => u.Statistics.Ranks.Global);
|
||||
levelRangeLower.Text = ranks.Min().ToString();
|
||||
levelRangeHigher.Text = ranks.Max().ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public ParticipantInfo(string rankPrefix = null)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 15f;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5f, 0f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
flagContainer = new Container
|
||||
{
|
||||
Width = 22f,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
},
|
||||
new Container //todo: team banners
|
||||
{
|
||||
Width = 38f,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
CornerRadius = 2f,
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"ad387e"),
|
||||
},
|
||||
},
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "hosted by",
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
TextSize = 14,
|
||||
},
|
||||
host = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
},
|
||||
},
|
||||
levelRangeContainer = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = rankPrefix,
|
||||
TextSize = 14,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "#",
|
||||
TextSize = 14,
|
||||
},
|
||||
levelRangeLower = new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = " - ",
|
||||
TextSize = 14,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "#",
|
||||
TextSize = 14,
|
||||
},
|
||||
levelRangeHigher = new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
levelRangeContainer.Colour = colours.Gray9;
|
||||
host.Colour = colours.Blue;
|
||||
}
|
||||
}
|
||||
}
|
111
osu.Game/Screens/Multi/Components/RoomStatusInfo.cs
Normal file
111
osu.Game/Screens/Multi/Components/RoomStatusInfo.cs
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class RoomStatusInfo : CompositeDrawable
|
||||
{
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
public RoomStatusInfo(Room room)
|
||||
{
|
||||
bindings.Room = room;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
StatusPart statusPart;
|
||||
EndDatePart endDatePart;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
statusPart = new StatusPart
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = "Exo2.0-Bold"
|
||||
},
|
||||
endDatePart = new EndDatePart { TextSize = 14 }
|
||||
}
|
||||
};
|
||||
|
||||
statusPart.EndDate.BindTo(bindings.EndDate);
|
||||
statusPart.Status.BindTo(bindings.Status);
|
||||
statusPart.Availability.BindTo(bindings.Availability);
|
||||
endDatePart.EndDate.BindTo(bindings.EndDate);
|
||||
}
|
||||
|
||||
private class EndDatePart : DrawableDate
|
||||
{
|
||||
public readonly IBindable<DateTimeOffset> EndDate = new Bindable<DateTimeOffset>();
|
||||
|
||||
public EndDatePart()
|
||||
: base(DateTimeOffset.UtcNow)
|
||||
{
|
||||
EndDate.BindValueChanged(d => Date = d);
|
||||
}
|
||||
|
||||
protected override string Format()
|
||||
{
|
||||
var diffToNow = Date.Subtract(DateTimeOffset.Now);
|
||||
|
||||
if (diffToNow.TotalSeconds < -5)
|
||||
return $"Closed {base.Format()}";
|
||||
|
||||
if (diffToNow.TotalSeconds < 0)
|
||||
return "Closed";
|
||||
|
||||
if (diffToNow.TotalSeconds < 5)
|
||||
return "Closing soon";
|
||||
|
||||
return $"Closing {base.Format()}";
|
||||
}
|
||||
}
|
||||
|
||||
private class StatusPart : EndDatePart
|
||||
{
|
||||
public readonly IBindable<RoomStatus> Status = new Bindable<RoomStatus>();
|
||||
public readonly IBindable<RoomAvailability> Availability = new Bindable<RoomAvailability>();
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; }
|
||||
|
||||
public StatusPart()
|
||||
{
|
||||
EndDate.BindValueChanged(_ => Format());
|
||||
Status.BindValueChanged(_ => Format());
|
||||
Availability.BindValueChanged(_ => Format());
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Text = Format();
|
||||
}
|
||||
|
||||
protected override string Format()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return string.Empty;
|
||||
|
||||
RoomStatus status = Date < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen();
|
||||
|
||||
this.FadeColour(status.GetAppropriateColour(colours), 100);
|
||||
return $"{Availability.Value.GetDescription()}, {status.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osu.Game.Screens.Multi.Screens;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -86,7 +85,12 @@ namespace osu.Game.Screens.Multi
|
||||
},
|
||||
};
|
||||
|
||||
breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type.ToLowerInvariant();
|
||||
breadcrumbs.Current.ValueChanged += s =>
|
||||
{
|
||||
if (s is IMultiplayerSubScreen mpScreen)
|
||||
screenType.Text = mpScreen.ShortTitle.ToLowerInvariant();
|
||||
};
|
||||
|
||||
breadcrumbs.Current.TriggerChange();
|
||||
}
|
||||
|
||||
@ -99,7 +103,8 @@ namespace osu.Game.Screens.Multi
|
||||
|
||||
private class HeaderBreadcrumbControl : ScreenBreadcrumbControl
|
||||
{
|
||||
public HeaderBreadcrumbControl(Screen initialScreen) : base(initialScreen)
|
||||
public HeaderBreadcrumbControl(Screen initialScreen)
|
||||
: base(initialScreen)
|
||||
{
|
||||
}
|
||||
|
||||
|
10
osu.Game/Screens/Multi/IMultiplayerSubScreen.cs
Normal file
10
osu.Game/Screens/Multi/IMultiplayerSubScreen.cs
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public interface IMultiplayerSubScreen
|
||||
{
|
||||
string ShortTitle { get; }
|
||||
}
|
||||
}
|
45
osu.Game/Screens/Multi/IRoomManager.cs
Normal file
45
osu.Game/Screens/Multi/IRoomManager.cs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public interface IRoomManager
|
||||
{
|
||||
/// <summary>
|
||||
/// All the active <see cref="Room"/>s.
|
||||
/// </summary>
|
||||
IBindableCollection<Room> Rooms { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Room"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to create.</param>
|
||||
/// <param name="onSuccess">An action to be invoked if the creation succeeds.</param>
|
||||
/// <param name="onError">An action to be invoked if an error occurred.</param>
|
||||
void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null);
|
||||
|
||||
/// <summary>
|
||||
/// Joins a <see cref="Room"/>.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to join. <see cref="Room.RoomID"/> must be populated.</param>
|
||||
/// <param name="onSuccess"></param>
|
||||
/// <param name="onError"></param>
|
||||
void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null);
|
||||
|
||||
/// <summary>
|
||||
/// Parts the currently-joined <see cref="Room"/>.
|
||||
/// </summary>
|
||||
void PartRoom();
|
||||
|
||||
/// <summary>
|
||||
/// Queries for <see cref="Room"/>s matching a new <see cref="FilterCriteria"/>.
|
||||
/// </summary>
|
||||
/// <param name="criteria">The <see cref="FilterCriteria"/> to match.</param>
|
||||
void Filter(FilterCriteria criteria);
|
||||
}
|
||||
}
|
@ -5,12 +5,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
@ -18,11 +16,11 @@ using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class DrawableRoom : OsuClickableContainer, IStateful<SelectionState>, IFilterable
|
||||
{
|
||||
@ -30,18 +28,21 @@ namespace osu.Game.Screens.Multi.Components
|
||||
private const float corner_radius = 5;
|
||||
private const float transition_duration = 60;
|
||||
private const float content_padding = 10;
|
||||
private const float height = 100;
|
||||
private const float height = 110;
|
||||
private const float side_strip_width = 5;
|
||||
private const float cover_width = 145;
|
||||
|
||||
private readonly Box selectionBox;
|
||||
public event Action<SelectionState> StateChanged;
|
||||
|
||||
private readonly Bindable<string> nameBind = new Bindable<string>();
|
||||
private readonly Bindable<User> hostBind = new Bindable<User>();
|
||||
private readonly Bindable<RoomStatus> statusBind = new Bindable<RoomStatus>();
|
||||
private readonly Bindable<GameType> typeBind = new Bindable<GameType>();
|
||||
private readonly Bindable<BeatmapInfo> beatmapBind = new Bindable<BeatmapInfo>();
|
||||
private readonly Bindable<IEnumerable<User>> participantsBind = new Bindable<IEnumerable<User>>();
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private readonly Box selectionBox;
|
||||
private UpdateableBeatmapBackgroundSprite background;
|
||||
private BeatmapTitle beatmapTitle;
|
||||
private ModeTypeInfo modeTypeInfo;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
public readonly Room Room;
|
||||
|
||||
@ -76,22 +77,10 @@ namespace osu.Game.Screens.Multi.Components
|
||||
}
|
||||
}
|
||||
|
||||
private Action<DrawableRoom> action;
|
||||
public new Action<DrawableRoom> Action
|
||||
{
|
||||
get { return action; }
|
||||
set
|
||||
{
|
||||
action = value;
|
||||
Enabled.Value = action != null;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<SelectionState> StateChanged;
|
||||
|
||||
public DrawableRoom(Room room)
|
||||
{
|
||||
Room = room;
|
||||
bindings.Room = room;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = height + SELECTION_BORDER_WIDTH * 2;
|
||||
@ -110,11 +99,8 @@ namespace osu.Game.Screens.Multi.Components
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Box sideStrip;
|
||||
UpdateableBeatmapSetCover cover;
|
||||
OsuSpriteText name, status;
|
||||
ParticipantInfo participantInfo;
|
||||
BeatmapTitle beatmapTitle;
|
||||
ModeTypeInfo modeTypeInfo;
|
||||
OsuSpriteText name;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -146,12 +132,13 @@ namespace osu.Game.Screens.Multi.Components
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = side_strip_width,
|
||||
},
|
||||
cover = new UpdateableBeatmapSetCover
|
||||
new Container
|
||||
{
|
||||
Width = cover_width,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = cover_width,
|
||||
Masking = true,
|
||||
Margin = new MarginPadding { Left = side_strip_width },
|
||||
Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -172,10 +159,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
Spacing = new Vector2(5f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
name = new OsuSpriteText
|
||||
{
|
||||
TextSize = 18,
|
||||
},
|
||||
name = new OsuSpriteText { TextSize = 18 },
|
||||
participantInfo = new ParticipantInfo(),
|
||||
},
|
||||
},
|
||||
@ -186,18 +170,11 @@ namespace osu.Game.Screens.Multi.Components
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
status = new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
},
|
||||
beatmapTitle = new BeatmapTitle
|
||||
{
|
||||
TextSize = 14,
|
||||
Colour = colours.Gray9
|
||||
},
|
||||
new RoomStatusInfo(Room),
|
||||
beatmapTitle = new BeatmapTitle { TextSize = 14 },
|
||||
},
|
||||
},
|
||||
modeTypeInfo = new ModeTypeInfo
|
||||
@ -212,32 +189,21 @@ namespace osu.Game.Screens.Multi.Components
|
||||
},
|
||||
};
|
||||
|
||||
nameBind.ValueChanged += n => name.Text = n;
|
||||
hostBind.ValueChanged += h => participantInfo.Host = h;
|
||||
typeBind.ValueChanged += m => modeTypeInfo.Type = m;
|
||||
participantsBind.ValueChanged += p => participantInfo.Participants = p;
|
||||
background.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
modeTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset);
|
||||
modeTypeInfo.Type.BindTo(bindings.Type);
|
||||
beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
participantInfo.Host.BindTo(bindings.Host);
|
||||
participantInfo.Participants.BindTo(bindings.Participants);
|
||||
participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount);
|
||||
|
||||
statusBind.ValueChanged += s =>
|
||||
bindings.Name.BindValueChanged(n => name.Text = n, true);
|
||||
bindings.Status.BindValueChanged(s =>
|
||||
{
|
||||
status.Text = s.Message;
|
||||
|
||||
foreach (Drawable d in new Drawable[] { selectionBox, sideStrip, status })
|
||||
foreach (Drawable d in new Drawable[] { selectionBox, sideStrip })
|
||||
d.FadeColour(s.GetAppropriateColour(colours), transition_duration);
|
||||
};
|
||||
|
||||
beatmapBind.ValueChanged += b =>
|
||||
{
|
||||
cover.BeatmapSet = b?.BeatmapSet;
|
||||
beatmapTitle.Beatmap = b;
|
||||
modeTypeInfo.Beatmap = b;
|
||||
};
|
||||
|
||||
nameBind.BindTo(Room.Name);
|
||||
hostBind.BindTo(Room.Host);
|
||||
statusBind.BindTo(Room.Status);
|
||||
typeBind.BindTo(Room.Type);
|
||||
beatmapBind.BindTo(Room.Beatmap);
|
||||
participantsBind.BindTo(Room.Participants);
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -245,16 +211,5 @@ namespace osu.Game.Screens.Multi.Components
|
||||
base.LoadComplete();
|
||||
this.FadeInFromZero(transition_duration);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (Enabled.Value)
|
||||
{
|
||||
Action?.Invoke(this);
|
||||
State = SelectionState.Selected;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
43
osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs
Normal file
43
osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class FilterControl : SearchableListFilterControl<PrimaryFilter, SecondaryFilter>
|
||||
{
|
||||
protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42");
|
||||
protected override PrimaryFilter DefaultTab => PrimaryFilter.Open;
|
||||
|
||||
public FilterControl()
|
||||
{
|
||||
DisplayStyleControl.Hide();
|
||||
}
|
||||
|
||||
public FilterCriteria CreateCriteria() => new FilterCriteria
|
||||
{
|
||||
SearchString = Search.Current.Value ?? string.Empty,
|
||||
PrimaryFilter = Tabs.Current,
|
||||
SecondaryFilter = DisplayStyleControl.Dropdown.Current
|
||||
};
|
||||
}
|
||||
|
||||
public enum PrimaryFilter
|
||||
{
|
||||
Open,
|
||||
[Description("Recently Ended")]
|
||||
RecentlyEnded,
|
||||
Participated,
|
||||
Owned,
|
||||
}
|
||||
|
||||
public enum SecondaryFilter
|
||||
{
|
||||
Public,
|
||||
//Private,
|
||||
}
|
||||
}
|
12
osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs
Normal file
12
osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class FilterCriteria
|
||||
{
|
||||
public string SearchString;
|
||||
public PrimaryFilter PrimaryFilter;
|
||||
public SecondaryFilter SecondaryFilter;
|
||||
}
|
||||
}
|
118
osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs
Normal file
118
osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class ParticipantInfo : Container
|
||||
{
|
||||
private readonly FillFlowContainer summaryContainer;
|
||||
|
||||
public readonly IBindable<User> Host = new Bindable<User>();
|
||||
public readonly IBindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
public readonly IBindable<int> ParticipantCount = new Bindable<int>();
|
||||
|
||||
public ParticipantInfo()
|
||||
{
|
||||
OsuSpriteText summary;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 15f;
|
||||
|
||||
OsuSpriteText levelRangeHigher;
|
||||
OsuSpriteText levelRangeLower;
|
||||
Container flagContainer;
|
||||
LinkFlowContainer hostText;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5f, 0f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
flagContainer = new Container
|
||||
{
|
||||
Width = 22f,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
},
|
||||
/*new Container //todo: team banners
|
||||
{
|
||||
Width = 38f,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
CornerRadius = 2f,
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"ad387e"),
|
||||
},
|
||||
},
|
||||
},*/
|
||||
hostText = new LinkFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
},
|
||||
summaryContainer = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new[]
|
||||
{
|
||||
summary = new OsuSpriteText
|
||||
{
|
||||
Text = "0 participants",
|
||||
TextSize = 14,
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Host.BindValueChanged(v =>
|
||||
{
|
||||
hostText.Clear();
|
||||
hostText.AddText("hosted by ");
|
||||
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 };
|
||||
});
|
||||
|
||||
ParticipantCount.BindValueChanged(v => summary.Text = $"{v:#,0}{" participant".Pluralize(v == 1)}");
|
||||
|
||||
/*Participants.BindValueChanged(v =>
|
||||
{
|
||||
var ranks = v.Select(u => u.Statistics.Ranks.Global);
|
||||
levelRangeLower.Text = ranks.Min().ToString();
|
||||
levelRangeHigher.Text = ranks.Max().ToString();
|
||||
});*/
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
summaryContainer.Colour = colours.Gray9;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
@ -17,66 +16,35 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class RoomInspector : Container
|
||||
{
|
||||
private const float transition_duration = 100;
|
||||
|
||||
public readonly IBindable<Room> Room = new Bindable<Room>();
|
||||
|
||||
private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 };
|
||||
private readonly Bindable<string> nameBind = new Bindable<string>();
|
||||
private readonly Bindable<User> hostBind = new Bindable<User>();
|
||||
private readonly Bindable<RoomStatus> statusBind = new Bindable<RoomStatus>();
|
||||
private readonly Bindable<GameType> typeBind = new Bindable<GameType>();
|
||||
private readonly Bindable<BeatmapInfo> beatmapBind = new Bindable<BeatmapInfo>();
|
||||
private readonly Bindable<int?> maxParticipantsBind = new Bindable<int?>();
|
||||
private readonly Bindable<IEnumerable<User>> participantsBind = new Bindable<IEnumerable<User>>();
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private OsuColour colours;
|
||||
private Box statusStrip;
|
||||
private UpdateableBeatmapSetCover cover;
|
||||
private ParticipantCount participantCount;
|
||||
private UpdateableBeatmapBackgroundSprite background;
|
||||
private ParticipantCountDisplay participantCount;
|
||||
private FillFlowContainer topFlow, participantsFlow;
|
||||
private OsuSpriteText name, status;
|
||||
private BeatmapTypeInfo beatmapTypeInfo;
|
||||
private ScrollContainer participantsScroll;
|
||||
private ParticipantInfo participantInfo;
|
||||
|
||||
private Room room;
|
||||
public Room Room
|
||||
{
|
||||
get { return room; }
|
||||
set
|
||||
{
|
||||
if (value == room) return;
|
||||
room = value;
|
||||
|
||||
nameBind.UnbindBindings();
|
||||
hostBind.UnbindBindings();
|
||||
statusBind.UnbindBindings();
|
||||
typeBind.UnbindBindings();
|
||||
beatmapBind.UnbindBindings();
|
||||
maxParticipantsBind.UnbindBindings();
|
||||
participantsBind.UnbindBindings();
|
||||
|
||||
if (room != null)
|
||||
{
|
||||
nameBind.BindTo(room.Name);
|
||||
hostBind.BindTo(room.Host);
|
||||
statusBind.BindTo(room.Status);
|
||||
typeBind.BindTo(room.Type);
|
||||
beatmapBind.BindTo(room.Beatmap);
|
||||
maxParticipantsBind.BindTo(room.MaxParticipants);
|
||||
participantsBind.BindTo(room.Participants);
|
||||
}
|
||||
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
@ -104,10 +72,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
cover = new UpdateableBeatmapSetCover
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both },
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -119,7 +84,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
Padding = new MarginPadding(20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
participantCount = new ParticipantCount
|
||||
participantCount = new ParticipantCountDisplay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
@ -177,7 +142,7 @@ namespace osu.Game.Screens.Multi.Components
|
||||
Padding = contentPadding,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
participantInfo = new ParticipantInfo(@"Rank Range "),
|
||||
participantInfo = new ParticipantInfo(),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -201,26 +166,48 @@ namespace osu.Game.Screens.Multi.Components
|
||||
},
|
||||
};
|
||||
|
||||
nameBind.ValueChanged += n => name.Text = n;
|
||||
hostBind.ValueChanged += h => participantInfo.Host = h;
|
||||
typeBind.ValueChanged += t => beatmapTypeInfo.Type = t;
|
||||
maxParticipantsBind.ValueChanged += m => participantCount.Max = m;
|
||||
statusBind.ValueChanged += displayStatus;
|
||||
participantInfo.Host.BindTo(bindings.Host);
|
||||
participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount);
|
||||
participantInfo.Participants.BindTo(bindings.Participants);
|
||||
|
||||
beatmapBind.ValueChanged += b =>
|
||||
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.Participants.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)));
|
||||
bindings.Name.BindValueChanged(n => name.Text = n);
|
||||
|
||||
Room.BindValueChanged(updateRoom, true);
|
||||
}
|
||||
|
||||
private void updateRoom(Room room)
|
||||
{
|
||||
bindings.Room = room;
|
||||
|
||||
if (room != null)
|
||||
{
|
||||
cover.BeatmapSet = b?.BeatmapSet;
|
||||
beatmapTypeInfo.Beatmap = b;
|
||||
};
|
||||
|
||||
participantsBind.ValueChanged += p =>
|
||||
participantsFlow.FadeIn(transition_duration);
|
||||
participantCount.FadeIn(transition_duration);
|
||||
beatmapTypeInfo.FadeIn(transition_duration);
|
||||
name.FadeIn(transition_duration);
|
||||
participantInfo.FadeIn(transition_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
participantCount.Count = p.Count();
|
||||
participantInfo.Participants = p;
|
||||
participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u));
|
||||
};
|
||||
participantsFlow.FadeOut(transition_duration);
|
||||
participantCount.FadeOut(transition_duration);
|
||||
beatmapTypeInfo.FadeOut(transition_duration);
|
||||
name.FadeOut(transition_duration);
|
||||
participantInfo.FadeOut(transition_duration);
|
||||
|
||||
updateState();
|
||||
displayStatus(new RoomStatusNoneSelected());
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
@ -239,32 +226,6 @@ namespace osu.Game.Screens.Multi.Components
|
||||
status.FadeColour(c, transition_duration);
|
||||
}
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
if (Room == null)
|
||||
{
|
||||
cover.BeatmapSet = null;
|
||||
participantsFlow.FadeOut(transition_duration);
|
||||
participantCount.FadeOut(transition_duration);
|
||||
beatmapTypeInfo.FadeOut(transition_duration);
|
||||
name.FadeOut(transition_duration);
|
||||
participantInfo.FadeOut(transition_duration);
|
||||
|
||||
displayStatus(new RoomStatusNoneSelected());
|
||||
}
|
||||
else
|
||||
{
|
||||
participantsFlow.FadeIn(transition_duration);
|
||||
participantCount.FadeIn(transition_duration);
|
||||
beatmapTypeInfo.FadeIn(transition_duration);
|
||||
name.FadeIn(transition_duration);
|
||||
participantInfo.FadeIn(transition_duration);
|
||||
|
||||
statusBind.TriggerChange();
|
||||
beatmapBind.TriggerChange();
|
||||
}
|
||||
}
|
||||
|
||||
private class UserTile : Container, IHasTooltip
|
||||
{
|
||||
private readonly User user;
|
119
osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs
Normal file
119
osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||
{
|
||||
public class RoomsContainer : CompositeDrawable
|
||||
{
|
||||
public Action<Room> JoinRequested;
|
||||
|
||||
private readonly Bindable<Room> selectedRoom = new Bindable<Room>();
|
||||
public IBindable<Room> SelectedRoom => selectedRoom;
|
||||
|
||||
private readonly IBindableCollection<Room> rooms = new BindableCollection<Room>();
|
||||
|
||||
private readonly FillFlowContainer<DrawableRoom> roomFlow;
|
||||
public IReadOnlyList<DrawableRoom> Rooms => roomFlow;
|
||||
|
||||
[Resolved]
|
||||
private IRoomManager roomManager { get; set; }
|
||||
|
||||
public RoomsContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChild = roomFlow = new FillFlowContainer<DrawableRoom>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(2),
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
rooms.BindTo(roomManager.Rooms);
|
||||
|
||||
rooms.ItemsAdded += addRooms;
|
||||
rooms.ItemsRemoved += removeRooms;
|
||||
|
||||
addRooms(rooms);
|
||||
}
|
||||
|
||||
private FilterCriteria currentFilter;
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
{
|
||||
roomFlow.Children.ForEach(r =>
|
||||
{
|
||||
if (criteria == null)
|
||||
r.MatchingFilter = true;
|
||||
else
|
||||
{
|
||||
bool matchingFilter = true;
|
||||
matchingFilter &= r.FilterTerms.Any(term => term.IndexOf(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase) >= 0);
|
||||
|
||||
switch (criteria.SecondaryFilter)
|
||||
{
|
||||
default:
|
||||
case SecondaryFilter.Public:
|
||||
r.MatchingFilter = r.Room.Availability.Value == RoomAvailability.Public;
|
||||
break;
|
||||
}
|
||||
|
||||
r.MatchingFilter = matchingFilter;
|
||||
}
|
||||
});
|
||||
|
||||
currentFilter = criteria;
|
||||
}
|
||||
|
||||
private void addRooms(IEnumerable<Room> rooms)
|
||||
{
|
||||
foreach (var r in rooms)
|
||||
roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) });
|
||||
|
||||
Filter(currentFilter);
|
||||
}
|
||||
|
||||
private void removeRooms(IEnumerable<Room> rooms)
|
||||
{
|
||||
foreach (var r in rooms)
|
||||
{
|
||||
var toRemove = roomFlow.Single(d => d.Room == r);
|
||||
toRemove.Action = null;
|
||||
|
||||
roomFlow.Remove(toRemove);
|
||||
|
||||
selectRoom(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectRoom(Room room)
|
||||
{
|
||||
var drawable = roomFlow.FirstOrDefault(r => r.Room == room);
|
||||
|
||||
if (drawable != null && drawable.State == SelectionState.Selected)
|
||||
JoinRequested?.Invoke(room);
|
||||
else
|
||||
roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected);
|
||||
|
||||
selectedRoom.Value = room;
|
||||
}
|
||||
}
|
||||
}
|
151
osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs
Normal file
151
osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
using osu.Game.Screens.Multi.Match;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Lounge
|
||||
{
|
||||
public class LoungeSubScreen : MultiplayerSubScreen
|
||||
{
|
||||
protected readonly FilterControl Filter;
|
||||
|
||||
private readonly Container content;
|
||||
private readonly RoomsContainer rooms;
|
||||
private readonly Action<Screen> pushGameplayScreen;
|
||||
private readonly ProcessingOverlay processingOverlay;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IRoomManager roomManager { get; set; }
|
||||
|
||||
public override string Title => "Lounge";
|
||||
|
||||
protected override Drawable TransitionContent => content;
|
||||
|
||||
public LoungeSubScreen(Action<Screen> pushGameplayScreen)
|
||||
{
|
||||
this.pushGameplayScreen = pushGameplayScreen;
|
||||
|
||||
RoomInspector inspector;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Filter = new FilterControl { Depth = -1 },
|
||||
content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.55f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ScrollbarOverlapsContent = false,
|
||||
Padding = new MarginPadding(10),
|
||||
Child = new SearchContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = rooms = new RoomsContainer { JoinRequested = joinRequested }
|
||||
},
|
||||
},
|
||||
processingOverlay = new ProcessingOverlay { Alpha = 0 }
|
||||
}
|
||||
},
|
||||
inspector = new RoomInspector
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.45f,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
inspector.Room.BindTo(rooms.SelectedRoom);
|
||||
|
||||
Filter.Search.Current.ValueChanged += s => filterRooms();
|
||||
Filter.Tabs.Current.ValueChanged += t => filterRooms();
|
||||
Filter.Search.Exit += Exit;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
content.Padding = new MarginPadding
|
||||
{
|
||||
Top = Filter.DrawHeight,
|
||||
Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH,
|
||||
Right = SearchableListOverlay.WIDTH_PADDING,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnFocus(FocusEvent e)
|
||||
{
|
||||
GetContainingInputManager().ChangeFocus(Filter.Search);
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
Filter.Search.HoldFocus = true;
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
Filter.Search.HoldFocus = false;
|
||||
// no base call; don't animate
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
base.OnSuspending(next);
|
||||
Filter.Search.HoldFocus = false;
|
||||
}
|
||||
|
||||
private void filterRooms()
|
||||
{
|
||||
rooms.Filter(Filter.CreateCriteria());
|
||||
roomManager?.Filter(Filter.CreateCriteria());
|
||||
}
|
||||
|
||||
private void joinRequested(Room room)
|
||||
{
|
||||
processingOverlay.Show();
|
||||
roomManager?.JoinRoom(room, r =>
|
||||
{
|
||||
Push(room);
|
||||
processingOverlay.Hide();
|
||||
}, _ => processingOverlay.Hide());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Push a room as a new subscreen.
|
||||
/// </summary>
|
||||
public void Push(Room room)
|
||||
{
|
||||
// Handles the case where a room is clicked 3 times in quick succession
|
||||
if (!IsCurrentScreen)
|
||||
return;
|
||||
|
||||
Push(new MatchSubScreen(room, s => pushGameplayScreen?.Invoke(s)));
|
||||
}
|
||||
}
|
||||
}
|
@ -9,17 +9,19 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.GameTypes;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens.Match.Settings
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class GameTypePicker : TabControl<GameType>
|
||||
public class GameTypePicker : DisableableTabControl<GameType>
|
||||
{
|
||||
private const float height = 40;
|
||||
private const float selection_width = 3;
|
||||
|
||||
protected override TabItem<GameType> CreateTabItem(GameType value) => new GameTypePickerItem(value);
|
||||
|
||||
protected override Dropdown<GameType> CreateDropdown() => null;
|
||||
|
||||
public GameTypePicker()
|
||||
@ -31,15 +33,17 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings
|
||||
AddItem(new GameTypeVersus());
|
||||
AddItem(new GameTypeTagTeam());
|
||||
AddItem(new GameTypeTeamVersus());
|
||||
AddItem(new GameTypeTimeshift());
|
||||
}
|
||||
|
||||
private class GameTypePickerItem : TabItem<GameType>
|
||||
private class GameTypePickerItem : DisableableTabItem<GameType>
|
||||
{
|
||||
private const float transition_duration = 200;
|
||||
|
||||
private readonly CircularContainer hover, selection;
|
||||
|
||||
public GameTypePickerItem(GameType value) : base(value)
|
||||
public GameTypePickerItem(GameType value)
|
||||
: base(value)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
147
osu.Game/Screens/Multi/Match/Components/Header.cs
Normal file
147
osu.Game/Screens/Multi/Match/Components/Header.cs
Normal file
@ -0,0 +1,147 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class Header : Container
|
||||
{
|
||||
public const float HEIGHT = 200;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private readonly Box tabStrip;
|
||||
|
||||
public readonly MatchTabControl Tabs;
|
||||
|
||||
public Action OnRequestSelectBeatmap;
|
||||
|
||||
public Header(Room room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
|
||||
bindings.Room = room;
|
||||
|
||||
BeatmapTypeInfo beatmapTypeInfo;
|
||||
BeatmapSelectButton beatmapButton;
|
||||
UpdateableBeatmapBackgroundSprite background;
|
||||
ModDisplay modDisplay;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both },
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.4f), Color4.Black.Opacity(0.6f)),
|
||||
},
|
||||
}
|
||||
},
|
||||
tabStrip = new Box
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = 20 },
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
beatmapTypeInfo = new BeatmapTypeInfo(),
|
||||
modDisplay = new ModDisplay
|
||||
{
|
||||
Scale = new Vector2(0.75f),
|
||||
DisplayUnrankedText = false
|
||||
},
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 200,
|
||||
Padding = new MarginPadding { Vertical = 10 },
|
||||
Child = beatmapButton = new BeatmapSelectButton(room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 1,
|
||||
},
|
||||
},
|
||||
Tabs = new MatchTabControl(room)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset);
|
||||
beatmapTypeInfo.Type.BindTo(bindings.Type);
|
||||
background.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
bindings.CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true);
|
||||
|
||||
beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
tabStrip.Colour = colours.Yellow;
|
||||
}
|
||||
|
||||
private class BeatmapSelectButton : HeaderButton
|
||||
{
|
||||
private readonly IBindable<int?> roomIDBind = new Bindable<int?>();
|
||||
|
||||
public BeatmapSelectButton(Room room)
|
||||
{
|
||||
Text = "Select beatmap";
|
||||
|
||||
roomIDBind.BindTo(room.RoomID);
|
||||
roomIDBind.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true);
|
||||
}
|
||||
}
|
||||
|
||||
private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite
|
||||
{
|
||||
protected override double FadeDuration => 200;
|
||||
}
|
||||
}
|
||||
}
|
48
osu.Game/Screens/Multi/Match/Components/HeaderButton.cs
Normal file
48
osu.Game/Screens/Multi/Match/Components/HeaderButton.cs
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class HeaderButton : TriangleButton
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
BackgroundColour = OsuColour.FromHex(@"1187aa");
|
||||
|
||||
Triangles.ColourLight = OsuColour.FromHex(@"277b9c");
|
||||
Triangles.ColourDark = OsuColour.FromHex(@"1f6682");
|
||||
Triangles.TriangleScale = 1.5f;
|
||||
|
||||
Add(new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 1f,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.15f,
|
||||
Blending = BlendingMode.Additive,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected override SpriteText CreateText() => new OsuSpriteText
|
||||
{
|
||||
Depth = -1,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Font = @"Exo2.0-Light",
|
||||
TextSize = 30,
|
||||
};
|
||||
}
|
||||
}
|
60
osu.Game/Screens/Multi/Match/Components/HostInfo.cs
Normal file
60
osu.Game/Screens/Multi/Match/Components/HostInfo.cs
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class HostInfo : CompositeDrawable
|
||||
{
|
||||
public readonly IBindable<User> Host = new Bindable<User>();
|
||||
|
||||
private readonly LinkFlowContainer linkContainer;
|
||||
private readonly UpdateableAvatar avatar;
|
||||
|
||||
public HostInfo()
|
||||
{
|
||||
AutoSizeAxes = Axes.X;
|
||||
Height = 50;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
avatar = new UpdateableAvatar { Size = new Vector2(50) },
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Child = linkContainer = new LinkFlowContainer { AutoSizeAxes = Axes.Both }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Host.BindValueChanged(updateHost);
|
||||
}
|
||||
|
||||
private void updateHost(User host)
|
||||
{
|
||||
avatar.User = host;
|
||||
|
||||
if (host != null)
|
||||
{
|
||||
linkContainer.AddText("hosted by");
|
||||
linkContainer.NewLine();
|
||||
linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", s => s.Font = "Exo2.0-BoldItalic");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
100
osu.Game/Screens/Multi/Match/Components/Info.cs
Normal file
100
osu.Game/Screens/Multi/Match/Components/Info.cs
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class Info : Container
|
||||
{
|
||||
public Action OnStart;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
public Info(Room room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
ReadyButton readyButton;
|
||||
ViewBeatmapButton viewBeatmapButton;
|
||||
HostInfo hostInfo;
|
||||
RoomStatusInfo statusInfo;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"28242d"),
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 10),
|
||||
Padding = new MarginPadding { Vertical = 20 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
TextSize = 30,
|
||||
Current = bindings.Name
|
||||
},
|
||||
new RoomStatusInfo(room),
|
||||
}
|
||||
},
|
||||
hostInfo = new HostInfo(),
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = 70,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
viewBeatmapButton = new ViewBeatmapButton(),
|
||||
readyButton = new ReadyButton(room)
|
||||
{
|
||||
Action = () => OnStart?.Invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
viewBeatmapButton.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
readyButton.Beatmap.BindTo(bindings.CurrentBeatmap);
|
||||
hostInfo.Host.BindTo(bindings.Host);
|
||||
|
||||
bindings.Room = room;
|
||||
}
|
||||
}
|
||||
}
|
36
osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs
Normal file
36
osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private ChannelManager channelManager { get; set; }
|
||||
|
||||
public MatchChatDisplay(Room room)
|
||||
: base(true)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
room.RoomID.BindValueChanged(v => updateChannel(), true);
|
||||
}
|
||||
|
||||
private void updateChannel()
|
||||
{
|
||||
if (room.RoomID.Value != null)
|
||||
Channel.Value = channelManager?.JoinChannel(new Channel { Id = room.ChannelId, Type = ChannelType.Multiplayer, Name = $"#mp_{room.RoomID}" });
|
||||
}
|
||||
}
|
||||
}
|
62
osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs
Normal file
62
osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchLeaderboard : Leaderboard<MatchLeaderboardScope, APIRoomScoreInfo>
|
||||
{
|
||||
public Action<IEnumerable<APIRoomScoreInfo>> ScoresLoaded;
|
||||
|
||||
private readonly Room room;
|
||||
|
||||
public MatchLeaderboard(Room room)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
room.RoomID.BindValueChanged(id =>
|
||||
{
|
||||
if (id == null)
|
||||
return;
|
||||
|
||||
Scores = null;
|
||||
UpdateScores();
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override APIRequest FetchScores(Action<IEnumerable<APIRoomScoreInfo>> scoresCallback)
|
||||
{
|
||||
if (room.RoomID == null)
|
||||
return null;
|
||||
|
||||
var req = new GetRoomScoresRequest(room.RoomID.Value ?? 0);
|
||||
|
||||
req.Success += r =>
|
||||
{
|
||||
scoresCallback?.Invoke(r);
|
||||
ScoresLoaded?.Invoke(r);
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) => new MatchLeaderboardScore(model, index);
|
||||
}
|
||||
|
||||
public enum MatchLeaderboardScope
|
||||
{
|
||||
Overall
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchLeaderboardScore : LeaderboardScore
|
||||
{
|
||||
public MatchLeaderboardScore(APIRoomScoreInfo score, int rank)
|
||||
: base(score, rank)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RankContainer.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override IEnumerable<LeaderboardScoreStatistic> GetStatistics(ScoreInfo model) => new[]
|
||||
{
|
||||
new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)),
|
||||
new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()),
|
||||
new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedBeatmaps.ToString()),
|
||||
};
|
||||
}
|
||||
}
|
28
osu.Game/Screens/Multi/Match/Components/MatchPage.cs
Normal file
28
osu.Game/Screens/Multi/Match/Components/MatchPage.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public abstract class MatchPage
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public readonly BindableBool Enabled = new BindableBool(true);
|
||||
|
||||
public override string ToString() => Name;
|
||||
public override int GetHashCode() => GetType().GetHashCode();
|
||||
public override bool Equals(object obj) => GetType() == obj?.GetType();
|
||||
}
|
||||
|
||||
public class SettingsMatchPage : MatchPage
|
||||
{
|
||||
public override string Name => "Settings";
|
||||
}
|
||||
|
||||
public class RoomMatchPage : MatchPage
|
||||
{
|
||||
public override string Name => "Room";
|
||||
}
|
||||
}
|
406
osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs
Normal file
406
osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs
Normal file
@ -0,0 +1,406 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchSettingsOverlay : FocusedOverlayContainer
|
||||
{
|
||||
private const float transition_duration = 350;
|
||||
private const float field_padding = 45;
|
||||
private const float disabled_alpha = 0.2f;
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private readonly Container content;
|
||||
|
||||
private readonly OsuSpriteText typeLabel;
|
||||
|
||||
protected readonly OsuTextBox NameField, MaxParticipantsField;
|
||||
protected readonly OsuDropdown<TimeSpan> DurationField;
|
||||
protected readonly RoomAvailabilityPicker AvailabilityPicker;
|
||||
protected readonly GameTypePicker TypePicker;
|
||||
protected readonly TriangleButton ApplyButton;
|
||||
protected readonly OsuPasswordTextBox PasswordField;
|
||||
|
||||
protected readonly OsuSpriteText ErrorText;
|
||||
|
||||
private readonly ProcessingOverlay processingOverlay;
|
||||
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IRoomManager manager { get; set; }
|
||||
|
||||
public MatchSettingsOverlay(Room room)
|
||||
{
|
||||
this.room = room;
|
||||
|
||||
bindings.Room = room;
|
||||
|
||||
Masking = true;
|
||||
|
||||
Child = content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"28242d"),
|
||||
},
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.Distributed),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
},
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
new ScrollContainer
|
||||
{
|
||||
Padding = new MarginPadding { Vertical = 10 },
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SectionContainer
|
||||
{
|
||||
Padding = new MarginPadding { Right = field_padding / 2 },
|
||||
Children = new[]
|
||||
{
|
||||
new Section("Room name")
|
||||
{
|
||||
Child = NameField = new SettingsTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
TabbableContentContainer = this,
|
||||
OnCommit = (sender, text) => apply(),
|
||||
},
|
||||
},
|
||||
new Section("Room visibility")
|
||||
{
|
||||
Alpha = disabled_alpha,
|
||||
Child = AvailabilityPicker = new RoomAvailabilityPicker(),
|
||||
},
|
||||
new Section("Game type")
|
||||
{
|
||||
Alpha = disabled_alpha,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(7),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
TypePicker = new GameTypePicker
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
typeLabel = new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
new SectionContainer
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Padding = new MarginPadding { Left = field_padding / 2 },
|
||||
Children = new[]
|
||||
{
|
||||
new Section("Max participants")
|
||||
{
|
||||
Alpha = disabled_alpha,
|
||||
Child = MaxParticipantsField = new SettingsNumberTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
TabbableContentContainer = this,
|
||||
OnCommit = (sender, text) => apply(),
|
||||
},
|
||||
},
|
||||
new Section("Duration")
|
||||
{
|
||||
Child = DurationField = new DurationDropdown
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Items = new[]
|
||||
{
|
||||
TimeSpan.FromMinutes(30),
|
||||
TimeSpan.FromHours(1),
|
||||
TimeSpan.FromHours(2),
|
||||
TimeSpan.FromHours(4),
|
||||
TimeSpan.FromHours(8),
|
||||
TimeSpan.FromHours(12),
|
||||
TimeSpan.FromHours(16),
|
||||
TimeSpan.FromHours(24),
|
||||
TimeSpan.FromDays(3),
|
||||
TimeSpan.FromDays(7)
|
||||
}
|
||||
}
|
||||
},
|
||||
new Section("Password (optional)")
|
||||
{
|
||||
Alpha = disabled_alpha,
|
||||
Child = PasswordField = new SettingsPasswordTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
TabbableContentContainer = this,
|
||||
OnCommit = (sender, text) => apply()
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Y = 2,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 20),
|
||||
Margin = new MarginPadding { Vertical = 20 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
ApplyButton = new CreateRoomButton
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Size = new Vector2(230, 55),
|
||||
Action = apply,
|
||||
},
|
||||
ErrorText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Alpha = 0,
|
||||
Depth = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
processingOverlay = new ProcessingOverlay { Alpha = 0 }
|
||||
},
|
||||
};
|
||||
|
||||
TypePicker.Current.ValueChanged += t => typeLabel.Text = t.Name;
|
||||
|
||||
bindings.Name.BindValueChanged(n => NameField.Text = n, true);
|
||||
bindings.Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true);
|
||||
bindings.Type.BindValueChanged(t => TypePicker.Current.Value = t, true);
|
||||
bindings.MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true);
|
||||
bindings.Duration.BindValueChanged(d => DurationField.Current.Value = d, true);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
typeLabel.Colour = colours.Yellow;
|
||||
ErrorText.Colour = colours.RedDark;
|
||||
|
||||
MaxParticipantsField.ReadOnly = true;
|
||||
PasswordField.ReadOnly = true;
|
||||
AvailabilityPicker.Enabled.Value = false;
|
||||
TypePicker.Enabled.Value = false;
|
||||
ApplyButton.Enabled.Value = false;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
ApplyButton.Enabled.Value = hasValidSettings;
|
||||
}
|
||||
|
||||
private bool hasValidSettings => bindings.Room.RoomID.Value == null && NameField.Text.Length > 0 && bindings.Playlist.Count > 0;
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
content.MoveToY(0, transition_duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
content.MoveToY(-1, transition_duration, Easing.InSine);
|
||||
}
|
||||
|
||||
private void apply()
|
||||
{
|
||||
hideError();
|
||||
|
||||
bindings.Name.Value = NameField.Text;
|
||||
bindings.Availability.Value = AvailabilityPicker.Current.Value;
|
||||
bindings.Type.Value = TypePicker.Current.Value;
|
||||
|
||||
if (int.TryParse(MaxParticipantsField.Text, out int max))
|
||||
bindings.MaxParticipants.Value = max;
|
||||
else
|
||||
bindings.MaxParticipants.Value = null;
|
||||
|
||||
bindings.Duration.Value = DurationField.Current.Value;
|
||||
|
||||
manager?.CreateRoom(room, onSuccess, onError);
|
||||
|
||||
processingOverlay.Show();
|
||||
}
|
||||
|
||||
private void hideError() => ErrorText.FadeOut(50);
|
||||
|
||||
private void onSuccess(Room room) => processingOverlay.Hide();
|
||||
|
||||
private void onError(string text)
|
||||
{
|
||||
ErrorText.Text = text;
|
||||
ErrorText.FadeIn(50);
|
||||
|
||||
processingOverlay.Hide();
|
||||
}
|
||||
|
||||
private class SettingsTextBox : OsuTextBox
|
||||
{
|
||||
protected override Color4 BackgroundUnfocused => Color4.Black;
|
||||
protected override Color4 BackgroundFocused => Color4.Black;
|
||||
}
|
||||
|
||||
private class SettingsNumberTextBox : SettingsTextBox
|
||||
{
|
||||
protected override bool CanAddCharacter(char character) => char.IsNumber(character);
|
||||
}
|
||||
|
||||
private class SettingsPasswordTextBox : OsuPasswordTextBox
|
||||
{
|
||||
protected override Color4 BackgroundUnfocused => Color4.Black;
|
||||
protected override Color4 BackgroundFocused => Color4.Black;
|
||||
}
|
||||
|
||||
private class SectionContainer : FillFlowContainer<Section>
|
||||
{
|
||||
public SectionContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Width = 0.5f;
|
||||
Direction = FillDirection.Vertical;
|
||||
Spacing = new Vector2(field_padding);
|
||||
}
|
||||
}
|
||||
|
||||
private class Section : Container
|
||||
{
|
||||
private readonly Container content;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
public Section(string title)
|
||||
{
|
||||
AutoSizeAxes = Axes.Y;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
TextSize = 12,
|
||||
Font = @"Exo2.0-Bold",
|
||||
Text = title.ToUpper(),
|
||||
},
|
||||
content = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class CreateRoomButton : TriangleButton
|
||||
{
|
||||
public CreateRoomButton()
|
||||
{
|
||||
Text = "Create";
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BackgroundColour = colours.Yellow;
|
||||
Triangles.ColourLight = colours.YellowLight;
|
||||
Triangles.ColourDark = colours.YellowDark;
|
||||
}
|
||||
}
|
||||
|
||||
private class DurationDropdown : OsuDropdown<TimeSpan>
|
||||
{
|
||||
public DurationDropdown()
|
||||
{
|
||||
Menu.MaxHeight = 100;
|
||||
}
|
||||
|
||||
protected override string GenerateItemText(TimeSpan item)
|
||||
{
|
||||
return item.Humanize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
66
osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs
Normal file
66
osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class MatchTabControl : PageTabControl<MatchPage>
|
||||
{
|
||||
private readonly IBindable<int?> roomIdBind = new Bindable<int?>();
|
||||
|
||||
public MatchTabControl(Room room)
|
||||
{
|
||||
roomIdBind.BindTo(room.RoomID);
|
||||
|
||||
AddItem(new RoomMatchPage());
|
||||
AddItem(new SettingsMatchPage());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
roomIdBind.BindValueChanged(v =>
|
||||
{
|
||||
if (v.HasValue)
|
||||
{
|
||||
Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage));
|
||||
Current.Value = new RoomMatchPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.ForEach(t => t.Enabled.Value = t is SettingsMatchPage);
|
||||
Current.Value = new SettingsMatchPage();
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override TabItem<MatchPage> CreateTabItem(MatchPage value) => new TabItem(value);
|
||||
|
||||
private class TabItem : PageTabItem
|
||||
{
|
||||
private readonly IBindable<bool> enabled = new BindableBool();
|
||||
|
||||
public TabItem(MatchPage value)
|
||||
: base(value)
|
||||
{
|
||||
enabled.BindTo(value.Enabled);
|
||||
enabled.BindValueChanged(v => Colour = v ? Color4.White : Color4.Gray);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (!enabled.Value)
|
||||
return true;
|
||||
return base.OnClick(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
@ -10,36 +11,20 @@ using osu.Game.Screens.Multi.Components;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens.Match
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class Participants : Container
|
||||
public class Participants : CompositeDrawable
|
||||
{
|
||||
private readonly ParticipantCount count;
|
||||
private readonly FillFlowContainer<UserPanel> usersFlow;
|
||||
|
||||
public IEnumerable<User> Users
|
||||
{
|
||||
set {
|
||||
usersFlow.Children = value.Select(u => new UserPanel(u)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Width = 300,
|
||||
OnLoadComplete = d => d.FadeInFromZero(60),
|
||||
}).ToList();
|
||||
|
||||
count.Count = value.Count();
|
||||
}
|
||||
}
|
||||
|
||||
public int? Max
|
||||
{
|
||||
set => count.Max = value;
|
||||
}
|
||||
public readonly IBindable<IEnumerable<User>> Users = new Bindable<IEnumerable<User>>();
|
||||
public readonly IBindable<int> ParticipantCount = new Bindable<int>();
|
||||
public readonly IBindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
|
||||
public Participants()
|
||||
{
|
||||
Child = new Container
|
||||
FillFlowContainer<UserPanel> usersFlow;
|
||||
ParticipantCountDisplay count;
|
||||
|
||||
InternalChild = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
|
||||
@ -51,7 +36,7 @@ namespace osu.Game.Screens.Multi.Screens.Match
|
||||
Padding = new MarginPadding { Top = 10 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
count = new ParticipantCount
|
||||
count = new ParticipantCountDisplay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
@ -69,6 +54,21 @@ namespace osu.Game.Screens.Multi.Screens.Match
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
count.Participants.BindTo(Users);
|
||||
count.ParticipantCount.BindTo(ParticipantCount);
|
||||
count.MaxParticipants.BindTo(MaxParticipants);
|
||||
|
||||
Users.BindValueChanged(v =>
|
||||
{
|
||||
usersFlow.Children = v.Select(u => new UserPanel(u)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Width = 300,
|
||||
OnLoadComplete = d => d.FadeInFromZero(60),
|
||||
}).ToList();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
90
osu.Game/Screens/Multi/Match/Components/ReadyButton.cs
Normal file
90
osu.Game/Screens/Multi/Match/Components/ReadyButton.cs
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class ReadyButton : HeaderButton
|
||||
{
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved]
|
||||
private IBindableBeatmap gameBeatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
private bool hasBeatmap;
|
||||
|
||||
public ReadyButton(Room room)
|
||||
{
|
||||
this.room = room;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Size = new Vector2(200, 1);
|
||||
|
||||
Text = "Start";
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
beatmaps.ItemAdded += beatmapAdded;
|
||||
|
||||
Beatmap.BindValueChanged(updateBeatmap, true);
|
||||
}
|
||||
|
||||
private void updateBeatmap(BeatmapInfo beatmap)
|
||||
{
|
||||
hasBeatmap = false;
|
||||
|
||||
if (beatmap?.OnlineBeatmapID == null)
|
||||
return;
|
||||
|
||||
hasBeatmap = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID) != null;
|
||||
}
|
||||
|
||||
private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent)
|
||||
{
|
||||
if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID))
|
||||
Schedule(() => hasBeatmap = true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
updateEnabledState();
|
||||
}
|
||||
|
||||
private void updateEnabledState()
|
||||
{
|
||||
if (gameBeatmap.Value == null)
|
||||
{
|
||||
Enabled.Value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < room.EndDate;
|
||||
|
||||
Enabled.Value = hasBeatmap && hasEnoughTime;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (beatmaps != null)
|
||||
beatmaps.ItemAdded -= beatmapAdded;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,12 +10,13 @@ using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens.Match.Settings
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class RoomAvailabilityPicker : TabControl<RoomAvailability>
|
||||
public class RoomAvailabilityPicker : DisableableTabControl<RoomAvailability>
|
||||
{
|
||||
protected override TabItem<RoomAvailability> CreateTabItem(RoomAvailability value) => new RoomAvailabilityPickerItem(value);
|
||||
protected override Dropdown<RoomAvailability> CreateDropdown() => null;
|
||||
@ -32,7 +33,7 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings
|
||||
AddItem(RoomAvailability.InviteOnly);
|
||||
}
|
||||
|
||||
private class RoomAvailabilityPickerItem : TabItem<RoomAvailability>
|
||||
private class RoomAvailabilityPickerItem : DisableableTabItem<RoomAvailability>
|
||||
{
|
||||
private const float transition_duration = 200;
|
||||
|
||||
@ -41,7 +42,7 @@ namespace osu.Game.Screens.Multi.Screens.Match.Settings
|
||||
public RoomAvailabilityPickerItem(RoomAvailability value) : base(value)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Width = 120;
|
||||
Width = 102;
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
46
osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs
Normal file
46
osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match.Components
|
||||
{
|
||||
public class ViewBeatmapButton : HeaderButton
|
||||
{
|
||||
public readonly IBindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuGame osuGame { get; set; }
|
||||
|
||||
public ViewBeatmapButton()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Size = new Vector2(200, 1);
|
||||
|
||||
Text = "View beatmap";
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (osuGame != null)
|
||||
Beatmap.BindValueChanged(updateAction, true);
|
||||
}
|
||||
|
||||
private void updateAction(BeatmapInfo beatmap)
|
||||
{
|
||||
if (beatmap == null)
|
||||
{
|
||||
Enabled.Value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Action = () => osuGame.ShowBeatmap(beatmap.OnlineBeatmapID ?? 0);
|
||||
Enabled.Value = true;
|
||||
}
|
||||
}
|
||||
}
|
209
osu.Game/Screens/Multi/Match/MatchSubScreen.cs
Normal file
209
osu.Game/Screens/Multi/Match/MatchSubScreen.cs
Normal file
@ -0,0 +1,209 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
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.Play;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Match
|
||||
{
|
||||
public class MatchSubScreen : MultiplayerSubScreen
|
||||
{
|
||||
public override bool AllowBeatmapRulesetChange => false;
|
||||
public override string Title => room.RoomID.Value == null ? "New room" : room.Name.Value;
|
||||
public override string ShortTitle => "room";
|
||||
|
||||
private readonly RoomBindings bindings = new RoomBindings();
|
||||
|
||||
private readonly MatchLeaderboard leaderboard;
|
||||
|
||||
private readonly Action<Screen> pushGameplayScreen;
|
||||
|
||||
[Cached]
|
||||
private readonly Room room;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuGame game { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IRoomManager manager { get; set; }
|
||||
|
||||
public MatchSubScreen(Room room, Action<Screen> pushGameplayScreen)
|
||||
{
|
||||
this.room = room;
|
||||
this.pushGameplayScreen = pushGameplayScreen;
|
||||
|
||||
bindings.Room = room;
|
||||
|
||||
MatchChatDisplay chat;
|
||||
Components.Header header;
|
||||
MatchSettingsOverlay settings;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[] { header = new Components.Header(room) { Depth = -1 } },
|
||||
new Drawable[] { new Info(room) { OnStart = onStart } },
|
||||
new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
leaderboard = new MatchLeaderboard(room)
|
||||
{
|
||||
Padding = new MarginPadding(10),
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Padding = new MarginPadding(10),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = chat = new MatchChatDisplay(room)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.Distributed),
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = Components.Header.HEIGHT },
|
||||
Child = settings = new MatchSettingsOverlay(room) { RelativeSizeAxes = Axes.Both },
|
||||
},
|
||||
};
|
||||
|
||||
header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect { Selected = addPlaylistItem });
|
||||
header.Tabs.Current.ValueChanged += t =>
|
||||
{
|
||||
if (t is SettingsMatchPage)
|
||||
settings.Show();
|
||||
else
|
||||
settings.Hide();
|
||||
};
|
||||
|
||||
chat.Exit += Exit;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
beatmapManager.ItemAdded += beatmapAdded;
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
manager?.PartRoom();
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
bindings.CurrentBeatmap.BindValueChanged(setBeatmap, true);
|
||||
bindings.CurrentMods.BindValueChanged(setMods, true);
|
||||
bindings.CurrentRuleset.BindValueChanged(setRuleset, true);
|
||||
}
|
||||
|
||||
private void setBeatmap(BeatmapInfo beatmap)
|
||||
{
|
||||
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
|
||||
var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID);
|
||||
|
||||
game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap));
|
||||
}
|
||||
|
||||
private void setMods(IEnumerable<Mod> mods)
|
||||
{
|
||||
Beatmap.Value.Mods.Value = mods.ToArray();
|
||||
}
|
||||
|
||||
private void setRuleset(RulesetInfo ruleset)
|
||||
{
|
||||
if (ruleset == null)
|
||||
return;
|
||||
|
||||
game?.ForcefullySetRuleset(ruleset);
|
||||
}
|
||||
|
||||
private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() =>
|
||||
{
|
||||
if (Beatmap.Value != beatmapManager.DefaultBeatmap)
|
||||
return;
|
||||
|
||||
if (bindings.CurrentBeatmap.Value == null)
|
||||
return;
|
||||
|
||||
// Try to retrieve the corresponding local beatmap
|
||||
var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == bindings.CurrentBeatmap.Value.OnlineBeatmapID);
|
||||
|
||||
if (localBeatmap != null)
|
||||
game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap));
|
||||
});
|
||||
|
||||
private void addPlaylistItem(PlaylistItem item)
|
||||
{
|
||||
bindings.Playlist.Clear();
|
||||
bindings.Playlist.Add(item);
|
||||
}
|
||||
|
||||
private void onStart()
|
||||
{
|
||||
switch (bindings.Type.Value)
|
||||
{
|
||||
default:
|
||||
case GameTypeTimeshift _:
|
||||
pushGameplayScreen?.Invoke(new PlayerLoader(() => {
|
||||
var player = new TimeshiftPlayer(room, room.Playlist.First().ID);
|
||||
player.Exited += _ => leaderboard.RefreshScores();
|
||||
|
||||
return player;
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (beatmapManager != null)
|
||||
beatmapManager.ItemAdded -= beatmapAdded;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -8,26 +9,43 @@ using osu.Framework.Screens;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.BeatmapSet.Buttons;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Multi.Screens.Lounge;
|
||||
using osu.Game.Screens.Multi.Lounge;
|
||||
using osu.Game.Screens.Multi.Match;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public class Multiplayer : OsuScreen
|
||||
[Cached]
|
||||
public class Multiplayer : OsuScreen, IOnlineComponent
|
||||
{
|
||||
private readonly MultiplayerWaveContainer waves;
|
||||
|
||||
protected override Container<Drawable> Content => waves;
|
||||
public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange;
|
||||
|
||||
private readonly OsuButton createButton;
|
||||
private readonly LoungeSubScreen loungeSubScreen;
|
||||
|
||||
private OsuScreen currentScreen;
|
||||
|
||||
[Cached(Type = typeof(IRoomManager))]
|
||||
private RoomManager roomManager;
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
public Multiplayer()
|
||||
{
|
||||
InternalChild = waves = new MultiplayerWaveContainer
|
||||
Child = waves = new MultiplayerWaveContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
|
||||
Lounge lounge;
|
||||
Children = new Drawable[]
|
||||
waves.AddRange(new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
@ -53,16 +71,61 @@ namespace osu.Game.Screens.Multi
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = Header.HEIGHT },
|
||||
Child = lounge = new Lounge(),
|
||||
Child = loungeSubScreen = new LoungeSubScreen(Push),
|
||||
},
|
||||
new Header(lounge),
|
||||
};
|
||||
new Header(loungeSubScreen),
|
||||
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,
|
||||
},
|
||||
Text = "Create room",
|
||||
Action = () => loungeSubScreen.Push(new Room
|
||||
{
|
||||
Name = { Value = $"{api.LocalUser}'s awesome room" }
|
||||
}),
|
||||
},
|
||||
roomManager = new RoomManager()
|
||||
});
|
||||
|
||||
lounge.Exited += s => Exit();
|
||||
screenAdded(loungeSubScreen);
|
||||
loungeSubScreen.Exited += _ => Exit();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
api.Register(this);
|
||||
}
|
||||
|
||||
public void APIStateChanged(APIAccess api, APIState state)
|
||||
{
|
||||
if (state != APIState.Online)
|
||||
forcefullyExit();
|
||||
}
|
||||
|
||||
private void forcefullyExit()
|
||||
{
|
||||
// This is temporary since we don't currently have a way to force screens to be exited
|
||||
if (IsCurrentScreen)
|
||||
Exit();
|
||||
else
|
||||
{
|
||||
MakeCurrent();
|
||||
Schedule(forcefullyExit);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
Content.FadeIn();
|
||||
|
||||
base.OnEntering(last);
|
||||
waves.Show();
|
||||
}
|
||||
@ -70,19 +133,41 @@ namespace osu.Game.Screens.Multi
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
waves.Hide();
|
||||
|
||||
Content.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
|
||||
|
||||
var track = Beatmap.Value.Track;
|
||||
if (track != null)
|
||||
track.Looping = false;
|
||||
|
||||
loungeSubScreen.MakeCurrent();
|
||||
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override void OnResuming(Screen last)
|
||||
{
|
||||
base.OnResuming(last);
|
||||
waves.Show();
|
||||
|
||||
Content.FadeIn(250);
|
||||
Content.ScaleTo(1, 250, Easing.OutSine);
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
Content.ScaleTo(1.1f, 250, Easing.InSine);
|
||||
Content.FadeOut(250);
|
||||
|
||||
cancelLooping();
|
||||
|
||||
base.OnSuspending(next);
|
||||
waves.Hide();
|
||||
}
|
||||
|
||||
private void cancelLooping()
|
||||
{
|
||||
var track = Beatmap.Value.Track;
|
||||
if (track != null)
|
||||
track.Looping = false;
|
||||
}
|
||||
|
||||
protected override void LogoExiting(OsuLogo logo)
|
||||
@ -92,6 +177,55 @@ namespace osu.Game.Screens.Multi
|
||||
base.LogoExiting(logo);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!IsCurrentScreen) return;
|
||||
|
||||
if (currentScreen is MatchSubScreen)
|
||||
{
|
||||
var track = Beatmap.Value.Track;
|
||||
if (track != null)
|
||||
{
|
||||
track.Looping = true;
|
||||
|
||||
if (!track.IsRunning)
|
||||
{
|
||||
Game.Audio.AddItemToList(track);
|
||||
track.Seek(Beatmap.Value.Metadata.PreviewTime);
|
||||
track.Start();
|
||||
}
|
||||
}
|
||||
|
||||
createButton.Hide();
|
||||
}
|
||||
else if (currentScreen is LoungeSubScreen)
|
||||
createButton.Show();
|
||||
}
|
||||
|
||||
private void screenAdded(Screen newScreen)
|
||||
{
|
||||
currentScreen = (OsuScreen)newScreen;
|
||||
|
||||
newScreen.ModePushed += screenAdded;
|
||||
newScreen.Exited += screenRemoved;
|
||||
}
|
||||
|
||||
private void screenRemoved(Screen newScreen)
|
||||
{
|
||||
if (currentScreen is MatchSubScreen)
|
||||
cancelLooping();
|
||||
|
||||
currentScreen = (OsuScreen)newScreen;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
api?.Unregister(this);
|
||||
}
|
||||
|
||||
private class MultiplayerWaveContainer : WaveContainer
|
||||
{
|
||||
protected override bool StartHidden => true;
|
||||
|
@ -2,20 +2,16 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public abstract class MultiplayerScreen : OsuScreen
|
||||
public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen
|
||||
{
|
||||
protected virtual Container<Drawable> TransitionContent => Content;
|
||||
protected virtual Drawable TransitionContent => Content;
|
||||
|
||||
/// <summary>
|
||||
/// The type to display in the title of the <see cref="Header"/>.
|
||||
/// </summary>
|
||||
public virtual string Type => Title;
|
||||
public virtual string ShortTitle => Title;
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
77
osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
Normal file
77
osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Ranking;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Ranking;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Play
|
||||
{
|
||||
public class TimeshiftPlayer : Player
|
||||
{
|
||||
private readonly Room room;
|
||||
private readonly int playlistItemId;
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
public TimeshiftPlayer(Room room, int playlistItemId)
|
||||
{
|
||||
this.room = room;
|
||||
this.playlistItemId = playlistItemId;
|
||||
}
|
||||
|
||||
private int? token;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
token = null;
|
||||
|
||||
bool failed = false;
|
||||
|
||||
var req = new CreateRoomScoreRequest(room.RoomID.Value ?? 0, playlistItemId);
|
||||
req.Success += r => token = r.ID;
|
||||
req.Failure += e =>
|
||||
{
|
||||
failed = true;
|
||||
|
||||
Logger.Error(e, "Failed to retrieve a score submission token.");
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
ValidForResume = false;
|
||||
Exit();
|
||||
});
|
||||
};
|
||||
|
||||
api.Queue(req);
|
||||
|
||||
while (!failed && !token.HasValue)
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
protected override ScoreInfo CreateScore()
|
||||
{
|
||||
var score = base.CreateScore();
|
||||
|
||||
Debug.Assert(token != null);
|
||||
|
||||
var request = new SubmitRoomScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score);
|
||||
request.Failure += e => Logger.Error(e, "Failed to submit score");
|
||||
api.Queue(request);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
protected override Results CreateResults(ScoreInfo score) => new MatchResults(score, room);
|
||||
}
|
||||
}
|
30
osu.Game/Screens/Multi/Ranking/MatchResults.cs
Normal file
30
osu.Game/Screens/Multi/Ranking/MatchResults.cs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Ranking.Types;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.Ranking.Types;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Ranking
|
||||
{
|
||||
public class MatchResults : Results
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
public MatchResults(ScoreInfo score, Room room)
|
||||
: base(score)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
|
||||
{
|
||||
new ScoreOverviewPageInfo(Score, Beatmap),
|
||||
new LocalLeaderboardPageInfo(Score, Beatmap),
|
||||
new RoomLeaderboardPageInfo(Score, Beatmap, room),
|
||||
};
|
||||
}
|
||||
}
|
140
osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs
Normal file
140
osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Lists;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Game.Screens.Ranking;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Ranking.Pages
|
||||
{
|
||||
public class RoomLeaderboardPage : ResultsPage
|
||||
{
|
||||
private readonly Room room;
|
||||
|
||||
private OsuColour colours;
|
||||
|
||||
private TextFlowContainer rankText;
|
||||
|
||||
public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
: base(score, beatmap)
|
||||
{
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
this.colours = colours;
|
||||
|
||||
MatchLeaderboard leaderboard;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Gray6,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BackgroundColour = colours.Gray6,
|
||||
Child = leaderboard = CreateLeaderboard(room)
|
||||
},
|
||||
rankText = new TextFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.5f,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Y = 50,
|
||||
TextAnchor = Anchor.TopCentre
|
||||
},
|
||||
};
|
||||
|
||||
leaderboard.Origin = Anchor.Centre;
|
||||
leaderboard.Anchor = Anchor.Centre;
|
||||
leaderboard.RelativeSizeAxes = Axes.Both;
|
||||
leaderboard.Height = 0.8f;
|
||||
leaderboard.Y = 55;
|
||||
leaderboard.ScoresLoaded = scoresLoaded;
|
||||
}
|
||||
|
||||
private void scoresLoaded(IEnumerable<APIRoomScoreInfo> scores)
|
||||
{
|
||||
Action<SpriteText> gray = s => s.Colour = colours.GrayC;
|
||||
Action<SpriteText> white = s =>
|
||||
{
|
||||
s.TextSize *= 1.4f;
|
||||
s.Colour = colours.GrayF;
|
||||
};
|
||||
|
||||
rankText.AddText(room.Name + "\n", white);
|
||||
rankText.AddText("You are placed ", gray);
|
||||
|
||||
int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer<APIRoomScoreInfo>((s1, s2) => s1.User.Id.Equals(s2.User.Id)));
|
||||
|
||||
rankText.AddText($"#{index + 1} ", s =>
|
||||
{
|
||||
s.Font = "Exo2.0-Bold";
|
||||
s.Colour = colours.YellowDark;
|
||||
});
|
||||
|
||||
rankText.AddText("in the room!", gray);
|
||||
}
|
||||
|
||||
protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new ResultsMatchLeaderboard(room);
|
||||
|
||||
public class ResultsMatchLeaderboard : MatchLeaderboard
|
||||
{
|
||||
public ResultsMatchLeaderboard(Room room)
|
||||
: base(room)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool FadeTop => true;
|
||||
|
||||
protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index)
|
||||
=> new ResultsMatchLeaderboardScore(model, index);
|
||||
|
||||
protected override FillFlowContainer<LeaderboardScore> CreateScoreFlow()
|
||||
{
|
||||
var flow = base.CreateScoreFlow();
|
||||
flow.Padding = new MarginPadding
|
||||
{
|
||||
Top = LeaderboardScore.HEIGHT * 2,
|
||||
Bottom = LeaderboardScore.HEIGHT * 3,
|
||||
};
|
||||
return flow;
|
||||
}
|
||||
|
||||
private class ResultsMatchLeaderboardScore : MatchLeaderboardScore
|
||||
{
|
||||
public ResultsMatchLeaderboardScore(APIRoomScoreInfo score, int rank)
|
||||
: base(score, rank)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Multi.Ranking.Pages;
|
||||
using osu.Game.Screens.Ranking;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Ranking.Types
|
||||
{
|
||||
public class RoomLeaderboardPageInfo : IResultPageInfo
|
||||
{
|
||||
private readonly ScoreInfo score;
|
||||
private readonly WorkingBeatmap beatmap;
|
||||
private readonly Room room;
|
||||
|
||||
public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room)
|
||||
{
|
||||
this.score = score;
|
||||
this.beatmap = beatmap;
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public FontAwesome Icon => FontAwesome.fa_users;
|
||||
|
||||
public string Name => "Room Leaderboard";
|
||||
|
||||
public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap, room);
|
||||
}
|
||||
}
|
106
osu.Game/Screens/Multi/RoomBindings.cs
Normal file
106
osu.Game/Screens/Multi/RoomBindings.cs
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class which binds to values from a <see cref="Room"/>.
|
||||
/// </summary>
|
||||
public class RoomBindings
|
||||
{
|
||||
public RoomBindings()
|
||||
{
|
||||
Playlist.ItemsAdded += _ => updatePlaylist();
|
||||
Playlist.ItemsRemoved += _ => updatePlaylist();
|
||||
}
|
||||
|
||||
private Room room;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Room"/> to bind to.
|
||||
/// </summary>
|
||||
public Room Room
|
||||
{
|
||||
get => room;
|
||||
set
|
||||
{
|
||||
if (room == value)
|
||||
return;
|
||||
|
||||
if (room != null)
|
||||
{
|
||||
Name.UnbindFrom(room.Name);
|
||||
Host.UnbindFrom(room.Host);
|
||||
Status.UnbindFrom(room.Status);
|
||||
Type.UnbindFrom(room.Type);
|
||||
Playlist.UnbindFrom(room.Playlist);
|
||||
Participants.UnbindFrom(room.Participants);
|
||||
ParticipantCount.UnbindFrom(room.ParticipantCount);
|
||||
MaxParticipants.UnbindFrom(room.MaxParticipants);
|
||||
EndDate.UnbindFrom(room.EndDate);
|
||||
Availability.UnbindFrom(room.Availability);
|
||||
Duration.UnbindFrom(room.Duration);
|
||||
}
|
||||
|
||||
room = value;
|
||||
|
||||
if (room != null)
|
||||
{
|
||||
Name.BindTo(room.Name);
|
||||
Host.BindTo(room.Host);
|
||||
Status.BindTo(room.Status);
|
||||
Type.BindTo(room.Type);
|
||||
Playlist.BindTo(room.Playlist);
|
||||
Participants.BindTo(room.Participants);
|
||||
ParticipantCount.BindTo(room.ParticipantCount);
|
||||
MaxParticipants.BindTo(room.MaxParticipants);
|
||||
EndDate.BindTo(room.EndDate);
|
||||
Availability.BindTo(room.Availability);
|
||||
Duration.BindTo(room.Duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePlaylist()
|
||||
{
|
||||
// Todo: We only ever have one playlist item for now. In the future, this will be user-settable
|
||||
|
||||
var playlistItem = Playlist.FirstOrDefault();
|
||||
|
||||
currentBeatmap.Value = playlistItem?.Beatmap;
|
||||
currentMods.Value = playlistItem?.RequiredMods ?? Enumerable.Empty<Mod>();
|
||||
currentRuleset.Value = playlistItem?.Ruleset;
|
||||
}
|
||||
|
||||
public readonly Bindable<string> Name = new Bindable<string>();
|
||||
public readonly Bindable<User> Host = new Bindable<User>();
|
||||
public readonly Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
|
||||
public readonly Bindable<GameType> Type = new Bindable<GameType>();
|
||||
public readonly BindableCollection<PlaylistItem> Playlist = new BindableCollection<PlaylistItem>();
|
||||
public readonly Bindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||
public readonly Bindable<int> ParticipantCount = new Bindable<int>();
|
||||
public readonly Bindable<int?> MaxParticipants = new Bindable<int?>();
|
||||
public readonly Bindable<DateTimeOffset> EndDate = new Bindable<DateTimeOffset>();
|
||||
public readonly Bindable<RoomAvailability> Availability = new Bindable<RoomAvailability>();
|
||||
public readonly Bindable<TimeSpan> Duration = new Bindable<TimeSpan>();
|
||||
|
||||
private readonly Bindable<BeatmapInfo> currentBeatmap = new Bindable<BeatmapInfo>();
|
||||
public IBindable<BeatmapInfo> CurrentBeatmap => currentBeatmap;
|
||||
|
||||
private readonly Bindable<IEnumerable<Mod>> currentMods = new Bindable<IEnumerable<Mod>>();
|
||||
public IBindable<IEnumerable<Mod>> CurrentMods => currentMods;
|
||||
|
||||
private readonly Bindable<RulesetInfo> currentRuleset = new Bindable<RulesetInfo>();
|
||||
public IBindable<RulesetInfo> CurrentRuleset => currentRuleset;
|
||||
}
|
||||
}
|
176
osu.Game/Screens/Multi/RoomManager.cs
Normal file
176
osu.Game/Screens/Multi/RoomManager.cs
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Multi.Lounge.Components;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public class RoomManager : PollingComponent, IRoomManager
|
||||
{
|
||||
private readonly BindableCollection<Room> rooms = new BindableCollection<Room>();
|
||||
public IBindableCollection<Room> Rooms => rooms;
|
||||
|
||||
private Room currentRoom;
|
||||
|
||||
private FilterCriteria currentFilter = new FilterCriteria();
|
||||
|
||||
[Resolved]
|
||||
private APIAccess api { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
public RoomManager()
|
||||
{
|
||||
TimeBetweenPolls = 5000;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
PartRoom();
|
||||
}
|
||||
|
||||
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
room.Host.Value = api.LocalUser;
|
||||
|
||||
var req = new CreateRoomRequest(room);
|
||||
|
||||
req.Success += result =>
|
||||
{
|
||||
update(room, result);
|
||||
addRoom(room);
|
||||
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
req.Failure += exception =>
|
||||
{
|
||||
if (req.Result != null)
|
||||
onError?.Invoke(req.Result.Error);
|
||||
else
|
||||
Logger.Log($"Failed to create the room: {exception}", level: LogLevel.Important);
|
||||
};
|
||||
|
||||
api.Queue(req);
|
||||
}
|
||||
|
||||
private JoinRoomRequest currentJoinRoomRequest;
|
||||
|
||||
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
|
||||
{
|
||||
currentJoinRoomRequest?.Cancel();
|
||||
currentJoinRoomRequest = null;
|
||||
|
||||
currentJoinRoomRequest = new JoinRoomRequest(room, api.LocalUser.Value);
|
||||
currentJoinRoomRequest.Success += () =>
|
||||
{
|
||||
currentRoom = room;
|
||||
onSuccess?.Invoke(room);
|
||||
};
|
||||
|
||||
currentJoinRoomRequest.Failure += exception =>
|
||||
{
|
||||
Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important);
|
||||
onError?.Invoke(exception.ToString());
|
||||
};
|
||||
|
||||
api.Queue(currentJoinRoomRequest);
|
||||
}
|
||||
|
||||
public void PartRoom()
|
||||
{
|
||||
if (currentRoom == null)
|
||||
return;
|
||||
|
||||
api.Queue(new PartRoomRequest(currentRoom, api.LocalUser.Value));
|
||||
currentRoom = null;
|
||||
}
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
{
|
||||
currentFilter = criteria;
|
||||
PollImmediately();
|
||||
}
|
||||
|
||||
private GetRoomsRequest pollReq;
|
||||
|
||||
protected override Task Poll()
|
||||
{
|
||||
if (!api.IsLoggedIn)
|
||||
return base.Poll();
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
pollReq?.Cancel();
|
||||
pollReq = new GetRoomsRequest(currentFilter.PrimaryFilter);
|
||||
|
||||
pollReq.Success += result =>
|
||||
{
|
||||
// Remove past matches
|
||||
foreach (var r in rooms.ToList())
|
||||
{
|
||||
if (result.All(e => e.RoomID.Value != r.RoomID.Value))
|
||||
rooms.Remove(r);
|
||||
}
|
||||
|
||||
// Add new matches, or update existing
|
||||
foreach (var r in result)
|
||||
{
|
||||
update(r, r);
|
||||
addRoom(r);
|
||||
}
|
||||
|
||||
tcs.SetResult(true);
|
||||
};
|
||||
|
||||
pollReq.Failure += _ => tcs.SetResult(false);
|
||||
|
||||
api.Queue(pollReq);
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a local <see cref="Room"/> with a remote copy.
|
||||
/// </summary>
|
||||
/// <param name="local">The local <see cref="Room"/> to update.</param>
|
||||
/// <param name="remote">The remote <see cref="Room"/> to update with.</param>
|
||||
private void update(Room local, Room remote)
|
||||
{
|
||||
foreach (var pi in remote.Playlist)
|
||||
pi.MapObjects(beatmaps, rulesets);
|
||||
|
||||
local.CopyFrom(remote);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="Room"/> to the list of available rooms.
|
||||
/// </summary>
|
||||
/// <param name="room">The <see cref="Room"/> to add.<</param>
|
||||
private void addRoom(Room room)
|
||||
{
|
||||
var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value);
|
||||
if (existing == null)
|
||||
rooms.Add(room);
|
||||
else
|
||||
existing.CopyFrom(room);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens.Lounge
|
||||
{
|
||||
public class FilterControl : SearchableListFilterControl<LoungeTab, LoungeTab>
|
||||
{
|
||||
protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42");
|
||||
protected override LoungeTab DefaultTab => LoungeTab.Public;
|
||||
|
||||
public FilterControl()
|
||||
{
|
||||
DisplayStyleControl.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public enum LoungeTab
|
||||
{
|
||||
Public = RoomAvailability.Public,
|
||||
Private = RoomAvailability.FriendsOnly,
|
||||
}
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens.Lounge
|
||||
{
|
||||
public class Lounge : MultiplayerScreen
|
||||
{
|
||||
private readonly Container content;
|
||||
private readonly SearchContainer search;
|
||||
|
||||
protected readonly FilterControl Filter;
|
||||
protected readonly FillFlowContainer<DrawableRoom> RoomsContainer;
|
||||
protected readonly RoomInspector Inspector;
|
||||
|
||||
public override string Title => "Lounge";
|
||||
|
||||
protected override Container<Drawable> TransitionContent => content;
|
||||
|
||||
private IEnumerable<Room> rooms;
|
||||
public IEnumerable<Room> Rooms
|
||||
{
|
||||
get { return rooms; }
|
||||
set
|
||||
{
|
||||
if (Equals(value, rooms)) return;
|
||||
rooms = value;
|
||||
|
||||
var enumerable = rooms.ToList();
|
||||
|
||||
RoomsContainer.Children = enumerable.Select(r => new DrawableRoom(r)
|
||||
{
|
||||
Action = didSelect,
|
||||
}).ToList();
|
||||
|
||||
if (!enumerable.Contains(Inspector.Room))
|
||||
Inspector.Room = null;
|
||||
|
||||
filterRooms();
|
||||
}
|
||||
}
|
||||
|
||||
public Lounge()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Filter = new FilterControl(),
|
||||
content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.55f,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Vertical = 35 - DrawableRoom.SELECTION_BORDER_WIDTH,
|
||||
Right = 20 - DrawableRoom.SELECTION_BORDER_WIDTH
|
||||
},
|
||||
Child = search = new SearchContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = RoomsContainer = new RoomsFilterContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(10 - DrawableRoom.SELECTION_BORDER_WIDTH * 2),
|
||||
},
|
||||
},
|
||||
},
|
||||
Inspector = new RoomInspector
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.45f,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Filter.Search.Current.ValueChanged += s => filterRooms();
|
||||
Filter.Tabs.Current.ValueChanged += t => filterRooms();
|
||||
Filter.Search.Exit += Exit;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
content.Padding = new MarginPadding
|
||||
{
|
||||
Top = Filter.DrawHeight,
|
||||
Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH,
|
||||
Right = SearchableListOverlay.WIDTH_PADDING,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnFocus(FocusEvent e)
|
||||
{
|
||||
GetContainingInputManager().ChangeFocus(Filter.Search);
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
Filter.Search.HoldFocus = true;
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
{
|
||||
Filter.Search.HoldFocus = false;
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override void OnResuming(Screen last)
|
||||
{
|
||||
base.OnResuming(last);
|
||||
Filter.Search.HoldFocus = true;
|
||||
}
|
||||
|
||||
protected override void OnSuspending(Screen next)
|
||||
{
|
||||
base.OnSuspending(next);
|
||||
Filter.Search.HoldFocus = false;
|
||||
}
|
||||
|
||||
private void filterRooms()
|
||||
{
|
||||
search.SearchTerm = Filter.Search.Current.Value ?? string.Empty;
|
||||
|
||||
foreach (DrawableRoom r in RoomsContainer.Children)
|
||||
{
|
||||
r.MatchingFilter = r.MatchingFilter &&
|
||||
r.Room.Availability.Value == (RoomAvailability)Filter.Tabs.Current.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private void didSelect(DrawableRoom room)
|
||||
{
|
||||
RoomsContainer.Children.ForEach(c =>
|
||||
{
|
||||
if (c != room)
|
||||
c.State = SelectionState.NotSelected;
|
||||
});
|
||||
|
||||
Inspector.Room = room.Room;
|
||||
|
||||
// open the room if its selected and is clicked again
|
||||
if (room.State == SelectionState.Selected)
|
||||
Push(new Match.Match(room.Room));
|
||||
}
|
||||
|
||||
private class RoomsFilterContainer : FillFlowContainer<DrawableRoom>, IHasFilterableChildren
|
||||
{
|
||||
public IEnumerable<string> FilterTerms => new string[] { };
|
||||
public IEnumerable<IFilterable> FilterableChildren => Children;
|
||||
|
||||
public bool MatchingFilter
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
InvalidateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public RoomsFilterContainer()
|
||||
{
|
||||
LayoutDuration = 200;
|
||||
LayoutEasing = Easing.OutQuint;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.SearchableList;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Screens.Match
|
||||
{
|
||||
public class Header : Container
|
||||
{
|
||||
public const float HEIGHT = 200;
|
||||
|
||||
private readonly Box tabStrip;
|
||||
private readonly UpdateableBeatmapSetCover cover;
|
||||
|
||||
public readonly PageTabControl<MatchHeaderPage> Tabs;
|
||||
|
||||
public BeatmapSetInfo BeatmapSet
|
||||
{
|
||||
set => cover.BeatmapSet = value;
|
||||
}
|
||||
|
||||
public Action OnRequestSelectBeatmap;
|
||||
|
||||
public Header()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
|
||||
BeatmapSelectButton beatmapButton;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
cover = new UpdateableBeatmapSetCover
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Black.Opacity(0.5f)),
|
||||
},
|
||||
tabStrip = new Box
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 200,
|
||||
Padding = new MarginPadding { Vertical = 5 },
|
||||
Child = beatmapButton = new BeatmapSelectButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
Tabs = new PageTabControl<MatchHeaderPage>
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
tabStrip.Colour = colours.Yellow;
|
||||
}
|
||||
|
||||
private class BeatmapSelectButton : OsuClickableContainer
|
||||
{
|
||||
private const float corner_radius = 5;
|
||||
private const float bg_opacity = 0.5f;
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly Box bg;
|
||||
private readonly Container border;
|
||||
|
||||
public BeatmapSelectButton()
|
||||
{
|
||||
Masking = true;
|
||||
CornerRadius = corner_radius;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
bg = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
Alpha = bg_opacity,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = @"Exo2.0-Bold",
|
||||
Text = "Select Beatmap",
|
||||
},
|
||||
border = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
BorderThickness = 4,
|
||||
Alpha = 0,
|
||||
Child = new Box // needs a child to show the border
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
border.BorderColour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
border.FadeIn(transition_duration);
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
base.OnHoverLost(e);
|
||||
border.FadeOut(transition_duration);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
bg.FadeTo(0.75f, 1000, Easing.Out);
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
bg.FadeTo(bg_opacity, transition_duration);
|
||||
return base.OnMouseUp(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MatchHeaderPage
|
||||
{
|
||||
Settings,
|
||||
Room,
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user