2022-11-02 03:46:32 +08:00
|
|
|
// 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.
|
|
|
|
|
2022-11-02 20:00:45 +08:00
|
|
|
using System;
|
2022-11-04 01:54:55 +08:00
|
|
|
using System.Collections.Generic;
|
2024-10-17 16:26:02 +08:00
|
|
|
using System.Linq;
|
2024-10-17 16:05:49 +08:00
|
|
|
using System.Threading;
|
2022-11-02 03:46:32 +08:00
|
|
|
using JetBrains.Annotations;
|
|
|
|
using osu.Framework.Allocation;
|
|
|
|
using osu.Framework.Bindables;
|
2022-11-23 15:39:13 +08:00
|
|
|
using osu.Framework.Extensions;
|
|
|
|
using osu.Framework.Extensions.LocalisationExtensions;
|
2022-11-02 03:46:32 +08:00
|
|
|
using osu.Framework.Graphics;
|
2022-12-04 03:44:54 +08:00
|
|
|
using osu.Framework.Graphics.Sprites;
|
2022-11-02 20:00:45 +08:00
|
|
|
using osu.Framework.Localisation;
|
2022-11-02 04:19:01 +08:00
|
|
|
using osu.Game.Beatmaps;
|
2022-11-02 03:46:32 +08:00
|
|
|
using osu.Game.Configuration;
|
2022-11-02 20:00:45 +08:00
|
|
|
using osu.Game.Extensions;
|
2022-11-02 03:46:32 +08:00
|
|
|
using osu.Game.Graphics.Sprites;
|
2022-11-02 20:00:45 +08:00
|
|
|
using osu.Game.Localisation;
|
2023-02-03 14:34:57 +08:00
|
|
|
using osu.Game.Localisation.SkinComponents;
|
2022-11-02 20:00:45 +08:00
|
|
|
using osu.Game.Resources.Localisation.Web;
|
2024-10-17 16:26:02 +08:00
|
|
|
using osu.Game.Rulesets;
|
|
|
|
using osu.Game.Rulesets.Mods;
|
|
|
|
using osu.Game.Utils;
|
2022-11-02 03:46:32 +08:00
|
|
|
|
|
|
|
namespace osu.Game.Skinning.Components
|
|
|
|
{
|
|
|
|
[UsedImplicitly]
|
2023-01-26 15:04:56 +08:00
|
|
|
public partial class BeatmapAttributeText : FontAdjustableSkinComponent
|
2022-11-02 03:46:32 +08:00
|
|
|
{
|
2023-02-02 07:44:00 +08:00
|
|
|
[SettingSource(typeof(BeatmapAttributeTextStrings), nameof(BeatmapAttributeTextStrings.Attribute), nameof(BeatmapAttributeTextStrings.AttributeDescription))]
|
2022-11-23 15:31:50 +08:00
|
|
|
public Bindable<BeatmapAttribute> Attribute { get; } = new Bindable<BeatmapAttribute>(BeatmapAttribute.StarRating);
|
2022-11-02 03:46:32 +08:00
|
|
|
|
2023-02-02 07:44:00 +08:00
|
|
|
[SettingSource(typeof(BeatmapAttributeTextStrings), nameof(BeatmapAttributeTextStrings.Template), nameof(BeatmapAttributeTextStrings.TemplateDescription))]
|
2023-10-06 15:51:24 +08:00
|
|
|
public Bindable<string> Template { get; } = new Bindable<string>("{Label}: {Value}");
|
2022-11-02 20:00:45 +08:00
|
|
|
|
2022-11-02 03:46:32 +08:00
|
|
|
[Resolved]
|
2022-11-02 20:00:45 +08:00
|
|
|
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
|
2022-11-02 03:46:32 +08:00
|
|
|
|
2024-10-17 16:26:02 +08:00
|
|
|
[Resolved]
|
|
|
|
private IBindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
|
|
|
|
|
|
|
|
[Resolved]
|
|
|
|
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
|
|
|
|
2024-10-17 16:05:49 +08:00
|
|
|
[Resolved]
|
|
|
|
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
|
|
|
|
|
2022-11-02 03:46:32 +08:00
|
|
|
private readonly OsuSpriteText text;
|
2024-10-17 16:05:49 +08:00
|
|
|
private IBindable<StarDifficulty?>? difficultyBindable;
|
|
|
|
private CancellationTokenSource? difficultyCancellationSource;
|
2022-11-02 03:46:32 +08:00
|
|
|
|
2022-11-23 15:31:50 +08:00
|
|
|
public BeatmapAttributeText()
|
2022-11-02 03:46:32 +08:00
|
|
|
{
|
2022-11-07 22:22:20 +08:00
|
|
|
AutoSizeAxes = Axes.Both;
|
2022-11-23 15:56:40 +08:00
|
|
|
|
2022-11-02 03:46:32 +08:00
|
|
|
InternalChildren = new Drawable[]
|
|
|
|
{
|
|
|
|
text = new OsuSpriteText
|
|
|
|
{
|
2022-11-02 20:00:45 +08:00
|
|
|
Anchor = Anchor.CentreLeft,
|
|
|
|
Origin = Anchor.CentreLeft,
|
2022-11-02 03:46:32 +08:00
|
|
|
}
|
|
|
|
};
|
2022-11-04 01:54:55 +08:00
|
|
|
}
|
|
|
|
|
2022-11-02 03:46:32 +08:00
|
|
|
protected override void LoadComplete()
|
|
|
|
{
|
|
|
|
base.LoadComplete();
|
2022-11-23 15:56:40 +08:00
|
|
|
|
2024-10-17 15:01:44 +08:00
|
|
|
Attribute.BindValueChanged(_ => updateText());
|
|
|
|
Template.BindValueChanged(_ => updateText());
|
2024-10-17 16:05:49 +08:00
|
|
|
|
|
|
|
beatmap.BindValueChanged(b =>
|
|
|
|
{
|
|
|
|
difficultyCancellationSource?.Cancel();
|
|
|
|
difficultyCancellationSource = new CancellationTokenSource();
|
|
|
|
|
|
|
|
difficultyBindable?.UnbindAll();
|
|
|
|
difficultyBindable = difficultyCache.GetBindableDifficulty(b.NewValue.BeatmapInfo, difficultyCancellationSource.Token);
|
|
|
|
difficultyBindable.BindValueChanged(_ => updateText());
|
|
|
|
|
|
|
|
updateText();
|
|
|
|
}, true);
|
2022-11-02 20:00:45 +08:00
|
|
|
|
2024-10-17 16:26:02 +08:00
|
|
|
mods.BindValueChanged(_ => updateText());
|
|
|
|
ruleset.BindValueChanged(_ => updateText());
|
|
|
|
|
2024-10-17 15:01:44 +08:00
|
|
|
updateText();
|
2022-11-04 01:54:55 +08:00
|
|
|
}
|
2022-11-23 15:56:40 +08:00
|
|
|
|
2024-10-17 15:01:44 +08:00
|
|
|
private void updateText()
|
2022-11-23 15:56:40 +08:00
|
|
|
{
|
2022-11-24 04:02:43 +08:00
|
|
|
string numberedTemplate = Template.Value
|
|
|
|
.Replace("{", "{{")
|
|
|
|
.Replace("}", "}}")
|
|
|
|
.Replace(@"{{Label}}", "{0}")
|
2024-10-17 15:01:44 +08:00
|
|
|
.Replace(@"{{Value}}", "{1}");
|
2022-11-24 04:02:43 +08:00
|
|
|
|
2024-10-17 15:01:44 +08:00
|
|
|
List<object?> values = new List<object?>
|
|
|
|
{
|
|
|
|
getLabelString(Attribute.Value),
|
|
|
|
getValueString(Attribute.Value)
|
|
|
|
};
|
2022-11-23 15:56:40 +08:00
|
|
|
|
2022-12-27 03:36:39 +08:00
|
|
|
foreach (var type in Enum.GetValues<BeatmapAttribute>())
|
2022-11-23 15:56:40 +08:00
|
|
|
{
|
2024-10-17 15:01:44 +08:00
|
|
|
numberedTemplate = numberedTemplate.Replace($"{{{{{type}}}}}", $"{{{values.Count}}}");
|
|
|
|
values.Add(getValueString(type));
|
|
|
|
}
|
|
|
|
|
|
|
|
text.Text = LocalisableString.Format(numberedTemplate, values.ToArray());
|
|
|
|
}
|
|
|
|
|
|
|
|
private LocalisableString getLabelString(BeatmapAttribute attribute)
|
|
|
|
{
|
|
|
|
switch (attribute)
|
|
|
|
{
|
|
|
|
case BeatmapAttribute.CircleSize:
|
|
|
|
return BeatmapsetsStrings.ShowStatsCs;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Accuracy:
|
|
|
|
return BeatmapsetsStrings.ShowStatsAccuracy;
|
|
|
|
|
|
|
|
case BeatmapAttribute.HPDrain:
|
|
|
|
return BeatmapsetsStrings.ShowStatsDrain;
|
|
|
|
|
|
|
|
case BeatmapAttribute.ApproachRate:
|
|
|
|
return BeatmapsetsStrings.ShowStatsAr;
|
|
|
|
|
|
|
|
case BeatmapAttribute.StarRating:
|
|
|
|
return BeatmapsetsStrings.ShowStatsStars;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Title:
|
|
|
|
return EditorSetupStrings.Title;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Artist:
|
|
|
|
return EditorSetupStrings.Artist;
|
|
|
|
|
|
|
|
case BeatmapAttribute.DifficultyName:
|
|
|
|
return EditorSetupStrings.DifficultyHeader;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Creator:
|
|
|
|
return EditorSetupStrings.Creator;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Source:
|
|
|
|
return EditorSetupStrings.Source;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Length:
|
|
|
|
return ArtistStrings.TracklistLength.ToTitle();
|
|
|
|
|
|
|
|
case BeatmapAttribute.RankedStatus:
|
|
|
|
return BeatmapDiscussionsStrings.IndexFormBeatmapsetStatusDefault;
|
|
|
|
|
|
|
|
case BeatmapAttribute.BPM:
|
|
|
|
return BeatmapsetsStrings.ShowStatsBpm;
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new ArgumentOutOfRangeException();
|
2022-11-23 15:56:40 +08:00
|
|
|
}
|
2024-10-17 15:01:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private LocalisableString getValueString(BeatmapAttribute attribute)
|
|
|
|
{
|
|
|
|
switch (attribute)
|
|
|
|
{
|
|
|
|
case BeatmapAttribute.Title:
|
|
|
|
return new RomanisableString(beatmap.Value.BeatmapInfo.Metadata.TitleUnicode, beatmap.Value.BeatmapInfo.Metadata.Title);
|
|
|
|
|
|
|
|
case BeatmapAttribute.Artist:
|
|
|
|
return new RomanisableString(beatmap.Value.BeatmapInfo.Metadata.ArtistUnicode, beatmap.Value.BeatmapInfo.Metadata.Artist);
|
|
|
|
|
|
|
|
case BeatmapAttribute.DifficultyName:
|
|
|
|
return beatmap.Value.BeatmapInfo.DifficultyName;
|
2022-11-23 15:56:40 +08:00
|
|
|
|
2024-10-17 15:01:44 +08:00
|
|
|
case BeatmapAttribute.Creator:
|
|
|
|
return beatmap.Value.BeatmapInfo.Metadata.Author.Username;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Source:
|
|
|
|
return beatmap.Value.BeatmapInfo.Metadata.Source;
|
|
|
|
|
|
|
|
case BeatmapAttribute.Length:
|
|
|
|
return TimeSpan.FromMilliseconds(beatmap.Value.BeatmapInfo.Length).ToFormattedDuration();
|
|
|
|
|
|
|
|
case BeatmapAttribute.RankedStatus:
|
|
|
|
return beatmap.Value.BeatmapInfo.Status.GetLocalisableDescription();
|
|
|
|
|
|
|
|
case BeatmapAttribute.BPM:
|
|
|
|
return beatmap.Value.BeatmapInfo.BPM.ToLocalisableString(@"F2");
|
|
|
|
|
|
|
|
case BeatmapAttribute.CircleSize:
|
2024-10-17 16:26:02 +08:00
|
|
|
return computeDifficulty().CircleSize.ToLocalisableString(@"F2");
|
2024-10-17 15:01:44 +08:00
|
|
|
|
|
|
|
case BeatmapAttribute.HPDrain:
|
2024-10-17 16:26:02 +08:00
|
|
|
return computeDifficulty().DrainRate.ToLocalisableString(@"F2");
|
2024-10-17 15:01:44 +08:00
|
|
|
|
|
|
|
case BeatmapAttribute.Accuracy:
|
2024-10-17 16:26:02 +08:00
|
|
|
return computeDifficulty().OverallDifficulty.ToLocalisableString(@"F2");
|
2024-10-17 15:01:44 +08:00
|
|
|
|
|
|
|
case BeatmapAttribute.ApproachRate:
|
2024-10-17 16:26:02 +08:00
|
|
|
return computeDifficulty().ApproachRate.ToLocalisableString(@"F2");
|
2024-10-17 15:01:44 +08:00
|
|
|
|
|
|
|
case BeatmapAttribute.StarRating:
|
2024-10-17 16:05:49 +08:00
|
|
|
return difficultyBindable?.Value is StarDifficulty starDifficulty
|
|
|
|
? starDifficulty.Stars.ToLocalisableString(@"F2")
|
|
|
|
: @"...";
|
2024-10-17 15:01:44 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
}
|
2024-10-17 16:26:02 +08:00
|
|
|
|
|
|
|
BeatmapDifficulty computeDifficulty()
|
|
|
|
{
|
|
|
|
BeatmapDifficulty difficulty = new BeatmapDifficulty(beatmap.Value.BeatmapInfo.Difficulty);
|
|
|
|
|
|
|
|
foreach (var mod in mods.Value.OfType<IApplicableToDifficulty>())
|
|
|
|
mod.ApplyToDifficulty(difficulty);
|
|
|
|
|
|
|
|
if (ruleset.Value is RulesetInfo rulesetInfo)
|
|
|
|
{
|
|
|
|
double rate = ModUtils.CalculateRateWithMods(mods.Value);
|
|
|
|
difficulty = rulesetInfo.CreateInstance().GetRateAdjustedDisplayDifficulty(difficulty, rate);
|
|
|
|
}
|
|
|
|
|
|
|
|
return difficulty;
|
|
|
|
}
|
2022-11-23 15:56:40 +08:00
|
|
|
}
|
2022-12-04 03:44:54 +08:00
|
|
|
|
|
|
|
protected override void SetFont(FontUsage font) => text.Font = font.With(size: 40);
|
2024-08-06 17:06:08 +08:00
|
|
|
|
2024-09-20 22:50:17 +08:00
|
|
|
protected override void SetTextColour(Colour4 textColour) => text.Colour = textColour;
|
2024-10-17 16:05:49 +08:00
|
|
|
|
|
|
|
protected override void Dispose(bool isDisposing)
|
|
|
|
{
|
|
|
|
base.Dispose(isDisposing);
|
|
|
|
|
|
|
|
difficultyCancellationSource?.Cancel();
|
|
|
|
difficultyCancellationSource?.Dispose();
|
|
|
|
difficultyCancellationSource = null;
|
|
|
|
}
|
2022-11-02 03:46:32 +08:00
|
|
|
}
|
|
|
|
|
2024-05-03 20:27:34 +08:00
|
|
|
// WARNING: DO NOT ADD ANY VALUES TO THIS ENUM ANYWHERE ELSE THAN AT THE END.
|
|
|
|
// Doing so will break existing user skins.
|
2022-11-23 15:31:50 +08:00
|
|
|
public enum BeatmapAttribute
|
2022-11-02 03:46:32 +08:00
|
|
|
{
|
|
|
|
CircleSize,
|
|
|
|
HPDrain,
|
2022-11-02 03:54:52 +08:00
|
|
|
Accuracy,
|
2022-11-02 03:46:32 +08:00
|
|
|
ApproachRate,
|
|
|
|
StarRating,
|
2022-11-23 15:39:13 +08:00
|
|
|
Title,
|
2022-11-02 03:46:32 +08:00
|
|
|
Artist,
|
2022-11-23 15:39:13 +08:00
|
|
|
DifficultyName,
|
|
|
|
Creator,
|
2022-11-02 03:46:32 +08:00
|
|
|
Length,
|
2022-11-23 15:39:13 +08:00
|
|
|
RankedStatus,
|
2022-11-02 03:46:32 +08:00
|
|
|
BPM,
|
2024-05-03 20:27:34 +08:00
|
|
|
Source,
|
2022-11-02 03:46:32 +08:00
|
|
|
}
|
|
|
|
}
|