mirror of
https://github.com/ppy/osu.git
synced 2025-03-16 00:37:19 +08:00
Allow keyboard selection of rooms at the multiplayer lounge
This commit is contained in:
parent
95096cbf5e
commit
601101147e
@ -9,13 +9,17 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Framework.Threading;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Multi.Lounge.Components
|
namespace osu.Game.Screens.Multi.Lounge.Components
|
||||||
{
|
{
|
||||||
public class RoomsContainer : CompositeDrawable
|
public class RoomsContainer : CompositeDrawable, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
public Action<Room> JoinRequested;
|
public Action<Room> JoinRequested;
|
||||||
|
|
||||||
@ -88,8 +92,22 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
|||||||
|
|
||||||
private void addRooms(IEnumerable<Room> rooms)
|
private void addRooms(IEnumerable<Room> rooms)
|
||||||
{
|
{
|
||||||
foreach (var r in rooms)
|
foreach (var room in rooms)
|
||||||
roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) });
|
{
|
||||||
|
roomFlow.Add(new DrawableRoom(room)
|
||||||
|
{
|
||||||
|
Action = () =>
|
||||||
|
{
|
||||||
|
if (room == selectedRoom.Value)
|
||||||
|
{
|
||||||
|
JoinRequested?.Invoke(room);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectRoom(room);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Filter(filter?.Value);
|
Filter(filter?.Value);
|
||||||
}
|
}
|
||||||
@ -115,16 +133,89 @@ namespace osu.Game.Screens.Multi.Lounge.Components
|
|||||||
|
|
||||||
private void selectRoom(Room room)
|
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);
|
roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected);
|
||||||
|
|
||||||
selectedRoom.Value = room;
|
selectedRoom.Value = room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Key selection logic
|
||||||
|
|
||||||
|
public bool OnPressed(GlobalAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case GlobalAction.SelectNext:
|
||||||
|
beginRepeatSelection(() => selectNext(1), action);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GlobalAction.SelectPrevious:
|
||||||
|
beginRepeatSelection(() => selectNext(-1), action);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(GlobalAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case GlobalAction.SelectNext:
|
||||||
|
case GlobalAction.SelectPrevious:
|
||||||
|
endRepeatSelection(action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScheduledDelegate repeatDelegate;
|
||||||
|
private object lastRepeatSource;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Begin repeating the specified selection action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">The action to perform.</param>
|
||||||
|
/// <param name="source">The source of the action. Used in conjunction with <see cref="endRepeatSelection"/> to only cancel the correct action (most recently pressed key).</param>
|
||||||
|
private void beginRepeatSelection(Action action, object source)
|
||||||
|
{
|
||||||
|
endRepeatSelection();
|
||||||
|
|
||||||
|
lastRepeatSource = source;
|
||||||
|
repeatDelegate = this.BeginKeyRepeat(Scheduler, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void endRepeatSelection(object source = null)
|
||||||
|
{
|
||||||
|
// only the most recent source should be able to cancel the current action.
|
||||||
|
if (source != null && !EqualityComparer<object>.Default.Equals(lastRepeatSource, source))
|
||||||
|
return;
|
||||||
|
|
||||||
|
repeatDelegate?.Cancel();
|
||||||
|
repeatDelegate = null;
|
||||||
|
lastRepeatSource = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectNext(int direction)
|
||||||
|
{
|
||||||
|
var visibleRooms = Rooms.AsEnumerable().Where(r => r.IsPresent);
|
||||||
|
|
||||||
|
Room room;
|
||||||
|
|
||||||
|
if (selectedRoom.Value == null)
|
||||||
|
room = visibleRooms.FirstOrDefault()?.Room;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (direction < 0)
|
||||||
|
visibleRooms = visibleRooms.Reverse();
|
||||||
|
|
||||||
|
room = visibleRooms.SkipWhile(r => r.Room != selectedRoom.Value).Skip(1).FirstOrDefault()?.Room;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we already have a valid selection only change selection if we still have a room to switch to.
|
||||||
|
if (room != null)
|
||||||
|
selectRoom(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user