// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; using Humanizer; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay; using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay; using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand; using osuTK.Input; namespace osu.Game.Tests.Visual.RankedPlay { public partial class TestScenePlayerCardHand : OsuManualInputManagerTestScene { [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); private PlayerHandOfCards handOfCards = null!; [BackgroundDependencyLoader] private void load() { Child = handOfCards = new PlayerHandOfCards { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, Height = 0.5f, }; } [SetUpSteps] public void SetupSteps() { AddStep("reset card hand", () => Child = handOfCards = new PlayerHandOfCards { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, Height = 0.5f, }); } [Test] public void TestSingleSelectionMode() { AddStep("add cards", () => { for (int i = 0; i < 5; i++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); AddStep("single selection mode", () => handOfCards.SelectionMode = HandSelectionMode.Single); AddStep("click first card", () => handOfCards.GetCardsInDisplayOrder()[0].TriggerClick()); AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item])); AddStep("click second card", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick()); AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[1].Item])); AddStep("click second card again", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick()); AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[1].Item])); } [Test] public void TestMultiSelectionMode() { AddStep("add cards", () => { for (int i = 0; i < 5; i++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); AddStep("multi selection mode", () => handOfCards.SelectionMode = HandSelectionMode.Multiple); AddStep("click first card", () => handOfCards.GetCardsInDisplayOrder().First().TriggerClick()); AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder().First().Item])); AddStep("click second card", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick()); AddAssert("both cards selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item, handOfCards.GetCardsInDisplayOrder()[1].Item])); AddStep("click second card again", () => handOfCards.GetCardsInDisplayOrder()[1].TriggerClick()); AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item])); } [Test] public void TestCardCount() { for (int i = 1; i <= 8; i++) { int numCards = i; AddStep($"{i} {"cards".Pluralize(i == 1)}", () => { Child = handOfCards = new PlayerHandOfCards { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, Height = 0.5f, }; for (int j = 0; j < numCards; j++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); } } [Test] public void TestKeyboardSelectionSingleSelection() { bool playActionTriggered = false; AddStep("add cards", () => { playActionTriggered = false; handOfCards.PlayCardAction = () => playActionTriggered = true; handOfCards.Clear(); for (int i = 0; i < 5; i++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); AddStep("single selection mode", () => handOfCards.SelectionMode = HandSelectionMode.Single); for (int i = 0; i < 5; i++) { int i1 = i; Key key = Key.Number1 + i; AddStep($"key {i + 1}", () => InputManager.Key(key)); AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[i1].Item])); } AddStep("right arrow", () => InputManager.Key(Key.Right)); AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item])); AddStep("right arrow", () => InputManager.Key(Key.Right)); AddAssert("second card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[1].Item])); AddStep("left arrow", () => InputManager.Key(Key.Left)); AddAssert("first card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[0].Item])); AddStep("left arrow", () => InputManager.Key(Key.Left)); AddAssert("last card selected", () => handOfCards.Selection.SequenceEqual([handOfCards.GetCardsInDisplayOrder()[^1].Item])); AddStep("space", () => InputManager.Key(Key.Space)); AddAssert("play action triggered", () => playActionTriggered); } [Test] public void TestKeyboardSelectionMultiSelection() { AddStep("add cards", () => { for (int i = 0; i < 5; i++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); AddStep("multi selection mode", () => handOfCards.SelectionMode = HandSelectionMode.Multiple); for (int i = 0; i < 5; i++) { int i1 = i; Key key = Key.Number1 + i; AddStep($"key {i + 1}", () => InputManager.Key(key)); AddAssert("card hovered", () => handOfCards.GetCardsInDisplayOrder()[i1].CardHovered); AddAssert("card not selected", () => !handOfCards.Selection.Contains(handOfCards.GetCardsInDisplayOrder()[i1].Card.Item)); AddStep("space", () => InputManager.Key(Key.Space)); AddAssert("card selected", () => handOfCards.Selection.Contains(handOfCards.GetCardsInDisplayOrder()[i1].Card.Item)); } } [Test] public void TestContract() { AddStep("add cards", () => { for (int i = 0; i < 5; i++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); AddWaitStep("wait", 5); AddStep("contract", () => handOfCards.Contract()); AddWaitStep("wait", 5); AddAssert( "all cards outside bounds", () => handOfCards .ChildrenOfType() .All(card => !card.ScreenSpaceDrawQuad.AABBFloat.IntersectsWith(handOfCards.ScreenSpaceDrawQuad.AABBFloat)) ); } [Test] public void TestRemoveCardsWhileDragging() { AddStep("add cards", () => { for (int i = 0; i < 5; i++) handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem())); }); AddStep("hover card", () => InputManager.MoveMouseTo(handOfCards.GetCardsInDisplayOrder()[0])); AddStep("start drag", () => InputManager.PressButton(MouseButton.Left)); AddStep("move card", () => InputManager.MoveMouseTo(handOfCards.GetCardsInDisplayOrder()[3])); AddStep("remove cards", () => { foreach (var card in handOfCards.Cards.ToArray()) handOfCards.RemoveCard(card.Item); }); AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left)); } [Test] public void TestKeyboardSelectionWithoutCards() { AddAssert("no cards", () => !handOfCards.Cards.Any()); AddStep("right arrow", () => InputManager.Key(Key.Right)); AddStep("left arrow", () => InputManager.Key(Key.Left)); } } }