diff --git a/osu.Android.props b/osu.Android.props
index 5688fd8cc4..c28085557e 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs
index a36f07ff7b..496d495b43 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs
@@ -17,11 +17,11 @@ using osu.Framework.Testing.Input;
using osu.Framework.Utils;
using osu.Game.Audio;
using osu.Game.Configuration;
-using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Skinning;
using osu.Game.Rulesets.Osu.UI.Cursor;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
+using osu.Game.Tests.Gameplay;
using osuTK;
namespace osu.Game.Rulesets.Osu.Tests
@@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Tests
public TestSceneGameplayCursor()
{
var ruleset = new OsuRuleset();
- gameplayState = new GameplayState(CreateBeatmap(ruleset.RulesetInfo), ruleset, Array.Empty());
+ gameplayState = TestGameplayState.Create(ruleset);
AddStep("change background colour", () =>
{
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs
index 53364b6d89..e9aa85f4ce 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs
@@ -6,7 +6,6 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
-using osu.Framework.Graphics.Containers;
using osu.Framework.Lists;
using osu.Framework.Testing;
using osu.Framework.Timing;
@@ -22,7 +21,6 @@ using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osu.Game.Skinning;
using osu.Game.Storyboards;
-using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual.Gameplay
{
@@ -33,18 +31,6 @@ namespace osu.Game.Tests.Visual.Gameplay
[Resolved]
private SkinManager skinManager { get; set; }
- [Cached]
- private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset());
-
- [Cached(typeof(HealthProcessor))]
- private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
-
- [Cached]
- private GameplayState gameplayState = new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset());
-
- [Cached]
- private readonly GameplayClock gameplayClock = new GameplayClock(new FramedClock());
-
protected override bool HasCustomSteps => true;
[Test]
@@ -81,11 +67,19 @@ namespace osu.Game.Tests.Visual.Gameplay
if (expectedComponentsContainer == null)
return false;
- var expectedComponentsAdjustmentContainer = new Container
+ var expectedComponentsAdjustmentContainer = new DependencyProvidingContainer
{
Position = actualComponentsContainer.Parent.ToSpaceOfOtherDrawable(actualComponentsContainer.DrawPosition, Content),
Size = actualComponentsContainer.DrawSize,
Child = expectedComponentsContainer,
+ // proxy the same required dependencies that `actualComponentsContainer` is using.
+ CachedDependencies = new (Type, object)[]
+ {
+ (typeof(ScoreProcessor), actualComponentsContainer.Dependencies.Get()),
+ (typeof(HealthProcessor), actualComponentsContainer.Dependencies.Get()),
+ (typeof(GameplayState), actualComponentsContainer.Dependencies.Get()),
+ (typeof(GameplayClock), actualComponentsContainer.Dependencies.Get())
+ },
};
Add(expectedComponentsAdjustmentContainer);
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs
index 2d12645811..83c557ee51 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs
@@ -15,7 +15,7 @@ using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
-using osu.Game.Tests.Beatmaps;
+using osu.Game.Tests.Gameplay;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
@@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
[Cached]
- private GameplayState gameplayState = new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset());
+ private GameplayState gameplayState = TestGameplayState.Create(new OsuRuleset());
[Cached]
private readonly GameplayClock gameplayClock = new GameplayClock(new FramedClock());
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs
index 81763564fa..8362739d3b 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs
@@ -1,7 +1,6 @@
// 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.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@@ -14,16 +13,15 @@ using osu.Framework.Input.Events;
using osu.Framework.Input.StateChanges;
using osu.Framework.Testing;
using osu.Framework.Threading;
-using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites;
using osu.Game.Replays;
using osu.Game.Rulesets;
-using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Screens.Play;
+using osu.Game.Tests.Gameplay;
using osu.Game.Tests.Mods;
using osuTK;
using osuTK.Graphics;
@@ -41,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private TestReplayRecorder recorder;
[Cached]
- private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty());
+ private GameplayState gameplayState = TestGameplayState.Create(new OsuRuleset());
[SetUpSteps]
public void SetUpSteps()
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs
index 8150252d45..5f838b8813 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs
@@ -11,7 +11,7 @@ using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Skinning.Editor;
-using osu.Game.Tests.Beatmaps;
+using osu.Game.Tests.Gameplay;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
@@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
[Cached]
- private GameplayState gameplayState = new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset());
+ private GameplayState gameplayState = TestGameplayState.Create(new OsuRuleset());
[Cached]
private readonly GameplayClock gameplayClock = new GameplayClock(new FramedClock());
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs
index ac5e408d90..5f2d9ee9e8 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs
@@ -16,7 +16,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
-using osu.Game.Tests.Beatmaps;
+using osu.Game.Tests.Gameplay;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
@@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
[Cached]
- private GameplayState gameplayState = new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset());
+ private GameplayState gameplayState = TestGameplayState.Create(new OsuRuleset());
[Cached]
private readonly GameplayClock gameplayClock = new GameplayClock(new FramedClock());
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs
index 8b420cebc8..b5cdd61ee5 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs
@@ -18,8 +18,8 @@ using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Screens;
using osu.Game.Screens.Play;
-using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Beatmaps.IO;
+using osu.Game.Tests.Gameplay;
using osu.Game.Tests.Visual.Multiplayer;
using osu.Game.Tests.Visual.Spectator;
using osuTK;
@@ -259,12 +259,15 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestFinalFramesPurgedBeforeEndingPlay()
{
- AddStep("begin playing", () => spectatorClient.BeginPlaying(new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset()), new Score()));
+ AddStep("begin playing", () => spectatorClient.BeginPlaying(TestGameplayState.Create(new OsuRuleset()), new Score()));
AddStep("send frames and finish play", () =>
{
spectatorClient.HandleFrame(new OsuReplayFrame(1000, Vector2.Zero));
- spectatorClient.EndPlaying(new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset()) { HasPassed = true });
+
+ var completedGameplayState = TestGameplayState.Create(new OsuRuleset());
+ completedGameplayState.HasPassed = true;
+ spectatorClient.EndPlaying(completedGameplayState);
});
// We can't access API because we're an "online" test.
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs
index f8748922cf..2d2e05c4c9 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs
@@ -20,13 +20,13 @@ using osu.Game.Online.Spectator;
using osu.Game.Replays;
using osu.Game.Replays.Legacy;
using osu.Game.Rulesets;
-using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Replays.Types;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Screens.Play;
+using osu.Game.Tests.Gameplay;
using osu.Game.Tests.Mods;
using osu.Game.Tests.Visual.Spectator;
using osuTK;
@@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.Gameplay
CachedDependencies = new[]
{
(typeof(SpectatorClient), (object)(spectatorClient = new TestSpectatorClient())),
- (typeof(GameplayState), new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty()))
+ (typeof(GameplayState), TestGameplayState.Create(new OsuRuleset()))
},
Children = new Drawable[]
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
index 7d010592ae..3172a68b81 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
@@ -124,13 +124,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
Status = { Value = new RoomStatusOpen() },
Category = { Value = RoomCategory.Spotlight },
}),
+ createLoungeRoom(new Room
+ {
+ Name = { Value = "Featured artist room" },
+ Status = { Value = new RoomStatusOpen() },
+ Category = { Value = RoomCategory.FeaturedArtist },
+ }),
}
};
});
- AddUntilStep("wait for panel load", () => rooms.Count == 5);
+ AddUntilStep("wait for panel load", () => rooms.Count == 6);
AddUntilStep("correct status text", () => rooms.ChildrenOfType().Count(s => s.Text.ToString().StartsWith("Currently playing", StringComparison.Ordinal)) == 2);
- AddUntilStep("correct status text", () => rooms.ChildrenOfType().Count(s => s.Text.ToString().StartsWith("Ready to play", StringComparison.Ordinal)) == 3);
+ AddUntilStep("correct status text", () => rooms.ChildrenOfType().Count(s => s.Text.ToString().StartsWith("Ready to play", StringComparison.Ordinal)) == 4);
}
[Test]
diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs
index ed6e2bb2c0..3151279b7c 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs
@@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Online
channelManager.CurrentChannel.Value = joinedChannel;
});
AddAssert("Overlay is visible", () => chatOverlay.State.Value == Visibility.Visible);
- AddUntilStep("Channel is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -150,10 +150,14 @@ namespace osu.Game.Tests.Visual.Online
public void TestChatHeight()
{
BindableFloat configChatHeight = new BindableFloat();
- config.BindWith(OsuSetting.ChatDisplayHeight, configChatHeight);
+
float newHeight = 0;
- AddStep("Reset config chat height", () => configChatHeight.SetDefault());
+ AddStep("Reset config chat height", () =>
+ {
+ config.BindWith(OsuSetting.ChatDisplayHeight, configChatHeight);
+ configChatHeight.SetDefault();
+ });
AddStep("Show overlay", () => chatOverlay.Show());
AddAssert("Overlay uses config height", () => chatOverlay.Height == configChatHeight.Default);
AddStep("Click top bar", () =>
@@ -177,7 +181,7 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("Listing is visible", () => listingIsVisible);
AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1));
AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1)));
- AddUntilStep("Channel 1 is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -186,7 +190,7 @@ namespace osu.Game.Tests.Visual.Online
AddStep("Show overlay", () => chatOverlay.Show());
AddAssert("Listing is visible", () => listingIsVisible);
AddStep("Search for 'number 2'", () => chatOverlayTextBox.Text = "number 2");
- AddUntilStep("Only channel 2 visibile", () =>
+ AddUntilStep("Only channel 2 visible", () =>
{
IEnumerable listingItems = chatOverlay.ChildrenOfType()
.Where(item => item.IsPresent);
@@ -276,7 +280,7 @@ namespace osu.Game.Tests.Visual.Online
});
});
AddStep("Highlight message", () => chatOverlay.HighlightMessage(message, testChannel1));
- AddUntilStep("Channel 1 is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -299,7 +303,7 @@ namespace osu.Game.Tests.Visual.Online
});
});
AddStep("Highlight message", () => chatOverlay.HighlightMessage(message, testChannel2));
- AddUntilStep("Channel 2 is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel2);
+ waitForChannel2Visible();
}
[Test]
@@ -323,7 +327,7 @@ namespace osu.Game.Tests.Visual.Online
});
AddStep("Leave channel 2", () => channelManager.LeaveChannel(testChannel2));
AddStep("Highlight message", () => chatOverlay.HighlightMessage(message, testChannel2));
- AddUntilStep("Channel 2 is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel2);
+ waitForChannel2Visible();
}
[Test]
@@ -343,7 +347,7 @@ namespace osu.Game.Tests.Visual.Online
});
});
AddStep("Highlight message", () => chatOverlay.HighlightMessage(message, testChannel1));
- AddUntilStep("Channel 1 is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -364,7 +368,7 @@ namespace osu.Game.Tests.Visual.Online
});
AddStep("Set null channel", () => channelManager.CurrentChannel.Value = null);
AddStep("Highlight message", () => chatOverlay.HighlightMessage(message, testChannel1));
- AddUntilStep("Channel 1 is visible", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -374,6 +378,7 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("TextBox is focused", () => InputManager.FocusedDrawable == chatOverlayTextBox);
AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1));
AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1)));
+ waitForChannel1Visible();
AddAssert("TextBox is focused", () => InputManager.FocusedDrawable == chatOverlayTextBox);
AddStep("Click drawable channel", () => clickDrawable(currentDrawableChannel));
AddAssert("TextBox is focused", () => InputManager.FocusedDrawable == chatOverlayTextBox);
@@ -411,11 +416,11 @@ namespace osu.Game.Tests.Visual.Online
AddStep("Finish channel 2 load", () => chatOverlay.GetSlowLoadingChannel(testChannel2).LoadEvent.Set());
AddAssert("Channel 2 loaded", () => chatOverlay.GetSlowLoadingChannel(testChannel2).IsLoaded);
- AddAssert("Channel 2 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel2);
+ waitForChannel2Visible();
AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1)));
AddAssert("Channel 1 loaded", () => chatOverlay.GetSlowLoadingChannel(testChannel1).IsLoaded);
- AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -426,13 +431,12 @@ namespace osu.Game.Tests.Visual.Online
channelManager.JoinChannel(testChannel1);
chatOverlay.Show();
});
- AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
-
+ waitForChannel1Visible();
AddStep("Press document close keys", () => InputManager.Keys(PlatformAction.DocumentClose));
AddAssert("Listing is visible", () => listingIsVisible);
AddStep("Press tab restore keys", () => InputManager.Keys(PlatformAction.TabRestore));
- AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
[Test]
@@ -443,8 +447,7 @@ namespace osu.Game.Tests.Visual.Online
channelManager.JoinChannel(testChannel1);
chatOverlay.Show();
});
- AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
-
+ waitForChannel1Visible();
AddStep("Press tab new keys", () => InputManager.Keys(PlatformAction.TabNew));
AddAssert("Listing is visible", () => listingIsVisible);
}
@@ -466,24 +469,29 @@ namespace osu.Game.Tests.Visual.Online
chatOverlay.Show();
});
- AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
+ AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext));
+ waitForChannel2Visible();
AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext));
- AddAssert("Channel 2 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel2);
+ AddUntilStep("PM Channel 1 displayed", () => channelIsVisible && currentDrawableChannel?.Channel == pmChannel1);
AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext));
- AddAssert("PM Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == pmChannel1);
+ AddUntilStep("PM Channel 2 displayed", () => channelIsVisible && currentDrawableChannel?.Channel == pmChannel2);
AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext));
- AddAssert("PM Channel 2 displayed", () => channelIsVisible && currentDrawableChannel.Channel == pmChannel2);
+ AddUntilStep("Announce channel displayed", () => channelIsVisible && currentDrawableChannel?.Channel == announceChannel);
AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext));
- AddAssert("Announce channel displayed", () => channelIsVisible && currentDrawableChannel.Channel == announceChannel);
-
- AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext));
- AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1);
+ waitForChannel1Visible();
}
+ private void waitForChannel1Visible() =>
+ AddUntilStep("Channel 1 is visible", () => channelIsVisible && currentDrawableChannel?.Channel == testChannel1);
+
+ private void waitForChannel2Visible() =>
+ AddUntilStep("Channel 2 is visible", () => channelIsVisible && currentDrawableChannel?.Channel == testChannel2);
+
private bool listingIsVisible =>
chatOverlay.ChildrenOfType().Single().State.Value == Visibility.Visible;
@@ -493,8 +501,9 @@ namespace osu.Game.Tests.Visual.Online
private bool channelIsVisible =>
!listingIsVisible && !loadingIsVisible;
+ [CanBeNull]
private DrawableChannel currentDrawableChannel =>
- chatOverlay.ChildrenOfType().Single();
+ chatOverlay.ChildrenOfType().SingleOrDefault();
private ChannelListItem getChannelListItem(Channel channel) =>
chatOverlay.ChildrenOfType().Single(item => item.Channel == channel);
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs
index 35281a85eb..1efe6d7380 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -13,6 +14,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.Objects;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking.Statistics;
using osu.Game.Rulesets.Osu.Objects;
@@ -114,10 +116,7 @@ namespace osu.Game.Tests.Visual.Ranking
throw new NotImplementedException();
}
- public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap)
- {
- throw new NotImplementedException();
- }
+ public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap);
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap)
{
@@ -151,6 +150,24 @@ namespace osu.Game.Tests.Visual.Ranking
}
}
};
+
+ private class TestBeatmapConverter : IBeatmapConverter
+ {
+#pragma warning disable CS0067 // The event is never used
+ public event Action> ObjectConverted;
+#pragma warning restore CS0067
+
+ public IBeatmap Beatmap { get; }
+
+ public TestBeatmapConverter(IBeatmap beatmap)
+ {
+ Beatmap = beatmap;
+ }
+
+ public bool CanConvert() => true;
+
+ public IBeatmap Convert(CancellationToken cancellationToken = default) => Beatmap.Clone();
+ }
}
private class TestRulesetAllStatsRequireHitEvents : TestRuleset
diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs
index afedf36cad..7fd94b57f3 100644
--- a/osu.Game/Graphics/OsuColour.cs
+++ b/osu.Game/Graphics/OsuColour.cs
@@ -4,6 +4,7 @@
using System;
using osu.Framework.Extensions.Color4Extensions;
using osu.Game.Beatmaps;
+using osu.Game.Online.Rooms;
using osu.Game.Overlays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
@@ -188,6 +189,24 @@ namespace osu.Game.Graphics
}
}
+ ///
+ /// Retrieves the main accent colour for a .
+ ///
+ public Color4? ForRoomCategory(RoomCategory roomCategory)
+ {
+ switch (roomCategory)
+ {
+ case RoomCategory.Spotlight:
+ return SpotlightColour;
+
+ case RoomCategory.FeaturedArtist:
+ return FeaturedArtistColour;
+
+ default:
+ return null;
+ }
+ }
+
///
/// Returns a foreground text colour that is supposed to contrast well with
/// the supplied .
@@ -360,5 +379,8 @@ namespace osu.Game.Graphics
public readonly Color4 ChatBlue = Color4Extensions.FromHex(@"17292e");
public readonly Color4 ContextMenuGray = Color4Extensions.FromHex(@"223034");
+
+ public Color4 SpotlightColour => Green2;
+ public Color4 FeaturedArtistColour => Blue2;
}
}
diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs
index ca9bf00b23..261724e315 100644
--- a/osu.Game/Online/HubClientConnector.cs
+++ b/osu.Game/Online/HubClientConnector.cs
@@ -20,6 +20,8 @@ namespace osu.Game.Online
{
public class HubClientConnector : IHubClientConnector
{
+ public const string SERVER_SHUTDOWN_MESSAGE = "Server is shutting down.";
+
///
/// Invoked whenever a new hub connection is built, to configure it before it's started.
///
@@ -64,20 +66,28 @@ namespace osu.Game.Online
this.preferMessagePack = preferMessagePack;
apiState.BindTo(api.State);
- apiState.BindValueChanged(state =>
- {
- switch (state.NewValue)
- {
- case APIState.Failing:
- case APIState.Offline:
- Task.Run(() => disconnect(true));
- break;
+ apiState.BindValueChanged(state => connectIfPossible(), true);
+ }
- case APIState.Online:
- Task.Run(connect);
- break;
- }
- }, true);
+ public void Reconnect()
+ {
+ Logger.Log($"{clientName} reconnecting...", LoggingTarget.Network);
+ Task.Run(connectIfPossible);
+ }
+
+ private void connectIfPossible()
+ {
+ switch (apiState.Value)
+ {
+ case APIState.Failing:
+ case APIState.Offline:
+ Task.Run(() => disconnect(true));
+ break;
+
+ case APIState.Online:
+ Task.Run(connect);
+ break;
+ }
}
private async Task connect()
diff --git a/osu.Game/Online/IHubClientConnector.cs b/osu.Game/Online/IHubClientConnector.cs
index d2ceb1f030..b168e4669f 100644
--- a/osu.Game/Online/IHubClientConnector.cs
+++ b/osu.Game/Online/IHubClientConnector.cs
@@ -30,5 +30,10 @@ namespace osu.Game.Online
/// Invoked whenever a new hub connection is built, to configure it before it's started.
///
public Action? ConfigureConnection { get; set; }
+
+ ///
+ /// Reconnect if already connected.
+ ///
+ void Reconnect();
}
}
diff --git a/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs b/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs
index 4729765084..cda313bd0a 100644
--- a/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs
+++ b/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs
@@ -25,12 +25,7 @@ namespace osu.Game.Online.Multiplayer
Debug.Assert(exception != null);
- string message = exception is HubException
- // HubExceptions arrive with additional message context added, but we want to display the human readable message:
- // "An unexpected error occurred invoking 'AddPlaylistItem' on the server.InvalidStateException: Can't enqueue more than 3 items at once."
- // We generally use the message field for a user-parseable error (eventually to be replaced), so drop the first part for now.
- ? exception.Message.Substring(exception.Message.IndexOf(':') + 1).Trim()
- : exception.Message;
+ string message = exception.GetHubExceptionMessage() ?? exception.Message;
Logger.Log(message, level: LogLevel.Important);
onError?.Invoke(exception);
@@ -40,5 +35,16 @@ namespace osu.Game.Online.Multiplayer
onSuccess?.Invoke();
}
});
+
+ public static string? GetHubExceptionMessage(this Exception exception)
+ {
+ if (exception is HubException hubException)
+ // HubExceptions arrive with additional message context added, but we want to display the human readable message:
+ // "An unexpected error occurred invoking 'AddPlaylistItem' on the server.InvalidStateException: Can't enqueue more than 3 items at once."
+ // We generally use the message field for a user-parseable error (eventually to be replaced), so drop the first part for now.
+ return hubException.Message.Substring(exception.Message.IndexOf(':') + 1).Trim();
+
+ return null;
+ }
}
}
diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
index 4dc23d8b85..a3423d4189 100644
--- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
@@ -3,10 +3,12 @@
#nullable enable
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Client;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -71,14 +73,23 @@ namespace osu.Game.Online.Multiplayer
}
}
- protected override Task JoinRoom(long roomId, string? password = null)
+ protected override async Task JoinRoom(long roomId, string? password = null)
{
if (!IsConnected.Value)
- return Task.FromCanceled(new CancellationToken(true));
+ throw new OperationCanceledException();
Debug.Assert(connection != null);
- return connection.InvokeAsync(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty);
+ try
+ {
+ return await connection.InvokeAsync(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty);
+ }
+ catch (HubException exception)
+ {
+ if (exception.GetHubExceptionMessage() == HubClientConnector.SERVER_SHUTDOWN_MESSAGE)
+ connector?.Reconnect();
+ throw;
+ }
}
protected override Task LeaveRoomInternal()
diff --git a/osu.Game/Online/Rooms/RoomCategory.cs b/osu.Game/Online/Rooms/RoomCategory.cs
index a1dcfa5fd9..bca4d78359 100644
--- a/osu.Game/Online/Rooms/RoomCategory.cs
+++ b/osu.Game/Online/Rooms/RoomCategory.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.ComponentModel;
+
namespace osu.Game.Online.Rooms
{
public enum RoomCategory
@@ -8,5 +10,8 @@ namespace osu.Game.Online.Rooms
// used for osu-web deserialization so names shouldn't be changed.
Normal,
Spotlight,
+
+ [Description("Featured Artist")]
+ FeaturedArtist,
}
}
diff --git a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs
index 4d6ca0b311..0f77f723db 100644
--- a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs
+++ b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs
@@ -5,10 +5,12 @@
using System.Diagnostics;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Client;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Online.API;
+using osu.Game.Online.Multiplayer;
namespace osu.Game.Online.Spectator
{
@@ -47,14 +49,23 @@ namespace osu.Game.Online.Spectator
}
}
- protected override Task BeginPlayingInternal(SpectatorState state)
+ protected override async Task BeginPlayingInternal(SpectatorState state)
{
if (!IsConnected.Value)
- return Task.CompletedTask;
+ return;
Debug.Assert(connection != null);
- return connection.SendAsync(nameof(ISpectatorServer.BeginPlaySession), state);
+ try
+ {
+ await connection.SendAsync(nameof(ISpectatorServer.BeginPlaySession), state);
+ }
+ catch (HubException exception)
+ {
+ if (exception.GetHubExceptionMessage() == HubClientConnector.SERVER_SHUTDOWN_MESSAGE)
+ connector?.Reconnect();
+ throw;
+ }
}
protected override Task SendFramesInternal(FrameDataBundle bundle)
diff --git a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs
index 4f336d85fc..20ee11c7f6 100644
--- a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs
+++ b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Overlays.BeatmapSet
private void load(OsuColour colours)
{
BadgeText = BeatmapsetsStrings.FeaturedArtistBadgeLabel;
- BadgeColour = colours.Blue1;
+ BadgeColour = colours.FeaturedArtistColour;
// todo: add linking support to allow redirecting featured artist badge to corresponding track.
}
}
diff --git a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs
index 3204f79b21..9c5378a967 100644
--- a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs
+++ b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Overlays.BeatmapSet
private void load(OsuColour colours)
{
BadgeText = BeatmapsetsStrings.SpotlightBadgeLabel;
- BadgeColour = colours.Pink1;
+ BadgeColour = colours.SpotlightColour;
// todo: add linking support to allow redirecting spotlight badge to https://osu.ppy.sh/wiki/en/Beatmap_Spotlights.
}
}
diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs
index a34776ddf0..a87e65b735 100644
--- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs
+++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs
@@ -127,9 +127,12 @@ namespace osu.Game.Overlays.Settings.Sections
dropdownItems.Add(skin.ToLive(realm));
dropdownItems.Insert(protectedCount, random_skin_info);
- skinDropdown.Items = dropdownItems;
+ Schedule(() =>
+ {
+ skinDropdown.Items = dropdownItems;
- updateSelectedSkinFromConfig();
+ updateSelectedSkinFromConfig();
+ });
}
private void updateSelectedSkinFromConfig()
diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs
index 46b8b35da2..929c362bd8 100644
--- a/osu.Game/Overlays/Volume/VolumeMeter.cs
+++ b/osu.Game/Overlays/Volume/VolumeMeter.cs
@@ -329,7 +329,7 @@ namespace osu.Game.Overlays.Volume
if (isPrecise)
{
- scrollAccumulation += delta * adjust_step * 0.1;
+ scrollAccumulation += delta * adjust_step;
while (Precision.AlmostBigger(Math.Abs(scrollAccumulation), precision))
{
diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs
index 7019dad803..aaee15eae8 100644
--- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs
+++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs
@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Edit
public abstract class DistancedHitObjectComposer : HitObjectComposer, IDistanceSnapProvider, IScrollBindingHandler
where TObject : HitObject
{
+ private const float adjust_step = 0.1f;
+
public Bindable DistanceSpacingMultiplier { get; } = new BindableDouble(1.0)
{
MinValue = 0.1,
@@ -61,7 +63,7 @@ namespace osu.Game.Rulesets.Edit
Child = distanceSpacingSlider = new ExpandableSlider>
{
Current = { BindTarget = DistanceSpacingMultiplier },
- KeyboardStep = 0.1f,
+ KeyboardStep = adjust_step,
}
}
});
@@ -93,7 +95,7 @@ namespace osu.Game.Rulesets.Edit
{
case GlobalAction.EditorIncreaseDistanceSpacing:
case GlobalAction.EditorDecreaseDistanceSpacing:
- return adjustDistanceSpacing(e.Action, 0.1f);
+ return adjustDistanceSpacing(e.Action, adjust_step);
}
return false;
@@ -109,7 +111,7 @@ namespace osu.Game.Rulesets.Edit
{
case GlobalAction.EditorIncreaseDistanceSpacing:
case GlobalAction.EditorDecreaseDistanceSpacing:
- return adjustDistanceSpacing(e.Action, e.ScrollAmount * (e.IsPrecise ? 0.01f : 0.1f));
+ return adjustDistanceSpacing(e.Action, e.ScrollAmount * adjust_step);
}
return false;
diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index d66c85f9ad..1414644a54 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -493,7 +493,7 @@ namespace osu.Game.Screens.Edit
if (scrollAccumulation != 0 && Math.Sign(scrollAccumulation) != scrollDirection)
scrollAccumulation = scrollDirection * (precision - Math.Abs(scrollAccumulation));
- scrollAccumulation += scrollComponent * (e.IsPrecise ? 0.1 : 1);
+ scrollAccumulation += scrollComponent;
// because we are doing snapped seeking, we need to add up precise scrolls until they accumulate to an arbitrary cut-off.
while (Math.Abs(scrollAccumulation) >= precision)
diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs
index b95aabc1c4..e0fc5f1aff 100644
--- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs
+++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs
@@ -41,7 +41,7 @@ namespace osu.Game.Screens.Edit.Setup
Add(new Box
{
- Colour = colourProvider.Background2,
+ Colour = colourProvider.Background3,
RelativeSizeAxes = Axes.Both,
});
diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs
index 4dd7a75d4a..57fcff6a4c 100644
--- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs
+++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs
@@ -10,6 +10,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
+using osu.Framework.Timing;
using osu.Framework.Utils;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics.Containers;
@@ -28,6 +29,8 @@ namespace osu.Game.Screens.Edit.Timing
private Drawable weight;
private Drawable stick;
+ private IAdjustableClock metronomeClock;
+
[Resolved]
private OverlayColourProvider overlayColourProvider { get; set; }
@@ -192,6 +195,8 @@ namespace osu.Game.Screens.Edit.Timing
Y = -3,
},
};
+
+ Clock = new FramedClock(metronomeClock = new StopwatchClock(true));
}
private double beatLength;
@@ -216,6 +221,8 @@ namespace osu.Game.Screens.Edit.Timing
if (BeatSyncSource.ControlPoints == null || BeatSyncSource.Clock == null)
return;
+ metronomeClock.Rate = IsBeatSyncedWithTrack ? BeatSyncSource.Clock.Rate : 1;
+
timingPoint = BeatSyncSource.ControlPoints.TimingPointAt(BeatSyncSource.Clock.CurrentTime);
if (beatLength != timingPoint.BeatLength)
diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs
index 74d43628e1..46bb62c9e0 100644
--- a/osu.Game/Screens/Edit/Timing/RowAttribute.cs
+++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs
@@ -19,6 +19,8 @@ namespace osu.Game.Screens.Edit.Timing
private readonly string label;
+ protected Drawable Background { get; private set; }
+
protected FillFlowContainer Content { get; private set; }
public RowAttribute(ControlPoint point, string label)
@@ -41,11 +43,11 @@ namespace osu.Game.Screens.Edit.Timing
Masking = true;
CornerRadius = 3;
- InternalChildren = new Drawable[]
+ InternalChildren = new[]
{
- new Box
+ Background = new Box
{
- Colour = overlayColours.Background4,
+ Colour = overlayColours.Background5,
RelativeSizeAxes = Axes.Both,
},
Content = new FillFlowContainer
diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs
index f8ec4aef25..8a07088545 100644
--- a/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs
+++ b/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs
@@ -7,6 +7,7 @@ using osu.Framework.Extensions;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Timing;
using osu.Game.Graphics.Sprites;
+using osu.Game.Overlays;
namespace osu.Game.Screens.Edit.Timing.RowAttributes
{
@@ -24,10 +25,12 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
}
[BackgroundDependencyLoader]
- private void load()
+ private void load(OverlayColourProvider colourProvider)
{
Content.Add(text = new AttributeText(Point));
+ Background.Colour = colourProvider.Background4;
+
timeSignature.BindValueChanged(_ => updateText());
beatLength.BindValueChanged(_ => updateText(), true);
}
diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs
index 415acc0e22..84b2609a61 100644
--- a/osu.Game/Screens/Edit/Verify/IssueList.cs
+++ b/osu.Game/Screens/Edit/Verify/IssueList.cs
@@ -51,7 +51,7 @@ namespace osu.Game.Screens.Edit.Verify
{
new Box
{
- Colour = colours.Background2,
+ Colour = colours.Background3,
RelativeSizeAxes = Axes.Both,
},
new OsuScrollContainer
diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs
index 9dc5a53907..56e16bb746 100644
--- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs
+++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs
@@ -41,7 +41,7 @@ namespace osu.Game.Screens.Edit.Verify
ColumnDimensions = new[]
{
new Dimension(),
- new Dimension(GridSizeMode.Absolute, 200),
+ new Dimension(GridSizeMode.Absolute, 250),
},
Content = new[]
{
diff --git a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs
index 760de354dc..a7ea32ee7c 100644
--- a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs
@@ -30,8 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
status.BindValueChanged(s =>
{
- this.FadeColour(category.Value == RoomCategory.Spotlight ? colours.Pink : s.NewValue.GetAppropriateColour(colours)
- , transitionDuration);
+ this.FadeColour(colours.ForRoomCategory(category.Value) ?? s.NewValue.GetAppropriateColour(colours), transitionDuration);
}, true);
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
index 8e3aa77e7b..772232f6b4 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
@@ -237,7 +237,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
roomCategory.BindTo(Room.Category);
roomCategory.BindValueChanged(c =>
{
- if (c.NewValue == RoomCategory.Spotlight)
+ if (c.NewValue > RoomCategory.Normal)
specialCategoryPill.Show();
else
specialCategoryPill.Hide();
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs
index 6cdbeb2af4..539af2ebaf 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
+using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
@@ -13,6 +14,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
public class RoomSpecialCategoryPill : OnlinePlayComposite
{
private SpriteText text;
+ private PillContainer pill;
+
+ [Resolved]
+ private OsuColour colours { get; set; }
public RoomSpecialCategoryPill()
{
@@ -20,9 +25,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
}
[BackgroundDependencyLoader]
- private void load(OsuColour colours)
+ private void load()
{
- InternalChild = new PillContainer
+ InternalChild = pill = new PillContainer
{
Background =
{
@@ -43,7 +48,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
base.LoadComplete();
- Category.BindValueChanged(c => text.Text = c.NewValue.ToString(), true);
+ Category.BindValueChanged(c =>
+ {
+ text.Text = c.NewValue.GetLocalisableDescription();
+
+ var backgroundColour = colours.ForRoomCategory(Category.Value);
+ if (backgroundColour != null)
+ pill.Background.Colour = backgroundColour.Value;
+ }, true);
}
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs
index d61fbea387..0fd9290880 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs
@@ -128,7 +128,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
foreach (var room in roomFlow)
{
- roomFlow.SetLayoutPosition(room, room.Room.Category.Value == RoomCategory.Spotlight
+ roomFlow.SetLayoutPosition(room, room.Room.Category.Value > RoomCategory.Normal
// Always show spotlight playlists at the top of the listing.
? float.MinValue
: -(room.Room.RoomID.Value ?? 0));
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs
index dced9b8691..b36e162e3d 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
@@ -49,6 +50,10 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
case PlaylistsCategory.Spotlight:
criteria.Category = @"spotlight";
break;
+
+ case PlaylistsCategory.FeaturedArtist:
+ criteria.Category = @"featured_artist";
+ break;
}
return criteria;
@@ -73,7 +78,10 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{
Any,
Normal,
- Spotlight
+ Spotlight,
+
+ [Description("Featured Artist")]
+ FeaturedArtist,
}
}
}
diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs
index 019a9f9730..bdc98e53f9 100644
--- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs
+++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
+using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Audio.Track;
@@ -80,16 +81,13 @@ namespace osu.Game.Screens.Play.HUD
difficultyCache.GetTimedDifficultyAttributesAsync(gameplayWorkingBeatmap, gameplayState.Ruleset, clonedMods, loadCancellationSource.Token)
.ContinueWith(task => Schedule(() =>
{
- if (task.Exception != null)
- return;
-
timedAttributes = task.GetResultSafely();
IsValid = true;
if (lastJudgement != null)
onJudgementChanged(lastJudgement);
- }));
+ }), TaskContinuationOptions.OnlyOnRanToCompletion);
}
}
diff --git a/osu.Game/Tests/Gameplay/TestGameplayState.cs b/osu.Game/Tests/Gameplay/TestGameplayState.cs
new file mode 100644
index 0000000000..0d00f52d15
--- /dev/null
+++ b/osu.Game/Tests/Gameplay/TestGameplayState.cs
@@ -0,0 +1,32 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+#nullable enable
+
+using System.Collections.Generic;
+using osu.Game.Rulesets;
+using osu.Game.Rulesets.Mods;
+using osu.Game.Scoring;
+using osu.Game.Screens.Play;
+using osu.Game.Tests.Beatmaps;
+
+namespace osu.Game.Tests.Gameplay
+{
+ ///
+ /// Static class providing a convenience method to retrieve a correctly-initialised instance in testing scenarios.
+ ///
+ public static class TestGameplayState
+ {
+ ///
+ /// Creates a correctly-initialised instance for use in testing.
+ ///
+ public static GameplayState Create(Ruleset ruleset, IReadOnlyList? mods = null, Score? score = null)
+ {
+ var beatmap = new TestBeatmap(ruleset.RulesetInfo);
+ var workingBeatmap = new TestWorkingBeatmap(beatmap);
+ var playableBeatmap = workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods);
+
+ return new GameplayState(playableBeatmap, ruleset, mods, score);
+ }
+ }
+}
diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs
index 2d3e1960d9..15e4fc4d8f 100644
--- a/osu.Game/Tests/Visual/EditorClockTestScene.cs
+++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
+using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
@@ -24,6 +25,8 @@ namespace osu.Game.Tests.Visual
[Cached]
protected new readonly EditorClock Clock;
+ private readonly Bindable frequencyAdjustment = new BindableDouble(1);
+
protected virtual bool ScrollUsingMouseWheel => true;
protected EditorClockTestScene()
@@ -44,14 +47,21 @@ namespace osu.Game.Tests.Visual
protected override void LoadComplete()
{
base.LoadComplete();
+
Beatmap.BindValueChanged(beatmapChanged, true);
+
+ AddSliderStep("editor clock rate", 0.0, 2.0, 1.0, v => frequencyAdjustment.Value = v);
}
private void beatmapChanged(ValueChangedEvent e)
{
+ e.OldValue?.Track.RemoveAdjustment(AdjustableProperty.Frequency, frequencyAdjustment);
+
Clock.Beatmap = e.NewValue.Beatmap;
Clock.ChangeSource(e.NewValue.Track);
Clock.ProcessFrame();
+
+ e.NewValue.Track.AddAdjustment(AdjustableProperty.Frequency, frequencyAdjustment);
}
protected override void Update()
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 5de0f4346c..79cfd7c917 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -35,7 +35,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index c1a473ff75..b1ba64beba 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -61,7 +61,7 @@
-
+
@@ -84,7 +84,7 @@
-
+