diff --git a/osu.Android.props b/osu.Android.props
index f757847c10..454bb46059 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -51,8 +51,8 @@
-
-
+
+
diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs
new file mode 100644
index 0000000000..fbbfee6b60
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs
@@ -0,0 +1,120 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Generic;
+using NUnit.Framework;
+using osu.Framework.Utils;
+using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.ControlPoints;
+using osu.Game.Rulesets.Catch.Beatmaps;
+using osu.Game.Rulesets.Catch.Mods;
+using osu.Game.Rulesets.Catch.Objects;
+using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Rulesets.Objects;
+using osuTK;
+
+namespace osu.Game.Rulesets.Catch.Tests.Mods
+{
+ [TestFixture]
+ public class CatchModMirrorTest
+ {
+ [Test]
+ public void TestModMirror()
+ {
+ IBeatmap original = createBeatmap(false);
+ IBeatmap mirrored = createBeatmap(true);
+
+ assertEffectivePositionsMirrored(original, mirrored);
+ }
+
+ private static IBeatmap createBeatmap(bool withMirrorMod)
+ {
+ var beatmap = createRawBeatmap();
+ var mirrorMod = new CatchModMirror();
+
+ var beatmapProcessor = new CatchBeatmapProcessor(beatmap);
+ beatmapProcessor.PreProcess();
+
+ foreach (var hitObject in beatmap.HitObjects)
+ hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
+
+ beatmapProcessor.PostProcess();
+
+ if (withMirrorMod)
+ mirrorMod.ApplyToBeatmap(beatmap);
+
+ return beatmap;
+ }
+
+ private static IBeatmap createRawBeatmap() => new Beatmap
+ {
+ HitObjects = new List
+ {
+ new Fruit
+ {
+ OriginalX = 150,
+ StartTime = 0
+ },
+ new Fruit
+ {
+ OriginalX = 450,
+ StartTime = 500
+ },
+ new JuiceStream
+ {
+ OriginalX = 250,
+ Path = new SliderPath
+ {
+ ControlPoints =
+ {
+ new PathControlPoint(new Vector2(-100, 1)),
+ new PathControlPoint(new Vector2(0, 2)),
+ new PathControlPoint(new Vector2(100, 3)),
+ new PathControlPoint(new Vector2(0, 4))
+ }
+ },
+ StartTime = 1000,
+ },
+ new BananaShower
+ {
+ StartTime = 5000,
+ Duration = 5000
+ }
+ }
+ };
+
+ private static void assertEffectivePositionsMirrored(IBeatmap original, IBeatmap mirrored)
+ {
+ if (original.HitObjects.Count != mirrored.HitObjects.Count)
+ Assert.Fail($"Top-level object count mismatch (original: {original.HitObjects.Count}, mirrored: {mirrored.HitObjects.Count})");
+
+ for (int i = 0; i < original.HitObjects.Count; ++i)
+ {
+ var originalObject = (CatchHitObject)original.HitObjects[i];
+ var mirroredObject = (CatchHitObject)mirrored.HitObjects[i];
+
+ // banana showers themselves are exempt, as we only really care about their nested bananas' positions.
+ if (!effectivePositionMirrored(originalObject, mirroredObject) && !(originalObject is BananaShower))
+ Assert.Fail($"{originalObject.GetType().Name} at time {originalObject.StartTime} is not mirrored ({printEffectivePositions(originalObject, mirroredObject)})");
+
+ if (originalObject.NestedHitObjects.Count != mirroredObject.NestedHitObjects.Count)
+ Assert.Fail($"{originalObject.GetType().Name} nested object count mismatch (original: {originalObject.NestedHitObjects.Count}, mirrored: {mirroredObject.NestedHitObjects.Count})");
+
+ for (int j = 0; j < originalObject.NestedHitObjects.Count; ++j)
+ {
+ var originalNested = (CatchHitObject)originalObject.NestedHitObjects[j];
+ var mirroredNested = (CatchHitObject)mirroredObject.NestedHitObjects[j];
+
+ if (!effectivePositionMirrored(originalNested, mirroredNested))
+ Assert.Fail($"{originalObject.GetType().Name}'s nested {originalNested.GetType().Name} at time {originalObject.StartTime} is not mirrored ({printEffectivePositions(originalNested, mirroredNested)})");
+ }
+ }
+ }
+
+ private static string printEffectivePositions(CatchHitObject original, CatchHitObject mirrored)
+ => $"original X: {original.EffectiveX}, mirrored X is: {mirrored.EffectiveX}, mirrored X should be: {CatchPlayfield.WIDTH - original.EffectiveX}";
+
+ private static bool effectivePositionMirrored(CatchHitObject original, CatchHitObject mirrored)
+ => Precision.AlmostEquals(original.EffectiveX, CatchPlayfield.WIDTH - mirrored.EffectiveX);
+ }
+}
diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs
index eafa1b9b9d..9fee6b2bc1 100644
--- a/osu.Game.Rulesets.Catch/CatchRuleset.cs
+++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs
@@ -117,6 +117,7 @@ namespace osu.Game.Rulesets.Catch
{
new CatchModDifficultyAdjust(),
new CatchModClassic(),
+ new CatchModMirror(),
};
case ModType.Automation:
diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs
new file mode 100644
index 0000000000..932c8cad85
--- /dev/null
+++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs
@@ -0,0 +1,87 @@
+// 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 osu.Game.Beatmaps;
+using osu.Game.Rulesets.Catch.Beatmaps;
+using osu.Game.Rulesets.Catch.Objects;
+using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Rulesets.Objects;
+using osuTK;
+
+namespace osu.Game.Rulesets.Catch.Mods
+{
+ public class CatchModMirror : ModMirror, IApplicableToBeatmap
+ {
+ public override string Description => "Fruits are flipped horizontally.";
+
+ ///
+ /// is used instead of ,
+ /// as applies offsets in .
+ /// runs after post-processing, while runs before it.
+ ///
+ public void ApplyToBeatmap(IBeatmap beatmap)
+ {
+ foreach (var hitObject in beatmap.HitObjects)
+ applyToHitObject(hitObject);
+ }
+
+ private void applyToHitObject(HitObject hitObject)
+ {
+ var catchObject = (CatchHitObject)hitObject;
+
+ switch (catchObject)
+ {
+ case Fruit fruit:
+ mirrorEffectiveX(fruit);
+ break;
+
+ case JuiceStream juiceStream:
+ mirrorEffectiveX(juiceStream);
+ mirrorJuiceStreamPath(juiceStream);
+ break;
+
+ case BananaShower bananaShower:
+ mirrorBananaShower(bananaShower);
+ break;
+ }
+ }
+
+ ///
+ /// Mirrors the effective X position of and its nested hit objects.
+ ///
+ private static void mirrorEffectiveX(CatchHitObject catchObject)
+ {
+ catchObject.OriginalX = CatchPlayfield.WIDTH - catchObject.OriginalX;
+ catchObject.XOffset = -catchObject.XOffset;
+
+ foreach (var nested in catchObject.NestedHitObjects.Cast())
+ {
+ nested.OriginalX = CatchPlayfield.WIDTH - nested.OriginalX;
+ nested.XOffset = -nested.XOffset;
+ }
+ }
+
+ ///
+ /// Mirrors the path of the .
+ ///
+ private static void mirrorJuiceStreamPath(JuiceStream juiceStream)
+ {
+ var controlPoints = juiceStream.Path.ControlPoints.Select(p => new PathControlPoint(p.Position.Value, p.Type.Value)).ToArray();
+ foreach (var point in controlPoints)
+ point.Position.Value = new Vector2(-point.Position.Value.X, point.Position.Value.Y);
+
+ juiceStream.Path = new SliderPath(controlPoints, juiceStream.Path.ExpectedDistance.Value);
+ }
+
+ ///
+ /// Mirrors X positions of all bananas in the .
+ ///
+ private static void mirrorBananaShower(BananaShower bananaShower)
+ {
+ foreach (var banana in bananaShower.NestedHitObjects.OfType())
+ banana.XOffset = CatchPlayfield.WIDTH - banana.XOffset;
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs
index 0e61c02e2d..d4f1602a46 100644
--- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs
+++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs
@@ -41,6 +41,11 @@ namespace osu.Game.Rulesets.Osu.Edit
protected override GameplayCursorContainer CreateCursor() => null;
+ public OsuEditorPlayfield()
+ {
+ HitPolicy = new AnyOrderHitPolicy();
+ }
+
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs
index 92941665e0..1c8dfeac52 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
// Roughly matches osu!stable's slider border portions.
=> base.CalculatedBorderPortion * 0.77f;
- public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f);
+ public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, 0.7f);
protected override Color4 ColourAt(float position)
{
diff --git a/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs
new file mode 100644
index 0000000000..b4de91562b
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs
@@ -0,0 +1,22 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.UI;
+
+namespace osu.Game.Rulesets.Osu.UI
+{
+ ///
+ /// An which allows hitobjects to be hit in any order.
+ ///
+ public class AnyOrderHitPolicy : IHitPolicy
+ {
+ public IHitObjectContainer HitObjectContainer { get; set; }
+
+ public bool IsHittable(DrawableHitObject hitObject, double time) => true;
+
+ public void HandleHit(DrawableHitObject hitObject)
+ {
+ }
+ }
+}
diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs
index 0ce71696bd..58f4c4c8db 100644
--- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs
+++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs
@@ -2,11 +2,13 @@
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
+using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.Scoring;
using osu.Game.Tests.Visual;
namespace osu.Game.Tests.Gameplay
@@ -121,6 +123,18 @@ namespace osu.Game.Tests.Gameplay
AddAssert("Drawable lifetime is restored", () => dho.LifetimeStart == 666 && dho.LifetimeEnd == 999);
}
+ [Test]
+ public void TestStateChangeBeforeLoadComplete()
+ {
+ TestDrawableHitObject dho = null;
+ AddStep("Add DHO and apply result", () =>
+ {
+ Child = dho = new TestDrawableHitObject(new HitObject { StartTime = Time.Current });
+ dho.MissForcefully();
+ });
+ AddAssert("DHO state is correct", () => dho.State.Value == ArmedState.Miss);
+ }
+
private class TestDrawableHitObject : DrawableHitObject
{
public const double INITIAL_LIFETIME_OFFSET = 100;
@@ -141,6 +155,19 @@ namespace osu.Game.Tests.Gameplay
if (SetLifetimeStartOnApply)
LifetimeStart = LIFETIME_ON_APPLY;
}
+
+ public void MissForcefully() => ApplyResult(r => r.Type = HitResult.Miss);
+
+ protected override void UpdateHitStateTransforms(ArmedState state)
+ {
+ if (state != ArmedState.Miss)
+ {
+ base.UpdateHitStateTransforms(state);
+ return;
+ }
+
+ this.FadeOut(1000);
+ }
}
private class TestLifetimeEntry : HitObjectLifetimeEntry
diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs
index 0983b806e2..07ec86b0e7 100644
--- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs
+++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs
@@ -24,6 +24,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
AddRepeatStep("add some users", () => Client.AddUser(new User { Id = id++ }), 5);
checkPlayingUserCount(0);
+ AddAssert("playlist item is available", () => Client.CurrentMatchPlayingItem.Value != null);
+
changeState(3, MultiplayerUserState.WaitingForLoad);
checkPlayingUserCount(3);
@@ -41,6 +43,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
AddStep("leave room", () => Client.LeaveRoom());
checkPlayingUserCount(0);
+
+ AddAssert("playlist item is null", () => Client.CurrentMatchPlayingItem.Value == null);
}
[Test]
diff --git a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs
index 2236f85b92..cc8503589d 100644
--- a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs
+++ b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs
@@ -8,6 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Logging;
+using osu.Framework.Testing;
using osu.Game.Graphics.Sprites;
using osu.Game.Online;
using osuTK;
@@ -15,6 +16,7 @@ using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Components
{
+ [HeadlessTest]
public class TestScenePollingComponent : OsuTestScene
{
private Container pollBox;
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
new file mode 100644
index 0000000000..299bbacf08
--- /dev/null
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
@@ -0,0 +1,168 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using System.Linq;
+using NUnit.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Bindables;
+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.Components;
+using osu.Game.Tests.Beatmaps;
+using osu.Game.Users;
+using osuTK;
+
+namespace osu.Game.Tests.Visual.Multiplayer
+{
+ public class TestSceneDrawableRoom : OsuTestScene
+ {
+ [Cached]
+ private readonly Bindable selectedRoom = new Bindable();
+
+ [Cached]
+ protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
+
+ [Test]
+ public void TestMultipleStatuses()
+ {
+ AddStep("create rooms", () =>
+ {
+ Child = new FillFlowContainer
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.9f),
+ Spacing = new Vector2(10),
+ Children = new Drawable[]
+ {
+ createDrawableRoom(new Room
+ {
+ Name = { Value = "Flyte's Trash Playlist" },
+ Status = { Value = new RoomStatusOpen() },
+ EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
+ Playlist =
+ {
+ new PlaylistItem
+ {
+ Beatmap =
+ {
+ Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
+ {
+ BeatmapInfo =
+ {
+ StarDifficulty = 2.5
+ }
+ }.BeatmapInfo,
+ }
+ }
+ }
+ }),
+ createDrawableRoom(new Room
+ {
+ Name = { Value = "Room 2" },
+ Status = { Value = new RoomStatusPlaying() },
+ EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
+ Playlist =
+ {
+ new PlaylistItem
+ {
+ Beatmap =
+ {
+ Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
+ {
+ BeatmapInfo =
+ {
+ StarDifficulty = 2.5
+ }
+ }.BeatmapInfo,
+ }
+ },
+ new PlaylistItem
+ {
+ Beatmap =
+ {
+ Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
+ {
+ BeatmapInfo =
+ {
+ StarDifficulty = 4.5
+ }
+ }.BeatmapInfo,
+ }
+ }
+ }
+ }),
+ createDrawableRoom(new Room
+ {
+ Name = { Value = "Room 3" },
+ Status = { Value = new RoomStatusEnded() },
+ EndDate = { Value = DateTimeOffset.Now },
+ }),
+ createDrawableRoom(new Room
+ {
+ Name = { Value = "Room 4 (realtime)" },
+ Status = { Value = new RoomStatusOpen() },
+ Category = { Value = RoomCategory.Realtime },
+ }),
+ createDrawableRoom(new Room
+ {
+ Name = { Value = "Room 4 (spotlight)" },
+ Status = { Value = new RoomStatusOpen() },
+ Category = { Value = RoomCategory.Spotlight },
+ }),
+ }
+ };
+ });
+ }
+
+ [Test]
+ public void TestEnableAndDisablePassword()
+ {
+ DrawableRoom drawableRoom = null;
+ Room room = null;
+
+ AddStep("create room", () => Child = drawableRoom = createDrawableRoom(room = new Room
+ {
+ Name = { Value = "Room with password" },
+ Status = { Value = new RoomStatusOpen() },
+ Category = { Value = RoomCategory.Realtime },
+ }));
+
+ AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha));
+
+ AddStep("set password", () => room.Password.Value = "password");
+ AddAssert("password icon visible", () => Precision.AlmostEquals(1, drawableRoom.ChildrenOfType().Single().Alpha));
+
+ AddStep("unset password", () => room.Password.Value = string.Empty);
+ AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha));
+ }
+
+ private DrawableRoom createDrawableRoom(Room room)
+ {
+ room.Host.Value ??= new User { Username = "peppy", Id = 2 };
+
+ if (room.RecentParticipants.Count == 0)
+ {
+ room.RecentParticipants.AddRange(Enumerable.Range(0, 20).Select(i => new User
+ {
+ Id = i,
+ Username = $"User {i}"
+ }));
+ }
+
+ var drawableRoom = new DrawableRoom(room) { MatchingFilter = true };
+ drawableRoom.Action = () => drawableRoom.State = drawableRoom.State == SelectionState.Selected ? SelectionState.NotSelected : SelectionState.Selected;
+
+ return drawableRoom;
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
index dfb78a235b..93bdbb79f4 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
@@ -14,7 +14,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics.Containers;
using osu.Game.Online.Rooms;
-using osu.Game.Overlays;
+using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
@@ -215,7 +215,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
assertDownloadButtonVisible(false);
void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}",
- () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0));
+ () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0));
}
[Test]
@@ -229,7 +229,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
createPlaylist(byOnlineId, byChecksum);
- AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent));
+ AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent));
}
[Test]
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs
deleted file mode 100644
index 471d0b6c98..0000000000
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System;
-using NUnit.Framework;
-using osu.Framework.Graphics;
-using osu.Game.Online.Rooms;
-using osu.Game.Online.Rooms.RoomStatuses;
-using osu.Game.Screens.OnlinePlay.Lounge.Components;
-using osu.Game.Tests.Visual.OnlinePlay;
-using osu.Game.Users;
-
-namespace osu.Game.Tests.Visual.Multiplayer
-{
- public class TestSceneLoungeRoomInfo : OnlinePlayTestScene
- {
- [SetUp]
- public new void Setup() => Schedule(() =>
- {
- SelectedRoom.Value = new Room();
-
- Child = new RoomInfo
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- Width = 500
- };
- });
-
- [Test]
- public void TestNonSelectedRoom()
- {
- AddStep("set null room", () => SelectedRoom.Value.RoomID.Value = null);
- }
-
- [Test]
- public void TestOpenRoom()
- {
- AddStep("set open room", () =>
- {
- SelectedRoom.Value.RoomID.Value = 0;
- SelectedRoom.Value.Name.Value = "Room 0";
- SelectedRoom.Value.Host.Value = new User { Username = "peppy", Id = 2 };
- SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMonths(1);
- SelectedRoom.Value.Status.Value = new RoomStatusOpen();
- });
- }
- }
-}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs
index 3118a23fd5..65b1d6d53a 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs
@@ -97,11 +97,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
TeamID = 1,
};
- SpectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId);
- SpectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId);
+ SpectatorClient.StartPlay(player1.UserID, importedBeatmapId);
+ SpectatorClient.StartPlay(player2.UserID, importedBeatmapId);
- playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID));
- playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID));
+ playingUsers.Add(player1);
+ playingUsers.Add(player2);
});
loadSpectateScreen();
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index cd3c50cf14..0ffa5209e3 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -423,10 +423,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createRoom(Func room)
{
- AddStep("open room", () =>
- {
- multiplayerScreen.OpenNewRoom(room());
- });
+ AddUntilStep("wait for lounge", () => multiplayerScreen.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().Open(room()));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs
index 0997de478b..3317ddc767 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs
@@ -12,6 +12,7 @@ using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Configuration;
using osu.Game.Online.API;
+using osu.Game.Online.Multiplayer;
using osu.Game.Online.Spectator;
using osu.Game.Replays.Legacy;
using osu.Game.Rulesets.Osu.Scoring;
@@ -51,12 +52,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
OsuScoreProcessor scoreProcessor;
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
- var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
+ var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
+ var multiplayerUsers = new List();
foreach (var user in users)
{
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
- OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true);
+ multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true));
}
Children = new Drawable[]
@@ -64,9 +66,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
scoreProcessor = new OsuScoreProcessor(),
};
- scoreProcessor.ApplyBeatmap(playable);
+ scoreProcessor.ApplyBeatmap(playableBeatmap);
- LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, Client.Room?.Users.ToArray())
+ LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, multiplayerUsers.ToArray())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs
index 274c9ea4b2..dfaf2f1dc3 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs
@@ -8,6 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Online.API;
+using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu.Scoring;
@@ -55,7 +56,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
OsuScoreProcessor scoreProcessor;
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
- var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
+ var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
+ var multiplayerUsers = new List();
foreach (var user in users)
{
@@ -66,6 +68,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
TeamID = RNG.Next(0, 2)
};
+
+ multiplayerUsers.Add(roomUser);
}
Children = new Drawable[]
@@ -73,9 +77,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
scoreProcessor = new OsuScoreProcessor(),
};
- scoreProcessor.ApplyBeatmap(playable);
+ scoreProcessor.ApplyBeatmap(playableBeatmap);
- LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, Client.Room?.Users.ToArray())
+ LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, multiplayerUsers.ToArray())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs
index 6526f7eea7..a3e6c8de3b 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs
@@ -155,6 +155,42 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("second user crown visible", () => this.ChildrenOfType().ElementAt(1).ChildrenOfType().First().Alpha == 1);
}
+ [Test]
+ public void TestKickButtonOnlyPresentWhenHost()
+ {
+ AddStep("add user", () => Client.AddUser(new User
+ {
+ Id = 3,
+ Username = "Second",
+ CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
+ }));
+
+ AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 1);
+
+ AddStep("make second user host", () => Client.TransferHost(3));
+
+ AddUntilStep("kick buttons not visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 0);
+
+ AddStep("make local user host again", () => Client.TransferHost(API.LocalUser.Value.Id));
+
+ AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 1);
+ }
+
+ [Test]
+ public void TestKickButtonKicks()
+ {
+ AddStep("add user", () => Client.AddUser(new User
+ {
+ Id = 3,
+ Username = "Second",
+ CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
+ }));
+
+ AddStep("kick second user", () => this.ChildrenOfType().Single(d => d.IsPresent).TriggerClick());
+
+ AddAssert("second user kicked", () => Client.Room?.Users.Single().UserID == API.LocalUser.Value.Id);
+ }
+
[Test]
public void TestManyUsers()
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs
new file mode 100644
index 0000000000..9e03743e8d
--- /dev/null
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs
@@ -0,0 +1,95 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Framework.Graphics;
+using osu.Game.Screens.OnlinePlay.Lounge.Components;
+using osu.Game.Users;
+
+namespace osu.Game.Tests.Visual.Multiplayer
+{
+ public class TestSceneRankRangePill : MultiplayerTestScene
+ {
+ [SetUp]
+ public new void Setup() => Schedule(() =>
+ {
+ Child = new RankRangePill
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre
+ };
+ });
+
+ [Test]
+ public void TestSingleUser()
+ {
+ AddStep("add user", () =>
+ {
+ Client.AddUser(new User
+ {
+ Id = 2,
+ Statistics = { GlobalRank = 1234 }
+ });
+
+ // Remove the local user so only the one above is displayed.
+ Client.RemoveUser(API.LocalUser.Value);
+ });
+ }
+
+ [Test]
+ public void TestMultipleUsers()
+ {
+ AddStep("add users", () =>
+ {
+ Client.AddUser(new User
+ {
+ Id = 2,
+ Statistics = { GlobalRank = 1234 }
+ });
+
+ Client.AddUser(new User
+ {
+ Id = 3,
+ Statistics = { GlobalRank = 3333 }
+ });
+
+ Client.AddUser(new User
+ {
+ Id = 4,
+ Statistics = { GlobalRank = 4321 }
+ });
+
+ // Remove the local user so only the ones above are displayed.
+ Client.RemoveUser(API.LocalUser.Value);
+ });
+ }
+
+ [TestCase(1, 10)]
+ [TestCase(10, 100)]
+ [TestCase(100, 1000)]
+ [TestCase(1000, 10000)]
+ [TestCase(10000, 100000)]
+ [TestCase(100000, 1000000)]
+ [TestCase(1000000, 10000000)]
+ public void TestRange(int min, int max)
+ {
+ AddStep("add users", () =>
+ {
+ Client.AddUser(new User
+ {
+ Id = 2,
+ Statistics = { GlobalRank = min }
+ });
+
+ Client.AddUser(new User
+ {
+ Id = 3,
+ Statistics = { GlobalRank = max }
+ });
+
+ // Remove the local user so only the ones above are displayed.
+ Client.RemoveUser(API.LocalUser.Value);
+ });
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs
new file mode 100644
index 0000000000..50ec2bf3ac
--- /dev/null
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRecentParticipantsList.cs
@@ -0,0 +1,143 @@
+// 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 NUnit.Framework;
+using osu.Framework.Graphics;
+using osu.Framework.Testing;
+using osu.Game.Online.Rooms;
+using osu.Game.Screens.OnlinePlay.Lounge.Components;
+using osu.Game.Tests.Visual.OnlinePlay;
+using osu.Game.Users;
+using osu.Game.Users.Drawables;
+
+namespace osu.Game.Tests.Visual.Multiplayer
+{
+ public class TestSceneRecentParticipantsList : OnlinePlayTestScene
+ {
+ private RecentParticipantsList list;
+
+ [SetUp]
+ public new void Setup() => Schedule(() =>
+ {
+ SelectedRoom.Value = new Room { Name = { Value = "test room" } };
+
+ Child = list = new RecentParticipantsList
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ NumberOfCircles = 4
+ };
+ });
+
+ [Test]
+ public void TestCircleCountNearLimit()
+ {
+ AddStep("add 8 users", () =>
+ {
+ for (int i = 0; i < 8; i++)
+ addUser(i);
+ });
+
+ AddStep("set 8 circles", () => list.NumberOfCircles = 8);
+ AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0);
+
+ AddStep("add one more user", () => addUser(9));
+ AddAssert("2 hidden users", () => list.ChildrenOfType().Single().Count == 2);
+
+ AddStep("remove first user", () => removeUserAt(0));
+ AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0);
+
+ AddStep("add one more user", () => addUser(9));
+ AddAssert("2 hidden users", () => list.ChildrenOfType().Single().Count == 2);
+
+ AddStep("remove last user", () => removeUserAt(8));
+ AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0);
+ }
+
+ [Test]
+ public void TestHiddenUsersBecomeDisplayed()
+ {
+ AddStep("add 8 users", () =>
+ {
+ for (int i = 0; i < 8; i++)
+ addUser(i);
+ });
+
+ AddStep("set 3 circles", () => list.NumberOfCircles = 3);
+
+ for (int i = 0; i < 8; i++)
+ {
+ AddStep("remove user", () => removeUserAt(0));
+ int remainingUsers = 7 - i;
+
+ int displayedUsers = remainingUsers > 3 ? 2 : remainingUsers;
+ AddAssert($"{displayedUsers} avatars displayed", () => list.ChildrenOfType().Count() == displayedUsers);
+ }
+ }
+
+ [Test]
+ public void TestCircleCount()
+ {
+ AddStep("add 50 users", () =>
+ {
+ for (int i = 0; i < 50; i++)
+ addUser(i);
+ });
+
+ AddStep("set 3 circles", () => list.NumberOfCircles = 3);
+ AddAssert("2 users displayed", () => list.ChildrenOfType().Count() == 2);
+ AddAssert("48 hidden users", () => list.ChildrenOfType().Single().Count == 48);
+
+ AddStep("set 10 circles", () => list.NumberOfCircles = 10);
+ AddAssert("9 users displayed", () => list.ChildrenOfType().Count() == 9);
+ AddAssert("41 hidden users", () => list.ChildrenOfType().Single().Count == 41);
+ }
+
+ [Test]
+ public void TestAddAndRemoveUsers()
+ {
+ AddStep("add 50 users", () =>
+ {
+ for (int i = 0; i < 50; i++)
+ addUser(i);
+ });
+
+ AddStep("remove from start", () => removeUserAt(0));
+ AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3);
+ AddAssert("46 hidden users", () => list.ChildrenOfType().Single().Count == 46);
+
+ AddStep("remove from end", () => removeUserAt(SelectedRoom.Value.RecentParticipants.Count - 1));
+ AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3);
+ AddAssert("45 hidden users", () => list.ChildrenOfType().Single().Count == 45);
+
+ AddRepeatStep("remove 45 users", () => removeUserAt(0), 45);
+ AddAssert("3 circles displayed", () => list.ChildrenOfType().Count() == 3);
+ AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0);
+ AddAssert("hidden users bubble hidden", () => list.ChildrenOfType().Single().Alpha < 0.5f);
+
+ AddStep("remove another user", () => removeUserAt(0));
+ AddAssert("2 circles displayed", () => list.ChildrenOfType().Count() == 2);
+ AddAssert("0 hidden users", () => list.ChildrenOfType().Single().Count == 0);
+
+ AddRepeatStep("remove the remaining two users", () => removeUserAt(0), 2);
+ AddAssert("0 circles displayed", () => !list.ChildrenOfType().Any());
+ }
+
+ private void addUser(int id)
+ {
+ SelectedRoom.Value.RecentParticipants.Add(new User
+ {
+ Id = id,
+ Username = $"User {id}"
+ });
+ SelectedRoom.Value.ParticipantCount.Value++;
+ }
+
+ private void removeUserAt(int index)
+ {
+ SelectedRoom.Value.RecentParticipants.RemoveAt(index);
+ SelectedRoom.Value.ParticipantCount.Value--;
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs
deleted file mode 100644
index 8c4133418c..0000000000
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System;
-using System.Linq;
-using NUnit.Framework;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Testing;
-using osu.Framework.Utils;
-using osu.Game.Online.Rooms;
-using osu.Game.Online.Rooms.RoomStatuses;
-using osu.Game.Screens.OnlinePlay.Lounge.Components;
-
-namespace osu.Game.Tests.Visual.Multiplayer
-{
- public class TestSceneRoomStatus : OsuTestScene
- {
- [Test]
- public void TestMultipleStatuses()
- {
- AddStep("create rooms", () =>
- {
- Child = new FillFlowContainer
- {
- RelativeSizeAxes = Axes.Both,
- Width = 0.5f,
- Children = new Drawable[]
- {
- new DrawableRoom(new Room
- {
- Name = { Value = "Open - ending in 1 day" },
- Status = { Value = new RoomStatusOpen() },
- EndDate = { Value = DateTimeOffset.Now.AddDays(1) }
- }) { MatchingFilter = true },
- new DrawableRoom(new Room
- {
- Name = { Value = "Playing - ending in 1 day" },
- Status = { Value = new RoomStatusPlaying() },
- EndDate = { Value = DateTimeOffset.Now.AddDays(1) }
- }) { MatchingFilter = true },
- new DrawableRoom(new Room
- {
- Name = { Value = "Ended" },
- Status = { Value = new RoomStatusEnded() },
- EndDate = { Value = DateTimeOffset.Now }
- }) { MatchingFilter = true },
- new DrawableRoom(new Room
- {
- Name = { Value = "Open" },
- Status = { Value = new RoomStatusOpen() },
- Category = { Value = RoomCategory.Realtime }
- }) { MatchingFilter = true },
- }
- };
- });
- }
-
- [Test]
- public void TestEnableAndDisablePassword()
- {
- DrawableRoom drawableRoom = null;
- Room room = null;
-
- AddStep("create room", () => Child = drawableRoom = new DrawableRoom(room = new Room
- {
- Name = { Value = "Room with password" },
- Status = { Value = new RoomStatusOpen() },
- Category = { Value = RoomCategory.Realtime },
- }) { MatchingFilter = true });
-
- AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha));
-
- AddStep("set password", () => room.Password.Value = "password");
- AddAssert("password icon visible", () => Precision.AlmostEquals(1, drawableRoom.ChildrenOfType().Single().Alpha));
-
- AddStep("unset password", () => room.Password.Value = string.Empty);
- AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha));
- }
- }
-}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
index e19665497d..a8fda19c60 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
@@ -17,6 +17,7 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens;
using osu.Game.Screens.OnlinePlay.Components;
+using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
@@ -150,10 +151,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createRoom(Func room)
{
- AddStep("open room", () =>
- {
- multiplayerScreen.OpenNewRoom(room());
- });
+ AddStep("open room", () => multiplayerScreen.ChildrenOfType().Single().Open(room()));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs
similarity index 98%
rename from osu.Game.Tests/Visual/TestSceneOsuGame.cs
rename to osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs
index c52d846a68..26641214b1 100644
--- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs
@@ -10,7 +10,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Textures;
using osu.Framework.Platform;
-using osu.Framework.Testing;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
@@ -30,10 +29,9 @@ using osu.Game.Skinning;
using osu.Game.Utils;
using osuTK.Graphics;
-namespace osu.Game.Tests.Visual
+namespace osu.Game.Tests.Visual.Navigation
{
[TestFixture]
- [HeadlessTest]
public class TestSceneOsuGame : OsuTestScene
{
private IReadOnlyList requiredGameDependencies => new[]
diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
index 7188a4e57f..3c65f46c79 100644
--- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
@@ -16,6 +16,7 @@ using osu.Game.Overlays.Toolbar;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.OnlinePlay.Components;
+using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
@@ -316,7 +317,8 @@ namespace osu.Game.Tests.Visual.Navigation
PushAndConfirm(() => multiplayer = new TestMultiplayer());
- AddStep("open room", () => multiplayer.OpenNewRoom());
+ AddUntilStep("wait for lounge", () => multiplayer.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayer.ChildrenOfType().Single().Open());
AddStep("press back button", () => Game.ChildrenOfType().First().Action());
AddWaitStep("wait two frames", 2);
}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs
index 8818ac75b1..8f000afb91 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using Humanizer;
using NUnit.Framework;
+using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
@@ -95,9 +96,11 @@ namespace osu.Game.Tests.Visual.Online
AddAssert(@"no stream selected", () => changelog.Header.Streams.Current.Value == null);
}
- [Test]
- public void ShowWithBuild()
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ShowWithBuild(bool isSupporter)
{
+ AddStep(@"set supporter", () => dummyAPI.LocalUser.Value.IsSupporter = isSupporter);
showBuild(() => new APIChangelogBuild
{
Version = "2018.712.0",
@@ -155,6 +158,8 @@ namespace osu.Game.Tests.Visual.Online
AddUntilStep(@"wait for streams", () => changelog.Streams?.Count > 0);
AddAssert(@"correct build displayed", () => changelog.Current.Value.Version == "2018.712.0");
AddAssert(@"correct stream selected", () => changelog.Header.Streams.Current.Value.Id == 5);
+ AddUntilStep(@"wait for content load", () => changelog.ChildrenOfType().Any());
+ AddAssert(@"supporter promo showed", () => changelog.ChildrenOfType().First().Alpha == (isSupporter ? 0 : 1));
}
[Test]
diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs
new file mode 100644
index 0000000000..22220a7d9c
--- /dev/null
+++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs
@@ -0,0 +1,35 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Overlays;
+using osu.Game.Overlays.Changelog;
+
+namespace osu.Game.Tests.Visual.Online
+{
+ public class TestSceneChangelogSupporterPromo : OsuTestScene
+ {
+ [Cached]
+ private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
+
+ public TestSceneChangelogSupporterPromo()
+ {
+ Child = new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = colourProvider.Background4,
+ },
+ new ChangelogSupporterPromo(),
+ }
+ };
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs
index 53693d1b70..3b43f8485a 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs
@@ -1,6 +1,8 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Collections.Generic;
+using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -68,13 +70,40 @@ namespace osu.Game.Tests.Visual.UserInterface
);
}
- private class MyContextMenuContainer : Container, IHasContextMenu
+ private static MenuItem[] makeMenu()
{
- public MenuItem[] ContextMenuItems => new MenuItem[]
+ return new MenuItem[]
{
new OsuMenuItem(@"Some option"),
new OsuMenuItem(@"Highlighted option", MenuItemType.Highlighted),
new OsuMenuItem(@"Another option"),
+ new OsuMenuItem(@"Nested option >")
+ {
+ Items = new MenuItem[]
+ {
+ new OsuMenuItem(@"Sub-One"),
+ new OsuMenuItem(@"Sub-Two"),
+ new OsuMenuItem(@"Sub-Three"),
+ new OsuMenuItem(@"Sub-Nested option >")
+ {
+ Items = new MenuItem[]
+ {
+ new OsuMenuItem(@"Double Sub-One"),
+ new OsuMenuItem(@"Double Sub-Two"),
+ new OsuMenuItem(@"Double Sub-Three"),
+ new OsuMenuItem(@"Sub-Sub-Nested option >")
+ {
+ Items = new MenuItem[]
+ {
+ new OsuMenuItem(@"Too Deep One"),
+ new OsuMenuItem(@"Too Deep Two"),
+ new OsuMenuItem(@"Too Deep Three"),
+ }
+ }
+ }
+ }
+ }
+ },
new OsuMenuItem(@"Choose me please"),
new OsuMenuItem(@"And me too"),
new OsuMenuItem(@"Trying to fill"),
@@ -82,17 +111,29 @@ namespace osu.Game.Tests.Visual.UserInterface
};
}
+ private class MyContextMenuContainer : Container, IHasContextMenu
+ {
+ public MenuItem[] ContextMenuItems => makeMenu();
+ }
+
private class AnotherContextMenuContainer : Container, IHasContextMenu
{
- public MenuItem[] ContextMenuItems => new MenuItem[]
+ public MenuItem[] ContextMenuItems
{
- new OsuMenuItem(@"Simple option"),
- new OsuMenuItem(@"Simple very very long option"),
- new OsuMenuItem(@"Change width", MenuItemType.Highlighted, () => this.ResizeWidthTo(Width * 2, 100, Easing.OutQuint)),
- new OsuMenuItem(@"Change height", MenuItemType.Highlighted, () => this.ResizeHeightTo(Height * 2, 100, Easing.OutQuint)),
- new OsuMenuItem(@"Change width back", MenuItemType.Destructive, () => this.ResizeWidthTo(Width / 2, 100, Easing.OutQuint)),
- new OsuMenuItem(@"Change height back", MenuItemType.Destructive, () => this.ResizeHeightTo(Height / 2, 100, Easing.OutQuint)),
- };
+ get
+ {
+ List
-
-
+
+
@@ -93,7 +93,7 @@
-
+