Split lounge-specific implementation from DrawableRoom

This commit is contained in:
smoogipoo 2021-08-18 20:53:17 +09:00
parent 63af67f61b
commit eadf02933a
8 changed files with 269 additions and 269 deletions

View File

@ -10,11 +10,11 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Rooms;
using osu.Game.Online.Rooms.RoomStatuses;
using osu.Game.Overlays;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Tests.Beatmaps;
using osu.Game.Users;
@ -159,10 +159,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
}));
}
var drawableRoom = new DrawableRoom(room) { MatchingFilter = true };
drawableRoom.Action = () => drawableRoom.State = drawableRoom.State == SelectionState.Selected ? SelectionState.NotSelected : SelectionState.Selected;
return drawableRoom;
return new DrawableLoungeRoom(room) { MatchingFilter = true };
}
}
}

View File

@ -9,6 +9,7 @@ using osu.Framework.Testing;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Tests.Visual.OnlinePlay;
using osuTK.Input;
@ -150,6 +151,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
private bool checkRoomSelected(Room room) => SelectedRoom.Value == room;
private Room getRoomInFlow(int index) =>
(container.ChildrenOfType<FillFlowContainer<DrawableRoom>>().First().FlowingChildren.ElementAt(index) as DrawableRoom)?.Room;
(container.ChildrenOfType<FillFlowContainer<DrawableLoungeRoom>>().First().FlowingChildren.ElementAt(index) as DrawableRoom)?.Room;
}
}

View File

@ -236,8 +236,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("select room", () => InputManager.Key(Key.Down));
AddStep("join room", () => InputManager.Key(Key.Enter));
DrawableRoom.PasswordEntryPopover passwordEntryPopover = null;
AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType<DrawableRoom.PasswordEntryPopover>().FirstOrDefault()) != null);
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().FirstOrDefault()) != null);
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "password");
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());

View File

@ -9,7 +9,6 @@ using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Tests.Visual.OnlinePlay;
using osuTK.Input;
@ -59,20 +58,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("select room", () => InputManager.Key(Key.Down));
AddStep("attempt join room", () => InputManager.Key(Key.Enter));
AddUntilStep("password prompt appeared", () => InputManager.ChildrenOfType<DrawableRoom.PasswordEntryPopover>().Any());
AddUntilStep("password prompt appeared", () => InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().Any());
AddStep("exit screen", () => Stack.Exit());
AddUntilStep("password prompt hidden", () => !InputManager.ChildrenOfType<DrawableRoom.PasswordEntryPopover>().Any());
AddUntilStep("password prompt hidden", () => !InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().Any());
}
[Test]
public void TestJoinRoomWithPassword()
{
DrawableRoom.PasswordEntryPopover passwordEntryPopover = null;
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true));
AddStep("select room", () => InputManager.Key(Key.Down));
AddStep("attempt join room", () => InputManager.Key(Key.Enter));
AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType<DrawableRoom.PasswordEntryPopover>().FirstOrDefault()) != null);
AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().FirstOrDefault()) != null);
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "password");
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());
@ -83,12 +82,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestJoinRoomWithPasswordViaKeyboardOnly()
{
DrawableRoom.PasswordEntryPopover passwordEntryPopover = null;
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true));
AddStep("select room", () => InputManager.Key(Key.Down));
AddStep("attempt join room", () => InputManager.Key(Key.Enter));
AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType<DrawableRoom.PasswordEntryPopover>().FirstOrDefault()) != null);
AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType<DrawableLoungeRoom.PasswordEntryPopover>().FirstOrDefault()) != null);
AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType<TextBox>().First().Text = "password");
AddStep("press enter", () => InputManager.Key(Key.Enter));

View File

