diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj
index 874f73da6d..66db439c82 100644
--- a/osu.Desktop/osu.Desktop.csproj
+++ b/osu.Desktop/osu.Desktop.csproj
@@ -27,8 +27,8 @@
-
-
+
+
diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
index feab3ed81c..3f8b3bf086 100644
--- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
+++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
@@ -2,9 +2,9 @@
-
+
-
+
diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
index e26d2433f9..fd17285a38 100644
--- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
+++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
@@ -2,9 +2,9 @@
-
+
-
+
diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
index 273d29c3de..8c31db9a7d 100644
--- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
+++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
@@ -2,9 +2,9 @@
-
+
-
+
diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs
index 50b3eabcf4..1a6e78d918 100644
--- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs
+++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs
@@ -1,6 +1,7 @@
// 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.Graphics.Cursor;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI;
@@ -19,10 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit
private class OsuPlayfieldNoCursor : OsuPlayfield
{
- public OsuPlayfieldNoCursor()
- {
- Cursor?.Expire();
- }
+ protected override CursorContainer CreateCursor() => null;
}
}
}
diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
index fade054382..72ce6c947b 100644
--- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
+++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
@@ -2,9 +2,9 @@
-
+
-
+
diff --git a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs
index 543a43b439..24380645d1 100644
--- a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs
+++ b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs
@@ -3,9 +3,13 @@
using System;
using System.Collections.Generic;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Game.Online.API;
using osu.Game.Overlays;
using osu.Game.Overlays.AccountCreation;
+using osu.Game.Users;
namespace osu.Game.Tests.Visual
{
@@ -21,12 +25,32 @@ namespace osu.Game.Tests.Visual
typeof(AccountCreationScreen),
};
+ [Cached(typeof(IAPIProvider))]
+ private DummyAPIAccess api = new DummyAPIAccess();
+
public TestCaseAccountCreationOverlay()
{
- var accountCreation = new AccountCreationOverlay();
- Child = accountCreation;
+ Container userPanelArea;
+ AccountCreationOverlay accountCreation;
- accountCreation.State = Visibility.Visible;
+ Children = new Drawable[]
+ {
+ api,
+ accountCreation = new AccountCreationOverlay(),
+ userPanelArea = new Container
+ {
+ Padding = new MarginPadding(10),
+ AutoSizeAxes = Axes.Both,
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopRight,
+ },
+ };
+
+ api.Logout();
+ api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true);
+
+ AddStep("show", () => accountCreation.State = Visibility.Visible);
+ AddStep("logout", () => api.Logout());
}
}
}
diff --git a/osu.Game.Tests/Visual/TestCaseDisclaimer.cs b/osu.Game.Tests/Visual/TestCaseDisclaimer.cs
index f08a2a54ca..8bba16e4b4 100644
--- a/osu.Game.Tests/Visual/TestCaseDisclaimer.cs
+++ b/osu.Game.Tests/Visual/TestCaseDisclaimer.cs
@@ -16,6 +16,8 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader]
private void load()
{
+ Add(api);
+
AddStep("load disclaimer", () => LoadScreen(new Disclaimer()));
AddStep("toggle support", () =>
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index b22c1aed99..938e1ae0f8 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -3,9 +3,9 @@
-
+
-
+
diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs
index 3d861e44bf..c5f6ef41c2 100644
--- a/osu.Game/Online/API/APIAccess.cs
+++ b/osu.Game/Online/API/APIAccess.cs
@@ -266,20 +266,18 @@ namespace osu.Game.Online.API
get => state;
private set
{
- APIState oldState = state;
- APIState newState = value;
+ if (state == value)
+ return;
+ APIState oldState = state;
state = value;
- if (oldState != newState)
+ log.Add($@"We just went {state}!");
+ Scheduler.Add(delegate
{
- log.Add($@"We just went {newState}!");
- Scheduler.Add(delegate
- {
- components.ForEach(c => c.APIStateChanged(this, newState));
- OnStateChange?.Invoke(oldState, newState);
- });
- }
+ components.ForEach(c => c.APIStateChanged(this, state));
+ OnStateChange?.Invoke(oldState, state);
+ });
}
}
diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs
index 0cb49951f7..99fde10309 100644
--- a/osu.Game/Online/API/DummyAPIAccess.cs
+++ b/osu.Game/Online/API/DummyAPIAccess.cs
@@ -1,12 +1,15 @@
// 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.Threading;
using osu.Framework.Bindables;
+using osu.Framework.Graphics;
using osu.Game.Users;
namespace osu.Game.Online.API
{
- public class DummyAPIAccess : IAPIProvider
+ public class DummyAPIAccess : Component, IAPIProvider
{
public Bindable LocalUser { get; } = new Bindable(new User
{
@@ -20,7 +23,23 @@ namespace osu.Game.Online.API
public string Endpoint => "http://localhost";
- public APIState State => LocalUser.Value.Id == 1 ? APIState.Offline : APIState.Online;
+ private APIState state = APIState.Online;
+
+ private readonly List components = new List();
+
+ public APIState State
+ {
+ get => state;
+ private set
+ {
+ if (state == value)
+ return;
+
+ state = value;
+
+ Scheduler.Add(() => components.ForEach(c => c.APIStateChanged(this, value)));
+ }
+ }
public virtual void Queue(APIRequest request)
{
@@ -28,28 +47,36 @@ namespace osu.Game.Online.API
public void Register(IOnlineComponent component)
{
- // todo: add support
+ Scheduler.Add(delegate { components.Add(component); });
+ component.APIStateChanged(this, state);
}
public void Unregister(IOnlineComponent component)
{
- // todo: add support
+ Scheduler.Add(delegate { components.Remove(component); });
}
public void Login(string username, string password)
{
LocalUser.Value = new User
{
- Username = @"Dummy",
+ Username = username,
Id = 1001,
};
+
+ State = APIState.Online;
}
public void Logout()
{
LocalUser.Value = new GuestUser();
+ State = APIState.Offline;
}
- public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) => null;
+ public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password)
+ {
+ Thread.Sleep(200);
+ return null;
+ }
}
}
diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs
index bfd1d3d236..d7240a40ad 100644
--- a/osu.Game/Screens/Select/BeatmapCarousel.cs
+++ b/osu.Game/Screens/Select/BeatmapCarousel.cs
@@ -55,9 +55,9 @@ namespace osu.Game.Screens.Select
public override bool HandlePositionalInput => AllowSelection;
///
- /// Used to avoid firing null selections before the initial beatmaps have been loaded via .
+ /// Whether carousel items have completed asynchronously loaded.
///
- private bool initialLoadComplete;
+ public bool BeatmapSetsLoaded { get; private set; }
private IEnumerable beatmapSets => root.Children.OfType();
@@ -90,7 +90,7 @@ namespace osu.Game.Screens.Select
Schedule(() =>
{
BeatmapSetsChanged?.Invoke();
- initialLoadComplete = true;
+ BeatmapSetsLoaded = true;
});
}));
}
@@ -327,6 +327,9 @@ namespace osu.Game.Screens.Select
private void select(CarouselItem item)
{
+ if (!AllowSelection)
+ return;
+
if (item == null) return;
item.State.Value = CarouselItemState.Selected;
@@ -593,7 +596,7 @@ namespace osu.Game.Screens.Select
currentY += DrawHeight / 2;
scrollableContent.Height = currentY;
- if (initialLoadComplete && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected))
+ if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected))
{
selectedBeatmapSet = null;
SelectionChanged?.Invoke(null);
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index a86d0beb39..8758df5151 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -300,6 +300,10 @@ namespace osu.Game.Screens.Select
/// Whether to trigger .
public void FinaliseSelection(BeatmapInfo beatmap = null, bool performStartAction = true)
{
+ // This is very important as we have not yet bound to screen-level bindables before the carousel load is completed.
+ if (!Carousel.BeatmapSetsLoaded)
+ return;
+
// if we have a pending filter operation, we want to run it now.
// it could change selection (ie. if the ruleset has been changed).
Carousel.FlushPendingFilterOperations();
@@ -373,6 +377,13 @@ namespace osu.Game.Screens.Select
var beatmap = beatmapNoDebounce;
var ruleset = rulesetNoDebounce;
+ selectionChangedDebounce?.Cancel();
+
+ if (beatmap == null)
+ run();
+ else
+ selectionChangedDebounce = Scheduler.AddDelayed(run, 200);
+
void run()
{
Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}");
@@ -417,13 +428,6 @@ namespace osu.Game.Screens.Select
if (this.IsCurrentScreen()) ensurePlayingSelected(preview);
UpdateBeatmap(Beatmap.Value);
}
-
- selectionChangedDebounce?.Cancel();
-
- if (beatmap == null)
- run();
- else
- selectionChangedDebounce = Scheduler.AddDelayed(run, 200);
}
private void triggerRandom()
@@ -593,18 +597,7 @@ namespace osu.Game.Screens.Select
private void carouselBeatmapsLoaded()
{
- if (rulesetNoDebounce == null)
- {
- // manual binding to parent ruleset to allow for delayed load in the incoming direction.
- rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value;
- Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue);
-
- decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue;
- decoupledRuleset.DisabledChanged += r => Ruleset.Disabled = r;
-
- Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true);
- Beatmap.BindValueChanged(workingBeatmapChanged);
- }
+ bindBindables();
if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false
&& Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false))
@@ -618,6 +611,26 @@ namespace osu.Game.Screens.Select
}
}
+ private bool boundLocalBindables;
+
+ private void bindBindables()
+ {
+ if (boundLocalBindables)
+ return;
+
+ // manual binding to parent ruleset to allow for delayed load in the incoming direction.
+ rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value;
+ Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue);
+
+ decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue;
+ decoupledRuleset.DisabledChanged += r => Ruleset.Disabled = r;
+
+ Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true);
+ Beatmap.BindValueChanged(workingBeatmapChanged);
+
+ boundLocalBindables = true;
+ }
+
private void delete(BeatmapSetInfo beatmap)
{
if (beatmap == null || beatmap.ID <= 0) return;
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index d8561770fd..dd69faad56 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -11,13 +11,13 @@
-
-
-
+
+
+
-
+