diff --git a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs new file mode 100644 index 0000000000..d8c10b814d --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs @@ -0,0 +1,108 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +using System; +using System.Diagnostics; +using System.Linq; +using Moq; +using NUnit.Framework; +using osu.Framework.Graphics.OpenGL.Textures; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Testing; +using osu.Game.Rulesets.Osu.Skinning.Legacy; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [HeadlessTest] + public class LegacyMainCirclePieceTest : OsuTestScene + { + private static readonly object?[][] texture_priority_cases = + { + // default priority lookup + new object?[] + { + // available textures + new[] { @"hitcircle", @"hitcircleoverlay" }, + // priority lookup prefix + null, + // expected circle and overlay + @"hitcircle", @"hitcircleoverlay", + }, + // custom priority lookup + new object?[] + { + new[] { @"hitcircle", @"hitcircleoverlay", @"sliderstartcircle", @"sliderstartcircleoverlay" }, + @"sliderstartcircle", + @"sliderstartcircle", @"sliderstartcircleoverlay", + }, + // when no sprites are available for the specified prefix, fall back to "hitcircle"/"hitcircleoverlay". + new object?[] + { + new[] { @"hitcircle", @"hitcircleoverlay" }, + @"sliderstartcircle", + @"hitcircle", @"hitcircleoverlay", + }, + // when a circle is available for the specified prefix but no overlay exists, no overlay is displayed. + new object?[] + { + new[] { @"hitcircle", @"hitcircleoverlay", @"sliderstartcircle" }, + @"sliderstartcircle", + @"sliderstartcircle", null + }, + // when no circle is available for the specified prefix but an overlay exists, the overlay is ignored. + new object?[] + { + new[] { @"hitcircle", @"hitcircleoverlay", @"sliderstartcircleoverlay" }, + @"sliderstartcircle", + @"hitcircle", @"hitcircleoverlay", + } + }; + + [TestCaseSource(nameof(texture_priority_cases))] + public void TestTexturePriorities(string[] textureFilenames, string priorityLookup, string? expectedCircle, string? expectedOverlay) + { + TestLegacyMainCirclePiece piece = null!; + + AddStep("load circle piece", () => + { + var skin = new Mock(); + + // shouldn't be required as GetTexture(string) calls GetTexture(string, WrapMode, WrapMode) by default, + // but moq doesn't handle that well, therefore explicitly requiring to use `CallBase`: + // https://github.com/moq/moq4/issues/972 + skin.Setup(s => s.GetTexture(It.IsAny())).CallBase(); + + skin.Setup(s => s.GetTexture(It.IsIn(textureFilenames), It.IsAny(), It.IsAny())) + .Returns((string componentName, WrapMode _, WrapMode __) => new Texture(1, 1) { AssetName = componentName }); + + Child = new DependencyProvidingContainer + { + CachedDependencies = new (Type, object)[] { (typeof(ISkinSource), skin.Object) }, + Child = piece = new TestLegacyMainCirclePiece(priorityLookup), + }; + + var sprites = this.ChildrenOfType().Where(s => s.Texture.AssetName != null).DistinctBy(s => s.Texture.AssetName).ToArray(); + Debug.Assert(sprites.Length <= 2); + }); + + AddAssert("check circle sprite", () => piece.CircleSprite?.Texture?.AssetName == expectedCircle); + AddAssert("check overlay sprite", () => piece.OverlaySprite?.Texture?.AssetName == expectedOverlay); + } + + private class TestLegacyMainCirclePiece : LegacyMainCirclePiece + { + public new Sprite? CircleSprite => base.CircleSprite.ChildrenOfType().DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); + public new Sprite? OverlaySprite => base.OverlaySprite.ChildrenOfType().DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); + + public TestLegacyMainCirclePiece(string? priorityLookupPrefix) + : base(priorityLookupPrefix, false) + { + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index 2d3cc3c103..a5282877ee 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Beatmaps @@ -20,13 +21,13 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { new BeatmapStatistic { - Name = @"Circle Count", + Name = BeatmapsetsStrings.ShowStatsCountCircles, Content = circles.ToString(), CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles), }, new BeatmapStatistic { - Name = @"Slider Count", + Name = BeatmapsetsStrings.ShowStatsCountSliders, Content = sliders.ToString(), CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders), }, diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index c6007885be..391147648f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -3,10 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; @@ -16,63 +16,61 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; +#nullable enable + namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacyMainCirclePiece : CompositeDrawable { public override bool RemoveCompletedTransforms => false; - private readonly string priorityLookup; + /// + /// A prioritised prefix to perform texture lookups with. + /// + private readonly string? priorityLookupPrefix; + private readonly bool hasNumber; - public LegacyMainCirclePiece(string priorityLookup = null, bool hasNumber = true) + protected Drawable CircleSprite = null!; + protected Drawable OverlaySprite = null!; + + protected Container OverlayLayer { get; private set; } = null!; + + private SkinnableSpriteText hitCircleText = null!; + + private readonly Bindable accentColour = new Bindable(); + private readonly IBindable indexInCurrentCombo = new Bindable(); + + [Resolved(canBeNull: true)] + private DrawableHitObject? drawableObject { get; set; } + + [Resolved] + private ISkinSource skin { get; set; } = null!; + + public LegacyMainCirclePiece(string? priorityLookupPrefix = null, bool hasNumber = true) { - this.priorityLookup = priorityLookup; + this.priorityLookupPrefix = priorityLookupPrefix; this.hasNumber = hasNumber; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); } - private Drawable hitCircleSprite; - - protected Container OverlayLayer { get; private set; } - - private Drawable hitCircleOverlay; - private SkinnableSpriteText hitCircleText; - - private readonly Bindable accentColour = new Bindable(); - private readonly IBindable indexInCurrentCombo = new Bindable(); - - [Resolved] - private DrawableHitObject drawableObject { get; set; } - - [Resolved] - private ISkinSource skin { get; set; } - [BackgroundDependencyLoader] private void load() { - var drawableOsuObject = (DrawableOsuHitObject)drawableObject; + var drawableOsuObject = (DrawableOsuHitObject?)drawableObject; - bool allowFallback = false; - - // attempt lookup using priority specification - Texture baseTexture = getTextureWithFallback(string.Empty); - - // if the base texture was not found without a fallback, switch on fallback mode and re-perform the lookup. - if (baseTexture == null) - { - allowFallback = true; - baseTexture = getTextureWithFallback(string.Empty); - } + // if a base texture for the specified prefix exists, continue using it for subsequent lookups. + // otherwise fall back to the default prefix "hitcircle". + string circleName = (priorityLookupPrefix != null && skin.GetTexture(priorityLookupPrefix) != null) ? priorityLookupPrefix : @"hitcircle"; // at this point, any further texture fetches should be correctly using the priority source if the base texture was retrieved using it. - // the flow above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist. - // expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png (potentially from the default/fall-through skin). + // the conditional above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist. + // expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png. InternalChildren = new[] { - hitCircleSprite = new KiaiFlashingDrawable(() => new Sprite { Texture = baseTexture }) + CircleSprite = new KiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(circleName) }) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -81,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Child = hitCircleOverlay = new KiaiFlashingDrawable(() => getAnimationWithFallback(@"overlay", 1000 / 2d)) + Child = OverlaySprite = new KiaiFlashingDrawable(() => skin.GetAnimation(@$"{circleName}overlay", true, true, frameLength: 1000 / 2d)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -105,39 +103,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy bool overlayAboveNumber = skin.GetConfig(OsuSkinConfiguration.HitCircleOverlayAboveNumber)?.Value ?? true; if (overlayAboveNumber) - OverlayLayer.ChangeChildDepth(hitCircleOverlay, float.MinValue); + OverlayLayer.ChangeChildDepth(OverlaySprite, float.MinValue); - accentColour.BindTo(drawableObject.AccentColour); - indexInCurrentCombo.BindTo(drawableOsuObject.IndexInCurrentComboBindable); - - Texture getTextureWithFallback(string name) + if (drawableOsuObject != null) { - Texture tex = null; - - if (!string.IsNullOrEmpty(priorityLookup)) - { - tex = skin.GetTexture($"{priorityLookup}{name}"); - - if (!allowFallback) - return tex; - } - - return tex ?? skin.GetTexture($"hitcircle{name}"); - } - - Drawable getAnimationWithFallback(string name, double frameLength) - { - Drawable animation = null; - - if (!string.IsNullOrEmpty(priorityLookup)) - { - animation = skin.GetAnimation($"{priorityLookup}{name}", true, true, frameLength: frameLength); - - if (!allowFallback) - return animation; - } - - return animation ?? skin.GetAnimation($"hitcircle{name}", true, true, frameLength: frameLength); + accentColour.BindTo(drawableOsuObject.AccentColour); + indexInCurrentCombo.BindTo(drawableOsuObject.IndexInCurrentComboBindable); } } @@ -145,28 +116,31 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { base.LoadComplete(); - accentColour.BindValueChanged(colour => hitCircleSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue), true); + accentColour.BindValueChanged(colour => CircleSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue), true); if (hasNumber) indexInCurrentCombo.BindValueChanged(index => hitCircleText.Text = (index.NewValue + 1).ToString(), true); - drawableObject.ApplyCustomUpdateState += updateStateTransforms; - updateStateTransforms(drawableObject, drawableObject.State.Value); + if (drawableObject != null) + { + drawableObject.ApplyCustomUpdateState += updateStateTransforms; + updateStateTransforms(drawableObject, drawableObject.State.Value); + } } private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state) { const double legacy_fade_duration = 240; - using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime)) + using (BeginAbsoluteSequence(drawableObject.AsNonNull().HitStateUpdateTime)) { switch (state) { case ArmedState.Hit: - hitCircleSprite.FadeOut(legacy_fade_duration, Easing.Out); - hitCircleSprite.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); + CircleSprite.FadeOut(legacy_fade_duration, Easing.Out); + CircleSprite.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); - hitCircleOverlay.FadeOut(legacy_fade_duration, Easing.Out); - hitCircleOverlay.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); + OverlaySprite.FadeOut(legacy_fade_duration, Easing.Out); + OverlaySprite.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); if (hasNumber) { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectScreen.cs new file mode 100644 index 0000000000..0db05e3a6a --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectScreen.cs @@ -0,0 +1,37 @@ +// 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.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Overlays.Mods; +using osu.Game.Screens.OnlinePlay; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneFreeModSelectScreen : MultiplayerTestScene + { + [Test] + public void TestFreeModSelect() + { + FreeModSelectScreen freeModSelectScreen = null; + + AddStep("create free mod select screen", () => Child = freeModSelectScreen = new FreeModSelectScreen + { + State = { Value = Visibility.Visible } + }); + + AddAssert("all visible mods are playable", + () => this.ChildrenOfType() + .Where(panel => panel.IsPresent) + .All(panel => panel.Mod.HasImplementation && panel.Mod.UserPlayable)); + + AddToggleStep("toggle visibility", visible => + { + if (freeModSelectScreen != null) + freeModSelectScreen.State.Value = visible ? Visibility.Visible : Visibility.Hidden; + }); + } + } +} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs index 7ceae0a69b..8af70df48a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; @@ -55,7 +56,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("no mods selected", () => SelectedMods.Value = Array.Empty()); - AddAssert("first bar text is Circle Size", () => advancedStats.ChildrenOfType().First().Text == "Circle Size"); + AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType().First().Text == BeatmapsetsStrings.ShowStatsCs); AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue)); AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain)); AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy)); @@ -78,7 +79,7 @@ namespace osu.Game.Tests.Visual.SongSelect StarRating = 8 }); - AddAssert("first bar text is Key Count", () => advancedStats.ChildrenOfType().First().Text == "Key Count"); + AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType().First().Text == BeatmapsetsStrings.ShowStatsCsMania); } [Test] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs index 34d9ddcc4e..4a738cb29d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.UserInterface [Resolved] private RulesetStore rulesetStore { get; set; } - private ModSelectScreen modSelectScreen; + private UserModSelectScreen modSelectScreen; [SetUpSteps] public void SetUpSteps() @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void createScreen() { - AddStep("create screen", () => Child = modSelectScreen = new ModSelectScreen + AddStep("create screen", () => Child = modSelectScreen = new UserModSelectScreen { RelativeSizeAxes = Axes.Both, State = { Value = Visibility.Visible }, diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupScreenTitle.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs similarity index 76% rename from osu.Game.Tests/Visual/UserInterface/TestScenePopupScreenTitle.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs index 22a8fa8a46..ef2b25cd92 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupScreenTitle.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs @@ -10,19 +10,19 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestScenePopupScreenTitle : OsuTestScene + public class TestSceneShearedOverlayHeader : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); [Test] - public void TestPopupScreenTitle() + public void TestShearedOverlayHeader() { AddStep("create content", () => { - Child = new PopupScreenTitle + Child = new ShearedOverlayHeader { - Title = "Popup Screen Title", + Title = "Sheared overlay header", Description = string.Join(" ", Enumerable.Repeat("This is a description.", 20)), Close = () => { } }; @@ -34,9 +34,9 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create content", () => { - Child = new PopupScreenTitle + Child = new ShearedOverlayHeader { - Title = "Popup Screen Title", + Title = "Sheared overlay header", Description = "This is a description." }; }); diff --git a/osu.Game/Beatmaps/BeatmapStatistic.cs b/osu.Game/Beatmaps/BeatmapStatistic.cs index 7d7ba09fcf..94ebb56a5c 100644 --- a/osu.Game/Beatmaps/BeatmapStatistic.cs +++ b/osu.Game/Beatmaps/BeatmapStatistic.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics; +using osu.Framework.Localisation; namespace osu.Game.Beatmaps { @@ -14,6 +15,6 @@ namespace osu.Game.Beatmaps public Func CreateIcon; public string Content; - public string Name; + public LocalisableString Name; } } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs index e2485e7a77..6ab92a2ba2 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables { @@ -104,7 +105,7 @@ namespace osu.Game.Beatmaps.Drawables if ((beatmapSet as IBeatmapSetOnlineInfo)?.Availability.DownloadDisabled == true) { button.Enabled.Value = false; - button.TooltipText = "this beatmap is currently not available for download."; + button.TooltipText = BeatmapsetsStrings.AvailabilityDisabled; } break; diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index 0fe41937ce..1da60415ba 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterface { @@ -15,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface { } - public OsuMenuItem(string text, MenuItemType type, Action action) + public OsuMenuItem(LocalisableString text, MenuItemType type, Action action) : base(text, action) { Type = type; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 005729580c..5c6d087279 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Bindables; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Graphics.UserInterface.PageSelector { @@ -29,7 +30,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector Direction = FillDirection.Horizontal, Children = new Drawable[] { - previousPageButton = new PageSelectorPrevNextButton(false, "prev") + previousPageButton = new PageSelectorPrevNextButton(false, CommonStrings.PaginationPrevious) { Action = () => CurrentPage.Value -= 1, }, @@ -38,7 +39,7 @@ namespace osu.Game.Graphics.UserInterface.PageSelector AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, }, - nextPageButton = new PageSelectorPrevNextButton(true, "next") + nextPageButton = new PageSelectorPrevNextButton(true, CommonStrings.PaginationNext) { Action = () => CurrentPage.Value += 1 } diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs index 7503ab8135..889917c397 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; using osuTK; @@ -13,12 +15,12 @@ namespace osu.Game.Graphics.UserInterface.PageSelector public class PageSelectorPrevNextButton : PageSelectorButton { private readonly bool rightAligned; - private readonly string text; + private readonly LocalisableString text; private SpriteIcon icon; private OsuSpriteText name; - public PageSelectorPrevNextButton(bool rightAligned, string text) + public PageSelectorPrevNextButton(bool rightAligned, LocalisableString text) { this.rightAligned = rightAligned; this.text = text; diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 6937782be6..dd9ed7c9e9 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Input; @@ -27,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface }); TextFlow.Padding = new MarginPadding { Right = 35 }; - PlaceholderText = "type to search"; + PlaceholderText = HomeStrings.SearchPlaceholder; } public override bool OnPressed(KeyBindingPressEvent e) diff --git a/osu.Game/Graphics/UserInterface/PopupScreenTitle.cs b/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs similarity index 96% rename from osu.Game/Graphics/UserInterface/PopupScreenTitle.cs rename to osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs index 5b7db09e77..9ed7bb35de 100644 --- a/osu.Game/Graphics/UserInterface/PopupScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs @@ -19,8 +19,10 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class PopupScreenTitle : CompositeDrawable + public class ShearedOverlayHeader : CompositeDrawable { + public const float HEIGHT = main_area_height + 2 * corner_radius; + public LocalisableString Title { set => titleSpriteText.Text = value; @@ -48,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface private readonly OsuTextFlowContainer descriptionText; private readonly IconButton closeButton; - public PopupScreenTitle() + public ShearedOverlayHeader() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -67,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface underlayContainer = new Container { RelativeSizeAxes = Axes.X, - Height = main_area_height + 2 * corner_radius, + Height = HEIGHT, CornerRadius = corner_radius, Masking = true, BorderThickness = 2, diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 615895074c..05dda324d4 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -11,7 +11,9 @@ using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osuTK; using System.Collections.Generic; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Graphics.UserInterface { @@ -80,7 +82,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), - Text = "show more".ToUpper(), + Text = CommonStrings.ButtonsShowMore.ToUpper(), }, rightIcon = new ChevronIcon { diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index 5240df74a2..cec319f28e 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -14,6 +14,7 @@ using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 @@ -139,7 +140,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 public MenuItem[] ContextMenuItems => new MenuItem[] { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteRequested?.Invoke()) + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => DeleteRequested?.Invoke()) }; } } diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 05c4d97ccc..6da2e4d272 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -9,16 +9,6 @@ namespace osu.Game.Localisation { private const string prefix = @"osu.Game.Resources.Localisation.Common"; - /// - /// "Cancel" - /// - public static LocalisableString Cancel => new TranslatableString(getKey(@"cancel"), @"Cancel"); - - /// - /// "Clear" - /// - public static LocalisableString Clear => new TranslatableString(getKey(@"clear"), @"Clear"); - /// /// "Back" /// diff --git a/osu.Game/Localisation/DebugLocalisationStore.cs b/osu.Game/Localisation/DebugLocalisationStore.cs new file mode 100644 index 0000000000..2b114b1bd8 --- /dev/null +++ b/osu.Game/Localisation/DebugLocalisationStore.cs @@ -0,0 +1,30 @@ +// 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.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public class DebugLocalisationStore : ILocalisationStore + { + public string Get(string lookup) => $@"[[{lookup.Substring(lookup.LastIndexOf('.') + 1)}]]"; + + public Task GetAsync(string lookup, CancellationToken cancellationToken = default) => Task.FromResult(Get(lookup)); + + public Stream GetStream(string name) => throw new NotImplementedException(); + + public IEnumerable GetAvailableResources() => throw new NotImplementedException(); + + public CultureInfo EffectiveCulture { get; } = CultureInfo.CurrentCulture; + + public void Dispose() + { + } + } +} diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index ab96d01c82..c13a1a10cb 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -110,6 +110,11 @@ namespace osu.Game.Localisation // zh_hk, [Description(@"繁體中文(台灣)")] - zh_hant + zh_hant, + +#if DEBUG + [Description(@"Debug (show raw keys)")] + debug +#endif } } diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index e2c0ed4301..ffb3a3be9b 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -13,8 +13,8 @@ namespace osu.Game.Online.API.Requests private readonly BeatmapSetType type; - public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int page = 0, int itemsPerPage = 6) - : base(page, itemsPerPage) + public GetUserBeatmapsRequest(long userId, BeatmapSetType type, PaginationParameters pagination) + : base(pagination) { this.userId = userId; this.type = type; diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index e90e297672..67d3ad26b0 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserKudosuHistoryRequest(long userId, int page = 0, int itemsPerPage = 5) - : base(page, itemsPerPage) + public GetUserKudosuHistoryRequest(long userId, PaginationParameters pagination) + : base(pagination) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index 9f094e51c4..bef3df42fb 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserMostPlayedBeatmapsRequest(long userId, int page = 0, int itemsPerPage = 5) - : base(page, itemsPerPage) + public GetUserMostPlayedBeatmapsRequest(long userId, PaginationParameters pagination) + : base(pagination) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index f2fa51bde7..79f0549d4a 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserRecentActivitiesRequest(long userId, int page = 0, int itemsPerPage = 5) - : base(page, itemsPerPage) + public GetUserRecentActivitiesRequest(long userId, PaginationParameters pagination) + : base(pagination) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 5d39799f6b..7250929f11 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -14,8 +14,8 @@ namespace osu.Game.Online.API.Requests private readonly ScoreType type; private readonly RulesetInfo ruleset; - public GetUserScoresRequest(long userId, ScoreType type, int page = 0, int itemsPerPage = 5, RulesetInfo ruleset = null) - : base(page, itemsPerPage) + public GetUserScoresRequest(long userId, ScoreType type, PaginationParameters pagination, RulesetInfo ruleset = null) + : base(pagination) { this.userId = userId; this.type = type; diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs index bddc34a0dc..3d719de958 100644 --- a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs +++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs @@ -8,21 +8,19 @@ namespace osu.Game.Online.API.Requests { public abstract class PaginatedAPIRequest : APIRequest where T : class { - private readonly int page; - private readonly int itemsPerPage; + private readonly PaginationParameters pagination; - protected PaginatedAPIRequest(int page, int itemsPerPage) + protected PaginatedAPIRequest(PaginationParameters pagination) { - this.page = page; - this.itemsPerPage = itemsPerPage; + this.pagination = pagination; } protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - req.AddParameter("offset", (page * itemsPerPage).ToString(CultureInfo.InvariantCulture)); - req.AddParameter("limit", itemsPerPage.ToString(CultureInfo.InvariantCulture)); + req.AddParameter("offset", pagination.Offset.ToString(CultureInfo.InvariantCulture)); + req.AddParameter("limit", pagination.Limit.ToString(CultureInfo.InvariantCulture)); return req; } diff --git a/osu.Game/Online/API/Requests/PaginationParameters.cs b/osu.Game/Online/API/Requests/PaginationParameters.cs new file mode 100644 index 0000000000..3593a4fe83 --- /dev/null +++ b/osu.Game/Online/API/Requests/PaginationParameters.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Online.API.Requests +{ + /// + /// Represents a pagination data used for . + /// + public readonly struct PaginationParameters + { + /// + /// The starting point of the request. + /// + public int Offset { get; } + + /// + /// The maximum number of items to return in this request. + /// + public int Limit { get; } + + public PaginationParameters(int offset, int limit) + { + Offset = offset; + Limit = limit; + } + + public PaginationParameters(int limit) + : this(0, limit) + { + } + + /// + /// Returns a of the next number of items defined by after this. + /// + /// The limit of the next pagination. + public PaginationParameters TakeNext(int limit) => new PaginationParameters(Offset + Limit, limit); + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs b/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs index 9573ae1825..a9d66f3d6a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs +++ b/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs @@ -1,22 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Online.API.Requests.Responses { public enum APIPlayStyle { - [Description("Keyboard")] + [LocalisableDescription(typeof(CommonStrings), nameof(CommonStrings.DeviceKeyboard))] Keyboard, - [Description("Mouse")] + [LocalisableDescription(typeof(CommonStrings), nameof(CommonStrings.DeviceMouse))] Mouse, - [Description("Tablet")] + [LocalisableDescription(typeof(CommonStrings), nameof(CommonStrings.DeviceTablet))] Tablet, - [Description("Touch Screen")] + [LocalisableDescription(typeof(CommonStrings), nameof(CommonStrings.DeviceTouch))] Touch, } } diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index f83bf4877e..6a7da52416 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -12,6 +12,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Chat; +using osu.Game.Resources.Localisation.Web; using osuTK.Graphics; namespace osu.Game.Online.Chat @@ -63,7 +64,7 @@ namespace osu.Game.Online.Chat { RelativeSizeAxes = Axes.X, Height = text_box_height, - PlaceholderText = "type your message", + PlaceholderText = ChatStrings.InputPlaceholder, CornerRadius = corner_radius, ReleaseFocusOnCommit = false, HoldFocus = true, diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index eecb7ff6b3..c75e98cdaa 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -30,6 +30,7 @@ using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; using osu.Game.Online.API; +using osu.Game.Resources.Localisation.Web; using osu.Game.Utils; namespace osu.Game.Online.Leaderboards @@ -291,8 +292,8 @@ namespace osu.Game.Online.Leaderboards protected virtual IEnumerable GetStatistics(ScoreInfo model) => new[] { - new LeaderboardScoreStatistic(FontAwesome.Solid.Link, "Max Combo", model.MaxCombo.ToString()), - new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", model.DisplayAccuracy) + new LeaderboardScoreStatistic(FontAwesome.Solid.Link, BeatmapsetsStrings.ShowScoreboardHeadersCombo, model.MaxCombo.ToString()), + new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, BeatmapsetsStrings.ShowScoreboardHeadersAccuracy, model.DisplayAccuracy) }; protected override bool OnHover(HoverEvent e) @@ -403,9 +404,9 @@ namespace osu.Game.Online.Leaderboards { public IconUsage Icon; public LocalisableString Value; - public string Name; + public LocalisableString Name; - public LeaderboardScoreStatistic(IconUsage icon, string name, LocalisableString value) + public LeaderboardScoreStatistic(IconUsage icon, LocalisableString name, LocalisableString value) { Icon = icon; Name = name; @@ -426,7 +427,7 @@ namespace osu.Game.Online.Leaderboards items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage).Export(Score))); if (!isOnlineScope) - items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); + items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); return items.ToArray(); } diff --git a/osu.Game/Online/Rooms/MatchType.cs b/osu.Game/Online/Rooms/MatchType.cs index 36f0dc0c81..278f0693eb 100644 --- a/osu.Game/Online/Rooms/MatchType.cs +++ b/osu.Game/Online/Rooms/MatchType.cs @@ -1,7 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Online.Rooms { @@ -11,10 +12,10 @@ namespace osu.Game.Online.Rooms Playlists, - [Description("Head to head")] + [LocalisableDescription(typeof(MatchesStrings), nameof(MatchesStrings.MatchTeamTypesHeadToHead))] HeadToHead, - [Description("Team VS")] + [LocalisableDescription(typeof(MatchesStrings), nameof(MatchesStrings.MatchTeamTypesTeamVs))] TeamVersus, } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7aa488d7a8..e9fe8c43de 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -630,6 +630,14 @@ namespace osu.Game foreach (var language in Enum.GetValues(typeof(Language)).OfType()) { +#if DEBUG + if (language == Language.debug) + { + Localisation.AddLanguage(Language.debug.ToString(), new DebugLocalisationStore()); + continue; + } +#endif + string cultureCode = language.ToCultureCode(); try diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index a2c04c6989..6cf3fb4267 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays.Settings; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -68,7 +69,7 @@ namespace osu.Game.Overlays.AccountCreation }, usernameTextBox = new OsuTextBox { - PlaceholderText = "username", + PlaceholderText = UsersStrings.LoginUsername, RelativeSizeAxes = Axes.X, TabbableContentContainer = this }, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs b/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs index dc46452dcb..b6e768d632 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet @@ -69,14 +70,14 @@ namespace osu.Game.Overlays.BeatmapSet { textContainer.Clear(); textContainer.AddParagraph(downloadDisabled - ? "This beatmap is currently not available for download." - : "Portions of this beatmap have been removed at the request of the creator or a third-party rights holder.", t => t.Colour = Color4.Orange); + ? BeatmapsetsStrings.AvailabilityDisabled + : BeatmapsetsStrings.AvailabilityPartsRemoved, t => t.Colour = Color4.Orange); if (hasExternalLink) { textContainer.NewParagraph(); textContainer.NewParagraph(); - textContainer.AddLink("Check here for more information.", BeatmapSet.Availability.ExternalLink, creationParameters: t => t.Font = OsuFont.GetFont(size: 10)); + textContainer.AddLink(BeatmapsetsStrings.AvailabilityMoreInfo, BeatmapSet.Availability.ExternalLink, creationParameters: t => t.Font = OsuFont.GetFont(size: 10)); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index b2c87a1477..d1a0960a08 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -7,6 +7,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -28,7 +29,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = @"You need to be an osu!supporter to access the friend and country rankings!", + Text = BeatmapsetsStrings.ShowScoreboardSupporterOnly, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), }, text = new LinkFlowContainer(t => t.Font = t.Font.With(size: 11)) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 64b972262b..034670cf37 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -160,7 +160,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, Height = 1, - PlaceholderText = "type your message", + PlaceholderText = Resources.Localisation.Web.ChatStrings.InputPlaceholder, ReleaseFocusOnCommit = false, HoldFocus = true, } diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs index 4998e5391e..4bb5b9d66d 100644 --- a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments.Buttons { @@ -25,7 +26,7 @@ namespace osu.Game.Overlays.Comments.Buttons { public ButtonContent() { - Text = "load replies"; + Text = CommentsStrings.LoadReplies; } } } diff --git a/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs index c115a8bb8f..4908e29b7d 100644 --- a/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics.Sprites; using System.Collections.Generic; using osuTK; using osu.Framework.Allocation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments.Buttons { @@ -38,7 +39,7 @@ namespace osu.Game.Overlays.Comments.Buttons { AlwaysPresent = true, Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), - Text = "show more" + Text = CommonStrings.ButtonsShowMore } }; diff --git a/osu.Game/Overlays/Comments/CancellableCommentEditor.cs b/osu.Game/Overlays/Comments/CancellableCommentEditor.cs index c226b7f07f..74c221bd82 100644 --- a/osu.Game/Overlays/Comments/CancellableCommentEditor.cs +++ b/osu.Game/Overlays/Comments/CancellableCommentEditor.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { @@ -54,7 +55,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Margin = new MarginPadding { Horizontal = 20 }, - Text = @"Cancel" + Text = CommonStrings.ButtonsCancel } } }; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 6a5734b553..a28b13fc12 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -16,6 +16,7 @@ using osu.Framework.Threading; using System.Collections.Generic; using JetBrains.Annotations; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Comments @@ -328,7 +329,7 @@ namespace osu.Game.Overlays.Comments Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Margin = new MarginPadding { Left = 50 }, - Text = @"No comments yet." + Text = CommentsStrings.Empty } }); } diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index bf80655c3d..e7d9e72dcc 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -12,7 +12,9 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { @@ -91,7 +93,7 @@ namespace osu.Game.Overlays.Comments Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold), - Text = @"Show deleted" + Text = CommonStrings.ButtonsShowDeleted } }, }); @@ -126,9 +128,13 @@ namespace osu.Game.Overlays.Comments public enum CommentsSortCriteria { - [System.ComponentModel.Description(@"Recent")] + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.New))] New, + + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Old))] Old, + + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Top))] Top } } diff --git a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs index adf64eabb1..b1ca39c3bf 100644 --- a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs +++ b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs @@ -2,7 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { @@ -18,7 +21,8 @@ namespace osu.Game.Overlays.Comments private void onCurrentChanged(ValueChangedEvent count) { - Text = $@"Show More ({count.NewValue})".ToUpper(); + Text = new TranslatableString(@"_", "{0} ({1})", + CommonStrings.ButtonsShowMore.ToUpper(), count.NewValue); } } } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3286b6c5c0..3ec91c8e63 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -150,7 +150,7 @@ namespace osu.Game.Overlays.Comments { Alpha = Comment.IsDeleted ? 1 : 0, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), - Text = "deleted" + Text = CommentsStrings.Deleted } } }, diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index 1bb9b52689..221a745189 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -9,6 +9,7 @@ using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments { @@ -39,7 +40,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: 20, italics: true), Colour = colourProvider.Light1, - Text = @"Comments" + Text = CommentsStrings.Title }, new CircularContainer { diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index 786401b7a8..9807a65250 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Spectator; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; @@ -138,7 +139,7 @@ namespace osu.Game.Overlays.Dashboard new PurpleTriangleButton { RelativeSizeAxes = Axes.X, - Text = "Watch", + Text = "Spectate", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Action = () => performer?.PerformFromScreen(s => s.Push(new SoloSpectator(User))), diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs index c73cc828e2..382bc00b1d 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; @@ -49,7 +50,7 @@ namespace osu.Game.Overlays.Dashboard.Home flow.AddRange(beatmapSets.Select(CreateBeatmapPanel)); } - protected abstract string Title { get; } + protected abstract LocalisableString Title { get; } protected abstract DashboardBeatmapPanel CreateBeatmapPanel(APIBeatmapSet beatmapSet); } diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs index 714e07a7ed..331fff0aea 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Home { @@ -15,6 +17,6 @@ namespace osu.Game.Overlays.Dashboard.Home protected override DashboardBeatmapPanel CreateBeatmapPanel(APIBeatmapSet beatmapSet) => new DashboardNewBeatmapPanel(beatmapSet); - protected override string Title => "New Ranked Beatmaps"; + protected override LocalisableString Title => HomeStrings.UserBeatmapsNew; } } diff --git a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs index 48b100b04e..154813dea1 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Home { @@ -15,6 +17,6 @@ namespace osu.Game.Overlays.Dashboard.Home protected override DashboardBeatmapPanel CreateBeatmapPanel(APIBeatmapSet beatmapSet) => new DashboardPopularBeatmapPanel(beatmapSet); - protected override string Title => "Popular Beatmaps"; + protected override LocalisableString Title => HomeStrings.UserBeatmapsPopular; } } diff --git a/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs index d25df6f189..f6e966957e 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osuTK.Graphics; namespace osu.Game.Overlays.Dashboard.Home.News @@ -35,7 +36,7 @@ namespace osu.Game.Overlays.Dashboard.Home.News Anchor = Anchor.Centre, Origin = Anchor.Centre, Margin = new MarginPadding { Vertical = 20 }, - Text = "see more" + Text = CommonStrings.ButtonsSeeMore } }; diff --git a/osu.Game/Overlays/Dialog/ConfirmDialog.cs b/osu.Game/Overlays/Dialog/ConfirmDialog.cs index d1c0d746d1..58ce84e13a 100644 --- a/osu.Game/Overlays/Dialog/ConfirmDialog.cs +++ b/osu.Game/Overlays/Dialog/ConfirmDialog.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dialog { @@ -33,7 +34,7 @@ namespace osu.Game.Overlays.Dialog }, new PopupDialogCancelButton { - Text = Localisation.CommonStrings.Cancel, + Text = CommonStrings.ButtonsCancel, Action = onCancel }, }; diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index f7842dcd30..c31416e078 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays.Settings; +using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Overlays.Login @@ -50,14 +51,14 @@ namespace osu.Game.Overlays.Login { username = new OsuTextBox { - PlaceholderText = "username", + PlaceholderText = UsersStrings.LoginUsername, RelativeSizeAxes = Axes.X, Text = api?.ProvidedUsername ?? string.Empty, TabbableContentContainer = this }, password = new OsuPasswordTextBox { - PlaceholderText = "password", + PlaceholderText = UsersStrings.LoginPassword, RelativeSizeAxes = Axes.X, TabbableContentContainer = this, }, @@ -88,7 +89,7 @@ namespace osu.Game.Overlays.Login AutoSizeAxes = Axes.Y, Child = new SettingsButton { - Text = "Sign in", + Text = UsersStrings.LoginButton, Action = performLogin }, } diff --git a/osu.Game/Overlays/Login/UserAction.cs b/osu.Game/Overlays/Login/UserAction.cs index 07b6b4bf7e..d216670a28 100644 --- a/osu.Game/Overlays/Login/UserAction.cs +++ b/osu.Game/Overlays/Login/UserAction.cs @@ -2,11 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Login { public enum UserAction { + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusOnline))] Online, [Description(@"Do not disturb")] diff --git a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs index 248d4f288e..66fd6a202d 100644 --- a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs +++ b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.X, Masking = true, CornerRadius = ModPanel.CORNER_RADIUS, - Shear = new Vector2(ModPanel.SHEAR_X, 0), + Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0), Children = new Drawable[] { underlayBackground = new Box @@ -98,7 +98,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.Centre, Origin = Anchor.Centre, Margin = new MarginPadding { Horizontal = 18 }, - Shear = new Vector2(-ModPanel.SHEAR_X, 0), + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Text = "Difficulty Multiplier", Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) } @@ -109,7 +109,7 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Shear = new Vector2(-ModPanel.SHEAR_X, 0), + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Direction = FillDirection.Horizontal, Spacing = new Vector2(2, 0), Children = new Drawable[] diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs index 4b6759c209..38781455fa 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs @@ -37,7 +37,9 @@ namespace osu.Game.Overlays.Mods private void updateIncompatibility() { - incompatible.Value = selectedMods.Value.Count > 0 && !selectedMods.Value.Contains(Mod) && !ModUtils.CheckCompatibleSet(selectedMods.Value.Append(Mod)); + incompatible.Value = selectedMods.Value.Count > 0 + && selectedMods.Value.All(selected => selected.GetType() != Mod.GetType()) + && !ModUtils.CheckCompatibleSet(selectedMods.Value.Append(Mod)); } protected override void UpdateState() @@ -46,8 +48,8 @@ namespace osu.Game.Overlays.Mods if (incompatible.Value) { - Colour4 backgroundColour = ColourProvider.Background5; - Colour4 textBackgroundColour = ColourProvider.Background4; + Colour4 backgroundColour = ColourProvider.Background6; + Colour4 textBackgroundColour = ColourProvider.Background5; Content.TransformTo(nameof(BorderColour), ColourInfo.GradientVertical(backgroundColour, textBackgroundColour), TRANSITION_DURATION, Easing.OutQuint); Background.FadeColour(backgroundColour, TRANSITION_DURATION, Easing.OutQuint); diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index f84ae4ac8a..1157c0c0c6 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -54,6 +54,8 @@ namespace osu.Game.Overlays.Mods public Bindable> SelectedMods = new Bindable>(Array.Empty()); + protected virtual ModPanel CreateModPanel(Mod mod) => new ModPanel(mod); + private readonly Key[]? toggleKeys; private readonly Bindable>> availableMods = new Bindable>>(); @@ -79,7 +81,7 @@ namespace osu.Game.Overlays.Mods Width = 320; RelativeSizeAxes = Axes.Y; - Shear = new Vector2(ModPanel.SHEAR_X, 0); + Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); Container controlContainer; InternalChildren = new Drawable[] @@ -113,7 +115,7 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.Y, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Shear = new Vector2(-ModPanel.SHEAR_X, 0), + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Padding = new MarginPadding { Horizontal = 17, @@ -193,7 +195,7 @@ namespace osu.Game.Overlays.Mods Scale = new Vector2(0.8f), RelativeSizeAxes = Axes.X, LabelText = "Enable All", - Shear = new Vector2(-ModPanel.SHEAR_X, 0) + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0) }); panelFlow.Padding = new MarginPadding { @@ -258,10 +260,7 @@ namespace osu.Game.Overlays.Mods cancellationTokenSource?.Cancel(); - var panels = newMods.Select(mod => new ModPanel(mod) - { - Shear = new Vector2(-ModPanel.SHEAR_X, 0) - }); + var panels = newMods.Select(mod => CreateModPanel(mod).With(panel => panel.Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0))); Task? loadTask; diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 312171cf74..7ae325bde7 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -42,7 +42,6 @@ namespace osu.Game.Overlays.Mods protected const double TRANSITION_DURATION = 150; - public const float SHEAR_X = 0.2f; public const float CORNER_RADIUS = 7; protected const float HEIGHT = 42; @@ -67,7 +66,7 @@ namespace osu.Game.Overlays.Mods Content.Masking = true; Content.CornerRadius = CORNER_RADIUS; Content.BorderThickness = 2; - Content.Shear = new Vector2(SHEAR_X, 0); + Content.Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); Children = new Drawable[] { @@ -83,7 +82,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.Centre, Origin = Anchor.Centre, Active = { BindTarget = Active }, - Shear = new Vector2(-SHEAR_X, 0), + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Scale = new Vector2(HEIGHT / ModSwitchSmall.DEFAULT_SIZE) } }, @@ -116,10 +115,10 @@ namespace osu.Game.Overlays.Mods { Text = mod.Name, Font = OsuFont.TorusAlternate.With(size: 18, weight: FontWeight.SemiBold), - Shear = new Vector2(-SHEAR_X, 0), + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Margin = new MarginPadding { - Left = -18 * SHEAR_X + Left = -18 * ShearedOverlayContainer.SHEAR } }, new OsuSpriteText @@ -128,7 +127,7 @@ namespace osu.Game.Overlays.Mods Font = OsuFont.Default.With(size: 12), RelativeSizeAxes = Axes.X, Truncate = true, - Shear = new Vector2(-SHEAR_X, 0) + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0) } } } @@ -159,7 +158,7 @@ namespace osu.Game.Overlays.Mods playStateChangeSamples(); UpdateState(); }); - Filtered.BindValueChanged(_ => updateFilterState()); + Filtered.BindValueChanged(_ => updateFilterState(), true); UpdateState(); FinishTransforms(true); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ec7e49920c..9ce79c25f7 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -20,6 +20,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; using osu.Game.Screens; using osu.Game.Utils; @@ -317,7 +318,7 @@ namespace osu.Game.Overlays.Mods CloseButton = new TriangleButton { Width = 180, - Text = "Close", + Text = CommonStrings.ButtonsClose, Action = Hide, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/Mods/ModSelectScreen.cs b/osu.Game/Overlays/Mods/ModSelectScreen.cs index 62080ec1b5..693c85fafc 100644 --- a/osu.Game/Overlays/Mods/ModSelectScreen.cs +++ b/osu.Game/Overlays/Mods/ModSelectScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -9,7 +11,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Layout; using osu.Game.Configuration; @@ -21,158 +22,58 @@ using osuTK.Input; namespace osu.Game.Overlays.Mods { - public class ModSelectScreen : OsuFocusedOverlayContainer + public abstract class ModSelectScreen : ShearedOverlayContainer { - [Cached] - private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + protected override OverlayColourScheme ColourScheme => OverlayColourScheme.Green; [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); - protected override bool StartHidden => true; + private Func isValidMod = m => true; + + public Func IsValidMod + { + get => isValidMod; + set + { + isValidMod = value ?? throw new ArgumentNullException(nameof(value)); + + if (IsLoaded) + updateAvailableMods(); + } + } + + /// + /// Whether configurable s can be configured by the local user. + /// + protected virtual bool AllowCustomisation => true; + + /// + /// Whether the total score multiplier calculated from the current selected set of mods should be shown. + /// + protected virtual bool ShowTotalMultiplier => true; + + protected virtual ModColumn CreateModColumn(ModType modType, Key[]? toggleKeys = null) => new ModColumn(modType, false, toggleKeys); private readonly BindableBool customisationVisible = new BindableBool(); - private DifficultyMultiplierDisplay multiplierDisplay; - private ModSettingsArea modSettingsArea; - private FillFlowContainer columnFlow; - private GridContainer grid; - private Container mainContent; - - private PopupScreenTitle header; - private Container footer; + private DifficultyMultiplierDisplay? multiplierDisplay; + private ModSettingsArea modSettingsArea = null!; + private FillFlowContainer columnFlow = null!; [BackgroundDependencyLoader] private void load() { - RelativeSizeAxes = Axes.Both; - RelativePositionAxes = Axes.Both; + Header.Title = "Mod Select"; + Header.Description = "Mods provide different ways to enjoy gameplay. Some have an effect on the score you can achieve during ranked play. Others are just for fun."; - InternalChildren = new Drawable[] + AddRange(new Drawable[] { - mainContent = new Container + new ClickToReturnContainer { - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - grid = new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 75), - }, - Content = new[] - { - new Drawable[] - { - header = new PopupScreenTitle - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Title = "Mod Select", - Description = "Mods provide different ways to enjoy gameplay. Some have an effect on the score you can achieve during ranked play. Others are just for fun.", - Close = Hide - } - }, - new Drawable[] - { - new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.X, - RelativePositionAxes = Axes.X, - X = 0.3f, - Height = DifficultyMultiplierDisplay.HEIGHT, - Margin = new MarginPadding - { - Horizontal = 100, - Vertical = 10 - }, - Child = multiplierDisplay = new DifficultyMultiplierDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - } - } - }, - new Drawable[] - { - new Container - { - Depth = float.MaxValue, - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Both, - Children = new Drawable[] - { - new OsuScrollContainer(Direction.Horizontal) - { - RelativeSizeAxes = Axes.Both, - Masking = false, - ClampExtension = 100, - ScrollbarOverlapsContent = false, - Child = columnFlow = new ModColumnContainer - { - Direction = FillDirection.Horizontal, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Spacing = new Vector2(10, 0), - Margin = new MarginPadding { Right = 70 }, - Children = new[] - { - new ModColumn(ModType.DifficultyReduction, false, new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }), - new ModColumn(ModType.DifficultyIncrease, false, new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L }), - new ModColumn(ModType.Automation, false, new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M }), - new ModColumn(ModType.Conversion, false), - new ModColumn(ModType.Fun, false) - } - } - } - } - } - }, - new[] { Empty() } - } - }, - footer = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.X, - Height = 50, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Colour = colourProvider.Background5 - }, - new ShearedToggleButton(200) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Vertical = 14, Left = 70 }, - Text = "Mod Customisation", - Active = { BindTarget = customisationVisible } - } - } - }, - new ClickToReturnContainer - { - RelativeSizeAxes = Axes.Both, - HandleMouse = { BindTarget = customisationVisible }, - OnClicked = () => customisationVisible.Value = false - } - } + HandleMouse = { BindTarget = customisationVisible }, + OnClicked = () => customisationVisible.Value = false }, modSettingsArea = new ModSettingsArea { @@ -180,9 +81,76 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.BottomCentre, Height = 0 } - }; + }); - columnFlow.Shear = new Vector2(ModPanel.SHEAR_X, 0); + MainAreaContent.AddRange(new Drawable[] + { + new Container + { + Padding = new MarginPadding + { + Top = (ShowTotalMultiplier ? DifficultyMultiplierDisplay.HEIGHT : 0) + PADDING, + }, + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Children = new Drawable[] + { + new OsuScrollContainer(Direction.Horizontal) + { + RelativeSizeAxes = Axes.Both, + Masking = false, + ClampExtension = 100, + ScrollbarOverlapsContent = false, + Child = columnFlow = new ModColumnContainer + { + Direction = FillDirection.Horizontal, + Shear = new Vector2(SHEAR, 0), + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Spacing = new Vector2(10, 0), + Margin = new MarginPadding { Right = 70 }, + Children = new[] + { + CreateModColumn(ModType.DifficultyReduction, new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }), + CreateModColumn(ModType.DifficultyIncrease, new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L }), + CreateModColumn(ModType.Automation, new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M }), + CreateModColumn(ModType.Conversion), + CreateModColumn(ModType.Fun) + } + } + } + } + } + }); + + if (ShowTotalMultiplier) + { + MainAreaContent.Add(new Container + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.X, + Height = DifficultyMultiplierDisplay.HEIGHT, + Margin = new MarginPadding { Horizontal = 100 }, + Child = multiplierDisplay = new DifficultyMultiplierDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, + }); + } + + if (AllowCustomisation) + { + Footer.Add(new ShearedToggleButton(200) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Vertical = PADDING, Left = 70 }, + Text = "Mod Customisation", + Active = { BindTarget = customisationVisible } + }); + } } protected override void LoadComplete() @@ -204,10 +172,15 @@ namespace osu.Game.Overlays.Mods } customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); + + updateAvailableMods(); } private void updateMultiplier() { + if (multiplierDisplay == null) + return; + double multiplier = 1.0; foreach (var mod in SelectedMods.Value) @@ -216,8 +189,17 @@ namespace osu.Game.Overlays.Mods multiplierDisplay.Current.Value = multiplier; } + private void updateAvailableMods() + { + foreach (var column in columnFlow) + column.Filter = isValidMod; + } + private void updateCustomisation(ValueChangedEvent> valueChangedEvent) { + if (!AllowCustomisation) + return; + bool anyCustomisableMod = false; bool anyModWithRequiredCustomisationAdded = false; @@ -247,12 +229,12 @@ namespace osu.Game.Overlays.Mods { const double transition_duration = 300; - grid.FadeColour(customisationVisible.Value ? Colour4.Gray : Colour4.White, transition_duration, Easing.InOutCubic); + MainAreaContent.FadeColour(customisationVisible.Value ? Colour4.Gray : Colour4.White, transition_duration, Easing.InOutCubic); float modAreaHeight = customisationVisible.Value ? ModSettingsArea.HEIGHT : 0; modSettingsArea.ResizeHeightTo(modAreaHeight, transition_duration, Easing.InOutCubic); - mainContent.TransformTo(nameof(Margin), new MarginPadding { Bottom = modAreaHeight }, transition_duration, Easing.InOutCubic); + TopLevelContent.MoveToY(-modAreaHeight, transition_duration, Easing.InOutCubic); } private bool selectionBindableSyncInProgress; @@ -287,12 +269,8 @@ namespace osu.Game.Overlays.Mods const double fade_in_duration = 400; base.PopIn(); - this.FadeIn(fade_in_duration, Easing.OutQuint); - header.MoveToY(0, fade_in_duration, Easing.OutQuint); - footer.MoveToY(0, fade_in_duration, Easing.OutQuint); - - multiplierDisplay + multiplierDisplay? .Delay(fade_in_duration * 0.65f) .FadeIn(fade_in_duration / 2, Easing.OutQuint) .ScaleTo(1, fade_in_duration, Easing.OutElastic); @@ -311,15 +289,11 @@ namespace osu.Game.Overlays.Mods const double fade_out_duration = 500; base.PopOut(); - this.FadeOut(fade_out_duration, Easing.OutQuint); - multiplierDisplay + multiplierDisplay? .FadeOut(fade_out_duration / 2, Easing.OutQuint) .ScaleTo(0.75f, fade_out_duration, Easing.OutQuint); - header.MoveToY(-header.DrawHeight, fade_out_duration, Easing.OutQuint); - footer.MoveToY(footer.DrawHeight, fade_out_duration, Easing.OutQuint); - for (int i = 0; i < columnFlow.Count; i++) { const float distance = 700; @@ -355,7 +329,7 @@ namespace osu.Game.Overlays.Mods { Padding = new MarginPadding { - Left = DrawHeight * ModPanel.SHEAR_X, + Left = DrawHeight * SHEAR, Bottom = 10 }; @@ -368,7 +342,7 @@ namespace osu.Game.Overlays.Mods { public BindableBool HandleMouse { get; } = new BindableBool(); - public Action OnClicked { get; set; } + public Action? OnClicked { get; set; } protected override bool Handle(UIEvent e) { diff --git a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs new file mode 100644 index 0000000000..62ed736dc2 --- /dev/null +++ b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs @@ -0,0 +1,138 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Mods +{ + /// + /// A sheared overlay which provides a header and footer and basic animations. + /// Exposes , and as valid targets for content. + /// + public abstract class ShearedOverlayContainer : OsuFocusedOverlayContainer + { + protected const float PADDING = 14; + + public const float SHEAR = 0.2f; + + [Cached] + protected readonly OverlayColourProvider ColourProvider; + + /// + /// The overlay's header. + /// + protected ShearedOverlayHeader Header { get; private set; } + + /// + /// The overlay's footer. + /// + protected Container Footer { get; private set; } + + /// + /// A container containing all content, including the header and footer. + /// May be used for overlay-wide animations. + /// + protected Container TopLevelContent { get; private set; } + + /// + /// A container for content that is to be displayed between the header and footer. + /// + protected Container MainAreaContent { get; private set; } + + /// + /// A container for content that is to be displayed inside the footer. + /// + protected Container FooterContent { get; private set; } + + protected abstract OverlayColourScheme ColourScheme { get; } + + protected override bool StartHidden => true; + + protected override bool BlockNonPositionalInput => true; + + protected ShearedOverlayContainer() + { + RelativeSizeAxes = Axes.Both; + + ColourProvider = new OverlayColourProvider(ColourScheme); + } + + [BackgroundDependencyLoader] + private void load() + { + const float footer_height = 50; + + Child = TopLevelContent = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Header = new ShearedOverlayHeader + { + Anchor = Anchor.TopCentre, + Depth = float.MinValue, + Origin = Anchor.TopCentre, + Close = Hide + }, + MainAreaContent = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Top = ShearedOverlayHeader.HEIGHT, + Bottom = footer_height + PADDING, + } + }, + Footer = new Container + { + RelativeSizeAxes = Axes.X, + Depth = float.MinValue, + Height = footer_height, + Margin = new MarginPadding { Top = PADDING }, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourProvider.Background5 + }, + FooterContent = new Container + { + RelativeSizeAxes = Axes.Both, + }, + } + } + } + }; + } + + protected override void PopIn() + { + const double fade_in_duration = 400; + + base.PopIn(); + this.FadeIn(fade_in_duration, Easing.OutQuint); + + Header.MoveToY(0, fade_in_duration, Easing.OutQuint); + Footer.MoveToY(0, fade_in_duration, Easing.OutQuint); + } + + protected override void PopOut() + { + const double fade_out_duration = 500; + + base.PopOut(); + this.FadeOut(fade_out_duration, Easing.OutQuint); + + Header.MoveToY(-Header.DrawHeight, fade_out_duration, Easing.OutQuint); + Footer.MoveToY(Footer.DrawHeight, fade_out_duration, Easing.OutQuint); + } + } +} diff --git a/osu.Game/Overlays/Mods/UserModSelectScreen.cs b/osu.Game/Overlays/Mods/UserModSelectScreen.cs new file mode 100644 index 0000000000..81943da514 --- /dev/null +++ b/osu.Game/Overlays/Mods/UserModSelectScreen.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 JetBrains.Annotations; +using osu.Game.Rulesets.Mods; +using osuTK.Input; + +namespace osu.Game.Overlays.Mods +{ + public class UserModSelectScreen : ModSelectScreen + { + protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new UserModColumn(modType, false, toggleKeys); + + private class UserModColumn : ModColumn + { + public UserModColumn(ModType modType, bool allowBulkSelection, [CanBeNull] Key[] toggleKeys = null) + : base(modType, allowBulkSelection, toggleKeys) + { + } + + protected override ModPanel CreateModPanel(Mod mod) => new IncompatibilityDisplayingModPanel(mod); + } + } +} diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 2b5909f45a..f1ed5c4ba6 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -15,7 +15,8 @@ using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Threading; using osu.Game.Graphics; -using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; +using NotificationsStrings = osu.Game.Localisation.NotificationsStrings; namespace osu.Game.Overlays { @@ -61,7 +62,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, Children = new[] { - new NotificationSection(@"Notifications", @"Clear All") + new NotificationSection(AccountsStrings.NotificationsTitle, "Clear All") { AcceptTypes = new[] { typeof(SimpleNotification) } }, diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index a23ff07a64..a4851ab365 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; @@ -34,9 +35,9 @@ namespace osu.Game.Overlays.Notifications private readonly string clearButtonText; - private readonly string titleText; + private readonly LocalisableString titleText; - public NotificationSection(string title, string clearButtonText) + public NotificationSection(LocalisableString title, string clearButtonText) { this.clearButtonText = clearButtonText.ToUpperInvariant(); titleText = title; @@ -84,7 +85,7 @@ namespace osu.Game.Overlays.Notifications { new OsuSpriteText { - Text = titleText.ToUpperInvariant(), + Text = titleText.ToUpper(), Font = OsuFont.GetFont(weight: FontWeight.Bold) }, countDrawable = new OsuSpriteText diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index ea52cec2e1..a70d57661b 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -11,10 +10,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -83,7 +84,7 @@ namespace osu.Game.Overlays.Profile.Header if (user == null) return; if (user.JoinDate.ToUniversalTime().Year < 2008) - topLinkContainer.AddText("Here since the beginning"); + topLinkContainer.AddText(UsersStrings.ShowFirstMembers); else { topLinkContainer.AddText("Joined "); @@ -94,7 +95,7 @@ namespace osu.Game.Overlays.Profile.Header if (user.IsOnline) { - topLinkContainer.AddText("Currently online"); + topLinkContainer.AddText(UsersStrings.ShowLastvisitOnline); addSpacer(topLinkContainer); } else if (user.LastVisit.HasValue) @@ -108,7 +109,16 @@ namespace osu.Game.Overlays.Profile.Header if (user.PlayStyles?.Length > 0) { topLinkContainer.AddText("Plays with "); - topLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); + + LocalisableString playStylesString = user.PlayStyles[0].GetLocalisableDescription(); + + for (int i = 1; i < user.PlayStyles.Length; i++) + { + playStylesString = new TranslatableString(@"_", @"{0}{1}", playStylesString, CommonStrings.ArrayAndWordsConnector); + playStylesString = new TranslatableString(@"_", @"{0}{1}", playStylesString, user.PlayStyles[i].GetLocalisableDescription()); + } + + topLinkContainer.AddText(playStylesString, embolden); addSpacer(topLinkContainer); } diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index d39074bd49..0424fe8bd9 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -20,11 +20,12 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps private const float panel_padding = 10f; private readonly BeatmapSetType type; + protected override int InitialItemsCount => type == BeatmapSetType.Graveyard ? 2 : 6; + public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, LocalisableString headerText) : base(user, headerText) { this.type = type; - ItemsPerPage = 6; } [BackgroundDependencyLoader] @@ -57,8 +58,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps } } - protected override APIRequest> CreateRequest() => - new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + protected override APIRequest> CreateRequest(PaginationParameters pagination) => + new GetUserBeatmapsRequest(User.Value.Id, type, pagination); protected override Drawable CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0 ? new BeatmapCardNormal(model) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index ad1192a13a..06de0f62dc 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -19,7 +19,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical public PaginatedMostPlayedBeatmapContainer(Bindable user) : base(user, UsersStrings.ShowExtraHistoricalMostPlayedTitle) { - ItemsPerPage = 5; } [BackgroundDependencyLoader] @@ -30,8 +29,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override int GetCount(APIUser user) => user.BeatmapPlayCountsCount; - protected override APIRequest> CreateRequest() => - new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); + protected override APIRequest> CreateRequest(PaginationParameters pagination) => + new GetUserMostPlayedBeatmapsRequest(User.Value.Id, pagination); protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap mostPlayed) => new DrawableMostPlayedBeatmap(mostPlayed); diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs index c4837cc0e2..9af854e6b9 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs @@ -17,11 +17,10 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu public PaginatedKudosuHistoryContainer(Bindable user) : base(user, missingText: UsersStrings.ShowExtraKudosuEntryEmpty) { - ItemsPerPage = 5; } - protected override APIRequest> CreateRequest() - => new GetUserKudosuHistoryRequest(User.Value.Id, VisiblePages++, ItemsPerPage); + protected override APIRequest> CreateRequest(PaginationParameters pagination) + => new GetUserKudosuHistoryRequest(User.Value.Id, pagination); protected override Drawable CreateDrawableItem(APIKudosuHistory item) => new DrawableKudosuHistoryItem(item); } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs index 9dcbf6142d..33bd155d71 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -21,11 +22,20 @@ namespace osu.Game.Overlays.Profile.Sections { public abstract class PaginatedProfileSubsection : ProfileSubsection { + /// + /// The number of items displayed per page. + /// + protected virtual int ItemsPerPage => 50; + + /// + /// The number of items displayed initially. + /// + protected virtual int InitialItemsCount => 5; + [Resolved] private IAPIProvider api { get; set; } - protected int VisiblePages; - protected int ItemsPerPage; + protected PaginationParameters? CurrentPage { get; private set; } protected ReverseChildIDFillFlowContainer ItemsContainer { get; private set; } @@ -87,7 +97,7 @@ namespace osu.Game.Overlays.Profile.Sections loadCancellation?.Cancel(); retrievalRequest?.Cancel(); - VisiblePages = 0; + CurrentPage = null; ItemsContainer.Clear(); if (e.NewValue != null) @@ -101,7 +111,9 @@ namespace osu.Game.Overlays.Profile.Sections { loadCancellation = new CancellationTokenSource(); - retrievalRequest = CreateRequest(); + CurrentPage = CurrentPage?.TakeNext(ItemsPerPage) ?? new PaginationParameters(InitialItemsCount); + + retrievalRequest = CreateRequest(CurrentPage.Value); retrievalRequest.Success += UpdateItems; api.Queue(retrievalRequest); @@ -111,7 +123,7 @@ namespace osu.Game.Overlays.Profile.Sections { OnItemsReceived(items); - if (!items.Any() && VisiblePages == 1) + if (!items.Any() && CurrentPage?.Offset == 0) { moreButton.Hide(); moreButton.IsLoading = false; @@ -125,7 +137,8 @@ namespace osu.Game.Overlays.Profile.Sections LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables => { missing.Hide(); - moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); + + moreButton.FadeTo(items.Count == CurrentPage?.Limit ? 1 : 0); moreButton.IsLoading = false; ItemsContainer.AddRange(drawables); @@ -138,7 +151,7 @@ namespace osu.Game.Overlays.Profile.Sections { } - protected abstract APIRequest> CreateRequest(); + protected abstract APIRequest> CreateRequest(PaginationParameters pagination); protected abstract Drawable CreateDrawableItem(TModel model); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 5c67da1911..ef9f4b5ff3 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -23,8 +23,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks : base(user, headerText) { this.type = type; - - ItemsPerPage = 5; } [BackgroundDependencyLoader] @@ -56,14 +54,14 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override void OnItemsReceived(List items) { - if (VisiblePages == 0) + if (CurrentPage == null || CurrentPage?.Offset == 0) drawableItemIndex = 0; base.OnItemsReceived(items); } - protected override APIRequest> CreateRequest() => - new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + protected override APIRequest> CreateRequest(PaginationParameters pagination) => + new GetUserScoresRequest(User.Value.Id, type, pagination); private int drawableItemIndex; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index c5ff896654..77008d5f34 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -19,7 +19,6 @@ namespace osu.Game.Overlays.Profile.Sections.Recent public PaginatedRecentActivityContainer(Bindable user) : base(user, missingText: EventsStrings.Empty) { - ItemsPerPage = 10; } [BackgroundDependencyLoader] @@ -28,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent ItemsContainer.Spacing = new Vector2(0, 8); } - protected override APIRequest> CreateRequest() => - new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); + protected override APIRequest> CreateRequest(PaginationParameters pagination) => + new GetUserRecentActivitiesRequest(User.Value.Id, pagination); protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model); } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 2405618917..459405f57d 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -21,7 +21,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Input.Bindings; -using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -402,7 +402,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public CancelButton() { - Text = CommonStrings.Cancel; + Text = CommonStrings.ButtonsCancel; Size = new Vector2(80, 20); } } @@ -411,7 +411,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public ClearButton() { - Text = CommonStrings.Clear; + Text = CommonStrings.ButtonsClear; Size = new Vector2(80, 20); } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index b0c9a04285..d8ba07dc3b 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; @@ -62,7 +63,7 @@ namespace osu.Game.Overlays.Toolbar switch (state.NewValue) { default: - Text = @"Guest"; + Text = UsersStrings.AnonymousUsername; avatar.User = new APIUser(); break; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index a22c18b0a4..11cab80a57 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -7,7 +7,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Wiki.Markdown { @@ -46,14 +48,14 @@ namespace osu.Game.Overlays.Wiki.Markdown { Add(new NoticeBox { - Text = "The content on this page is incomplete or outdated. If you are able to help out, please consider updating the article!", + Text = WikiStrings.ShowIncompleteOrOutdated, }); } else if (needsCleanup) { Add(new NoticeBox { - Text = "This page does not meet the standards of the osu! wiki and needs to be cleaned up or rewritten. If you are able to help out, please consider updating the article!", + Text = WikiStrings.ShowNeedsCleanupOrRewrite, }); } } @@ -63,7 +65,7 @@ namespace osu.Game.Overlays.Wiki.Markdown [Resolved] private IMarkdownTextFlowComponent parentFlowComponent { get; set; } - public string Text { get; set; } + public LocalisableString Text { get; set; } [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider, OsuColour colour) diff --git a/osu.Game/Overlays/Wiki/WikiSidebar.cs b/osu.Game/Overlays/Wiki/WikiSidebar.cs index ee4e195f3f..da96885fb5 100644 --- a/osu.Game/Overlays/Wiki/WikiSidebar.cs +++ b/osu.Game/Overlays/Wiki/WikiSidebar.cs @@ -3,11 +3,13 @@ using Markdig.Syntax; using Markdig.Syntax.Inlines; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Wiki { @@ -24,7 +26,7 @@ namespace osu.Game.Overlays.Wiki { new OsuSpriteText { - Text = "CONTENTS", + Text = WikiStrings.ShowToc.ToUpper(), Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Margin = new MarginPadding { Bottom = 5 }, }, diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 9d5d8013b7..78b98a3649 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -17,6 +17,7 @@ using osu.Framework.Input.Events; using osu.Framework.Utils; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Edit; using osuTK; using osuTK.Input; @@ -358,7 +359,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (SelectedBlueprints.Count == 1) items.AddRange(SelectedBlueprints[0].ContextMenuItems); - items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, DeleteSelected)); + items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, DeleteSelected)); return items.ToArray(); } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 602b7563ac..30c57733ed 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -29,6 +29,7 @@ using osu.Game.Input.Bindings; using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Components; @@ -252,7 +253,7 @@ namespace osu.Game.Screens.Edit { Items = createFileMenuItems() }, - new MenuItem("Edit") + new MenuItem(CommonStrings.ButtonsEdit) { Items = new[] { diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 75c6a89a66..e799081115 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Edit.Setup { @@ -27,7 +28,7 @@ namespace osu.Game.Screens.Edit.Setup { circleSizeSlider = new LabelledSliderBar { - Label = "Object Size", + Label = BeatmapsetsStrings.ShowStatsCs, FixedLabelWidth = LABEL_WIDTH, Description = "The size of all hit objects", Current = new BindableFloat(Beatmap.Difficulty.CircleSize) @@ -40,7 +41,7 @@ namespace osu.Game.Screens.Edit.Setup }, healthDrainSlider = new LabelledSliderBar { - Label = "Health Drain", + Label = BeatmapsetsStrings.ShowStatsDrain, FixedLabelWidth = LABEL_WIDTH, Description = "The rate of passive health drain throughout playable time", Current = new BindableFloat(Beatmap.Difficulty.DrainRate) @@ -53,7 +54,7 @@ namespace osu.Game.Screens.Edit.Setup }, approachRateSlider = new LabelledSliderBar { - Label = "Approach Rate", + Label = BeatmapsetsStrings.ShowStatsAr, FixedLabelWidth = LABEL_WIDTH, Description = "The speed at which objects are presented to the player", Current = new BindableFloat(Beatmap.Difficulty.ApproachRate) @@ -66,7 +67,7 @@ namespace osu.Game.Screens.Edit.Setup }, overallDifficultySlider = new LabelledSliderBar { - Label = "Overall Difficulty", + Label = BeatmapsetsStrings.ShowStatsAccuracy, FixedLabelWidth = LABEL_WIDTH, Description = "The harshness of hit windows and difficulty of special objects (ie. spinners)", Current = new BindableFloat(Beatmap.Difficulty.OverallDifficulty) diff --git a/osu.Game/Screens/Edit/Setup/MetadataSection.cs b/osu.Game/Screens/Edit/Setup/MetadataSection.cs index 571dfb3f6f..6262b4c18b 100644 --- a/osu.Game/Screens/Edit/Setup/MetadataSection.cs +++ b/osu.Game/Screens/Edit/Setup/MetadataSection.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Edit.Setup { @@ -48,15 +49,15 @@ namespace osu.Game.Screens.Edit.Setup creatorTextBox = createTextBox("Creator", metadata.Author.Username), difficultyTextBox = createTextBox("Difficulty Name", Beatmap.BeatmapInfo.DifficultyName), - sourceTextBox = createTextBox("Source", metadata.Source), - tagsTextBox = createTextBox("Tags", metadata.Tags) + sourceTextBox = createTextBox(BeatmapsetsStrings.ShowInfoSource, metadata.Source), + tagsTextBox = createTextBox(BeatmapsetsStrings.ShowInfoTags, metadata.Tags) }; foreach (var item in Children.OfType()) item.OnCommit += onCommit; } - private TTextBox createTextBox(string label, string initialValue) + private TTextBox createTextBox(LocalisableString label, string initialValue) where TTextBox : LabelledTextBox, new() => new TTextBox { diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index a153eda0c4..885f4903b0 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -26,7 +26,6 @@ using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -120,9 +119,6 @@ namespace osu.Game.Screens.Menu [Resolved] private IAPIProvider api { get; set; } - [Resolved(CanBeNull = true)] - private INotificationOverlay notifications { get; set; } - [Resolved(CanBeNull = true)] private LoginOverlay loginOverlay { get; set; } @@ -166,17 +162,7 @@ namespace osu.Game.Screens.Menu { if (api.State.Value != APIState.Online) { - notifications?.Post(new SimpleNotification - { - Text = "You gotta be online to multi 'yo!", - Icon = FontAwesome.Solid.Globe, - Activated = () => - { - loginOverlay?.Show(); - return true; - } - }); - + loginOverlay?.Show(); return; } @@ -187,17 +173,7 @@ namespace osu.Game.Screens.Menu { if (api.State.Value != APIState.Online) { - notifications?.Post(new SimpleNotification - { - Text = "You gotta be online to view playlists 'yo!", - Icon = FontAwesome.Solid.Globe, - Activated = () => - { - loginOverlay?.Show(); - return true; - } - }); - + loginOverlay?.Show(); return; } diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs index 08a0a3405e..f667a3c1d2 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; @@ -34,7 +35,7 @@ namespace osu.Game.Screens.OnlinePlay.Components private readonly Circle line; private readonly OsuSpriteText details; - public OverlinedHeader(string title) + public OverlinedHeader(LocalisableString title) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 25b36e0774..459b861d96 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -26,6 +26,7 @@ using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Online.Rooms; using osu.Game.Overlays.BeatmapSet; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; @@ -449,7 +450,7 @@ namespace osu.Game.Screens.OnlinePlay Size = new Vector2(30, 30), Alpha = AllowEditing ? 1 : 0, Action = () => RequestEdit?.Invoke(Item), - TooltipText = "Edit" + TooltipText = CommonStrings.ButtonsEdit }, removeButton = new PlaylistRemoveButton { diff --git a/osu.Game/Screens/OnlinePlay/FreeModSelectScreen.cs b/osu.Game/Screens/OnlinePlay/FreeModSelectScreen.cs new file mode 100644 index 0000000000..c85a4fc38b --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/FreeModSelectScreen.cs @@ -0,0 +1,29 @@ +// 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.Game.Overlays.Mods; +using osu.Game.Rulesets.Mods; +using osuTK.Input; + +namespace osu.Game.Screens.OnlinePlay +{ + public class FreeModSelectScreen : ModSelectScreen + { + protected override bool AllowCustomisation => false; + protected override bool ShowTotalMultiplier => false; + + public new Func IsValidMod + { + get => base.IsValidMod; + set => base.IsValidMod = m => m.HasImplementation && m.UserPlayable && value.Invoke(m); + } + + public FreeModSelectScreen() + { + IsValidMod = _ => true; + } + + protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new ModColumn(modType, true, toggleKeys); + } +} diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs index cf7e33fd63..799983342b 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Resources.Localisation.Web; using osu.Game.Scoring; namespace osu.Game.Screens.OnlinePlay.Match.Components @@ -30,8 +31,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override IEnumerable GetStatistics(ScoreInfo model) => new[] { - new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", model.DisplayAccuracy), - new LeaderboardScoreStatistic(FontAwesome.Solid.Sync, "Total Attempts", score.TotalAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, RankingsStrings.StatAccuracy, model.DisplayAccuracy), + new LeaderboardScoreStatistic(FontAwesome.Solid.Sync, RankingsStrings.StatPlayCount, score.TotalAttempts.ToString()), new LeaderboardScoreStatistic(FontAwesome.Solid.Check, "Completed Beatmaps", score.CompletedBeatmaps.ToString()), }; } diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index cdd2ae0c9c..1828a072f8 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match.Components; using osuTK; @@ -49,7 +50,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { RelativeSizeAxes = Axes.Y, Size = new Vector2(100, 1), - Text = "Edit", + Text = CommonStrings.ButtonsEdit, Action = () => OnEdit?.Invoke() }); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs index 7e442c6568..ef84c4b4fa 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Game.Online.Multiplayer; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.OnlinePlay.Components; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants @@ -13,7 +14,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants private MultiplayerClient client { get; set; } public ParticipantsListHeader() - : base("Participants") + : base(RankingsStrings.SpotlightParticipants) { } diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 0d759bacf0..e8021d4065 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; using osuTK; @@ -158,7 +159,7 @@ namespace osu.Game.Screens.Play { new Drawable[] { - new MetadataLineLabel("Source"), + new MetadataLineLabel(BeatmapsetsStrings.ShowInfoSource), new MetadataLineInfo(metadata.Source) }, new Drawable[] @@ -213,7 +214,7 @@ namespace osu.Game.Screens.Play private class MetadataLineLabel : OsuSpriteText { - public MetadataLineLabel(string text) + public MetadataLineLabel(LocalisableString text) { Anchor = Anchor.TopRight; Origin = Anchor.TopRight; diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index 6349ebd9a7..f95e949920 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osu.Game.Scoring; using osuTK; @@ -42,7 +43,7 @@ namespace osu.Game.Screens.Play.Break Direction = FillDirection.Vertical, Children = new Drawable[] { - AccuracyDisplay = new PercentageBreakInfoLine("Accuracy"), + AccuracyDisplay = new PercentageBreakInfoLine(BeatmapsetsStrings.ShowStatsAccuracy), // See https://github.com/ppy/osu/discussions/15185 // RankDisplay = new BreakInfoLine("Rank"), diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 87f514ffd5..4cae90e50f 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.Break private readonly string prefix; - public BreakInfoLine(string name, string prefix = @"") + public BreakInfoLine(LocalisableString name, string prefix = @"") { this.prefix = prefix; @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play.Break public class PercentageBreakInfoLine : BreakInfoLine { - public PercentageBreakInfoLine(string name, string prefix = "") + public PercentageBreakInfoLine(LocalisableString name, string prefix = "") : base(name, prefix) { } diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index 8b1e0ae83e..019a9f9730 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -19,6 +19,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Judgements; @@ -200,7 +201,7 @@ namespace osu.Game.Screens.Play.HUD { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Text = @"pp", + Text = BeatmapsetsStrings.ShowScoreboardHeaderspp, Font = OsuFont.Numeric.With(size: 8), Padding = new MarginPadding { Bottom = 1.5f }, // align baseline better } diff --git a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs index 32de5333e1..90caf6f0f3 100644 --- a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Scoring; namespace osu.Game.Screens.Play.PlayerSettings @@ -20,7 +21,7 @@ namespace osu.Game.Screens.Play.PlayerSettings { Children = new Drawable[] { - beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = "Beatmap hitsounds" }, + beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = SkinSettingsStrings.BeatmapHitsounds }, new BeatmapOffsetControl { ReferenceScore = { BindTarget = ReferenceScore }, diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 81950efa9e..a999b32cb4 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Graphics.Sprites; +using osu.Game.Localisation; namespace osu.Game.Screens.Play.PlayerSettings { @@ -23,7 +24,7 @@ namespace osu.Game.Screens.Play.PlayerSettings { new OsuSpriteText { - Text = "Background dim:" + Text = GameplaySettingsStrings.BackgroundDim }, dimSliderBar = new PlayerSliderBar { @@ -31,7 +32,7 @@ namespace osu.Game.Screens.Play.PlayerSettings }, new OsuSpriteText { - Text = "Background blur:" + Text = GameplaySettingsStrings.BackgroundBlur }, blurSliderBar = new PlayerSliderBar { @@ -41,9 +42,9 @@ namespace osu.Game.Screens.Play.PlayerSettings { Text = "Toggles:" }, - showStoryboardToggle = new PlayerCheckbox { LabelText = "Storyboard / Video" }, - beatmapSkinsToggle = new PlayerCheckbox { LabelText = "Beatmap skins" }, - beatmapColorsToggle = new PlayerCheckbox { LabelText = "Beatmap colours" }, + showStoryboardToggle = new PlayerCheckbox { LabelText = GraphicsSettingsStrings.StoryboardVideo }, + beatmapSkinsToggle = new PlayerCheckbox { LabelText = SkinSettingsStrings.BeatmapSkins }, + beatmapColorsToggle = new PlayerCheckbox { LabelText = SkinSettingsStrings.BeatmapColours }, }; } diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs index f9aff28bef..bb286f41c0 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs @@ -9,9 +9,11 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Leaderboards; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; @@ -127,8 +129,8 @@ namespace osu.Game.Screens.Ranking.Contracted Spacing = new Vector2(0, 5), Children = new[] { - createStatistic("Max Combo", $"x{score.MaxCombo}"), - createStatistic("Accuracy", $"{score.Accuracy.FormatAccuracy()}"), + createStatistic(BeatmapsetsStrings.ShowScoreboardHeadersCombo, $"x{score.MaxCombo}"), + createStatistic(BeatmapsetsStrings.ShowScoreboardHeadersAccuracy, $"{score.Accuracy.FormatAccuracy()}"), } }, new ModFlowDisplay @@ -200,7 +202,7 @@ namespace osu.Game.Screens.Ranking.Contracted private Drawable createStatistic(HitResultDisplayStatistic result) => createStatistic(result.DisplayName, result.MaxCount == null ? $"{result.Count}" : $"{result.Count}/{result.MaxCount}"); - private Drawable createStatistic(string key, string value) => new Container + private Drawable createStatistic(LocalisableString key, string value) => new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs index 476c9fb42f..25a644d8d9 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs @@ -6,6 +6,7 @@ using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.Ranking.Expanded.Accuracy; using osu.Game.Utils; using osuTK; @@ -26,7 +27,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// /// The accuracy to display. public AccuracyStatistic(double accuracy) - : base("accuracy") + : base(BeatmapsetsStrings.ShowScoreboardHeadersAccuracy) { this.accuracy = accuracy; } diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs index 0e42ec026a..cb25736f6e 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.Ranking.Expanded.Accuracy; using osuTK; @@ -27,7 +28,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// The combo to be displayed. /// The maximum value of . public ComboStatistic(int combo, int? maxCombo) - : base("combo", combo, maxCombo) + : base(BeatmapsetsStrings.ShowScoreboardHeadersCombo, combo, maxCombo) { isPerfect = combo == maxCombo; } diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs index d37f6c5e5f..b1c72173da 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -26,7 +27,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics /// The name of the statistic. /// The value to display. /// The maximum value of . Not displayed if null. - public CounterStatistic(string header, int count, int? maxCount = null) + public CounterStatistic(LocalisableString header, int count, int? maxCount = null) : base(header) { this.count = count; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs index 95f017d625..c681946a2f 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osu.Game.Scoring; namespace osu.Game.Screens.Ranking.Expanded.Statistics @@ -23,7 +24,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics private RollingCounter counter; public PerformanceStatistic(ScoreInfo score) - : base("PP") + : base(BeatmapsetsStrings.ShowScoreboardHeaderspp) { this.score = score; } diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs index 9206c58bc9..c034abc916 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs @@ -3,10 +3,12 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -19,14 +21,14 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics { protected SpriteText HeaderText { get; private set; } - private readonly string header; + private readonly LocalisableString header; private Drawable content; /// /// Creates a new . /// /// The name of the statistic. - protected StatisticDisplay(string header) + protected StatisticDisplay(LocalisableString header) { this.header = header; RelativeSizeAxes = Axes.X; @@ -60,7 +62,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.Torus.With(size: 12, weight: FontWeight.SemiBold), - Text = header.ToUpperInvariant(), + Text = header.ToUpper(), } } }, diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index bbe0a37d8e..9ff1574fe4 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -16,6 +16,7 @@ using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.BeatmapSet; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.Select.Details; using osuTK; using osuTK.Graphics; @@ -155,7 +156,7 @@ namespace osu.Game.Screens.Select { new OsuSpriteText { - Text = "Points of Failure", + Text = BeatmapsetsStrings.ShowInfoPointsOfFailure, Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, failRetryGraph = new FailRetryGraph diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 3576b77ae8..c6037d1bd6 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -24,6 +24,7 @@ using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -136,14 +137,7 @@ namespace osu.Game.Screens.Select.Carousel }, new OsuSpriteText { - Text = "mapped by", - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft - }, - new OsuSpriteText - { - Text = $"{beatmapInfo.Metadata.Author.Username}", - Font = OsuFont.GetFont(italics: true), + Text = BeatmapsetsStrings.ShowDetailsMappedBy(beatmapInfo.Metadata.Author.Username), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, @@ -235,7 +229,7 @@ namespace osu.Game.Screens.Select.Carousel items.Add(new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested(beatmapInfo))); if (editRequested != null) - items.Add(new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested(beatmapInfo))); + items.Add(new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Standard, () => editRequested(beatmapInfo))); if (beatmapInfo.OnlineID > 0 && beatmapOverlay != null) items.Add(new OsuMenuItem("Details...", MenuItemType.Standard, () => beatmapOverlay.FetchAndShowBeatmap(beatmapInfo.OnlineID))); @@ -250,7 +244,7 @@ namespace osu.Game.Screens.Select.Carousel } if (hideRequested != null) - items.Add(new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested(beatmapInfo))); + items.Add(new OsuMenuItem(CommonStrings.ButtonsHide, MenuItemType.Destructive, () => hideRequested(beatmapInfo))); return items.ToArray(); } diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index adaaa6425c..a6f2520472 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -21,6 +21,7 @@ using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Configuration; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; namespace osu.Game.Screens.Select.Details @@ -63,10 +64,10 @@ namespace osu.Game.Screens.Select.Details Children = new[] { FirstValue = new StatisticRow(), // circle size/key amount - HpDrain = new StatisticRow { Title = "HP Drain" }, - Accuracy = new StatisticRow { Title = "Accuracy" }, - ApproachRate = new StatisticRow { Title = "Approach Rate" }, - starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" }, + HpDrain = new StatisticRow { Title = BeatmapsetsStrings.ShowStatsDrain }, + Accuracy = new StatisticRow { Title = BeatmapsetsStrings.ShowStatsAccuracy }, + ApproachRate = new StatisticRow { Title = BeatmapsetsStrings.ShowStatsAr }, + starDifficulty = new StatisticRow(10, true) { Title = BeatmapsetsStrings.ShowStatsStars }, }, }; } @@ -120,12 +121,12 @@ namespace osu.Game.Screens.Select.Details case 3: // Account for mania differences locally for now // Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes - FirstValue.Title = "Key Count"; + FirstValue.Title = BeatmapsetsStrings.ShowStatsCsMania; FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, null); break; default: - FirstValue.Title = "Circle Size"; + FirstValue.Title = BeatmapsetsStrings.ShowStatsCs; FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize); break; } diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index 18c5d713e1..1ab54fa069 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.cs @@ -2,36 +2,38 @@ // See the LICENCE file in the repository root for full licence text. using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Select.Filter { public enum SortMode { - [Description("Artist")] + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingArtist))] Artist, [Description("Author")] Author, - [Description("BPM")] + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatsBpm))] BPM, [Description("Date Added")] DateAdded, - [Description("Difficulty")] + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingDifficulty))] Difficulty, - [Description("Length")] + [LocalisableDescription(typeof(SortStrings), nameof(SortStrings.ArtistTracksLength))] Length, - [Description("Rank Achieved")] + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchFiltersRank))] RankAchieved, - [Description("Source")] + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoSource))] Source, - [Description("Title")] + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingTitle))] Title, } } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b53d64260a..65dde146bb 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; using osuTK; @@ -139,7 +140,7 @@ namespace osu.Game.Screens.Select }, new OsuSpriteText { - Text = "Sort by", + Text = SortStrings.Default, Font = OsuFont.GetFont(size: 14), Margin = new MarginPadding(5), Anchor = Anchor.BottomRight, diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index b5fdbd225f..1a8b69d859 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -13,6 +13,7 @@ using osuTK.Input; using osu.Game.Graphics.Containers; using osu.Framework.Input.Events; using System.Linq; +using osu.Framework.Localisation; namespace osu.Game.Screens.Select.Options { @@ -63,7 +64,7 @@ namespace osu.Game.Screens.Select.Options /// Colour of the button. /// Icon of the button. /// Binding the button does. - public void AddButton(string firstLine, string secondLine, IconUsage icon, Color4 colour, Action action) + public void AddButton(LocalisableString firstLine, string secondLine, IconUsage icon, Color4 colour, Action action) { var button = new BeatmapOptionsButton { diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 21c18413f4..7f275b3b2a 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -1,20 +1,22 @@ // 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.Localisation; using osuTK.Graphics; using osu.Game.Graphics; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Users { public abstract class UserStatus { - public abstract string Message { get; } + public abstract LocalisableString Message { get; } public abstract Color4 GetAppropriateColour(OsuColour colours); } public class UserStatusOnline : UserStatus { - public override string Message => @"Online"; + public override LocalisableString Message => UsersStrings.StatusOnline; public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight; } @@ -25,13 +27,13 @@ namespace osu.Game.Users public class UserStatusOffline : UserStatus { - public override string Message => @"Offline"; + public override LocalisableString Message => UsersStrings.StatusOffline; public override Color4 GetAppropriateColour(OsuColour colours) => Color4.Black; } public class UserStatusDoNotDisturb : UserStatus { - public override string Message => @"Do not disturb"; + public override LocalisableString Message => "Do not disturb"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.RedDark; } }