@ -1,32 +1,19 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Input.Bindings;
using osu.Game.Online.Rooms;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.Components;
@ -35,104 +22,17 @@ using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
public class DrawableRoom : OsuClickableContainer, IStateful<SelectionState>, IFilterable, IHasContextMenu, IHasPopover, IKeyBindingHandler<GlobalAction>
public class DrawableRoom : CompositeDrawable
{
public const float SELECTION_BORDER_WIDTH = 4;
private const float corner_radius = 10;
private const float transition_duration = 60;
protected const float CORNER_RADIUS = 10;
private const float height = 100;
public event Action<SelectionState> StateChanged;
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds();
private Drawable selectionBox;
[Resolved(canBeNull: true)]
private LoungeSubScreen loungeScreen { get; set; }
public readonly Room Room;
[Resolved]
private BeatmapManager beatmaps { get; set; }
[Resolved(canBeNull: true)]
private Bindable<Room> selectedRoom { get; set; }
[Resolved(canBeNull: true)]
private LoungeSubScreen lounge { get; set; }
public readonly Room Room;
private SelectionState state;
private Sample sampleSelect;
private Sample sampleJoin;
public SelectionState State
{
get => state;
set
{
if (value == state)
return;
state = value;
if (selectionBox != null)
{
if (state == SelectionState.Selected)
selectionBox.FadeIn(transition_duration);
else
selectionBox.FadeOut(transition_duration);
}
StateChanged?.Invoke(State);
}
}
public IEnumerable<string> FilterTerms => new[] { Room.Name.Value };
private bool matchingFilter;
public bool MatchingFilter
{
get => matchingFilter;
set
{
matchingFilter = value;
if (!IsLoaded)
return;
if (matchingFilter)
this.FadeIn(200);
else
Hide();
}
}
private int numberOfAvatars = 7;
public int NumberOfAvatars
{
get => numberOfAvatars;
set
{
numberOfAvatars = value;
if (recentParticipantsList != null)
recentParticipantsList.NumberOfCircles = value;
}
}
public bool FilteringActive { get; set; }
protected readonly Container ButtonsContainer = new Container
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X
};
protected Container ButtonsContainer { get; private set; }
private readonly Bindable<RoomCategory> roomCategory = new Bindable<RoomCategory>();
private readonly Bindable<bool> hasPassword = new Bindable<bool>();
@ -149,7 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
Height = height;
Masking = true;
CornerRadius = corner_radius;
CornerRadius = CORNER_RADIUS;
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
@ -159,9 +59,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colours, AudioManager audio)
private void load(OverlayColourProvider colours)
{
Children = new Drawable[]
InternalChildren = new Drawable[]
{
// This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites.
new Box
@ -183,7 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = corner_radius,
CornerRadius = CORNER_RADIUS,
Children = new Drawable[]
{
new GridContainer
@ -303,7 +203,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
},
Children = new Drawable[]
{
ButtonsContainer,
ButtonsContainer = new Container
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X
},
recentParticipantsList = new RecentParticipantsList
{
Anchor = Anchor.CentreRight,
@ -316,36 +222,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
},
},
},
new StatusColouredContainer(transition_duration)
{
RelativeSizeAxes = Axes.Both,
Child = selectionBox = new Container
{
RelativeSizeAxes = Axes.Both,
Alpha = state == SelectionState.Selected ? 1 : 0,
Masking = true,
CornerRadius = corner_radius,
BorderThickness = SELECTION_BORDER_WIDTH,
BorderColour = Color4.White,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
}
}
},
};
sampleSelect = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select");
sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Submit.GetDescription()}-select");
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
return new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent))
{
Model = { Value = Room }
};
}
@ -353,11 +229,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
base.LoadComplete();
if (matchingFilter)
this.FadeInFromZero(transition_duration);
else
Alpha = 0;
roomCategory.BindTo(Room.Category);
roomCategory.BindValueChanged(c =>
{
@ -371,57 +242,26 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
hasPassword.BindValueChanged(v => passwordIcon.Alpha = v.NewValue ? 1 : 0, true);
}
public Popover GetPopover() => new PasswordEntryPopover(Room) { JoinRequested = lounge.Join };
public MenuItem[] ContextMenuItems => new MenuItem[]
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
new OsuMenuItem("Create copy", MenuItemType.Standard, () =>
return new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent))
{
lounge?.Open(Room.DeepClone());
})
};
public bool OnPressed(GlobalAction action)
{
if (selectedRoom.Value != Room)
return false;
switch (action)
{
case GlobalAction.Select:
TriggerClick();
return true;
}
return false;
Model = { Value = Room }
};
}
public void OnReleased(GlobalAction action)
private int numberOfAvatars = 7;
public int NumberOfAvatars
{
}
protected override bool ShouldBeConsideredForInput(Drawable child) => state == SelectionState.Selected || child is HoverSounds;
protected override bool OnClick(ClickEvent e)
{
if (Room != selectedRoom.Value)
get => numberOfAvatars;
set
{
sampleSelect?.Play();
selectedRoom.Value = Room;
return true;
numberOfAvatars = value;
if (recentParticipantsList != null)
recentParticipantsList.NumberOfCircles = value;
}
if (Room.HasPassword.Value)
{
sampleJoin?.Play();
this.ShowPopover();
return true;
}
sampleJoin?.Play();
lounge?.Join(Room, null);
return base.OnClick(e);
}
private class RoomNameText : OsuSpriteText
@ -508,52 +348,5 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
};
}
}
public class PasswordEntryPopover : OsuPopover
{
private readonly Room room;
public Action<Room, string> JoinRequested;
public PasswordEntryPopover(Room room)
{
this.room = room;
}
private OsuPasswordTextBox passwordTextbox;
[BackgroundDependencyLoader]
private void load()
{
Child = new FillFlowContainer
{
Margin = new MarginPadding(10),
Spacing = new Vector2(5),
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
passwordTextbox = new OsuPasswordTextBox
{
Width = 200,
},
new TriangleButton
{
Width = 80,
Text = "Join Room",
Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text)
}
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox));
passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text);
}
}
}
}

View File

