Merge pull request #14117 from peppy/multiplayer-create-with-enter

Add the ability to create multiplayer games using only the keyboard
This commit is contained in:
Dan Balasescu 2021-08-05 17:27:04 +09:00 committed by GitHub
commit f0d11ebd89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 142 additions and 12 deletions

View File

@ -8,6 +8,7 @@ using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Framework.Testing; using osu.Framework.Testing;
@ -88,6 +89,28 @@ namespace osu.Game.Tests.Visual.Multiplayer
// used to test the flow of multiplayer from visual tests. // used to test the flow of multiplayer from visual tests.
} }
[Test]
public void TestCreateRoomViaKeyboard()
{
// create room dialog
AddStep("Press new document", () => InputManager.Keys(PlatformAction.DocumentNew));
AddUntilStep("wait for settings", () => InputManager.ChildrenOfType<MultiplayerMatchSettingsOverlay>().FirstOrDefault() != null);
// edit playlist item
AddStep("Press select", () => InputManager.Key(Key.Enter));
AddUntilStep("wait for song select", () => InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault() != null);
// select beatmap
AddStep("Press select", () => InputManager.Key(Key.Enter));
AddUntilStep("wait for return to screen", () => InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault() == null);
// create room
AddStep("Press select", () => InputManager.Key(Key.Enter));
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
AddUntilStep("wait for join", () => client.Room != null);
}
[Test] [Test]
public void TestCreateRoomWithoutPassword() public void TestCreateRoomWithoutPassword()
{ {

View File

@ -0,0 +1,39 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Input;
using osu.Framework.Input.Bindings;
namespace osu.Game.Screens.OnlinePlay.Match.Components
{
public abstract class CreateRoomButton : PurpleTriangleButton, IKeyBindingHandler<PlatformAction>
{
[BackgroundDependencyLoader]
private void load()
{
Triangles.TriangleScale = 1.5f;
}
public bool OnPressed(PlatformAction action)
{
if (!Enabled.Value)
return false;
switch (action)
{
case PlatformAction.DocumentNew:
// might as well also handle new tab. it's a bit of an undefined flow on this screen.
case PlatformAction.TabNew:
TriggerClick();
return true;
}
return false;
}
public void OnReleased(PlatformAction action)
{
}
}
}

View File

@ -4,15 +4,17 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Match.Components namespace osu.Game.Screens.OnlinePlay.Match.Components
{ {
public abstract class MatchSettingsOverlay : FocusedOverlayContainer public abstract class MatchSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler<GlobalAction>
{ {
protected const float TRANSITION_DURATION = 350; protected const float TRANSITION_DURATION = 350;
protected const float FIELD_PADDING = 45; protected const float FIELD_PADDING = 45;
@ -21,6 +23,10 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
protected override bool BlockScrollInput => false; protected override bool BlockScrollInput => false;
protected abstract OsuButton SubmitButton { get; }
protected abstract bool IsLoading { get; }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -29,6 +35,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
Add(Settings = CreateSettings()); Add(Settings = CreateSettings());
} }
protected abstract void SelectBeatmap();
protected abstract OnlinePlayComposite CreateSettings(); protected abstract OnlinePlayComposite CreateSettings();
protected override void PopIn() protected override void PopIn()
@ -41,6 +49,33 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine);
} }
public bool OnPressed(GlobalAction action)
{
switch (action)
{
case GlobalAction.Select:
if (IsLoading)
return true;
if (SubmitButton.Enabled.Value)
{
SubmitButton.TriggerClick();
return true;
}
else
{
SelectBeatmap();
return true;
}
}
return false;
}
public void OnReleased(GlobalAction action)
{
}
protected class SettingsTextBox : OsuTextBox protected class SettingsTextBox : OsuTextBox
{ {
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -8,7 +8,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
namespace osu.Game.Screens.OnlinePlay.Multiplayer namespace osu.Game.Screens.OnlinePlay.Multiplayer
{ {
public class CreateMultiplayerMatchButton : PurpleTriangleButton public class CreateMultiplayerMatchButton : CreateRoomButton
{ {
private IBindable<bool> isConnected; private IBindable<bool> isConnected;
private IBindable<bool> operationInProgress; private IBindable<bool> operationInProgress;
@ -22,8 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Triangles.TriangleScale = 1.5f;
Text = "Create room"; Text = "Create room";
isConnected = multiplayerClient.IsConnected.GetBoundCopy(); isConnected = multiplayerClient.IsConnected.GetBoundCopy();

View File

@ -47,7 +47,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 40, Height = 40,
Text = "Select beatmap", Text = "Select beatmap",
Action = () => matchSubScreen.Push(new MultiplayerMatchSongSelect()), Action = () =>
{
if (matchSubScreen.IsCurrentScreen())
matchSubScreen.Push(new MultiplayerMatchSongSelect());
},
Alpha = 0 Alpha = 0
} }
} }
@ -68,6 +72,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
}, true); }, true);
} }
public void BeginSelection() => selectButton.TriggerClick();
private void updateBeatmap() private void updateBeatmap()
{ {
if (SelectedItem.Value == null) if (SelectedItem.Value == null)

View File

@ -28,8 +28,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{ {
public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay
{ {
private MatchSettings settings;
protected override OsuButton SubmitButton => settings.ApplyButton;
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; }
protected override bool IsLoading => ongoingOperationTracker.InProgress.Value;
protected override void SelectBeatmap() => settings.SelectBeatmap();
protected override OnlinePlayComposite CreateSettings() protected override OnlinePlayComposite CreateSettings()
=> new MatchSettings => settings = new MatchSettings
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Y, RelativePositionAxes = Axes.Y,
@ -54,6 +65,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private LoadingLayer loadingLayer; private LoadingLayer loadingLayer;
private BeatmapSelectionControl initialBeatmapControl; private BeatmapSelectionControl initialBeatmapControl;
public void SelectBeatmap() => initialBeatmapControl.BeginSelection();
[Resolved] [Resolved]
private IRoomManager manager { get; set; } private IRoomManager manager { get; set; }

View File

@ -6,13 +6,11 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
namespace osu.Game.Screens.OnlinePlay.Playlists namespace osu.Game.Screens.OnlinePlay.Playlists
{ {
public class CreatePlaylistsRoomButton : PurpleTriangleButton public class CreatePlaylistsRoomButton : CreateRoomButton
{ {
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Triangles.TriangleScale = 1.5f;
Text = "Create playlist"; Text = "Create playlist";
} }
} }

View File

@ -26,8 +26,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{ {
public Action EditPlaylist; public Action EditPlaylist;
private MatchSettings settings;
protected override OsuButton SubmitButton => settings.ApplyButton;
protected override bool IsLoading => settings.IsLoading; // should probably be replaced with an OngoingOperationTracker.
protected override void SelectBeatmap() => settings.SelectBeatmap();
protected override OnlinePlayComposite CreateSettings() protected override OnlinePlayComposite CreateSettings()
=> new MatchSettings => settings = new MatchSettings
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Y, RelativePositionAxes = Axes.Y,
@ -45,12 +53,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
public RoomAvailabilityPicker AvailabilityPicker; public RoomAvailabilityPicker AvailabilityPicker;
public TriangleButton ApplyButton; public TriangleButton ApplyButton;
public bool IsLoading => loadingLayer.State.Value == Visibility.Visible;
public OsuSpriteText ErrorText; public OsuSpriteText ErrorText;
private LoadingLayer loadingLayer; private LoadingLayer loadingLayer;
private DrawableRoomPlaylist playlist; private DrawableRoomPlaylist playlist;
private OsuSpriteText playlistLength; private OsuSpriteText playlistLength;
private PurpleTriangleButton editPlaylistButton;
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
private IRoomManager manager { get; set; } private IRoomManager manager { get; set; }
@ -199,7 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
}, },
new Drawable[] new Drawable[]
{ {
new PurpleTriangleButton editPlaylistButton = new PurpleTriangleButton
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 40, Height = 40,
@ -292,6 +304,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
ApplyButton.Enabled.Value = hasValidSettings; ApplyButton.Enabled.Value = hasValidSettings;
} }
public void SelectBeatmap() => editPlaylistButton.TriggerClick();
private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) => private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) =>
playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}"; playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}";

View File

@ -230,7 +230,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
settingsOverlay = new PlaylistsMatchSettingsOverlay settingsOverlay = new PlaylistsMatchSettingsOverlay
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
EditPlaylist = () => this.Push(new PlaylistsSongSelect()), EditPlaylist = () =>
{
if (this.IsCurrentScreen())
this.Push(new PlaylistsSongSelect());
},
State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden } State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden }
} }
}); });