1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-05 07:42:54 +08:00

Merge pull request #14704 from peppy/modicon-imod-support

Update `LeaderboardModSelector` to avoid creating mod instances
This commit is contained in:
Dan Balasescu 2021-09-10 16:43:32 +09:00 committed by GitHub
commit f4b1d8b9d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 25 deletions

View File

@ -1,7 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
@ -17,5 +19,16 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("create mod icon", () => Child = icon = new ModIcon(new OsuModDoubleTime())); AddStep("create mod icon", () => Child = icon = new ModIcon(new OsuModDoubleTime()));
AddStep("change mod", () => icon.Mod = new OsuModEasy()); AddStep("change mod", () => icon.Mod = new OsuModEasy());
} }
[Test]
public void TestInterfaceModType()
{
ModIcon icon = null;
var ruleset = new OsuRuleset();
AddStep("create mod icon", () => Child = icon = new ModIcon(ruleset.AllMods.First(m => m.Acronym == "DT")));
AddStep("change mod", () => icon.Mod = ruleset.AllMods.First(m => m.Acronym == "EZ"));
}
} }
} }

View File

@ -18,9 +18,9 @@ namespace osu.Game.Online.API.Requests
private readonly BeatmapInfo beatmap; private readonly BeatmapInfo beatmap;
private readonly BeatmapLeaderboardScope scope; private readonly BeatmapLeaderboardScope scope;
private readonly RulesetInfo ruleset; private readonly RulesetInfo ruleset;
private readonly IEnumerable<Mod> mods; private readonly IEnumerable<IMod> mods;
public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable<Mod> mods = null) public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable<IMod> mods = null)
{ {
if (!beatmap.OnlineBeatmapID.HasValue) if (!beatmap.OnlineBeatmapID.HasValue)
throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}."); throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}.");
@ -31,7 +31,7 @@ namespace osu.Game.Online.API.Requests
this.beatmap = beatmap; this.beatmap = beatmap;
this.scope = scope; this.scope = scope;
this.ruleset = ruleset ?? throw new ArgumentNullException(nameof(ruleset)); this.ruleset = ruleset ?? throw new ArgumentNullException(nameof(ruleset));
this.mods = mods ?? Array.Empty<Mod>(); this.mods = mods ?? Array.Empty<IMod>();
Success += onSuccess; Success += onSuccess;
} }

View File

@ -19,7 +19,7 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
public class LeaderboardModSelector : CompositeDrawable public class LeaderboardModSelector : CompositeDrawable
{ {
public readonly BindableList<Mod> SelectedMods = new BindableList<Mod>(); public readonly BindableList<IMod> SelectedMods = new BindableList<IMod>();
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>(); public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
private readonly FillFlowContainer<ModButton> modsContainer; private readonly FillFlowContainer<ModButton> modsContainer;
@ -54,7 +54,7 @@ namespace osu.Game.Overlays.BeatmapSet
return; return;
modsContainer.Add(new ModButton(new ModNoMod())); modsContainer.Add(new ModButton(new ModNoMod()));
modsContainer.AddRange(ruleset.NewValue.CreateInstance().AllMods.Where(m => m.UserPlayable).Select(m => new ModButton(m.CreateInstance()))); modsContainer.AddRange(ruleset.NewValue.CreateInstance().AllMods.Where(m => m.UserPlayable).Select(m => new ModButton(m)));
modsContainer.ForEach(button => modsContainer.ForEach(button =>
{ {
@ -76,7 +76,7 @@ namespace osu.Game.Overlays.BeatmapSet
updateHighlighted(); updateHighlighted();
} }
private void selectionChanged(Mod mod, bool selected) private void selectionChanged(IMod mod, bool selected)
{ {
if (selected) if (selected)
SelectedMods.Add(mod); SelectedMods.Add(mod);
@ -101,9 +101,9 @@ namespace osu.Game.Overlays.BeatmapSet
private const int duration = 200; private const int duration = 200;
public readonly BindableBool Highlighted = new BindableBool(); public readonly BindableBool Highlighted = new BindableBool();
public Action<Mod, bool> OnSelectionChanged; public Action<IMod, bool> OnSelectionChanged;
public ModButton(Mod mod) public ModButton(IMod mod)
: base(mod) : base(mod)
{ {
Scale = new Vector2(0.4f); Scale = new Vector2(0.4f);

View File

@ -13,6 +13,21 @@ namespace osu.Game.Rulesets.Mods
/// </summary> /// </summary>
string Acronym { get; } string Acronym { get; }
/// <summary>
/// The name of this mod.
/// </summary>
string Name { get; }
/// <summary>
/// The user readable description of this mod.
/// </summary>
string Description { get; }
/// <summary>
/// The type of this mod.
/// </summary>
ModType Type { get; }
/// <summary> /// <summary>
/// The icon of this mod. /// The icon of this mod.
/// </summary> /// </summary>

View File

@ -22,29 +22,17 @@ namespace osu.Game.Rulesets.Mods
[ExcludeFromDynamicCompile] [ExcludeFromDynamicCompile]
public abstract class Mod : IMod, IEquatable<Mod>, IDeepCloneable<Mod> public abstract class Mod : IMod, IEquatable<Mod>, IDeepCloneable<Mod>
{ {
/// <summary>
/// The name of this mod.
/// </summary>
[JsonIgnore] [JsonIgnore]
public abstract string Name { get; } public abstract string Name { get; }
/// <summary>
/// The shortened name of this mod.
/// </summary>
public abstract string Acronym { get; } public abstract string Acronym { get; }
[JsonIgnore] [JsonIgnore]
public virtual IconUsage? Icon => null; public virtual IconUsage? Icon => null;
/// <summary>
/// The type of this mod.
/// </summary>
[JsonIgnore] [JsonIgnore]
public virtual ModType Type => ModType.Fun; public virtual ModType Type => ModType.Fun;
/// <summary>
/// The user readable description of this mod.
/// </summary>
[JsonIgnore] [JsonIgnore]
public abstract string Description { get; } public abstract string Description { get; }

View File

@ -30,12 +30,12 @@ namespace osu.Game.Rulesets.UI
private const float size = 80; private const float size = 80;
public virtual LocalisableString TooltipText => showTooltip ? mod.IconTooltip : null; public virtual LocalisableString TooltipText => showTooltip ? ((mod as Mod)?.IconTooltip ?? mod.Name) : null;
private Mod mod; private IMod mod;
private readonly bool showTooltip; private readonly bool showTooltip;
public Mod Mod public IMod Mod
{ {
get => mod; get => mod;
set set
@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.UI
/// </summary> /// </summary>
/// <param name="mod">The mod to be displayed</param> /// <param name="mod">The mod to be displayed</param>
/// <param name="showTooltip">Whether a tooltip describing the mod should display on hover.</param> /// <param name="showTooltip">Whether a tooltip describing the mod should display on hover.</param>
public ModIcon(Mod mod, bool showTooltip = true) public ModIcon(IMod mod, bool showTooltip = true)
{ {
this.mod = mod ?? throw new ArgumentNullException(nameof(mod)); this.mod = mod ?? throw new ArgumentNullException(nameof(mod));
this.showTooltip = showTooltip; this.showTooltip = showTooltip;
@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI
updateMod(mod); updateMod(mod);
} }
private void updateMod(Mod value) private void updateMod(IMod value)
{ {
modAcronym.Text = value.Acronym; modAcronym.Text = value.Acronym;
modIcon.Icon = value.Icon ?? FontAwesome.Solid.Question; modIcon.Icon = value.Icon ?? FontAwesome.Solid.Question;