diff --git a/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs b/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs
index 0ef4953e83..87de9fd72a 100644
--- a/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs
+++ b/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs
@@ -22,7 +22,9 @@ namespace osu.Game.Screens.Multi.Ranking
private readonly int roomId;
private readonly PlaylistItem playlistItem;
- private LoadingSpinner loadingLayer;
+ private LoadingSpinner leftLoadingLayer;
+ private LoadingSpinner centreLoadingLayer;
+ private LoadingSpinner rightLoadingLayer;
private MultiplayerScores higherScores;
private MultiplayerScores lowerScores;
@@ -39,13 +41,29 @@ namespace osu.Game.Screens.Multi.Ranking
[BackgroundDependencyLoader]
private void load()
{
- AddInternal(loadingLayer = new LoadingLayer
+ AddInternal(new Container
{
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- X = -10,
- State = { Value = Score == null ? Visibility.Visible : Visibility.Hidden },
- Padding = new MarginPadding { Bottom = TwoLayerButton.SIZE_EXTENDED.Y }
+ RelativeSizeAxes = Axes.Both,
+ Padding = new MarginPadding { Bottom = TwoLayerButton.SIZE_EXTENDED.Y },
+ Children = new Drawable[]
+ {
+ leftLoadingLayer = new PanelListLoadingSpinner(ScorePanelList)
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.Centre,
+ },
+ centreLoadingLayer = new PanelListLoadingSpinner(ScorePanelList)
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ State = { Value = Score == null ? Visibility.Visible : Visibility.Hidden },
+ },
+ rightLoadingLayer = new PanelListLoadingSpinner(ScorePanelList)
+ {
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.Centre,
+ },
+ }
});
}
@@ -91,6 +109,11 @@ namespace osu.Game.Screens.Multi.Ranking
if (pivot?.Cursor == null)
return null;
+ if (pivot == higherScores)
+ leftLoadingLayer.Show();
+ else
+ rightLoadingLayer.Show();
+
return createIndexRequest(scoresCallback, pivot);
}
@@ -114,10 +137,10 @@ namespace osu.Game.Screens.Multi.Ranking
else
higherScores = r;
- performSuccessCallback(scoresCallback, r.Scores, pivot);
+ performSuccessCallback(scoresCallback, r.Scores, r);
};
- indexReq.Failure += _ => loadingLayer.Hide();
+ indexReq.Failure += _ => hideLoadingSpinners(pivot);
return indexReq;
}
@@ -146,7 +169,45 @@ namespace osu.Game.Screens.Multi.Ranking
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
callback.Invoke(scoreInfos.Where(s => s.ID != Score?.OnlineScoreID));
- loadingLayer.Hide();
+ hideLoadingSpinners(pivot);
+ }
+
+ private void hideLoadingSpinners([CanBeNull] MultiplayerScores pivot = null)
+ {
+ centreLoadingLayer.Hide();
+
+ if (pivot == lowerScores)
+ rightLoadingLayer.Hide();
+ else if (pivot == higherScores)
+ leftLoadingLayer.Hide();
+ }
+
+ private class PanelListLoadingSpinner : LoadingSpinner
+ {
+ private readonly ScorePanelList list;
+
+ ///
+ /// Creates a new .
+ ///
+ /// The list to track.
+ /// Whether the spinner should have a surrounding black box for visibility.
+ public PanelListLoadingSpinner(ScorePanelList list, bool withBox = true)
+ : base(withBox)
+ {
+ this.list = list;
+ }
+
+ protected override void Update()
+ {
+ base.Update();
+
+ float panelOffset = list.DrawWidth / 2 - ScorePanel.EXPANDED_WIDTH;
+
+ if ((Anchor & Anchor.x0) > 0)
+ X = (float)(panelOffset - list.Current);
+ else if ((Anchor & Anchor.x2) > 0)
+ X = (float)(list.ScrollableExtent - list.Current - panelOffset);
+ }
}
}
}
diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs
index 254ab76f5b..2506a63cc0 100644
--- a/osu.Game/Screens/Ranking/ResultsScreen.cs
+++ b/osu.Game/Screens/Ranking/ResultsScreen.cs
@@ -37,7 +37,8 @@ namespace osu.Game.Screens.Ranking
public readonly Bindable SelectedScore = new Bindable();
public readonly ScoreInfo Score;
- private readonly bool allowRetry;
+
+ protected ScorePanelList ScorePanelList { get; private set; }
[Resolved(CanBeNull = true)]
private Player player { get; set; }
@@ -47,12 +48,13 @@ namespace osu.Game.Screens.Ranking
private StatisticsPanel statisticsPanel;
private Drawable bottomPanel;
- private ScorePanelList scorePanelList;
private Container detachedPanelContainer;
private bool fetchedInitialScores;
private APIRequest nextPageRequest;
+ private readonly bool allowRetry;
+
protected ResultsScreen(ScoreInfo score, bool allowRetry = true)
{
Score = score;
@@ -87,7 +89,7 @@ namespace osu.Game.Screens.Ranking
RelativeSizeAxes = Axes.Both,
Score = { BindTarget = SelectedScore }
},
- scorePanelList = new ScorePanelList
+ ScorePanelList = new ScorePanelList
{
RelativeSizeAxes = Axes.Both,
SelectedScore = { BindTarget = SelectedScore },
@@ -145,7 +147,7 @@ namespace osu.Game.Screens.Ranking
};
if (Score != null)
- scorePanelList.AddScore(Score);
+ ScorePanelList.AddScore(Score);
if (player != null && allowRetry)
{
@@ -181,9 +183,9 @@ namespace osu.Game.Screens.Ranking
if (fetchedInitialScores && nextPageRequest == null)
{
- if (scorePanelList.IsScrolledToStart)
+ if (ScorePanelList.IsScrolledToStart)
nextPageRequest = FetchNextPage(-1, fetchScoresCallback);
- else if (scorePanelList.IsScrolledToEnd)
+ else if (ScorePanelList.IsScrolledToEnd)
nextPageRequest = FetchNextPage(1, fetchScoresCallback);
if (nextPageRequest != null)
@@ -249,7 +251,7 @@ namespace osu.Game.Screens.Ranking
private void addScore(ScoreInfo score)
{
- var panel = scorePanelList.AddScore(score);
+ var panel = ScorePanelList.AddScore(score);
if (detachedPanel != null)
panel.Alpha = 0;
@@ -262,11 +264,11 @@ namespace osu.Game.Screens.Ranking
if (state.NewValue == Visibility.Visible)
{
// Detach the panel in its original location, and move into the desired location in the local container.
- var expandedPanel = scorePanelList.GetPanelForScore(SelectedScore.Value);
+ var expandedPanel = ScorePanelList.GetPanelForScore(SelectedScore.Value);
var screenSpacePos = expandedPanel.ScreenSpaceDrawQuad.TopLeft;
// Detach and move into the local container.
- scorePanelList.Detach(expandedPanel);
+ ScorePanelList.Detach(expandedPanel);
detachedPanelContainer.Add(expandedPanel);
// Move into its original location in the local container first, then to the final location.
@@ -276,9 +278,9 @@ namespace osu.Game.Screens.Ranking
.MoveTo(new Vector2(StatisticsPanel.SIDE_PADDING, origLocation.Y), 150, Easing.OutQuint);
// Hide contracted panels.
- foreach (var contracted in scorePanelList.GetScorePanels().Where(p => p.State == PanelState.Contracted))
+ foreach (var contracted in ScorePanelList.GetScorePanels().Where(p => p.State == PanelState.Contracted))
contracted.FadeOut(150, Easing.OutQuint);
- scorePanelList.HandleInput = false;
+ ScorePanelList.HandleInput = false;
// Dim background.
Background.FadeTo(0.1f, 150);
@@ -291,7 +293,7 @@ namespace osu.Game.Screens.Ranking
// Remove from the local container and re-attach.
detachedPanelContainer.Remove(detachedPanel);
- scorePanelList.Attach(detachedPanel);
+ ScorePanelList.Attach(detachedPanel);
// Move into its original location in the attached container first, then to the final location.
var origLocation = detachedPanel.Parent.ToLocalSpace(screenSpacePos);
@@ -300,9 +302,9 @@ namespace osu.Game.Screens.Ranking
.MoveTo(new Vector2(0, origLocation.Y), 150, Easing.OutQuint);
// Show contracted panels.
- foreach (var contracted in scorePanelList.GetScorePanels().Where(p => p.State == PanelState.Contracted))
+ foreach (var contracted in ScorePanelList.GetScorePanels().Where(p => p.State == PanelState.Contracted))
contracted.FadeIn(150, Easing.OutQuint);
- scorePanelList.HandleInput = true;
+ ScorePanelList.HandleInput = true;
// Un-dim background.
Background.FadeTo(0.5f, 150);
diff --git a/osu.Game/Screens/Ranking/ScorePanelList.cs b/osu.Game/Screens/Ranking/ScorePanelList.cs
index b2e1e91831..10bd99c8ce 100644
--- a/osu.Game/Screens/Ranking/ScorePanelList.cs
+++ b/osu.Game/Screens/Ranking/ScorePanelList.cs
@@ -41,6 +41,16 @@ namespace osu.Game.Screens.Ranking
///
public bool IsScrolledToEnd => flow.Count > 0 && scroll.ScrollableExtent > 0 && scroll.IsScrolledToEnd(scroll_endpoint_distance);
+ ///
+ /// The current scroll position.
+ ///
+ public double Current => scroll.Current;
+
+ ///
+ /// The scrollable extent.
+ ///
+ public double ScrollableExtent => scroll.ScrollableExtent;
+
///
/// An action to be invoked if a is clicked while in an expanded state.
///