Split out simple DifficultyIcon with no calculation overhead and update usages

This commit is contained in:
Dean Herbert
2022-06-23 18:37:53 +09:00
parent 4a2ca4394b
commit 7dec530ca5
8 changed files with 120 additions and 70 deletions

View File

@ -0,0 +1,80 @@
#nullable enable
// 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.
using System;
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osuTK;
namespace osu.Game.Beatmaps.Drawables
{
/// <summary>
/// A difficulty icon which automatically calculates difficulty in the background.
/// </summary>
public class CalculatingDifficultyIcon : CompositeDrawable
{
/// <summary>
/// Size of this difficulty icon.
/// </summary>
public new Vector2 Size
{
get => difficultyIcon.Size;
set => difficultyIcon.Size = value;
}
private readonly IRulesetInfo? ruleset;
private readonly IReadOnlyList<Mod>? mods;
private readonly IBeatmapInfo beatmapInfo;
private readonly DifficultyIcon difficultyIcon;
/// <summary>
/// Creates a new <see cref="CalculatingDifficultyIcon"/> with a given <see cref="RulesetInfo"/> and <see cref="Mod"/> combination.
/// </summary>
/// <param name="beatmapInfo">The beatmap to show the difficulty of.</param>
/// <param name="ruleset">The ruleset to show the difficulty with.</param>
/// <param name="mods">The mods to show the difficulty with.</param>
/// <param name="shouldShowTooltip">Whether to display a tooltip when hovered.</param>
/// <param name="performBackgroundDifficultyLookup">Whether to perform difficulty lookup (including calculation if necessary).</param>
public CalculatingDifficultyIcon(IBeatmapInfo beatmapInfo, IRulesetInfo? ruleset, IReadOnlyList<Mod>? mods, bool shouldShowTooltip = true,
bool performBackgroundDifficultyLookup = true)
: this(beatmapInfo, shouldShowTooltip, performBackgroundDifficultyLookup)
{
this.ruleset = ruleset ?? beatmapInfo.Ruleset;
this.mods = mods ?? Array.Empty<Mod>();
}
/// <summary>
/// Creates a new <see cref="CalculatingDifficultyIcon"/> that follows the currently-selected ruleset and mods.
/// </summary>
/// <param name="beatmapInfo">The beatmap to show the difficulty of.</param>
/// <param name="shouldShowTooltip">Whether to display a tooltip when hovered.</param>
/// <param name="performBackgroundDifficultyLookup">Whether to perform difficulty lookup (including calculation if necessary).</param>
public CalculatingDifficultyIcon(IBeatmapInfo beatmapInfo, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true)
{
this.beatmapInfo = beatmapInfo ?? throw new ArgumentNullException(nameof(beatmapInfo));
AutoSizeAxes = Axes.Both;
InternalChildren = new Drawable[]
{
difficultyIcon = new DifficultyIcon(beatmapInfo, beatmapInfo.Ruleset),
new DelayedLoadUnloadWrapper(createDifficultyRetriever, 0)
};
}
private Drawable createDifficultyRetriever()
{
if (ruleset != null && mods != null)
return new DifficultyRetriever(beatmapInfo, ruleset, mods) { StarDifficulty = { BindTarget = difficultyIcon.Current } };
return new DifficultyRetriever(beatmapInfo) { StarDifficulty = { BindTarget = difficultyIcon.Current } };
}
}
}

View File

