diff --git a/osu.Android.props b/osu.Android.props
index 490e43b5e6..1f60f02fb1 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,6 +52,6 @@
-
+
diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs
new file mode 100644
index 0000000000..3090facf8c
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs
@@ -0,0 +1,12 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Tests.Visual;
+
+namespace osu.Game.Rulesets.Taiko.Tests.Mods
+{
+ public abstract class TaikoModTestScene : ModTestScene
+ {
+ protected sealed override Ruleset CreatePlayerRuleset() => new TaikoRuleset();
+ }
+}
diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs
new file mode 100644
index 0000000000..7abbb9d186
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs
@@ -0,0 +1,24 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using NUnit.Framework;
+using osu.Game.Rulesets.Taiko.Mods;
+
+namespace osu.Game.Rulesets.Taiko.Tests.Mods
+{
+ public class TestSceneTaikoModHidden : TaikoModTestScene
+ {
+ [Test]
+ public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData
+ {
+ Mod = new TaikoModHidden(),
+ Autoplay = true,
+ PassCondition = checkSomeAutoplayHits
+ });
+
+ private bool checkSomeAutoplayHits()
+ => Player.ScoreProcessor.JudgedHits >= 4
+ && Player.Results.All(result => result.Type == result.Judgement.MaxResult);
+ }
+}
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
index 7739ecaf5b..0fd3625a93 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs
@@ -1,23 +1,93 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using osu.Framework.Graphics;
+using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.Scoring;
+using osu.Game.Rulesets.Taiko.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.Mods
{
- public class TaikoModHidden : ModHidden
+ public class TaikoModHidden : ModHidden, IApplicableToDifficulty
{
public override string Description => @"Beats fade out before you hit them!";
public override double ScoreMultiplier => 1.06;
- public override bool HasImplementation => false;
+
+ ///
+ /// In osu-stable, the hit position is 160, so the active playfield is essentially 160 pixels shorter
+ /// than the actual screen width. The normalized playfield height is 480, so on a 4:3 screen the
+ /// playfield ratio of the active area up to the hit position will actually be (640 - 160) / 480 = 1.
+ /// For custom resolutions/aspect ratios (x:y), the screen width given the normalized height becomes 480 * x / y instead,
+ /// and the playfield ratio becomes (480 * x / y - 160) / 480 = x / y - 1/3.
+ /// This constant is equal to the playfield ratio on 4:3 screens divided by the playfield ratio on 16:9 screens.
+ ///
+ private const double hd_sv_scale = (4.0 / 3.0 - 1.0 / 3.0) / (16.0 / 9.0 - 1.0 / 3.0);
+
+ private double originalSliderMultiplier;
+
+ private ControlPointInfo controlPointInfo;
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
{
+ ApplyNormalVisibilityState(hitObject, state);
+ }
+
+ protected double MultiplierAt(double position)
+ {
+ double beatLength = controlPointInfo.TimingPointAt(position).BeatLength;
+ double speedMultiplier = controlPointInfo.DifficultyPointAt(position).SpeedMultiplier;
+
+ return originalSliderMultiplier * speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength;
}
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
{
+ switch (hitObject)
+ {
+ case DrawableDrumRollTick _:
+ case DrawableHit _:
+ double preempt = 10000 / MultiplierAt(hitObject.HitObject.StartTime);
+ double start = hitObject.HitObject.StartTime - preempt * 0.6;
+ double duration = preempt * 0.3;
+
+ using (hitObject.BeginAbsoluteSequence(start))
+ {
+ hitObject.FadeOut(duration);
+
+ // DrawableHitObject sets LifetimeEnd to LatestTransformEndTime if it isn't manually changed.
+ // in order for the object to not be killed before its actual end time (as the latest transform ends earlier), set lifetime end explicitly.
+ hitObject.LifetimeEnd = state == ArmedState.Idle || !hitObject.AllJudged
+ ? hitObject.HitObject.GetEndTime() + hitObject.HitObject.HitWindows.WindowFor(HitResult.Miss)
+ : hitObject.HitStateUpdateTime;
+ }
+
+ break;
+ }
+ }
+
+ public void ReadFromDifficulty(BeatmapDifficulty difficulty)
+ {
+ }
+
+ public void ApplyToDifficulty(BeatmapDifficulty difficulty)
+ {
+ // needs to be read after all processing has been run (TaikoBeatmapConverter applies an adjustment which would otherwise be omitted).
+ originalSliderMultiplier = difficulty.SliderMultiplier;
+
+ // osu-stable has an added playfield cover that essentially forces a 4:3 playfield ratio, by cutting off all objects past that size.
+ // This is not yet implemented; instead a playfield adjustment container is present which maintains a 16:9 ratio.
+ // For now, increase the slider multiplier proportionally so that the notes stay on the screen for the same amount of time as on stable.
+ // Note that this means that the notes will scroll faster as they have a longer distance to travel on the screen in that same amount of time.
+ difficulty.SliderMultiplier /= hd_sv_scale;
+ }
+
+ public override void ApplyToBeatmap(IBeatmap beatmap)
+ {
+ controlPointInfo = beatmap.ControlPointInfo;
}
}
}
diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs
index d3a4b635f5..25d0843a71 100644
--- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs
+++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Framework.Lists;
@@ -66,6 +67,7 @@ namespace osu.Game.Beatmaps.ControlPoints
///
/// The time to find the difficulty control point at.
/// The difficulty control point.
+ [NotNull]
public DifficultyControlPoint DifficultyPointAt(double time) => binarySearchWithFallback(DifficultyPoints, time, DifficultyControlPoint.DEFAULT);
///
@@ -73,6 +75,7 @@ namespace osu.Game.Beatmaps.ControlPoints
///
/// The time to find the effect control point at.
/// The effect control point.
+ [NotNull]
public EffectControlPoint EffectPointAt(double time) => binarySearchWithFallback(EffectPoints, time, EffectControlPoint.DEFAULT);
///
@@ -80,6 +83,7 @@ namespace osu.Game.Beatmaps.ControlPoints
///
/// The time to find the sound control point at.
/// The sound control point.
+ [NotNull]
public SampleControlPoint SamplePointAt(double time) => binarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : SampleControlPoint.DEFAULT);
///
@@ -87,6 +91,7 @@ namespace osu.Game.Beatmaps.ControlPoints
///
/// The time to find the timing control point at.
/// The timing control point.
+ [NotNull]
public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : TimingControlPoint.DEFAULT);
///
diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs
index dbcce9a84a..0c220336a5 100644
--- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs
@@ -160,7 +160,7 @@ namespace osu.Game.Graphics.UserInterface
Margin = new MarginPadding { Top = 5, Bottom = 5 },
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
- Text = (value as IHasDescription)?.Description ?? (value as Enum)?.GetDescription() ?? value.ToString(),
+ Text = (value as IHasDescription)?.Description ?? (value as Enum)?.GetLocalisableDescription() ?? value.ToString(),
Font = OsuFont.GetFont(size: 14)
},
Bar = new Box
diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs
index d05a08108a..1ba9ad53bb 100644
--- a/osu.Game/Graphics/UserInterface/PageTabControl.cs
+++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs
@@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
+using osu.Framework.Localisation;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface
@@ -81,7 +82,7 @@ namespace osu.Game.Graphics.UserInterface
Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Torus, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true);
}
- protected virtual string CreateText() => (Value as Enum)?.GetDescription() ?? Value.ToString();
+ protected virtual LocalisableString CreateText() => (Value as Enum)?.GetLocalisableDescription() ?? Value.ToString();
protected override bool OnHover(HoverEvent e)
{
diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs
index abfffe907f..b39934b56f 100644
--- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs
+++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs
@@ -1,9 +1,9 @@
// Copyright (c) ppy Pty Ltd . 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 osu.Framework.Extensions;
using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Scoring;
@@ -33,38 +33,7 @@ namespace osu.Game.Overlays.BeatmapListing
{
}
- protected override LocalisableString LabelFor(ScoreRank value)
- {
- switch (value)
- {
- case ScoreRank.XH:
- return BeatmapsStrings.RankXH;
-
- case ScoreRank.X:
- return BeatmapsStrings.RankX;
-
- case ScoreRank.SH:
- return BeatmapsStrings.RankSH;
-
- case ScoreRank.S:
- return BeatmapsStrings.RankS;
-
- case ScoreRank.A:
- return BeatmapsStrings.RankA;
-
- case ScoreRank.B:
- return BeatmapsStrings.RankB;
-
- case ScoreRank.C:
- return BeatmapsStrings.RankC;
-
- case ScoreRank.D:
- return BeatmapsStrings.RankD;
-
- default:
- throw new ArgumentException("Unsupported value.", nameof(value));
- }
- }
+ protected override LocalisableString LabelFor(ScoreRank value) => value.GetLocalisableDescription();
}
}
}
diff --git a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs
index d64ee59682..46cb1e822f 100644
--- a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs
+++ b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs
@@ -67,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapListing
///
/// Returns the label text to be used for the supplied .
///
- protected virtual LocalisableString LabelFor(T value) => (value as Enum)?.GetDescription() ?? value.ToString();
+ protected virtual LocalisableString LabelFor(T value) => (value as Enum)?.GetLocalisableDescription() ?? value.ToString();
private void updateState()
{
diff --git a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs
index 84859bf5b5..8a9df76af3 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs
@@ -1,10 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.ComponentModel;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchCategoryEnumLocalisationMapper))]
public enum SearchCategory
{
Any,
@@ -23,4 +27,43 @@ namespace osu.Game.Overlays.BeatmapListing
[Description("My Maps")]
Mine,
}
+
+ public class SearchCategoryEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchCategory value)
+ {
+ switch (value)
+ {
+ case SearchCategory.Any:
+ return BeatmapsStrings.StatusAny;
+
+ case SearchCategory.Leaderboard:
+ return BeatmapsStrings.StatusLeaderboard;
+
+ case SearchCategory.Ranked:
+ return BeatmapsStrings.StatusRanked;
+
+ case SearchCategory.Qualified:
+ return BeatmapsStrings.StatusQualified;
+
+ case SearchCategory.Loved:
+ return BeatmapsStrings.StatusLoved;
+
+ case SearchCategory.Favourites:
+ return BeatmapsStrings.StatusFavourites;
+
+ case SearchCategory.Pending:
+ return BeatmapsStrings.StatusPending;
+
+ case SearchCategory.Graveyard:
+ return BeatmapsStrings.StatusGraveyard;
+
+ case SearchCategory.Mine:
+ return BeatmapsStrings.StatusMine;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs
index 3e57cdd48c..78e6a4e094 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs
@@ -1,11 +1,34 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
+
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchExplicitEnumLocalisationMapper))]
public enum SearchExplicit
{
Hide,
Show
}
+
+ public class SearchExplicitEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchExplicit value)
+ {
+ switch (value)
+ {
+ case SearchExplicit.Hide:
+ return BeatmapsStrings.NsfwExclude;
+
+ case SearchExplicit.Show:
+ return BeatmapsStrings.NsfwInclude;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs
index af37e3264f..4b3fb6e833 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs
@@ -1,10 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.ComponentModel;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchExtraEnumLocalisationMapper))]
public enum SearchExtra
{
[Description("Has Video")]
@@ -13,4 +17,22 @@ namespace osu.Game.Overlays.BeatmapListing
[Description("Has Storyboard")]
Storyboard
}
+
+ public class SearchExtraEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchExtra value)
+ {
+ switch (value)
+ {
+ case SearchExtra.Video:
+ return BeatmapsStrings.ExtraVideo;
+
+ case SearchExtra.Storyboard:
+ return BeatmapsStrings.ExtraStoryboard;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs
index 175942c626..b4c629f7fa 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs
@@ -1,10 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.ComponentModel;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchGeneralEnumLocalisationMapper))]
public enum SearchGeneral
{
[Description("Recommended difficulty")]
@@ -16,4 +20,25 @@ namespace osu.Game.Overlays.BeatmapListing
[Description("Subscribed mappers")]
Follows
}
+
+ public class SearchGeneralEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchGeneral value)
+ {
+ switch (value)
+ {
+ case SearchGeneral.Recommended:
+ return BeatmapsStrings.GeneralRecommended;
+
+ case SearchGeneral.Converts:
+ return BeatmapsStrings.GeneralConverts;
+
+ case SearchGeneral.Follows:
+ return BeatmapsStrings.GeneralFollows;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs
index de437fac3e..b2709ecd2e 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs
@@ -1,10 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.ComponentModel;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchGenreEnumLocalisationMapper))]
public enum SearchGenre
{
Any = 0,
@@ -26,4 +30,58 @@ namespace osu.Game.Overlays.BeatmapListing
Folk = 13,
Jazz = 14
}
+
+ public class SearchGenreEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchGenre value)
+ {
+ switch (value)
+ {
+ case SearchGenre.Any:
+ return BeatmapsStrings.GenreAny;
+
+ case SearchGenre.Unspecified:
+ return BeatmapsStrings.GenreUnspecified;
+
+ case SearchGenre.VideoGame:
+ return BeatmapsStrings.GenreVideoGame;
+
+ case SearchGenre.Anime:
+ return BeatmapsStrings.GenreAnime;
+
+ case SearchGenre.Rock:
+ return BeatmapsStrings.GenreRock;
+
+ case SearchGenre.Pop:
+ return BeatmapsStrings.GenrePop;
+
+ case SearchGenre.Other:
+ return BeatmapsStrings.GenreOther;
+
+ case SearchGenre.Novelty:
+ return BeatmapsStrings.GenreNovelty;
+
+ case SearchGenre.HipHop:
+ return BeatmapsStrings.GenreHipHop;
+
+ case SearchGenre.Electronic:
+ return BeatmapsStrings.GenreElectronic;
+
+ case SearchGenre.Metal:
+ return BeatmapsStrings.GenreMetal;
+
+ case SearchGenre.Classical:
+ return BeatmapsStrings.GenreClassical;
+
+ case SearchGenre.Folk:
+ return BeatmapsStrings.GenreFolk;
+
+ case SearchGenre.Jazz:
+ return BeatmapsStrings.GenreJazz;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs
index 015cee8ce3..fc176c305a 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs
@@ -1,10 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using osu.Framework.Localisation;
using osu.Framework.Utils;
+using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchLanguageEnumLocalisationMapper))]
[HasOrderedElements]
public enum SearchLanguage
{
@@ -53,4 +57,61 @@ namespace osu.Game.Overlays.BeatmapListing
[Order(13)]
Other
}
+
+ public class SearchLanguageEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchLanguage value)
+ {
+ switch (value)
+ {
+ case SearchLanguage.Any:
+ return BeatmapsStrings.LanguageAny;
+
+ case SearchLanguage.Unspecified:
+ return BeatmapsStrings.LanguageUnspecified;
+
+ case SearchLanguage.English:
+ return BeatmapsStrings.LanguageEnglish;
+
+ case SearchLanguage.Japanese:
+ return BeatmapsStrings.LanguageJapanese;
+
+ case SearchLanguage.Chinese:
+ return BeatmapsStrings.LanguageChinese;
+
+ case SearchLanguage.Instrumental:
+ return BeatmapsStrings.LanguageInstrumental;
+
+ case SearchLanguage.Korean:
+ return BeatmapsStrings.LanguageKorean;
+
+ case SearchLanguage.French:
+ return BeatmapsStrings.LanguageFrench;
+
+ case SearchLanguage.German:
+ return BeatmapsStrings.LanguageGerman;
+
+ case SearchLanguage.Swedish:
+ return BeatmapsStrings.LanguageSwedish;
+
+ case SearchLanguage.Spanish:
+ return BeatmapsStrings.LanguageSpanish;
+
+ case SearchLanguage.Italian:
+ return BeatmapsStrings.LanguageItalian;
+
+ case SearchLanguage.Russian:
+ return BeatmapsStrings.LanguageRussian;
+
+ case SearchLanguage.Polish:
+ return BeatmapsStrings.LanguagePolish;
+
+ case SearchLanguage.Other:
+ return BeatmapsStrings.LanguageOther;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs
index eb7fb46158..f24cf46c2d 100644
--- a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs
+++ b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs
@@ -1,12 +1,38 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
+
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SearchPlayedEnumLocalisationMapper))]
public enum SearchPlayed
{
Any,
Played,
Unplayed
}
+
+ public class SearchPlayedEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SearchPlayed value)
+ {
+ switch (value)
+ {
+ case SearchPlayed.Any:
+ return BeatmapsStrings.PlayedAny;
+
+ case SearchPlayed.Played:
+ return BeatmapsStrings.PlayedPlayed;
+
+ case SearchPlayed.Unplayed:
+ return BeatmapsStrings.PlayedUnplayed;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs
index e409cbdda7..5ea885eecc 100644
--- a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs
+++ b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs
@@ -1,8 +1,13 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
+
namespace osu.Game.Overlays.BeatmapListing
{
+ [LocalisableEnum(typeof(SortCriteriaLocalisationMapper))]
public enum SortCriteria
{
Title,
@@ -14,4 +19,40 @@ namespace osu.Game.Overlays.BeatmapListing
Favourites,
Relevance
}
+
+ public class SortCriteriaLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(SortCriteria value)
+ {
+ switch (value)
+ {
+ case SortCriteria.Title:
+ return BeatmapsStrings.ListingSearchSortingTitle;
+
+ case SortCriteria.Artist:
+ return BeatmapsStrings.ListingSearchSortingArtist;
+
+ case SortCriteria.Difficulty:
+ return BeatmapsStrings.ListingSearchSortingDifficulty;
+
+ case SortCriteria.Ranked:
+ return BeatmapsStrings.ListingSearchSortingRanked;
+
+ case SortCriteria.Rating:
+ return BeatmapsStrings.ListingSearchSortingRating;
+
+ case SortCriteria.Plays:
+ return BeatmapsStrings.ListingSearchSortingPlays;
+
+ case SortCriteria.Favourites:
+ return BeatmapsStrings.ListingSearchSortingFavourites;
+
+ case SortCriteria.Relevance:
+ return BeatmapsStrings.ListingSearchSortingRelevance;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/Overlays/OverlaySortTabControl.cs b/osu.Game/Overlays/OverlaySortTabControl.cs
index 15c43eeb01..b230acca11 100644
--- a/osu.Game/Overlays/OverlaySortTabControl.cs
+++ b/osu.Game/Overlays/OverlaySortTabControl.cs
@@ -144,7 +144,7 @@ namespace osu.Game.Overlays
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold),
- Text = (value as Enum)?.GetDescription() ?? value.ToString()
+ Text = (value as Enum)?.GetLocalisableDescription() ?? value.ToString()
}
}
});
diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs
index 7798dfa576..e6f7e250a7 100644
--- a/osu.Game/Overlays/TabControlOverlayHeader.cs
+++ b/osu.Game/Overlays/TabControlOverlayHeader.cs
@@ -106,7 +106,19 @@ namespace osu.Game.Overlays
public OverlayHeaderTabItem(T value)
: base(value)
{
- Text.Text = ((Value as Enum)?.GetDescription() ?? Value.ToString()).ToLower();
+ if (!(Value is Enum enumValue))
+ Text.Text = Value.ToString().ToLower();
+ else
+ {
+ var localisableDescription = enumValue.GetLocalisableDescription();
+ var nonLocalisableDescription = enumValue.GetDescription();
+
+ // If localisable == non-localisable, then we must have a basic string, so .ToLower() is used.
+ Text.Text = localisableDescription.Equals(nonLocalisableDescription)
+ ? nonLocalisableDescription.ToLower()
+ : localisableDescription;
+ }
+
Text.Font = OsuFont.GetFont(size: 14);
Text.Margin = new MarginPadding { Vertical = 16.5f }; // 15px padding + 1.5px line-height difference compensation
Bar.Margin = new MarginPadding { Bottom = bar_height };
diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs
index 696d493830..f3b4551ff8 100644
--- a/osu.Game/Scoring/ScoreRank.cs
+++ b/osu.Game/Scoring/ScoreRank.cs
@@ -1,10 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.ComponentModel;
+using osu.Framework.Localisation;
+using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Scoring
{
+ [LocalisableEnum(typeof(ScoreRankEnumLocalisationMapper))]
public enum ScoreRank
{
[Description(@"D")]
@@ -31,4 +35,40 @@ namespace osu.Game.Scoring
[Description(@"SS+")]
XH,
}
+
+ public class ScoreRankEnumLocalisationMapper : EnumLocalisationMapper
+ {
+ public override LocalisableString Map(ScoreRank value)
+ {
+ switch (value)
+ {
+ case ScoreRank.XH:
+ return BeatmapsStrings.RankXH;
+
+ case ScoreRank.X:
+ return BeatmapsStrings.RankX;
+
+ case ScoreRank.SH:
+ return BeatmapsStrings.RankSH;
+
+ case ScoreRank.S:
+ return BeatmapsStrings.RankS;
+
+ case ScoreRank.A:
+ return BeatmapsStrings.RankA;
+
+ case ScoreRank.B:
+ return BeatmapsStrings.RankB;
+
+ case ScoreRank.C:
+ return BeatmapsStrings.RankC;
+
+ case ScoreRank.D:
+ return BeatmapsStrings.RankD;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 8eeaad1127..68ffb87c6c 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -34,7 +34,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index db442238ce..8aa79762fc 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -70,7 +70,7 @@
-
+
@@ -93,7 +93,7 @@
-
+