1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-06 22:45:53 +08:00

Merge pull request #33142 from frenzibyte/ssv2-score-opens-results

SongSelectV2: Open results screen when clicking leaderboard scores
This commit is contained in:
Bartłomiej Dach
2025-05-16 14:10:07 +02:00
committed by GitHub
Unverified
7 changed files with 105 additions and 13 deletions
@@ -15,10 +15,12 @@ using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Online.Leaderboards;
using osu.Game.Overlays;
using osu.Game.Overlays.Toolbar;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens;
using osu.Game.Screens.Footer;
using osu.Game.Screens.Menu;
@@ -33,6 +35,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
protected BeatmapManager Beatmaps { get; private set; } = null!;
protected RealmRulesetStore Rulesets { get; private set; } = null!;
protected OsuConfigManager Config { get; private set; } = null!;
protected ScoreManager ScoreManager { get; private set; } = null!;
private RealmDetachedBeatmapStore beatmapStore = null!;
@@ -51,6 +54,9 @@ namespace osu.Game.Tests.Visual.SongSelectV2
[Cached(typeof(INotificationOverlay))]
private readonly INotificationOverlay notificationOverlay = new NotificationOverlay();
[Cached]
protected readonly LeaderboardManager LeaderboardManager = new LeaderboardManager();
protected SongSelectTestScene()
{
Children = new Drawable[]
@@ -60,6 +66,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
LeaderboardManager,
new Toolbar
{
State = { Value = Visibility.Visible },
@@ -90,6 +97,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
dependencies.Cache(Realm);
dependencies.Cache(Beatmaps = new BeatmapManager(LocalStorage, Realm, null, Dependencies.Get<AudioManager>(), Resources, Dependencies.Get<GameHost>(), Beatmap.Default));
dependencies.Cache(Config = new OsuConfigManager(LocalStorage));
dependencies.Cache(ScoreManager = new ScoreManager(Rulesets, () => Beatmaps, LocalStorage, Realm, API, Config));
dependencies.CacheAs<BeatmapStore>(beatmapStore = new RealmDetachedBeatmapStore());
@@ -8,12 +8,19 @@ using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.Leaderboards;
using osu.Game.Overlays.Dialog;
using osu.Game.Overlays.Mods;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Screens.SelectV2;
using osuTK.Input;
using FooterButtonMods = osu.Game.Screens.SelectV2.FooterButtonMods;
using FooterButtonOptions = osu.Game.Screens.SelectV2.FooterButtonOptions;
@@ -22,6 +29,55 @@ namespace osu.Game.Tests.Visual.SongSelectV2
{
public partial class TestSceneSongSelect : SongSelectTestScene
{
[Test]
public void TestResultsScreenWhenClickingLeaderboardScore()
{
LoadSongSelect();
ImportBeatmapForRuleset(0);
AddAssert("beatmap imported", () => Beatmaps.GetAllUsableBeatmapSets().Any(), () => Is.True);
// song select should automatically select the beatmap for us but this is not implemented yet.
// todo: remove when that's the case.
AddAssert("no beatmap selected", () => Beatmap.IsDefault);
AddStep("select beatmap", () => Beatmap.Value = Beatmaps.GetWorkingBeatmap(Beatmaps.GetAllUsableBeatmapSets().Single().Beatmaps.First()));
AddAssert("beatmap selected", () => !Beatmap.IsDefault);
AddStep("import score", () =>
{
var beatmapInfo = Beatmaps.GetAllUsableBeatmapSets().Single().Beatmaps.First();
ScoreManager.Import(new ScoreInfo
{
Hash = Guid.NewGuid().ToString(),
BeatmapHash = beatmapInfo.Hash,
BeatmapInfo = beatmapInfo,
Ruleset = new OsuRuleset().RulesetInfo,
User = new GuestUser(),
});
});
AddStep("select ranking tab", () =>
{
InputManager.MoveMouseTo(SongSelect.ChildrenOfType<BeatmapDetailsArea.WedgeSelector<BeatmapDetailsArea.Header.Selection>>().Last());
InputManager.Click(MouseButton.Left);
});
// probably should be done via dropdown menu instead of forcing this way?
AddStep("set local scope", () =>
{
var current = LeaderboardManager.CurrentCriteria!;
LeaderboardManager.FetchWithCriteria(new LeaderboardCriteria(current.Beatmap, current.Ruleset, BeatmapLeaderboardScope.Local, null));
});
AddUntilStep("wait for score panel", () => SongSelect.ChildrenOfType<BeatmapLeaderboardScore>().Any());
AddStep("click score panel", () =>
{
InputManager.MoveMouseTo(SongSelect.ChildrenOfType<BeatmapLeaderboardScore>().Single());
InputManager.Click(MouseButton.Left);
});
AddUntilStep("wait for results screen", () => Stack.CurrentScreen is ResultsScreen);
}
#region Hotkeys
[Test]
@@ -50,6 +50,9 @@ namespace osu.Game.Screens.SelectV2
[Resolved]
private OverlayColourProvider colourProvider { get; set; } = null!;
[Resolved]
private ISongSelect? songSelect { get; set; }
private Container<Placeholder> placeholderContainer = null!;
private Placeholder? placeholder;
@@ -244,6 +247,7 @@ namespace osu.Game.Screens.SelectV2
Rank = i + 1,
IsPersonalBest = s.OnlineID == userScore?.OnlineID,
SelectedMods = { BindTarget = mods },
Action = () => onLeaderboardScoreClicked(s),
}), loadedScores =>
{
int delay = 200;
@@ -279,6 +283,7 @@ namespace osu.Game.Screens.SelectV2
IsPersonalBest = true,
Rank = userScore.Position,
SelectedMods = { BindTarget = mods },
Action = () => onLeaderboardScoreClicked(userScore),
};
scoresScroll.TransformTo(nameof(scoresScroll.Padding), new MarginPadding { Bottom = personal_best_height }, 300, Easing.OutQuint);
@@ -308,6 +313,8 @@ namespace osu.Game.Screens.SelectV2
scoresScroll.TransformTo(nameof(scoresScroll.Padding), new MarginPadding(), 300, Easing.OutQuint);
}
private void onLeaderboardScoreClicked(ScoreInfo score) => songSelect?.PresentScore(score);
private LeaderboardState displayedState;
protected void SetState(LeaderboardState state)
@@ -23,7 +23,7 @@ namespace osu.Game.Screens.SelectV2
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
[Resolved]
private ISongSelectBeatmapActions? beatmapActions { get; set; }
private ISongSelect? songSelect { get; set; }
[BackgroundDependencyLoader]
private void load(OsuColour colour)
@@ -51,7 +51,7 @@ namespace osu.Game.Screens.SelectV2
public Framework.Graphics.UserInterface.Popover GetPopover() => new Popover(this, beatmap.Value)
{
ColourProvider = colourProvider,
BeatmapActions = beatmapActions
SongSelect = songSelect
};
}
}
@@ -37,7 +37,7 @@ namespace osu.Game.Screens.SelectV2
// Can't use DI for these due to popover being initialised from a footer button which ends up being on the global
// PopoverContainer.
public ISongSelectBeatmapActions? BeatmapActions { get; init; }
public ISongSelect? SongSelect { get; init; }
public required OverlayColourProvider ColourProvider { get; init; }
public Popover(FooterButtonOptions footerButton, WorkingBeatmap beatmap)
@@ -59,20 +59,20 @@ namespace osu.Game.Screens.SelectV2
};
addHeader(CommonStrings.General);
addButton(SongSelectStrings.ManageCollections, FontAwesome.Solid.Book, () => BeatmapActions?.ManageCollections());
addButton(SongSelectStrings.ManageCollections, FontAwesome.Solid.Book, () => SongSelect?.ManageCollections());
addHeader(SongSelectStrings.ForAllDifficulties, beatmap.BeatmapSetInfo.ToString());
addButton(SongSelectStrings.DeleteBeatmap, FontAwesome.Solid.Trash, () => BeatmapActions?.Delete(beatmap.BeatmapSetInfo), colours.Red1);
addButton(SongSelectStrings.DeleteBeatmap, FontAwesome.Solid.Trash, () => SongSelect?.Delete(beatmap.BeatmapSetInfo), colours.Red1);
addHeader(SongSelectStrings.ForSelectedDifficulty, beatmap.BeatmapInfo.DifficultyName);
// TODO: replace with "remove from played" button when beatmap is already played.
addButton(SongSelectStrings.MarkAsPlayed, FontAwesome.Regular.TimesCircle, () => BeatmapActions?.MarkPlayed(beatmap.BeatmapInfo));
addButton(SongSelectStrings.ClearAllLocalScores, FontAwesome.Solid.Eraser, () => BeatmapActions?.ClearScores(beatmap.BeatmapInfo), colours.Red1);
addButton(SongSelectStrings.MarkAsPlayed, FontAwesome.Regular.TimesCircle, () => SongSelect?.MarkPlayed(beatmap.BeatmapInfo));
addButton(SongSelectStrings.ClearAllLocalScores, FontAwesome.Solid.Eraser, () => SongSelect?.ClearScores(beatmap.BeatmapInfo), colours.Red1);
if (BeatmapActions?.EditingAllowed == true)
addButton(SongSelectStrings.EditBeatmap, FontAwesome.Solid.PencilAlt, () => BeatmapActions.Edit(beatmap.BeatmapInfo));
if (SongSelect?.EditingAllowed == true)
addButton(SongSelectStrings.EditBeatmap, FontAwesome.Solid.PencilAlt, () => SongSelect.Edit(beatmap.BeatmapInfo));
addButton(WebCommonStrings.ButtonsHide.ToSentence(), FontAwesome.Solid.Magic, () => BeatmapActions?.Hide(beatmap.BeatmapInfo));
addButton(WebCommonStrings.ButtonsHide.ToSentence(), FontAwesome.Solid.Magic, () => SongSelect?.Hide(beatmap.BeatmapInfo));
}
protected override void LoadComplete()
@@ -2,13 +2,14 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps;
using osu.Game.Scoring;
namespace osu.Game.Screens.SelectV2
{
/// <summary>
/// Actions exposed by song select which are used by subcomponents to perform top-level operations.
/// </summary>
public interface ISongSelectBeatmapActions
public interface ISongSelect
{
/// <summary>
/// Requests the user for confirmation to delete the given beatmap set.
@@ -44,5 +45,10 @@ namespace osu.Game.Screens.SelectV2
/// Hides a beatmap from user's vision.
/// </summary>
void Hide(BeatmapInfo beatmap);
/// <summary>
/// Present the provided score at the results screen.
/// </summary>
void PresentScore(ScoreInfo score);
}
}
+17 -2
View File
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
@@ -23,9 +24,11 @@ using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Overlays.Volume;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Footer;
using osu.Game.Screens.Menu;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
using osu.Game.Skinning;
using osu.Game.Utils;
@@ -39,8 +42,8 @@ namespace osu.Game.Screens.SelectV2
/// This screen is intended to house all components introduced in the new song select design to add transitions and examine the overall look.
/// This will be gradually built upon and ultimately replace <see cref="Select.SongSelect"/> once everything is in place.
/// </summary>
[Cached(typeof(ISongSelectBeatmapActions))]
public abstract partial class SongSelect : OsuScreen, IKeyBindingHandler<GlobalAction>, ISongSelectBeatmapActions
[Cached(typeof(ISongSelect))]
public abstract partial class SongSelect : OsuScreen, IKeyBindingHandler<GlobalAction>, ISongSelect
{
private const float logo_scale = 0.4f;
private const double fade_duration = 300;
@@ -401,6 +404,18 @@ namespace osu.Game.Screens.SelectV2
#endregion
/// <summary>
/// Opens results screen with the given score.
/// This assumes active beatmap and ruleset selection matches the score.
/// </summary>
public void PresentScore(ScoreInfo score)
{
Debug.Assert(Beatmap.Value.BeatmapInfo.Equals(score.BeatmapInfo));
Debug.Assert(Ruleset.Value.Equals(score.Ruleset));
this.Push(new SoloResultsScreen(score));
}
#region Beatmap management
public virtual bool EditingAllowed => false;