@ -1,11 +1,6 @@
// 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.
#nullable disable
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
@ -15,16 +10,16 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Beatmaps.Drawables
{
public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip<DifficultyIconTooltipContent>
public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip<DifficultyIconTooltipContent>, IHasCurrentValue<StarDifficulty>
{
/// <summary>
/// Size of this difficulty icon.
@ -35,58 +30,46 @@ namespace osu.Game.Beatmaps.Drawables
set => iconContainer.Size = value;
}
[NotNull]
private readonly IBeatmapInfo beatmapInfo;
private readonly IBeatmapInfo? beatmap;
[CanBeNull]
private readonly IRulesetInfo ruleset;
[CanBeNull]
private readonly IReadOnlyList<Mod> mods;
[Resolved]
private IRulesetStore rulesets { get; set; }
private readonly bool shouldShowTooltip;
private readonly bool performBackgroundDifficultyLookup;
private Drawable background;
private Drawable background = null!;
private readonly Container iconContainer;
private readonly Bindable<StarDifficulty> difficultyBindable = new Bindable<StarDifficulty>();
private readonly BindableWithCurrent<StarDifficulty> difficulty = new BindableWithCurrent<StarDifficulty>();
public virtual Bindable<StarDifficulty> Current
{
get => difficulty.Current;
set => difficulty.Current = value;
}
[Resolved]
private IRulesetStore rulesets { get; set; } = null!;
/// <summary>
/// Creates a new <see cref="DifficultyIcon"/> with a given <see cref="RulesetInfo"/> and <see cref="Mod"/> combination.
/// Creates a new <see cref="DifficultyIcon"/> with a tooltip. Will use provided beatmap's <see cref="BeatmapInfo.StarRating"/> for initial value.
/// </summary>
/// <param name="beatmapInfo">The beatmap to show the difficulty of.</param>
/// <param name="ruleset">The ruleset to show the difficulty with.</param>
/// <param name="mods">The mods to show the difficulty with.</param>
/// <param name="shouldShowTooltip">Whether to display a tooltip when hovered.</param>
/// <param name="performBackgroundDifficultyLookup">Whether to perform difficulty lookup (including calculation if necessary).</param>
public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo ruleset, [CanBeNull] IReadOnlyList<Mod> mods, bool shouldShowTooltip = true,
bool performBackgroundDifficultyLookup = true)
: this(beatmapInfo, shouldShowTooltip, performBackgroundDifficultyLookup)
/// <param name="beatmap">The beatmap to be displayed in the tooltip, and to be used for the initial star rating value.</param>
/// <param name="ruleset">An optional ruleset to be used for the icon display, in place of the beatmap's ruleset.</param>
public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset)
: this(ruleset ?? beatmap.Ruleset)
{
this.ruleset = ruleset ?? beatmapInfo.Ruleset;
this.mods = mods ?? Array.Empty<Mod>();
this.beatmap = beatmap;
Current.Value = new StarDifficulty(beatmap.StarRating, 0);
}
/// <summary>
/// Creates a new <see cref="DifficultyIcon"/> that follows the currently-selected ruleset and mods.
/// Creates a new <see cref="DifficultyIcon"/> with no tooltip.
/// </summary>
/// <param name="beatmapInfo">The beatmap to show the difficulty of.</param>
/// <param name="shouldShowTooltip">Whether to display a tooltip when hovered.</param>
/// <param name="performBackgroundDifficultyLookup">Whether to perform difficulty lookup (including calculation if necessary).</param>
public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true)
/// <param name="ruleset">The ruleset to be used for the icon display.</param>
public DifficultyIcon(IRulesetInfo ruleset)
{
this.beatmapInfo = beatmapInfo ?? throw new ArgumentNullException(nameof(beatmapInfo));
this.shouldShowTooltip = shouldShowTooltip;
this.performBackgroundDifficultyLookup = performBackgroundDifficultyLookup;
this.ruleset = ruleset;
AutoSizeAxes = Axes.Both;
InternalChild = iconContainer = new Container { Size = new Vector2(20f) };
}
@ -111,7 +94,6 @@ namespace osu.Game.Beatmaps.Drawables
Child = background = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colours.ForStarDifficulty(beatmapInfo.StarRating) // Default value that will be re-populated once difficulty calculation completes
},
},
new ConstrainedIconContainer
@ -124,25 +106,12 @@ namespace osu.Game.Beatmaps.Drawables
},
};
if (performBackgroundDifficultyLookup)
iconContainer.Add(new DelayedLoadUnloadWrapper(createDifficultyRetriever, 0));
else
difficultyBindable.Value = new StarDifficulty(beatmapInfo.StarRating, 0);
difficultyBindable.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars));
}
private Drawable createDifficultyRetriever()
{
if (ruleset != null && mods != null)
return new DifficultyRetriever(beatmapInfo, ruleset, mods) { StarDifficulty = { BindTarget = difficultyBindable } };
return new DifficultyRetriever(beatmapInfo) { StarDifficulty = { BindTarget = difficultyBindable } };
Current.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars), true);
}
private Drawable getRulesetIcon()
{
int? onlineID = (ruleset ?? beatmapInfo.Ruleset).OnlineID;
int? onlineID = ruleset.OnlineID;
if (onlineID >= 0 && rulesets.GetRuleset(onlineID.Value)?.CreateInstance() is Ruleset rulesetInstance)
return rulesetInstance.CreateIcon();
@ -154,6 +123,6 @@ namespace osu.Game.Beatmaps.Drawables
GetCustomTooltip() => new DifficultyIconTooltip();
DifficultyIconTooltipContent IHasCustomTooltip<DifficultyIconTooltipContent>.
TooltipContent => shouldShowTooltip ? new DifficultyIconTooltipContent(beatmapInfo, difficultyBindable) : null;
TooltipContent => (beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current) : null)!;
}
}

