2019-01-24 16:43:03 +08:00
|
|
|
// 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.
|
2018-12-11 18:07:40 +08:00
|
|
|
|
2022-06-17 15:37:17 +08:00
|
|
|
#nullable disable
|
|
|
|
|
2018-12-11 18:07:40 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
2020-09-01 10:56:23 +08:00
|
|
|
using System.Collections.Specialized;
|
2018-12-11 18:07:40 +08:00
|
|
|
using System.Linq;
|
|
|
|
using osu.Framework.Allocation;
|
2019-02-21 18:04:31 +08:00
|
|
|
using osu.Framework.Bindables;
|
2018-12-11 18:07:40 +08:00
|
|
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
|
|
|
using osu.Framework.Graphics;
|
|
|
|
using osu.Framework.Graphics.Containers;
|
2020-07-09 16:15:16 +08:00
|
|
|
using osu.Framework.Input.Bindings;
|
2021-02-16 12:44:36 +08:00
|
|
|
using osu.Framework.Input.Events;
|
2020-12-25 23:50:00 +08:00
|
|
|
using osu.Game.Graphics.Cursor;
|
2020-07-09 16:15:16 +08:00
|
|
|
using osu.Game.Input.Bindings;
|
2020-12-25 12:38:11 +08:00
|
|
|
using osu.Game.Online.Rooms;
|
2020-12-25 23:50:00 +08:00
|
|
|
using osuTK;
|
2018-12-11 18:07:40 +08:00
|
|
|
|
2020-12-25 23:50:00 +08:00
|
|
|
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
2018-12-11 18:07:40 +08:00
|
|
|
{
|
2020-07-09 16:15:16 +08:00
|
|
|
public class RoomsContainer : CompositeDrawable, IKeyBindingHandler<GlobalAction>
|
2018-12-11 18:07:40 +08:00
|
|
|
{
|
2021-08-19 15:49:08 +08:00
|
|
|
public readonly Bindable<Room> SelectedRoom = new Bindable<Room>();
|
|
|
|
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>();
|
2021-07-26 12:22:11 +08:00
|
|
|
|
|
|
|
public IReadOnlyList<DrawableRoom> Rooms => roomFlow.FlowingChildren.Cast<DrawableRoom>().ToArray();
|
2018-12-11 18:07:40 +08:00
|
|
|
|
2021-08-19 15:49:08 +08:00
|
|
|
private readonly IBindableList<Room> rooms = new BindableList<Room>();
|
|
|
|
private readonly FillFlowContainer<DrawableLoungeRoom> roomFlow;
|
2019-02-08 13:57:51 +08:00
|
|
|
|
2018-12-11 18:07:40 +08:00
|
|
|
[Resolved]
|
2018-12-25 10:45:50 +08:00
|
|
|
private IRoomManager roomManager { get; set; }
|
2018-12-11 18:07:40 +08:00
|
|
|
|
2021-02-16 12:44:36 +08:00
|
|
|
// handle deselection
|
|
|
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
|
|
|
|
2018-12-11 18:07:40 +08:00
|
|
|
public RoomsContainer()
|
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.X;
|
|
|
|
AutoSizeAxes = Axes.Y;
|
|
|
|
|
2021-08-12 18:38:53 +08:00
|
|
|
// account for the fact we are in a scroll container and want a bit of spacing from the scroll bar.
|
|
|
|
Padding = new MarginPadding { Right = 5 };
|
|
|
|
|
2021-07-13 15:35:49 +08:00
|
|
|
InternalChild = new OsuContextMenuContainer
|
2018-12-11 18:07:40 +08:00
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.X,
|
|
|
|
AutoSizeAxes = Axes.Y,
|
2021-08-18 19:53:17 +08:00
|
|
|
Child = roomFlow = new FillFlowContainer<DrawableLoungeRoom>
|
2020-08-10 07:16:01 +08:00
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.X,
|
|
|
|
AutoSizeAxes = Axes.Y,
|
2021-07-13 15:35:49 +08:00
|
|
|
Direction = FillDirection.Vertical,
|
2021-07-13 15:00:42 +08:00
|
|
|
Spacing = new Vector2(10),
|
2020-08-10 07:16:01 +08:00
|
|
|
}
|
2018-12-11 18:07:40 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-02-06 11:12:52 +08:00
|
|
|
protected override void LoadComplete()
|
2018-12-11 18:07:40 +08:00
|
|
|
{
|
2020-09-01 10:56:23 +08:00
|
|
|
rooms.CollectionChanged += roomsChanged;
|
2018-12-28 00:45:19 +08:00
|
|
|
roomManager.RoomsUpdated += updateSorting;
|
|
|
|
|
2020-02-06 11:12:52 +08:00
|
|
|
rooms.BindTo(roomManager.Rooms);
|
2020-02-06 12:36:49 +08:00
|
|
|
|
2021-08-17 08:36:43 +08:00
|
|
|
Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true);
|
2019-11-15 07:23:56 +08:00
|
|
|
}
|
|
|
|
|
2021-08-17 08:36:43 +08:00
|
|
|
private void applyFilterCriteria(FilterCriteria criteria)
|
2018-12-11 18:07:40 +08:00
|
|
|
{
|
2018-12-19 15:56:51 +08:00
|
|
|
roomFlow.Children.ForEach(r =>
|
|
|
|
{
|
|
|
|
if (criteria == null)
|
|
|
|
r.MatchingFilter = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool matchingFilter = true;
|
2020-02-06 10:56:09 +08:00
|
|
|
|
2022-02-21 23:14:33 +08:00
|
|
|
matchingFilter &= criteria.Ruleset == null || r.Room.PlaylistItemStats.Value?.RulesetIDs.Any(id => id == criteria.Ruleset.OnlineID) != false;
|
2020-02-06 10:56:09 +08:00
|
|
|
|
2020-02-06 12:02:38 +08:00
|
|
|
if (!string.IsNullOrEmpty(criteria.SearchString))
|
2022-05-16 13:09:37 +08:00
|
|
|
{
|
|
|
|
// Room name isn't translatable, so ToString() is used here for simplicity.
|
|
|
|
matchingFilter &= r.FilterTerms.Any(term => term.ToString().Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase));
|
|
|
|
}
|
2018-12-19 15:56:51 +08:00
|
|
|
|
2022-07-01 16:26:40 +08:00
|
|
|
matchingFilter &= matchPermissions(r, criteria.Permissions);
|
2022-06-23 05:01:28 +08:00
|
|
|
|
2018-12-19 15:56:51 +08:00
|
|
|
r.MatchingFilter = matchingFilter;
|
|
|
|
}
|
|
|
|
});
|
2022-06-24 00:03:04 +08:00
|
|
|
|
2022-07-01 16:26:40 +08:00
|
|
|
static bool matchPermissions(DrawableLoungeRoom room, RoomPermissionsFilter accessType)
|
2022-06-24 00:03:04 +08:00
|
|
|
{
|
|
|
|
switch (accessType)
|
|
|
|
{
|
2022-07-01 16:26:40 +08:00
|
|
|
case RoomPermissionsFilter.All:
|
2022-06-24 00:03:04 +08:00
|
|
|
return true;
|
|
|
|
|
2022-07-01 16:26:40 +08:00
|
|
|
case RoomPermissionsFilter.Public:
|
2022-06-24 00:03:04 +08:00
|
|
|
return !room.Room.HasPassword.Value;
|
|
|
|
|
2022-07-01 16:26:40 +08:00
|
|
|
case RoomPermissionsFilter.Private:
|
2022-06-24 00:03:04 +08:00
|
|
|
return room.Room.HasPassword.Value;
|
|
|
|
|
|
|
|
default:
|
2022-07-01 16:26:40 +08:00
|
|
|
throw new ArgumentOutOfRangeException(nameof(accessType), accessType, $"Unsupported {nameof(RoomPermissionsFilter)} in filter");
|
2022-06-24 00:03:04 +08:00
|
|
|
}
|
|
|
|
}
|
2018-12-11 18:07:40 +08:00
|
|
|
}
|
|
|
|
|
2020-09-01 10:56:23 +08:00
|
|
|
private void roomsChanged(object sender, NotifyCollectionChangedEventArgs args)
|
|
|
|
{
|
|
|
|
switch (args.Action)
|
|
|
|
{
|
|
|
|
case NotifyCollectionChangedAction.Add:
|
|
|
|
addRooms(args.NewItems.Cast<Room>());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NotifyCollectionChangedAction.Remove:
|
|
|
|
removeRooms(args.OldItems.Cast<Room>());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-11 18:07:40 +08:00
|
|
|
private void addRooms(IEnumerable<Room> rooms)
|
|
|
|
{
|
2020-07-09 16:15:16 +08:00
|
|
|
foreach (var room in rooms)
|
2021-08-19 15:49:08 +08:00
|
|
|
roomFlow.Add(new DrawableLoungeRoom(room) { SelectedRoom = { BindTarget = SelectedRoom } });
|
2018-12-11 18:07:40 +08:00
|
|
|
|
2021-08-17 08:36:43 +08:00
|
|
|
applyFilterCriteria(Filter?.Value);
|
2018-12-11 18:07:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void removeRooms(IEnumerable<Room> rooms)
|
|
|
|
{
|
|
|
|
foreach (var r in rooms)
|
|
|
|
{
|
2022-08-26 14:19:05 +08:00
|
|
|
roomFlow.RemoveAll(d => d.Room == r, true);
|
2018-12-20 14:17:08 +08:00
|
|
|
|
2021-08-12 13:56:58 +08:00
|
|
|
// selection may have a lease due to being in a sub screen.
|
2021-08-19 15:49:08 +08:00
|
|
|
if (!SelectedRoom.Disabled)
|
|
|
|
SelectedRoom.Value = null;
|
2018-12-11 18:07:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-28 00:45:19 +08:00
|
|
|
private void updateSorting()
|
|
|
|
{
|
|
|
|
foreach (var room in roomFlow)
|
2022-02-21 16:59:09 +08:00
|
|
|
{
|
2022-05-27 19:18:46 +08:00
|
|
|
roomFlow.SetLayoutPosition(room, room.Room.Category.Value > RoomCategory.Normal
|
2022-02-21 16:59:09 +08:00
|
|
|
// Always show spotlight playlists at the top of the listing.
|
|
|
|
? float.MinValue
|
|
|
|
: -(room.Room.RoomID.Value ?? 0));
|
|
|
|
}
|
2018-12-28 00:45:19 +08:00
|
|
|
}
|
|
|
|
|
2021-02-16 12:44:36 +08:00
|
|
|
protected override bool OnClick(ClickEvent e)
|
|
|
|
{
|
2021-08-19 15:49:08 +08:00
|
|
|
if (!SelectedRoom.Disabled)
|
|
|
|
SelectedRoom.Value = null;
|
2021-02-16 12:44:36 +08:00
|
|
|
return base.OnClick(e);
|
|
|
|
}
|
|
|
|
|
2022-05-04 18:36:43 +08:00
|
|
|
#region Key selection logic (shared with BeatmapCarousel and DrawableRoomPlaylist)
|
2020-07-09 16:15:16 +08:00
|
|
|
|
2021-09-16 17:26:12 +08:00
|
|
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
2020-07-09 16:15:16 +08:00
|
|
|
{
|
2021-09-16 17:26:12 +08:00
|
|
|
switch (e.Action)
|
2020-07-09 16:15:16 +08:00
|
|
|
{
|
|
|
|
case GlobalAction.SelectNext:
|
2021-11-18 11:38:20 +08:00
|
|
|
selectNext(1);
|
2020-07-09 16:15:16 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
case GlobalAction.SelectPrevious:
|
2021-11-18 11:38:20 +08:00
|
|
|
selectNext(-1);
|
2020-07-09 16:15:16 +08:00
|
|
|
return true;
|
|
|
|
}
|
2018-12-11 18:07:40 +08:00
|
|
|
|
2020-07-09 16:15:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-09-16 17:26:12 +08:00
|
|
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
2020-07-09 16:15:16 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private void selectNext(int direction)
|
|
|
|
{
|
2021-08-19 15:49:08 +08:00
|
|
|
if (SelectedRoom.Disabled)
|
2021-08-13 13:29:28 +08:00
|
|
|
return;
|
|
|
|
|
2020-07-09 16:15:16 +08:00
|
|
|
var visibleRooms = Rooms.AsEnumerable().Where(r => r.IsPresent);
|
|
|
|
|
|
|
|
Room room;
|
|
|
|
|
2021-08-19 15:49:08 +08:00
|
|
|
if (SelectedRoom.Value == null)
|
2020-07-09 16:15:16 +08:00
|
|
|
room = visibleRooms.FirstOrDefault()?.Room;
|
2018-12-11 18:07:40 +08:00
|
|
|
else
|
2020-07-09 16:15:16 +08:00
|
|
|
{
|
|
|
|
if (direction < 0)
|
|
|
|
visibleRooms = visibleRooms.Reverse();
|
2018-12-20 19:58:34 +08:00
|
|
|
|
2021-08-19 15:49:08 +08:00
|
|
|
room = visibleRooms.SkipWhile(r => r.Room != SelectedRoom.Value).Skip(1).FirstOrDefault()?.Room;
|
2020-07-09 16:15:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// we already have a valid selection only change selection if we still have a room to switch to.
|
|
|
|
if (room != null)
|
2021-08-19 15:49:08 +08:00
|
|
|
SelectedRoom.Value = room;
|
2018-12-11 18:07:40 +08:00
|
|
|
}
|
2018-12-28 00:45:19 +08:00
|
|
|
|
2020-07-09 16:15:16 +08:00
|
|
|
#endregion
|
|
|
|
|
2018-12-28 00:45:19 +08:00
|
|
|
protected override void Dispose(bool isDisposing)
|
|
|
|
{
|
|
|
|
base.Dispose(isDisposing);
|
|
|
|
|
|
|
|
if (roomManager != null)
|
|
|
|
roomManager.RoomsUpdated -= updateSorting;
|
|
|
|
}
|
2018-12-11 18:07:40 +08:00
|
|
|
}
|
|
|
|
}
|