1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-16 01:17:27 +08:00
osu-lazer/osu.Game/Skinning/Components/BeatmapAttributeText.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

274 lines
9.8 KiB
C#
Raw Normal View History

// 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 System.Linq;
using System.Threading;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
2022-12-04 03:44:54 +08:00
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Graphics.Sprites;
using osu.Game.Localisation;
using osu.Game.Localisation.SkinComponents;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Utils;
namespace osu.Game.Skinning.Components
{
[UsedImplicitly]
public partial class BeatmapAttributeText : FontAdjustableSkinComponent
{
[SettingSource(typeof(BeatmapAttributeTextStrings), nameof(BeatmapAttributeTextStrings.Attribute), nameof(BeatmapAttributeTextStrings.AttributeDescription))]
public Bindable<BeatmapAttribute> Attribute { get; } = new Bindable<BeatmapAttribute>(BeatmapAttribute.StarRating);
[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}");
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
[Resolved]
private IBindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
[Resolved]
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
[Resolved]
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
private readonly OsuSpriteText text;
private IBindable<StarDifficulty?>? difficultyBindable;
private CancellationTokenSource? difficultyCancellationSource;
2024-10-17 16:42:40 +08:00
private ModSettingChangeTracker? modSettingTracker;
public BeatmapAttributeText()
{
2022-11-07 22:22:20 +08:00
AutoSizeAxes = Axes.Both;
2022-11-23 15:56:40 +08:00
InternalChildren = new Drawable[]
{
text = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
2022-11-23 15:56:40 +08:00
Attribute.BindValueChanged(_ => updateText());
Template.BindValueChanged(_ => updateText());
beatmap.BindValueChanged(b =>
{
difficultyCancellationSource?.Cancel();
difficultyCancellationSource = new CancellationTokenSource();
difficultyBindable?.UnbindAll();
difficultyBindable = difficultyCache.GetBindableDifficulty(b.NewValue.BeatmapInfo, difficultyCancellationSource.Token);
difficultyBindable.BindValueChanged(_ => updateText());
updateText();
}, true);
2024-10-17 16:42:40 +08:00
mods.BindValueChanged(m =>
{
modSettingTracker?.Dispose();
modSettingTracker = new ModSettingChangeTracker(m.NewValue)
{
SettingChanged = _ => updateText()
};
updateText();
}, true);
ruleset.BindValueChanged(_ => updateText());
updateText();
}
2022-11-23 15:56:40 +08:00
private void updateText()
2022-11-23 15:56:40 +08:00
{
string numberedTemplate = Template.Value
.Replace("{", "{{")
.Replace("}", "}}")
.Replace(@"{{Label}}", "{0}")
.Replace(@"{{Value}}", "{1}");
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
{
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
}
}
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
case BeatmapAttribute.Creator:
return beatmap.Value.BeatmapInfo.Metadata.Author.Username;
case BeatmapAttribute.Source:
return beatmap.Value.BeatmapInfo.Metadata.Source;
case BeatmapAttribute.Length:
2024-10-17 16:32:32 +08:00
return Math.Round(beatmap.Value.BeatmapInfo.Length / ModUtils.CalculateRateWithMods(mods.Value)).ToFormattedDuration();
case BeatmapAttribute.RankedStatus:
return beatmap.Value.BeatmapInfo.Status.GetLocalisableDescription();
case BeatmapAttribute.BPM:
2024-10-17 16:32:32 +08:00
return FormatUtils.RoundBPM(beatmap.Value.BeatmapInfo.BPM, ModUtils.CalculateRateWithMods(mods.Value)).ToLocalisableString(@"F2");
case BeatmapAttribute.CircleSize:
return computeDifficulty().CircleSize.ToLocalisableString(@"F2");
case BeatmapAttribute.HPDrain:
return computeDifficulty().DrainRate.ToLocalisableString(@"F2");
case BeatmapAttribute.Accuracy:
return computeDifficulty().OverallDifficulty.ToLocalisableString(@"F2");
case BeatmapAttribute.ApproachRate:
return computeDifficulty().ApproachRate.ToLocalisableString(@"F2");
case BeatmapAttribute.StarRating:
return difficultyBindable?.Value is StarDifficulty starDifficulty
? starDifficulty.Stars.ToLocalisableString(@"F2")
: @"...";
default:
throw new ArgumentOutOfRangeException();
}
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-09-20 22:50:17 +08:00
protected override void SetTextColour(Colour4 textColour) => text.Colour = textColour;
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
difficultyCancellationSource?.Cancel();
difficultyCancellationSource?.Dispose();
difficultyCancellationSource = null;
}
}
// WARNING: DO NOT ADD ANY VALUES TO THIS ENUM ANYWHERE ELSE THAN AT THE END.
// Doing so will break existing user skins.
public enum BeatmapAttribute
{
CircleSize,
HPDrain,
Accuracy,
ApproachRate,
StarRating,
Title,
Artist,
DifficultyName,
Creator,
Length,
RankedStatus,
BPM,
Source,
}
}