View File

@ -19,7 +19,7 @@ namespace osu.Game.Beatmaps.Drawables
/// <remarks>
/// Used in cases when there are too many difficulty icons to show.
/// </remarks>
public class GroupedDifficultyIcon : DifficultyIcon
public class GroupedDifficultyIcon : CalculatingDifficultyIcon
{
public GroupedDifficultyIcon(IEnumerable<IBeatmapInfo> beatmaps, IRulesetInfo ruleset, Color4 counterColour)
: base(beatmaps.OrderBy(b => b.StarRating).Last(), ruleset, null, false)

View File

@ -274,8 +274,9 @@ namespace osu.Game.Overlays.BeatmapSet
Alpha = 0.5f
}
},
icon = new DifficultyIcon(beatmapInfo, shouldShowTooltip: false)
icon = new DifficultyIcon(beatmapInfo.Ruleset)
{
Current = { Value = new StarDifficulty(beatmapInfo.StarRating, 0) },
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(size - tile_icon_padding * 2),

View File

@ -266,7 +266,7 @@ namespace osu.Game.Screens.OnlinePlay
}
if (beatmap != null)
difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) };
difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset) { Size = new Vector2(icon_height) };
else
difficultyIconContainer.Clear();

View File

@ -113,7 +113,7 @@ namespace osu.Game.Screens.Select.Carousel
Origin = Anchor.CentreLeft,
Children = new Drawable[]
{
new DifficultyIcon(beatmapInfo, shouldShowTooltip: false)
new CalculatingDifficultyIcon(beatmapInfo, shouldShowTooltip: false)
{
Scale = new Vector2(1.8f),
},

View File

@ -10,7 +10,7 @@ using osu.Game.Beatmaps.Drawables;
namespace osu.Game.Screens.Select.Carousel
{
public class FilterableDifficultyIcon : DifficultyIcon
public class FilterableDifficultyIcon : CalculatingDifficultyIcon
{
private readonly BindableBool filtered = new BindableBool();
@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select.Carousel
public readonly CarouselBeatmap Item;
public FilterableDifficultyIcon(CarouselBeatmap item)
: base(item.BeatmapInfo, performBackgroundDifficultyLookup: false)
: base(item.BeatmapInfo)
{
filtered.BindTo(item.Filtered);
filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100));

View File

@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select.Carousel
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
Status = beatmapSet.Status
},
new FillFlowContainer<DifficultyIcon>
new FillFlowContainer<CalculatingDifficultyIcon>
{
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(3),
@ -87,13 +87,13 @@ namespace osu.Game.Screens.Select.Carousel
private const int maximum_difficulty_icons = 18;
private IEnumerable<DifficultyIcon> getDifficultyIcons()
private IEnumerable<CalculatingDifficultyIcon> getDifficultyIcons()
{
var beatmaps = carouselSet.Beatmaps.ToList();
return beatmaps.Count > maximum_difficulty_icons
? (IEnumerable<DifficultyIcon>)beatmaps.GroupBy(b => b.BeatmapInfo.Ruleset)
.Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Last().BeatmapInfo.Ruleset))
? (IEnumerable<CalculatingDifficultyIcon>)beatmaps.GroupBy(b => b.BeatmapInfo.Ruleset)
.Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Last().BeatmapInfo.Ruleset))
: beatmaps.Select(b => new FilterableDifficultyIcon(b));
}
}