@ -15,7 +15,6 @@ using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Extensions;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osu.Game.Online.Rooms;
using osuTK;
@ -26,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
private readonly IBindableList<Room> rooms = new BindableList<Room>();
private readonly FillFlowContainer<DrawableRoom> roomFlow;
private readonly FillFlowContainer<DrawableLoungeRoom> roomFlow;
public IReadOnlyList<DrawableRoom> Rooms => roomFlow.FlowingChildren.Cast<DrawableRoom>().ToArray();
@ -56,7 +55,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Child = roomFlow = new FillFlowContainer<DrawableRoom>
Child = roomFlow = new FillFlowContainer<DrawableLoungeRoom>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
@ -74,16 +73,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
rooms.BindTo(roomManager.Rooms);
Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true);
selectedRoom.BindValueChanged(selection =>
{
updateSelection();
}, true);
}
private void updateSelection() =>
roomFlow.Children.ForEach(r => r.State = r.Room == selectedRoom.Value ? SelectionState.Selected : SelectionState.NotSelected);
private void applyFilterCriteria(FilterCriteria criteria)
{
roomFlow.Children.ForEach(r =>
@ -122,22 +113,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
foreach (var room in rooms)
{
roomFlow.Add(new DrawableRoom(room));
roomFlow.Add(new DrawableLoungeRoom(room));
}
applyFilterCriteria(Filter?.Value);
updateSelection();
}
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);
roomFlow.RemoveAll(d => d.Room == r);
// selection may have a lease due to being in a sub screen.
if (!selectedRoom.Disabled)

View File

@ -0,0 +1,225 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Input.Bindings;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Lounge
{
/// <summary>
/// A <see cref="DrawableRoom"/> with lounge-specific interactions such as selection and hover sounds.
/// </summary>
public class DrawableLoungeRoom : DrawableRoom, IFilterable, IHasContextMenu, IHasPopover, IKeyBindingHandler<GlobalAction>
{
private const float transition_duration = 60;
private const float selection_border_width = 4;
[Resolved(canBeNull: true)]
private LoungeSubScreen lounge { get; set; }
[Resolved(canBeNull: true)]
private Bindable<Room> selectedRoom { get; set; }
private Sample sampleSelect;
private Sample sampleJoin;
private Drawable selectionBox;
public DrawableLoungeRoom(Room room)
: base(room)
{
}
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
sampleSelect = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select");
sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Submit.GetDescription()}-select");
AddRangeInternal(new Drawable[]
{
new StatusColouredContainer(transition_duration)
{
RelativeSizeAxes = Axes.Both,
Child = selectionBox = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = CORNER_RADIUS,
BorderThickness = selection_border_width,
BorderColour = Color4.White,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
}
}
},
new HoverSounds()
});
}
protected override void LoadComplete()
{
base.LoadComplete();
if (matchingFilter)
this.FadeInFromZero(transition_duration);
else
Alpha = 0;
selectedRoom.BindValueChanged(updateSelectedRoom, true);
}
private void updateSelectedRoom(ValueChangedEvent<Room> selected)
{
if (selected.NewValue == Room)
selectionBox.FadeIn(transition_duration);
else
selectionBox.FadeOut(transition_duration);
}
public bool FilteringActive { get; set; }
public IEnumerable<string> FilterTerms => new[] { Room.Name.Value };
private bool matchingFilter;
public bool MatchingFilter
{
get => matchingFilter;
set
{
matchingFilter = value;
if (!IsLoaded)
return;
if (matchingFilter)
this.FadeIn(200);
else
Hide();
}
}
public Popover GetPopover() => new PasswordEntryPopover(Room) { JoinRequested = lounge.Join };
public MenuItem[] ContextMenuItems => new MenuItem[]
{
new OsuMenuItem("Create copy", MenuItemType.Standard, () =>
{
lounge?.Open(Room.DeepClone());
})
};
public bool OnPressed(GlobalAction action)
{
if (selectedRoom.Value != Room)
return false;
switch (action)
{
case GlobalAction.Select:
TriggerClick();
return true;
}
return false;
}
public void OnReleased(GlobalAction action)
{
}
protected override bool ShouldBeConsideredForInput(Drawable child) => selectedRoom.Value == Room || child is HoverSounds;
protected override bool OnClick(ClickEvent e)
{
if (Room != selectedRoom.Value)
{
sampleSelect?.Play();
selectedRoom.Value = Room;
return true;
}
if (Room.HasPassword.Value)
{
sampleJoin?.Play();
this.ShowPopover();
return true;
}
sampleJoin?.Play();
lounge?.Join(Room, null);
return base.OnClick(e);
}
public class PasswordEntryPopover : OsuPopover
{
private readonly Room room;
public Action<Room, string> JoinRequested;
public PasswordEntryPopover(Room room)
{
this.room = room;
}
private OsuPasswordTextBox passwordTextbox;
[BackgroundDependencyLoader]
private void load()
{
Child = new FillFlowContainer
{
Margin = new MarginPadding(10),
Spacing = new Vector2(5),
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
passwordTextbox = new OsuPasswordTextBox
{
Width = 200,
},
new TriangleButton
{
Width = 80,
Text = "Join Room",
Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text)
}
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox));
passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text);
}
}
}
}

View File

@ -134,7 +134,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
{
new DrawableMatchRoom(Room, allowEdit)
{
MatchingFilter = true,
OnEdit = () => settingsOverlay.Show()
}
},