1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-28 01:47:33 +08:00

Merge branch 'master' into settings-delayed-load

This commit is contained in:
Dean Herbert 2021-08-17 17:42:23 +09:00
commit 1b49e92e99
77 changed files with 1234 additions and 223 deletions

View File

@ -5,23 +5,23 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Screens.Play;
namespace osu.Desktop.Windows namespace osu.Desktop.Windows
{ {
public class GameplayWinKeyBlocker : Component public class GameplayWinKeyBlocker : Component
{ {
private Bindable<bool> disableWinKey; private Bindable<bool> disableWinKey;
private Bindable<bool> localUserPlaying; private IBindable<bool> localUserPlaying;
[Resolved] [Resolved]
private GameHost host { get; set; } private GameHost host { get; set; }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGame game, OsuConfigManager config) private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config)
{ {
localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy();
localUserPlaying.BindValueChanged(_ => updateBlocking()); localUserPlaying.BindValueChanged(_ => updateBlocking());
disableWinKey = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey); disableWinKey = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey);

View File

@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Difficulty.Skills namespace osu.Game.Rulesets.Catch.Difficulty.Skills
{ {
public class Movement : StrainSkill public class Movement : StrainDecaySkill
{ {
private const float absolute_player_positioning_error = 16f; private const float absolute_player_positioning_error = 16f;
private const float normalized_hitobject_radius = 41.0f; private const float normalized_hitobject_radius = 41.0f;

View File

@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Difficulty.Skills namespace osu.Game.Rulesets.Mania.Difficulty.Skills
{ {
public class Strain : StrainSkill public class Strain : StrainDecaySkill
{ {
private const double individual_decay_base = 0.125; private const double individual_decay_base = 0.125;
private const double overall_decay_base = 0.30; private const double overall_decay_base = 0.30;
@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
return individualStrain + overallStrain - CurrentStrain; return individualStrain + overallStrain - CurrentStrain;
} }
protected override double GetPeakStrain(double offset) protected override double CalculateInitialStrain(double offset)
=> applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base) => applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base)
+ applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base); + applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base);

View File

@ -10,7 +10,7 @@ using osu.Framework.Utils;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{ {
public abstract class OsuStrainSkill : StrainSkill public abstract class OsuStrainSkill : StrainDecaySkill
{ {
/// <summary> /// <summary>
/// The number of sections with the highest strains, which the peak strain reductions will apply to. /// The number of sections with the highest strains, which the peak strain reductions will apply to.

View File

@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
/// <summary> /// <summary>
/// Calculates the colour coefficient of taiko difficulty. /// Calculates the colour coefficient of taiko difficulty.
/// </summary> /// </summary>
public class Colour : StrainSkill public class Colour : StrainDecaySkill
{ {
protected override double SkillMultiplier => 1; protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.4; protected override double StrainDecayBase => 0.4;

View File

@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
/// <summary> /// <summary>
/// Calculates the rhythm coefficient of taiko difficulty. /// Calculates the rhythm coefficient of taiko difficulty.
/// </summary> /// </summary>
public class Rhythm : StrainSkill public class Rhythm : StrainDecaySkill
{ {
protected override double SkillMultiplier => 10; protected override double SkillMultiplier => 10;
protected override double StrainDecayBase => 0; protected override double StrainDecayBase => 0;

View File

@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
/// <remarks> /// <remarks>
/// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit). /// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit).
/// </remarks> /// </remarks>
public class Stamina : StrainSkill public class Stamina : StrainDecaySkill
{ {
protected override double SkillMultiplier => 1; protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.4; protected override double StrainDecayBase => 0.4;

View File

@ -6,13 +6,17 @@ using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osu.Game.Screens.Play.PlayerSettings;
using osu.Game.Tests.Beatmaps.IO; using osu.Game.Tests.Beatmaps.IO;
using osu.Game.Users; using osu.Game.Users;
@ -23,6 +27,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Resolved] [Resolved]
private OsuGameBase game { get; set; } private OsuGameBase game { get; set; }
[Resolved]
private OsuConfigManager config { get; set; }
[Resolved] [Resolved]
private BeatmapManager beatmapManager { get; set; } private BeatmapManager beatmapManager { get; set; }
@ -80,6 +87,32 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddWaitStep("wait a bit", 20); AddWaitStep("wait a bit", 20);
} }
[Test]
public void TestSpectatorPlayerInteractiveElementsHidden()
{
HUDVisibilityMode originalConfigValue = default;
AddStep("get original config hud visibility", () => originalConfigValue = config.Get<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode));
AddStep("set config hud visibility to always", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always));
start(new[] { PLAYER_1_ID, PLAYER_2_ID });
loadSpectateScreen(false);
AddUntilStep("wait for player loaders", () => this.ChildrenOfType<PlayerLoader>().Count() == 2);
AddAssert("all player loader settings hidden", () => this.ChildrenOfType<PlayerLoader>().All(l => !l.ChildrenOfType<FillFlowContainer<PlayerSettingsGroup>>().Any()));
AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded);
// components wrapped in skinnable target containers load asynchronously, potentially taking more than one frame to load.
// therefore use until step rather than direct assert to account for that.
AddUntilStep("all interactive elements removed", () => this.ChildrenOfType<Player>().All(p =>
!p.ChildrenOfType<PlayerSettingsOverlay>().Any() &&
!p.ChildrenOfType<HoldForMenuButton>().Any() &&
p.ChildrenOfType<SongProgressBar>().SingleOrDefault()?.ShowHandle == false));
AddStep("restore config hud visibility", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue));
}
[Test] [Test]
public void TestTeamDisplay() public void TestTeamDisplay()
{ {

View File

@ -1,8 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -174,6 +176,60 @@ namespace osu.Game.Tests.Visual.UserInterface
checkBindableAtValue("Circle Size", null); checkBindableAtValue("Circle Size", null);
} }
[Test]
public void TestModSettingChangeTracker()
{
ModSettingChangeTracker tracker = null;
Queue<Mod> settingsChangedQueue = null;
setBeatmapWithDifficultyParameters(5);
AddStep("add mod settings change tracker", () =>
{
settingsChangedQueue = new Queue<Mod>();
tracker = new ModSettingChangeTracker(modDifficultyAdjust.Yield())
{
SettingChanged = settingsChangedQueue.Enqueue
};
});
AddAssert("no settings changed", () => settingsChangedQueue.Count == 0);
setSliderValue("Circle Size", 3);
settingsChangedFired();
setSliderValue("Circle Size", 5);
checkBindableAtValue("Circle Size", 5);
settingsChangedFired();
AddStep("reset mod settings", () => modDifficultyAdjust.CircleSize.SetDefault());
checkBindableAtValue("Circle Size", null);
settingsChangedFired();
setExtendedLimits(true);
settingsChangedFired();
AddStep("dispose tracker", () =>
{
tracker.Dispose();
tracker = null;
});
void settingsChangedFired()
{
AddAssert("setting changed event fired", () =>
{
settingsChangedQueue.Dequeue();
return settingsChangedQueue.Count == 0;
});
}
}
private void resetToDefault(string name) private void resetToDefault(string name)
{ {
AddStep($"Reset {name} to default", () => AddStep($"Reset {name} to default", () =>

View File

@ -101,7 +101,7 @@ namespace osu.Game.Configuration
SetDefault(OsuSetting.HitLighting, true); SetDefault(OsuSetting.HitLighting, true);
SetDefault(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); SetDefault(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always);
SetDefault(OsuSetting.ShowDifficultyGraph, true); SetDefault(OsuSetting.ShowProgressGraph, true);
SetDefault(OsuSetting.ShowHealthDisplayWhenCantFail, true); SetDefault(OsuSetting.ShowHealthDisplayWhenCantFail, true);
SetDefault(OsuSetting.FadePlayfieldWhenHealthLow, true); SetDefault(OsuSetting.FadePlayfieldWhenHealthLow, true);
SetDefault(OsuSetting.KeyOverlay, false); SetDefault(OsuSetting.KeyOverlay, false);
@ -201,6 +201,8 @@ namespace osu.Game.Configuration
public Func<GlobalAction, string> LookupKeyBindings { get; set; } public Func<GlobalAction, string> LookupKeyBindings { get; set; }
} }
// IMPORTANT: These are used in user configuration files.
// The naming of these keys should not be changed once they are deployed in a release, unless migration logic is also added.
public enum OsuSetting public enum OsuSetting
{ {
Ruleset, Ruleset,
@ -217,7 +219,7 @@ namespace osu.Game.Configuration
AlwaysPlayFirstComboBreak, AlwaysPlayFirstComboBreak,
FloatingComments, FloatingComments,
HUDVisibilityMode, HUDVisibilityMode,
ShowDifficultyGraph, ShowProgressGraph,
ShowHealthDisplayWhenCantFail, ShowHealthDisplayWhenCantFail,
FadePlayfieldWhenHealthLow, FadePlayfieldWhenHealthLow,
MouseDisableButtons, MouseDisableButtons,

View File

@ -7,6 +7,7 @@ using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Screens.Play;
namespace osu.Game.Input namespace osu.Game.Input
{ {
@ -24,14 +25,14 @@ namespace osu.Game.Input
private IBindable<bool> localUserPlaying; private IBindable<bool> localUserPlaying;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGame game, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager) private void load(ILocalUserPlayInfo localUserInfo, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager)
{ {
frameworkConfineMode = frameworkConfigManager.GetBindable<ConfineMouseMode>(FrameworkSetting.ConfineMouseMode); frameworkConfineMode = frameworkConfigManager.GetBindable<ConfineMouseMode>(FrameworkSetting.ConfineMouseMode);
frameworkWindowMode = frameworkConfigManager.GetBindable<WindowMode>(FrameworkSetting.WindowMode); frameworkWindowMode = frameworkConfigManager.GetBindable<WindowMode>(FrameworkSetting.WindowMode);
frameworkWindowMode.BindValueChanged(_ => updateConfineMode()); frameworkWindowMode.BindValueChanged(_ => updateConfineMode());
osuConfineMode = osuConfigManager.GetBindable<OsuConfineMouseMode>(OsuSetting.ConfineMouseMode); osuConfineMode = osuConfigManager.GetBindable<OsuConfineMouseMode>(OsuSetting.ConfineMouseMode);
localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy();
osuConfineMode.ValueChanged += _ => updateConfineMode(); osuConfineMode.ValueChanged += _ => updateConfineMode();
localUserPlaying.BindValueChanged(_ => updateConfineMode(), true); localUserPlaying.BindValueChanged(_ => updateConfineMode(), true);

View File

@ -0,0 +1,64 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class AudioSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.AudioSettings";
/// <summary>
/// "Audio"
/// </summary>
public static LocalisableString AudioSectionHeader => new TranslatableString(getKey(@"audio_section_header"), @"Audio");
/// <summary>
/// "Devices"
/// </summary>
public static LocalisableString AudioDevicesHeader => new TranslatableString(getKey(@"audio_devices_header"), @"Devices");
/// <summary>
/// "Volume"
/// </summary>
public static LocalisableString VolumeHeader => new TranslatableString(getKey(@"volume_header"), @"Volume");
/// <summary>
/// "Master"
/// </summary>
public static LocalisableString MasterVolume => new TranslatableString(getKey(@"master_volume"), @"Master");
/// <summary>
/// "Master (window inactive)"
/// </summary>
public static LocalisableString MasterVolumeInactive => new TranslatableString(getKey(@"master_volume_inactive"), @"Master (window inactive)");
/// <summary>
/// "Effect"
/// </summary>
public static LocalisableString EffectVolume => new TranslatableString(getKey(@"effect_volume"), @"Effect");
/// <summary>
/// "Music"
/// </summary>
public static LocalisableString MusicVolume => new TranslatableString(getKey(@"music_volume"), @"Music");
/// <summary>
/// "Offset Adjustment"
/// </summary>
public static LocalisableString OffsetHeader => new TranslatableString(getKey(@"offset_header"), @"Offset Adjustment");
/// <summary>
/// "Audio offset"
/// </summary>
public static LocalisableString AudioOffset => new TranslatableString(getKey(@"audio_offset"), @"Audio offset");
/// <summary>
/// "Offset wizard"
/// </summary>
public static LocalisableString OffsetWizard => new TranslatableString(getKey(@"offset_wizard"), @"Offset wizard");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -14,11 +14,21 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString Cancel => new TranslatableString(getKey(@"cancel"), @"Cancel"); public static LocalisableString Cancel => new TranslatableString(getKey(@"cancel"), @"Cancel");
/// <summary>
/// "Clear"
/// </summary>
public static LocalisableString Clear => new TranslatableString(getKey(@"clear"), @"Clear");
/// <summary> /// <summary>
/// "Enabled" /// "Enabled"
/// </summary> /// </summary>
public static LocalisableString Enabled => new TranslatableString(getKey(@"enabled"), @"Enabled"); public static LocalisableString Enabled => new TranslatableString(getKey(@"enabled"), @"Enabled");
/// <summary>
/// "Default"
/// </summary>
public static LocalisableString Default => new TranslatableString(getKey(@"default"), @"Default");
/// <summary> /// <summary>
/// "Width" /// "Width"
/// </summary> /// </summary>
@ -31,4 +41,4 @@ namespace osu.Game.Localisation
private static string getKey(string key) => $@"{prefix}:{key}"; private static string getKey(string key) => $@"{prefix}:{key}";
} }
} }

View File

@ -0,0 +1,49 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class DebugSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.DebugSettings";
/// <summary>
/// "Debug"
/// </summary>
public static LocalisableString DebugSectionHeader => new TranslatableString(getKey(@"debug_section_header"), @"Debug");
/// <summary>
/// "General"
/// </summary>
public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General");
/// <summary>
/// "Show log overlay"
/// </summary>
public static LocalisableString ShowLogOverlay => new TranslatableString(getKey(@"show_log_overlay"), @"Show log overlay");
/// <summary>
/// "Bypass front-to-back render pass"
/// </summary>
public static LocalisableString BypassFrontToBackPass => new TranslatableString(getKey(@"bypass_front_to_back_pass"), @"Bypass front-to-back render pass");
/// <summary>
/// "Import files"
/// </summary>
public static LocalisableString ImportFiles => new TranslatableString(getKey(@"import_files"), @"Import files");
/// <summary>
/// "Memory"
/// </summary>
public static LocalisableString MemoryHeader => new TranslatableString(getKey(@"memory_header"), @"Memory");
/// <summary>
/// "Clear all caches"
/// </summary>
public static LocalisableString ClearAllCaches => new TranslatableString(getKey(@"clear_all_caches"), @"Clear all caches");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,94 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class GameplaySettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.GameplaySettings";
/// <summary>
/// "Gameplay"
/// </summary>
public static LocalisableString GameplaySectionHeader => new TranslatableString(getKey(@"gameplay_section_header"), @"Gameplay");
/// <summary>
/// "General"
/// </summary>
public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General");
/// <summary>
/// "Background dim"
/// </summary>
public static LocalisableString BackgroundDim => new TranslatableString(getKey(@"dim"), @"Background dim");
/// <summary>
/// "Background blur"
/// </summary>
public static LocalisableString BackgroundBlur => new TranslatableString(getKey(@"blur"), @"Background blur");
/// <summary>
/// "Lighten playfield during breaks"
/// </summary>
public static LocalisableString LightenDuringBreaks => new TranslatableString(getKey(@"lighten_during_breaks"), @"Lighten playfield during breaks");
/// <summary>
/// "HUD overlay visibility mode"
/// </summary>
public static LocalisableString HUDVisibilityMode => new TranslatableString(getKey(@"hud_visibility_mode"), @"HUD overlay visibility mode");
/// <summary>
/// "Show difficulty graph on progress bar"
/// </summary>
public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_difficulty_graph"), @"Show difficulty graph on progress bar");
/// <summary>
/// "Show health display even when you can't fail"
/// </summary>
public static LocalisableString ShowHealthDisplayWhenCantFail => new TranslatableString(getKey(@"show_health_display_when_cant_fail"), @"Show health display even when you can't fail");
/// <summary>
/// "Fade playfield to red when health is low"
/// </summary>
public static LocalisableString FadePlayfieldWhenHealthLow => new TranslatableString(getKey(@"fade_playfield_when_health_low"), @"Fade playfield to red when health is low");
/// <summary>
/// "Always show key overlay"
/// </summary>
public static LocalisableString AlwaysShowKeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay");
/// <summary>
/// "Positional hitsounds"
/// </summary>
public static LocalisableString PositionalHitsounds => new TranslatableString(getKey(@"positional_hitsounds"), @"Positional hitsounds");
/// <summary>
/// "Always play first combo break sound"
/// </summary>
public static LocalisableString AlwaysPlayFirstComboBreak => new TranslatableString(getKey(@"always_play_first_combo_break"), @"Always play first combo break sound");
/// <summary>
/// "Score display mode"
/// </summary>
public static LocalisableString ScoreDisplayMode => new TranslatableString(getKey(@"score_display_mode"), @"Score display mode");
/// <summary>
/// "Disable Windows key during gameplay"
/// </summary>
public static LocalisableString DisableWinKey => new TranslatableString(getKey(@"disable_win_key"), @"Disable Windows key during gameplay");
/// <summary>
/// "Mods"
/// </summary>
public static LocalisableString ModsHeader => new TranslatableString(getKey(@"mods_header"), @"Mods");
/// <summary>
/// "Increase visibility of first object when visual impairment mods are enabled"
/// </summary>
public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,59 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class GeneralSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.GeneralSettings";
/// <summary>
/// "General"
/// </summary>
public static LocalisableString GeneralSectionHeader => new TranslatableString(getKey(@"general_section_header"), @"General");
/// <summary>
/// "Language"
/// </summary>
public static LocalisableString LanguageHeader => new TranslatableString(getKey(@"language_header"), @"Language");
/// <summary>
/// "Language"
/// </summary>
public static LocalisableString LanguageDropdown => new TranslatableString(getKey(@"language_dropdown"), @"Language");
/// <summary>
/// "Prefer metadata in original language"
/// </summary>
public static LocalisableString PreferOriginalMetadataLanguage => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language");
/// <summary>
/// "Updates"
/// </summary>
public static LocalisableString UpdateHeader => new TranslatableString(getKey(@"update_header"), @"Updates");
/// <summary>
/// "Release stream"
/// </summary>
public static LocalisableString ReleaseStream => new TranslatableString(getKey(@"release_stream"), @"Release stream");
/// <summary>
/// "Check for updates"
/// </summary>
public static LocalisableString CheckUpdate => new TranslatableString(getKey(@"check_update"), @"Check for updates");
/// <summary>
/// "Open osu! folder"
/// </summary>
public static LocalisableString OpenOsuFolder => new TranslatableString(getKey(@"open_osu_folder"), @"Open osu! folder");
/// <summary>
/// "Change folder location..."
/// </summary>
public static LocalisableString ChangeFolderLocation => new TranslatableString(getKey(@"change_folder_location"), @"Change folder location...");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,119 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class GraphicsSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.GraphicsSettings";
/// <summary>
/// "Graphics"
/// </summary>
public static LocalisableString GraphicsSectionHeader => new TranslatableString(getKey(@"graphics_section_header"), @"Graphics");
/// <summary>
/// "Renderer"
/// </summary>
public static LocalisableString RendererHeader => new TranslatableString(getKey(@"renderer_header"), @"Renderer");
/// <summary>
/// "Frame limiter"
/// </summary>
public static LocalisableString FrameLimiter => new TranslatableString(getKey(@"frame_limiter"), @"Frame limiter");
/// <summary>
/// "Threading mode"
/// </summary>
public static LocalisableString ThreadingMode => new TranslatableString(getKey(@"threading_mode"), @"Threading mode");
/// <summary>
/// "Show FPS"
/// </summary>
public static LocalisableString ShowFPS => new TranslatableString(getKey(@"show_fps"), @"Show FPS");
/// <summary>
/// "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. "2x refresh rate" is recommended."
/// </summary>
public static LocalisableString UnlimitedFramesNote => new TranslatableString(getKey(@"unlimited_frames_note"), @"Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. ""2x refresh rate"" is recommended.");
/// <summary>
/// "Layout"
/// </summary>
public static LocalisableString LayoutHeader => new TranslatableString(getKey(@"layout_header"), @"Layout");
/// <summary>
/// "Screen mode"
/// </summary>
public static LocalisableString ScreenMode => new TranslatableString(getKey(@"screen_mode"), @"Screen mode");
/// <summary>
/// "Resolution"
/// </summary>
public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution");
/// <summary>
/// "UI scaling"
/// </summary>
public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI scaling");
/// <summary>
/// "Screen scaling"
/// </summary>
public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen scaling");
/// <summary>
/// "Horizontal position"
/// </summary>
public static LocalisableString HorizontalPosition => new TranslatableString(getKey(@"horizontal_position"), @"Horizontal position");
/// <summary>
/// "Vertical position"
/// </summary>
public static LocalisableString VerticalPosition => new TranslatableString(getKey(@"vertical_position"), @"Vertical position");
/// <summary>
/// "Horizontal scale"
/// </summary>
public static LocalisableString HorizontalScale => new TranslatableString(getKey(@"horizontal_scale"), @"Horizontal scale");
/// <summary>
/// "Vertical scale"
/// </summary>
public static LocalisableString VerticalScale => new TranslatableString(getKey(@"vertical_scale"), @"Vertical scale");
/// <summary>
/// "Running without fullscreen mode will increase your input latency!"
/// </summary>
public static LocalisableString NotFullscreenNote => new TranslatableString(getKey(@"not_fullscreen_note"), @"Running without fullscreen mode will increase your input latency!");
/// <summary>
/// "Detail Settings"
/// </summary>
public static LocalisableString DetailSettingsHeader => new TranslatableString(getKey(@"detail_settings_header"), @"Detail Settings");
/// <summary>
/// "Storyboard / video"
/// </summary>
public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / video");
/// <summary>
/// "Hit lighting"
/// </summary>
public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit lighting");
/// <summary>
/// "Screenshot format"
/// </summary>
public static LocalisableString ScreenshotFormat => new TranslatableString(getKey(@"screenshot_format"), @"Screenshot format");
/// <summary>
/// "Show menu cursor in screenshots"
/// </summary>
public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@"show_cursor_in_screenshots"), @"Show menu cursor in screenshots");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,59 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class InputSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.InputSettings";
/// <summary>
/// "Input"
/// </summary>
public static LocalisableString InputSectionHeader => new TranslatableString(getKey(@"input_section_header"), @"Input");
/// <summary>
/// "Global"
/// </summary>
public static LocalisableString GlobalKeyBindingHeader => new TranslatableString(getKey(@"global_key_binding_header"), @"Global");
/// <summary>
/// "Song Select"
/// </summary>
public static LocalisableString SongSelectSection => new TranslatableString(getKey(@"song_select_section"), @"Song Select");
/// <summary>
/// "In Game"
/// </summary>
public static LocalisableString InGameSection => new TranslatableString(getKey(@"in_game_section"), @"In Game");
/// <summary>
/// "Audio"
/// </summary>
public static LocalisableString AudioSection => new TranslatableString(getKey(@"audio_section"), @"Audio");
/// <summary>
/// "Editor"
/// </summary>
public static LocalisableString EditorSection => new TranslatableString(getKey(@"editor_section"), @"Editor");
/// <summary>
/// "Reset all bindings in section"
/// </summary>
public static LocalisableString ResetSectionButton => new TranslatableString(getKey(@"reset_section_button"), @"Reset all bindings in section");
/// <summary>
/// "key configuration"
/// </summary>
public static LocalisableString KeyBindingPanelHeader => new TranslatableString(getKey(@"key_binding_panel_header"), @"key configuration");
/// <summary>
/// "Customise your keys!"
/// </summary>
public static LocalisableString KeyBindingPanelDescription => new TranslatableString(getKey(@"key_binding_panel_description"), @"Customise your keys!");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class MaintenanceSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.MaintenanceSettings";
/// <summary>
/// "Maintenance"
/// </summary>
public static LocalisableString MaintenanceSectionHeader => new TranslatableString(getKey(@"maintenance_section_header"), @"Maintenance");
/// <summary>
/// "Select directory"
/// </summary>
public static LocalisableString SelectDirectory => new TranslatableString(getKey(@"select_directory"), @"Select directory");
/// <summary>
/// "Import beatmaps from stable"
/// </summary>
public static LocalisableString ImportBeatmapsFromStable => new TranslatableString(getKey(@"import_beatmaps_from_stable"), @"Import beatmaps from stable");
/// <summary>
/// "Delete ALL beatmaps"
/// </summary>
public static LocalisableString DeleteAllBeatmaps => new TranslatableString(getKey(@"delete_all_beatmaps"), @"Delete ALL beatmaps");
/// <summary>
/// "Import scores from stable"
/// </summary>
public static LocalisableString ImportScoresFromStable => new TranslatableString(getKey(@"import_scores_from_stable"), @"Import scores from stable");
/// <summary>
/// "Delete ALL scores"
/// </summary>
public static LocalisableString DeleteAllScores => new TranslatableString(getKey(@"delete_all_scores"), @"Delete ALL scores");
/// <summary>
/// "Import skins from stable"
/// </summary>
public static LocalisableString ImportSkinsFromStable => new TranslatableString(getKey(@"import_skins_from_stable"), @"Import skins from stable");
/// <summary>
/// "Delete ALL skins"
/// </summary>
public static LocalisableString DeleteAllSkins => new TranslatableString(getKey(@"delete_all_skins"), @"Delete ALL skins");
/// <summary>
/// "Import collections from stable"
/// </summary>
public static LocalisableString ImportCollectionsFromStable => new TranslatableString(getKey(@"import_collections_from_stable"), @"Import collections from stable");
/// <summary>
/// "Delete ALL collections"
/// </summary>
public static LocalisableString DeleteAllCollections => new TranslatableString(getKey(@"delete_all_collections"), @"Delete ALL collections");
/// <summary>
/// "Restore all hidden difficulties"
/// </summary>
public static LocalisableString RestoreAllHiddenDifficulties => new TranslatableString(getKey(@"restore_all_hidden_difficulties"), @"Restore all hidden difficulties");
/// <summary>
/// "Restore all recently deleted beatmaps"
/// </summary>
public static LocalisableString RestoreAllRecentlyDeletedBeatmaps => new TranslatableString(getKey(@"restore_all_recently_deleted_beatmaps"), @"Restore all recently deleted beatmaps");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,69 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class OnlineSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.OnlineSettings";
/// <summary>
/// "Online"
/// </summary>
public static LocalisableString OnlineSectionHeader => new TranslatableString(getKey(@"online_section_header"), @"Online");
/// <summary>
/// "Alerts and Privacy"
/// </summary>
public static LocalisableString AlertsAndPrivacyHeader => new TranslatableString(getKey(@"alerts_and_privacy_header"), @"Alerts and Privacy");
/// <summary>
/// "Show a notification when someone mentions your name"
/// </summary>
public static LocalisableString NotifyOnMentioned => new TranslatableString(getKey(@"notify_on_mentioned"), @"Show a notification when someone mentions your name");
/// <summary>
/// "Show a notification when you receive a private message"
/// </summary>
public static LocalisableString NotifyOnPrivateMessage => new TranslatableString(getKey(@"notify_on_private_message"), @"Show a notification when you receive a private message");
/// <summary>
/// "Integrations"
/// </summary>
public static LocalisableString IntegrationsHeader => new TranslatableString(getKey(@"integrations_header"), @"Integrations");
/// <summary>
/// "Discord Rich Presence"
/// </summary>
public static LocalisableString DiscordRichPresence => new TranslatableString(getKey(@"discord_rich_presence"), @"Discord Rich Presence");
/// <summary>
/// "Web"
/// </summary>
public static LocalisableString WebHeader => new TranslatableString(getKey(@"web_header"), @"Web");
/// <summary>
/// "Warn about opening external links"
/// </summary>
public static LocalisableString ExternalLinkWarning => new TranslatableString(getKey(@"external_link_warning"), @"Warn about opening external links");
/// <summary>
/// "Prefer downloads without video"
/// </summary>
public static LocalisableString PreferNoVideo => new TranslatableString(getKey(@"prefer_no_video"), @"Prefer downloads without video");
/// <summary>
/// "Automatically download beatmaps when spectating"
/// </summary>
public static LocalisableString AutomaticallyDownloadWhenSpectating => new TranslatableString(getKey(@"automatically_download_when_spectating"), @"Automatically download beatmaps when spectating");
/// <summary>
/// "Show explicit content in search results"
/// </summary>
public static LocalisableString ShowExplicitContent => new TranslatableString(getKey(@"show_explicit_content"), @"Show explicit content in search results");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,54 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class SkinSettingsStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.SkinSettings";
/// <summary>
/// "Skin"
/// </summary>
public static LocalisableString SkinSectionHeader => new TranslatableString(getKey(@"skin_section_header"), @"Skin");
/// <summary>
/// "Skin layout editor"
/// </summary>
public static LocalisableString SkinLayoutEditor => new TranslatableString(getKey(@"skin_layout_editor"), @"Skin layout editor");
/// <summary>
/// "Gameplay cursor size"
/// </summary>
public static LocalisableString GameplayCursorSize => new TranslatableString(getKey(@"gameplay_cursor_size"), @"Gameplay cursor size");
/// <summary>
/// "Adjust gameplay cursor size based on current beatmap"
/// </summary>
public static LocalisableString AutoCursorSize => new TranslatableString(getKey(@"auto_cursor_size"), @"Adjust gameplay cursor size based on current beatmap");
/// <summary>
/// "Beatmap skins"
/// </summary>
public static LocalisableString BeatmapSkins => new TranslatableString(getKey(@"beatmap_skins"), @"Beatmap skins");
/// <summary>
/// "Beatmap colours"
/// </summary>
public static LocalisableString BeatmapColours => new TranslatableString(getKey(@"beatmap_colours"), @"Beatmap colours");
/// <summary>
/// "Beatmap hitsounds"
/// </summary>
public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds");
/// <summary>
/// "Export selected skin"
/// </summary>
public static LocalisableString ExportSkinButton => new TranslatableString(getKey(@"export_skin_button"), @"Export selected skin");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -0,0 +1,114 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Localisation;
namespace osu.Game.Localisation
{
public static class UserInterfaceStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.UserInterface";
/// <summary>
/// "User Interface"
/// </summary>
public static LocalisableString UserInterfaceSectionHeader => new TranslatableString(getKey(@"user_interface_section_header"), @"User Interface");
/// <summary>
/// "General"
/// </summary>
public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General");
/// <summary>
/// "Rotate cursor when dragging"
/// </summary>
public static LocalisableString CursorRotation => new TranslatableString(getKey(@"cursor_rotation"), @"Rotate cursor when dragging");
/// <summary>
/// "Menu cursor size"
/// </summary>
public static LocalisableString MenuCursorSize => new TranslatableString(getKey(@"menu_cursor_size"), @"Menu cursor size");
/// <summary>
/// "Parallax"
/// </summary>
public static LocalisableString Parallax => new TranslatableString(getKey(@"parallax"), @"Parallax");
/// <summary>
/// "Hold-to-confirm activation time"
/// </summary>
public static LocalisableString HoldToConfirmActivationTime => new TranslatableString(getKey(@"hold_to_confirm_activation_time"), @"Hold-to-confirm activation time");
/// <summary>
/// "Main Menu"
/// </summary>
public static LocalisableString MainMenuHeader => new TranslatableString(getKey(@"main_menu_header"), @"Main Menu");
/// <summary>
/// "Interface voices"
/// </summary>
public static LocalisableString InterfaceVoices => new TranslatableString(getKey(@"interface_voices"), @"Interface voices");
/// <summary>
/// "osu! music theme"
/// </summary>
public static LocalisableString OsuMusicTheme => new TranslatableString(getKey(@"osu_music_theme"), @"osu! music theme");
/// <summary>
/// "Intro sequence"
/// </summary>
public static LocalisableString IntroSequence => new TranslatableString(getKey(@"intro_sequence"), @"Intro sequence");
/// <summary>
/// "Background source"
/// </summary>
public static LocalisableString BackgroundSource => new TranslatableString(getKey(@"background_source"), @"Background source");
/// <summary>
/// "Seasonal backgrounds"
/// </summary>
public static LocalisableString SeasonalBackgrounds => new TranslatableString(getKey(@"seasonal_backgrounds"), @"Seasonal backgrounds");
/// <summary>
/// "Changes to this setting will only apply with an active osu!supporter tag."
/// </summary>
public static LocalisableString NotSupporterNote => new TranslatableString(getKey(@"not_supporter_note"), @"Changes to this setting will only apply with an active osu!supporter tag.");
/// <summary>
/// "Song Select"
/// </summary>
public static LocalisableString SongSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select");
/// <summary>
/// "Right mouse drag to absolute scroll"
/// </summary>
public static LocalisableString RightMouseScroll => new TranslatableString(getKey(@"right_mouse_scroll"), @"Right mouse drag to absolute scroll");
/// <summary>
/// "Show converted beatmaps"
/// </summary>
public static LocalisableString ShowConvertedBeatmaps => new TranslatableString(getKey(@"show_converted_beatmaps"), @"Show converted beatmaps");
/// <summary>
/// "Display beatmaps from"
/// </summary>
public static LocalisableString StarsMinimum => new TranslatableString(getKey(@"stars_minimum"), @"Display beatmaps from");
/// <summary>
/// "up to"
/// </summary>
public static LocalisableString StarsMaximum => new TranslatableString(getKey(@"stars_maximum"), @"up to");
/// <summary>
/// "Random selection algorithm"
/// </summary>
public static LocalisableString RandomSelectionAlgorithm => new TranslatableString(getKey(@"random_selection_algorithm"), @"Random selection algorithm");
/// <summary>
/// "no limit"
/// </summary>
public static LocalisableString NoLimit => new TranslatableString(getKey(@"no_limit"), @"no limit");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -62,7 +62,7 @@ namespace osu.Game
/// The full osu! experience. Builds on top of <see cref="OsuGameBase"/> to add menus and binding logic /// The full osu! experience. Builds on top of <see cref="OsuGameBase"/> to add menus and binding logic
/// for initial components that are generally retrieved via DI. /// for initial components that are generally retrieved via DI.
/// </summary> /// </summary>
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction> public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>, ILocalUserPlayInfo
{ {
/// <summary> /// <summary>
/// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications).
@ -1085,5 +1085,7 @@ namespace osu.Game
if (newScreen == null) if (newScreen == null)
Exit(); Exit();
} }
IBindable<bool> ILocalUserPlayInfo.IsPlaying => LocalUserPlaying;
} }
} }

View File

@ -139,19 +139,24 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
LoadComponentAsync(Preview = previewTrackManager.Get(beatmapSet), preview => LoadComponentAsync(Preview = previewTrackManager.Get(beatmapSet), preview =>
{ {
// beatmapset may have changed. // Make sure that we schedule to after the next audio frame to fix crashes in single-threaded execution.
if (Preview != preview) // See: https://github.com/ppy/osu-framework/issues/4692
return; Schedule(() =>
{
// beatmapset may have changed.
if (Preview != preview)
return;
AddInternal(preview); AddInternal(preview);
loading = false; loading = false;
// make sure that the update of value of Playing (and the ensuing value change callbacks) // make sure that the update of value of Playing (and the ensuing value change callbacks)
// are marshaled back to the update thread. // are marshaled back to the update thread.
preview.Stopped += () => Schedule(() => playing.Value = false); preview.Stopped += () => Schedule(() => playing.Value = false);
// user may have changed their mind. // user may have changed their mind.
if (playing.Value) if (playing.Value)
attemptStart(); attemptStart();
});
}); });
} }
else else

View File

@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Changelog
public class ChangelogSupporterPromo : CompositeDrawable public class ChangelogSupporterPromo : CompositeDrawable
{ {
private const float image_container_width = 164; private const float image_container_width = 164;
private const float heart_size = 75;
private readonly FillFlowContainer textContainer; private readonly FillFlowContainer textContainer;
private readonly Container imageContainer; private readonly Container imageContainer;
@ -134,18 +135,30 @@ namespace osu.Game.Overlays.Changelog
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Margin = new MarginPadding { Bottom = 28 },
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fill, FillMode = FillMode.Fill,
Texture = textures.Get(@"Online/supporter-pippi"), Texture = textures.Get(@"Online/supporter-pippi"),
}, },
new Sprite new Container
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Width = 75, Size = new Vector2(heart_size),
Height = 75,
Margin = new MarginPadding { Top = 70 }, Margin = new MarginPadding { Top = 70 },
Texture = textures.Get(@"Online/supporter-heart"), Masking = true,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = colour.Pink,
Radius = 10,
Roundness = heart_size / 2,
},
Child = new Sprite
{
Size = new Vector2(heart_size),
Texture = textures.Get(@"Online/supporter-heart"),
},
}, },
}; };
} }

View File

@ -8,12 +8,13 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Audio namespace osu.Game.Overlays.Settings.Sections.Audio
{ {
public class AudioDevicesSettings : SettingsSubsection public class AudioDevicesSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Devices"; protected override LocalisableString Header => AudioSettingsStrings.AudioDevicesHeader;
[Resolved] [Resolved]
private AudioManager audio { get; set; } private AudioManager audio { get; set; }
@ -76,7 +77,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
private class AudioDeviceDropdownControl : DropdownControl private class AudioDeviceDropdownControl : DropdownControl
{ {
protected override LocalisableString GenerateItemText(string item) protected override LocalisableString GenerateItemText(string item)
=> string.IsNullOrEmpty(item) ? "Default" : base.GenerateItemText(item); => string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item);
} }
} }
} }

View File

@ -1,17 +1,22 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Audio namespace osu.Game.Overlays.Settings.Sections.Audio
{ {
public class OffsetSettings : SettingsSubsection public class OffsetSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Offset Adjustment"; protected override LocalisableString Header => AudioSettingsStrings.OffsetHeader;
public override IEnumerable<string> FilterTerms => base.FilterTerms.Concat(new[] { "universal", "uo", "timing" });
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -20,13 +25,13 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
{ {
new SettingsSlider<double, OffsetSlider> new SettingsSlider<double, OffsetSlider>
{ {
LabelText = "Audio offset", LabelText = AudioSettingsStrings.AudioOffset,
Current = config.GetBindable<double>(OsuSetting.AudioOffset), Current = config.GetBindable<double>(OsuSetting.AudioOffset),
KeyboardStep = 1f KeyboardStep = 1f
}, },
new SettingsButton new SettingsButton
{ {
Text = "Offset wizard" Text = AudioSettingsStrings.OffsetWizard
} }
}; };
} }

View File

@ -6,12 +6,13 @@ using osu.Framework.Audio;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Audio namespace osu.Game.Overlays.Settings.Sections.Audio
{ {
public class VolumeSettings : SettingsSubsection public class VolumeSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Volume"; protected override LocalisableString Header => AudioSettingsStrings.VolumeHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio, OsuConfigManager config) private void load(AudioManager audio, OsuConfigManager config)
@ -20,28 +21,28 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
{ {
new SettingsSlider<double> new SettingsSlider<double>
{ {
LabelText = "Master", LabelText = AudioSettingsStrings.MasterVolume,
Current = audio.Volume, Current = audio.Volume,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<double> new SettingsSlider<double>
{ {
LabelText = "Master (window inactive)", LabelText = AudioSettingsStrings.MasterVolumeInactive,
Current = config.GetBindable<double>(OsuSetting.VolumeInactive), Current = config.GetBindable<double>(OsuSetting.VolumeInactive),
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<double> new SettingsSlider<double>
{ {
LabelText = "Effect", LabelText = AudioSettingsStrings.EffectVolume,
Current = audio.VolumeSample, Current = audio.VolumeSample,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<double> new SettingsSlider<double>
{ {
LabelText = "Music", LabelText = AudioSettingsStrings.MusicVolume,
Current = audio.VolumeTrack, Current = audio.VolumeTrack,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true

View File

@ -3,15 +3,17 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Localisation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.Audio; using osu.Game.Overlays.Settings.Sections.Audio;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class AudioSection : SettingsSection public class AudioSection : SettingsSection
{ {
public override string Header => "Audio"; public override LocalisableString Header => AudioSettingsStrings.AudioSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -6,13 +6,14 @@ using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Localisation;
using osu.Game.Screens.Import; using osu.Game.Screens.Import;
namespace osu.Game.Overlays.Settings.Sections.Debug namespace osu.Game.Overlays.Settings.Sections.Debug
{ {
public class GeneralSettings : SettingsSubsection public class GeneralSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "General"; protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, OsuGame game) private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, OsuGame game)
@ -21,18 +22,18 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show log overlay", LabelText = DebugSettingsStrings.ShowLogOverlay,
Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowLogOverlay) Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowLogOverlay)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Bypass front-to-back render pass", LabelText = DebugSettingsStrings.BypassFrontToBackPass,
Current = config.GetBindable<bool>(DebugSetting.BypassFrontToBackPass) Current = config.GetBindable<bool>(DebugSetting.BypassFrontToBackPass)
} }
}; };
Add(new SettingsButton Add(new SettingsButton
{ {
Text = "Import files", Text = DebugSettingsStrings.ImportFiles,
Action = () => game?.PerformFromScreen(menu => menu.Push(new FileImportScreen())) Action = () => game?.PerformFromScreen(menu => menu.Push(new FileImportScreen()))
}); });
} }

View File

@ -6,12 +6,13 @@ using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Debug namespace osu.Game.Overlays.Settings.Sections.Debug
{ {
public class MemorySettings : SettingsSubsection public class MemorySettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Memory"; protected override LocalisableString Header => DebugSettingsStrings.MemoryHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(FrameworkDebugConfigManager config, GameHost host) private void load(FrameworkDebugConfigManager config, GameHost host)
@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
{ {
new SettingsButton new SettingsButton
{ {
Text = "Clear all caches", Text = DebugSettingsStrings.ClearAllCaches,
Action = host.Collect Action = host.Collect
}, },
}; };

View File

@ -3,13 +3,15 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.Debug; using osu.Game.Overlays.Settings.Sections.Debug;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class DebugSection : SettingsSection public class DebugSection : SettingsSection
{ {
public override string Header => "Debug"; public override LocalisableString Header => DebugSettingsStrings.DebugSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -6,13 +6,14 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Overlays.Settings.Sections.Gameplay namespace osu.Game.Overlays.Settings.Sections.Gameplay
{ {
public class GeneralSettings : SettingsSubsection public class GeneralSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "General"; protected override LocalisableString Header => GameplaySettingsStrings.GeneralHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -21,62 +22,62 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
{ {
new SettingsSlider<double> new SettingsSlider<double>
{ {
LabelText = "Background dim", LabelText = GameplaySettingsStrings.BackgroundDim,
Current = config.GetBindable<double>(OsuSetting.DimLevel), Current = config.GetBindable<double>(OsuSetting.DimLevel),
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<double> new SettingsSlider<double>
{ {
LabelText = "Background blur", LabelText = GameplaySettingsStrings.BackgroundBlur,
Current = config.GetBindable<double>(OsuSetting.BlurLevel), Current = config.GetBindable<double>(OsuSetting.BlurLevel),
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Lighten playfield during breaks", LabelText = GameplaySettingsStrings.LightenDuringBreaks,
Current = config.GetBindable<bool>(OsuSetting.LightenDuringBreaks) Current = config.GetBindable<bool>(OsuSetting.LightenDuringBreaks)
}, },
new SettingsEnumDropdown<HUDVisibilityMode> new SettingsEnumDropdown<HUDVisibilityMode>
{ {
LabelText = "HUD overlay visibility mode", LabelText = GameplaySettingsStrings.HUDVisibilityMode,
Current = config.GetBindable<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode) Current = config.GetBindable<HUDVisibilityMode>(OsuSetting.HUDVisibilityMode)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show difficulty graph on progress bar", LabelText = GameplaySettingsStrings.ShowDifficultyGraph,
Current = config.GetBindable<bool>(OsuSetting.ShowDifficultyGraph) Current = config.GetBindable<bool>(OsuSetting.ShowProgressGraph)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show health display even when you can't fail", LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail,
Current = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail), Current = config.GetBindable<bool>(OsuSetting.ShowHealthDisplayWhenCantFail),
Keywords = new[] { "hp", "bar" } Keywords = new[] { "hp", "bar" }
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Fade playfield to red when health is low", LabelText = GameplaySettingsStrings.FadePlayfieldWhenHealthLow,
Current = config.GetBindable<bool>(OsuSetting.FadePlayfieldWhenHealthLow), Current = config.GetBindable<bool>(OsuSetting.FadePlayfieldWhenHealthLow),
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Always show key overlay", LabelText = GameplaySettingsStrings.AlwaysShowKeyOverlay,
Current = config.GetBindable<bool>(OsuSetting.KeyOverlay) Current = config.GetBindable<bool>(OsuSetting.KeyOverlay)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Positional hitsounds", LabelText = GameplaySettingsStrings.PositionalHitsounds,
Current = config.GetBindable<bool>(OsuSetting.PositionalHitSounds) Current = config.GetBindable<bool>(OsuSetting.PositionalHitSounds)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Always play first combo break sound", LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak,
Current = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak) Current = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak)
}, },
new SettingsEnumDropdown<ScoringMode> new SettingsEnumDropdown<ScoringMode>
{ {
LabelText = "Score display mode", LabelText = GameplaySettingsStrings.ScoreDisplayMode,
Current = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode), Current = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode),
Keywords = new[] { "scoring" } Keywords = new[] { "scoring" }
}, },
@ -86,7 +87,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
{ {
Add(new SettingsCheckbox Add(new SettingsCheckbox
{ {
LabelText = "Disable Windows key during gameplay", LabelText = GameplaySettingsStrings.DisableWinKey,
Current = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey) Current = config.GetBindable<bool>(OsuSetting.GameplayDisableWinKey)
}); });
} }

View File

@ -6,12 +6,13 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Gameplay namespace osu.Game.Overlays.Settings.Sections.Gameplay
{ {
public class ModsSettings : SettingsSubsection public class ModsSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Mods"; protected override LocalisableString Header => GameplaySettingsStrings.ModsHeader;
public override IEnumerable<string> FilterTerms => base.FilterTerms.Concat(new[] { "mod" }); public override IEnumerable<string> FilterTerms => base.FilterTerms.Concat(new[] { "mod" });
@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Increase visibility of first object when visual impairment mods are enabled", LabelText = GameplaySettingsStrings.IncreaseFirstObjectVisibility,
Current = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility), Current = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility),
}, },
}; };

View File

@ -9,12 +9,14 @@ using osu.Game.Rulesets;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class GameplaySection : SettingsSection public class GameplaySection : SettingsSection
{ {
public override string Header => "Gameplay"; public override LocalisableString Header => GameplaySettingsStrings.GameplaySectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
private SettingsDropdown<Language> languageSelection; private SettingsDropdown<Language> languageSelection;
private Bindable<string> frameworkLocale; private Bindable<string> frameworkLocale;
protected override LocalisableString Header => "Language"; protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(FrameworkConfigManager frameworkConfig) private void load(FrameworkConfigManager frameworkConfig)
@ -27,11 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
languageSelection = new SettingsEnumDropdown<Language> languageSelection = new SettingsEnumDropdown<Language>
{ {
LabelText = "Language", LabelText = GeneralSettingsStrings.LanguageDropdown,
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Prefer metadata in original language", LabelText = GeneralSettingsStrings.PreferOriginalMetadataLanguage,
Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowUnicode) Current = frameworkConfig.GetBindable<bool>(FrameworkSetting.ShowUnicode)
}, },
}; };

View File

@ -9,6 +9,7 @@ using osu.Framework.Localisation;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Overlays.Settings.Sections.Maintenance;
using osu.Game.Updater; using osu.Game.Updater;
@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
private UpdateManager updateManager { get; set; } private UpdateManager updateManager { get; set; }
protected override LocalisableString Header => "Updates"; protected override LocalisableString Header => GeneralSettingsStrings.UpdateHeader;
private SettingsButton checkForUpdatesButton; private SettingsButton checkForUpdatesButton;
@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
Add(new SettingsEnumDropdown<ReleaseStream> Add(new SettingsEnumDropdown<ReleaseStream>
{ {
LabelText = "Release stream", LabelText = GeneralSettingsStrings.ReleaseStream,
Current = config.GetBindable<ReleaseStream>(OsuSetting.ReleaseStream), Current = config.GetBindable<ReleaseStream>(OsuSetting.ReleaseStream),
}); });
@ -40,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
Add(checkForUpdatesButton = new SettingsButton Add(checkForUpdatesButton = new SettingsButton
{ {
Text = "Check for updates", Text = GeneralSettingsStrings.CheckUpdate,
Action = () => Action = () =>
{ {
checkForUpdatesButton.Enabled.Value = false; checkForUpdatesButton.Enabled.Value = false;
@ -65,13 +66,13 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
Add(new SettingsButton Add(new SettingsButton
{ {
Text = "Open osu! folder", Text = GeneralSettingsStrings.OpenOsuFolder,
Action = storage.OpenInNativeExplorer, Action = storage.OpenInNativeExplorer,
}); });
Add(new SettingsButton Add(new SettingsButton
{ {
Text = "Change folder location...", Text = GeneralSettingsStrings.ChangeFolderLocation,
Action = () => game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())) Action = () => game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen()))
}); });
} }

View File

@ -3,13 +3,15 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.General; using osu.Game.Overlays.Settings.Sections.General;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class GeneralSection : SettingsSection public class GeneralSection : SettingsSection
{ {
public override string Header => "General"; public override LocalisableString Header => GeneralSettingsStrings.GeneralSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -5,12 +5,13 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Graphics namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
public class DetailSettings : SettingsSubsection public class DetailSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Detail Settings"; protected override LocalisableString Header => GraphicsSettingsStrings.DetailSettingsHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -19,22 +20,22 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Storyboard / Video", LabelText = GraphicsSettingsStrings.StoryboardVideo,
Current = config.GetBindable<bool>(OsuSetting.ShowStoryboard) Current = config.GetBindable<bool>(OsuSetting.ShowStoryboard)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Hit Lighting", LabelText = GraphicsSettingsStrings.HitLighting,
Current = config.GetBindable<bool>(OsuSetting.HitLighting) Current = config.GetBindable<bool>(OsuSetting.HitLighting)
}, },
new SettingsEnumDropdown<ScreenshotFormat> new SettingsEnumDropdown<ScreenshotFormat>
{ {
LabelText = "Screenshot format", LabelText = GraphicsSettingsStrings.ScreenshotFormat,
Current = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat) Current = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show menu cursor in screenshots", LabelText = GraphicsSettingsStrings.ShowCursorInScreenshots,
Current = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor) Current = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor)
} }
}; };

View File

@ -16,13 +16,14 @@ using osu.Framework.Platform;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Overlays.Settings.Sections.Graphics namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
public class LayoutSettings : SettingsSubsection public class LayoutSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Layout"; protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader;
private FillFlowContainer<SettingsSlider<float>> scalingSettings; private FillFlowContainer<SettingsSlider<float>> scalingSettings;
@ -67,20 +68,20 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
windowModeDropdown = new SettingsDropdown<WindowMode> windowModeDropdown = new SettingsDropdown<WindowMode>
{ {
LabelText = "Screen mode", LabelText = GraphicsSettingsStrings.ScreenMode,
ItemSource = windowModes, ItemSource = windowModes,
Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode), Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
}, },
resolutionDropdown = new ResolutionSettingsDropdown resolutionDropdown = new ResolutionSettingsDropdown
{ {
LabelText = "Resolution", LabelText = GraphicsSettingsStrings.Resolution,
ShowsDefaultIndicator = false, ShowsDefaultIndicator = false,
ItemSource = resolutions, ItemSource = resolutions,
Current = sizeFullscreen Current = sizeFullscreen
}, },
new SettingsSlider<float, UIScaleSlider> new SettingsSlider<float, UIScaleSlider>
{ {
LabelText = "UI Scaling", LabelText = GraphicsSettingsStrings.UIScaling,
TransferValueOnCommit = true, TransferValueOnCommit = true,
Current = osuConfig.GetBindable<float>(OsuSetting.UIScale), Current = osuConfig.GetBindable<float>(OsuSetting.UIScale),
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
@ -88,7 +89,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
}, },
new SettingsEnumDropdown<ScalingMode> new SettingsEnumDropdown<ScalingMode>
{ {
LabelText = "Screen Scaling", LabelText = GraphicsSettingsStrings.ScreenScaling,
Current = osuConfig.GetBindable<ScalingMode>(OsuSetting.Scaling), Current = osuConfig.GetBindable<ScalingMode>(OsuSetting.Scaling),
Keywords = new[] { "scale", "letterbox" }, Keywords = new[] { "scale", "letterbox" },
}, },
@ -102,28 +103,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
new SettingsSlider<float> new SettingsSlider<float>
{ {
LabelText = "Horizontal position", LabelText = GraphicsSettingsStrings.HorizontalPosition,
Current = scalingPositionX, Current = scalingPositionX,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<float> new SettingsSlider<float>
{ {
LabelText = "Vertical position", LabelText = GraphicsSettingsStrings.VerticalPosition,
Current = scalingPositionY, Current = scalingPositionY,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<float> new SettingsSlider<float>
{ {
LabelText = "Horizontal scale", LabelText = GraphicsSettingsStrings.HorizontalScale,
Current = scalingSizeX, Current = scalingSizeX,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
}, },
new SettingsSlider<float> new SettingsSlider<float>
{ {
LabelText = "Vertical scale", LabelText = GraphicsSettingsStrings.VerticalScale,
Current = scalingSizeY, Current = scalingSizeY,
KeyboardStep = 0.01f, KeyboardStep = 0.01f,
DisplayAsPercentage = true DisplayAsPercentage = true
@ -143,9 +144,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
updateResolutionDropdown(); updateResolutionDropdown();
const string not_fullscreen_note = "Running without fullscreen mode will increase your input latency!"; windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : default;
windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty;
}, true); }, true);
windowModes.BindCollectionChanged((sender, args) => windowModes.BindCollectionChanged((sender, args) =>
@ -253,7 +252,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
protected override LocalisableString GenerateItemText(Size item) protected override LocalisableString GenerateItemText(Size item)
{ {
if (item == new Size(9999, 9999)) if (item == new Size(9999, 9999))
return "Default"; return CommonStrings.Default;
return $"{item.Width}x{item.Height}"; return $"{item.Width}x{item.Height}";
} }

View File

@ -7,12 +7,13 @@ using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Graphics namespace osu.Game.Overlays.Settings.Sections.Graphics
{ {
public class RendererSettings : SettingsSubsection public class RendererSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Renderer"; protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader;
private SettingsEnumDropdown<FrameSync> frameLimiterDropdown; private SettingsEnumDropdown<FrameSync> frameLimiterDropdown;
@ -25,17 +26,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
// TODO: this needs to be a custom dropdown at some point // TODO: this needs to be a custom dropdown at some point
frameLimiterDropdown = new SettingsEnumDropdown<FrameSync> frameLimiterDropdown = new SettingsEnumDropdown<FrameSync>
{ {
LabelText = "Frame limiter", LabelText = GraphicsSettingsStrings.FrameLimiter,
Current = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync) Current = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync)
}, },
new SettingsEnumDropdown<ExecutionMode> new SettingsEnumDropdown<ExecutionMode>
{ {
LabelText = "Threading mode", LabelText = GraphicsSettingsStrings.ThreadingMode,
Current = config.GetBindable<ExecutionMode>(FrameworkSetting.ExecutionMode) Current = config.GetBindable<ExecutionMode>(FrameworkSetting.ExecutionMode)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show FPS", LabelText = GraphicsSettingsStrings.ShowFPS,
Current = osuConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay) Current = osuConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay)
}, },
}; };
@ -47,9 +48,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
frameLimiterDropdown.Current.BindValueChanged(limit => frameLimiterDropdown.Current.BindValueChanged(limit =>
{ {
const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. \"2x refresh rate\" is recommended."; frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : default;
frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty;
}, true); }, true);
} }
} }

View File

@ -3,13 +3,15 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.Graphics; using osu.Game.Overlays.Settings.Sections.Graphics;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class GraphicsSection : SettingsSection public class GraphicsSection : SettingsSection
{ {
public override string Header => "Graphics"; public override LocalisableString Header => GraphicsSettingsStrings.GraphicsSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -5,6 +5,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Input namespace osu.Game.Overlays.Settings.Sections.Input
{ {
@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
Icon = FontAwesome.Solid.Globe Icon = FontAwesome.Solid.Globe
}; };
public override string Header => "Global"; public override LocalisableString Header => InputSettingsStrings.GlobalKeyBindingHeader;
public GlobalKeyBindingsSection(GlobalActionContainer manager) public GlobalKeyBindingsSection(GlobalActionContainer manager)
{ {
@ -39,7 +40,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private class SongSelectKeyBindingSubsection : KeyBindingsSubsection private class SongSelectKeyBindingSubsection : KeyBindingsSubsection
{ {
protected override LocalisableString Header => "Song Select"; protected override LocalisableString Header => InputSettingsStrings.SongSelectSection;
public SongSelectKeyBindingSubsection(GlobalActionContainer manager) public SongSelectKeyBindingSubsection(GlobalActionContainer manager)
: base(null) : base(null)
@ -50,7 +51,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private class InGameKeyBindingsSubsection : KeyBindingsSubsection private class InGameKeyBindingsSubsection : KeyBindingsSubsection
{ {
protected override LocalisableString Header => "In Game"; protected override LocalisableString Header => InputSettingsStrings.InGameSection;
public InGameKeyBindingsSubsection(GlobalActionContainer manager) public InGameKeyBindingsSubsection(GlobalActionContainer manager)
: base(null) : base(null)
@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection
{ {
protected override LocalisableString Header => "Audio"; protected override LocalisableString Header => InputSettingsStrings.AudioSection;
public AudioControlKeyBindingsSubsection(GlobalActionContainer manager) public AudioControlKeyBindingsSubsection(GlobalActionContainer manager)
: base(null) : base(null)
@ -72,7 +73,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private class EditorKeyBindingsSubsection : KeyBindingsSubsection private class EditorKeyBindingsSubsection : KeyBindingsSubsection
{ {
protected override LocalisableString Header => "Editor"; protected override LocalisableString Header => InputSettingsStrings.EditorSection;
public EditorKeyBindingsSubsection(GlobalActionContainer manager) public EditorKeyBindingsSubsection(GlobalActionContainer manager)
: base(null) : base(null)

View File

@ -4,13 +4,14 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Localisation;
using osu.Game.Rulesets; using osu.Game.Rulesets;
namespace osu.Game.Overlays.Settings.Sections.Input namespace osu.Game.Overlays.Settings.Sections.Input
{ {
public class KeyBindingPanel : SettingsSubPanel public class KeyBindingPanel : SettingsSubPanel
{ {
protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); protected override Drawable CreateHeader() => new SettingsHeader(InputSettingsStrings.KeyBindingPanelHeader, InputSettingsStrings.KeyBindingPanelDescription);
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(permitNulls: true)]
private void load(RulesetStore rulesets, GlobalActionContainer global) private void load(RulesetStore rulesets, GlobalActionContainer global)

View File

@ -20,6 +20,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Input; using osu.Game.Input;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Localisation;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osuTK.Input; using osuTK.Input;
@ -385,7 +386,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
public CancelButton() public CancelButton()
{ {
Text = "Cancel"; Text = CommonStrings.Cancel;
Size = new Vector2(80, 20); Size = new Vector2(80, 20);
} }
} }
@ -394,7 +395,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
public ClearButton() public ClearButton()
{ {
Text = "Clear"; Text = CommonStrings.Clear;
Size = new Vector2(80, 20); Size = new Vector2(80, 20);
} }
} }

View File

@ -10,6 +10,7 @@ using osu.Game.Database;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Localisation;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Settings.Sections.Input namespace osu.Game.Overlays.Settings.Sections.Input
@ -64,7 +65,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Text = "Reset all bindings in section"; Text = InputSettingsStrings.ResetSectionButton;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Width = 0.5f; Width = 0.5f;
Anchor = Anchor.TopCentre; Anchor = Anchor.TopCentre;

View File

@ -3,6 +3,7 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
Icon = OsuIcon.Hot Icon = OsuIcon.Hot
}; };
public override string Header => ruleset.Name; public override LocalisableString Header => ruleset.Name;
private readonly RulesetInfo ruleset; private readonly RulesetInfo ruleset;

View File

@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
private readonly ITabletHandler tabletHandler; private readonly ITabletHandler tabletHandler;
private readonly Bindable<bool> enabled = new BindableBool(true);
private readonly Bindable<Vector2> areaOffset = new Bindable<Vector2>(); private readonly Bindable<Vector2> areaOffset = new Bindable<Vector2>();
private readonly Bindable<Vector2> areaSize = new Bindable<Vector2>(); private readonly Bindable<Vector2> areaSize = new Bindable<Vector2>();
private readonly IBindable<TabletInfo> tablet = new Bindable<TabletInfo>(); private readonly IBindable<TabletInfo> tablet = new Bindable<TabletInfo>();
@ -74,7 +76,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
LabelText = CommonStrings.Enabled, LabelText = CommonStrings.Enabled,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Current = tabletHandler.Enabled Current = enabled,
}, },
noTabletMessage = new FillFlowContainer noTabletMessage = new FillFlowContainer
{ {
@ -194,6 +196,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
base.LoadComplete(); base.LoadComplete();
enabled.BindTo(tabletHandler.Enabled);
enabled.BindValueChanged(_ => Scheduler.AddOnce(updateVisibility));
rotation.BindTo(tabletHandler.Rotation); rotation.BindTo(tabletHandler.Rotation);
areaOffset.BindTo(tabletHandler.AreaOffset); areaOffset.BindTo(tabletHandler.AreaOffset);
@ -239,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
tablet.BindTo(tabletHandler.Tablet); tablet.BindTo(tabletHandler.Tablet);
tablet.BindValueChanged(val => tablet.BindValueChanged(val =>
{ {
Scheduler.AddOnce(toggleVisibility); Scheduler.AddOnce(updateVisibility);
var tab = val.NewValue; var tab = val.NewValue;
@ -259,19 +264,18 @@ namespace osu.Game.Overlays.Settings.Sections.Input
}, true); }, true);
} }
private void toggleVisibility() private void updateVisibility()
{ {
bool tabletFound = tablet.Value != null; mainSettings.Hide();
if (!tabletFound)
{
mainSettings.Hide();
noTabletMessage.Show();
return;
}
mainSettings.Show();
noTabletMessage.Hide(); noTabletMessage.Hide();
if (!tabletHandler.Enabled.Value)
return;
if (tablet.Value != null)
mainSettings.Show();
else
noTabletMessage.Show();
} }
private void applyAspectRatio(BindableNumber<float> sizeChanged) private void applyAspectRatio(BindableNumber<float> sizeChanged)

View File

@ -11,6 +11,7 @@ using osu.Framework.Input.Handlers.Mouse;
using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Input.Handlers.Tablet;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.Input; using osu.Game.Overlays.Settings.Sections.Input;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections
{ {
private readonly KeyBindingPanel keyConfig; private readonly KeyBindingPanel keyConfig;
public override string Header => "Input"; public override LocalisableString Header => InputSettingsStrings.InputSectionHeader;
[Resolved] [Resolved]
private GameHost host { get; set; } private GameHost host { get; set; }
@ -95,7 +96,7 @@ namespace osu.Game.Overlays.Settings.Sections
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Enabled", LabelText = CommonStrings.Enabled,
Current = handler.Enabled Current = handler.Enabled
}, },
}; };

View File

@ -14,6 +14,7 @@ using osu.Framework.Localisation;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Maintenance namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
@ -104,7 +105,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Origin = Anchor.Centre, Origin = Anchor.Centre,
Width = 300, Width = 300,
Margin = new MarginPadding(10), Margin = new MarginPadding(10),
Text = "Select directory", Text = MaintenanceSettingsStrings.SelectDirectory,
Action = () => OnSelection(directorySelector.CurrentPath.Value) Action = () => OnSelection(directorySelector.CurrentPath.Value)
}, },
} }

View File

@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
using osu.Game.Collections; using osu.Game.Collections;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
Add(importBeatmapsButton = new SettingsButton Add(importBeatmapsButton = new SettingsButton
{ {
Text = "Import beatmaps from stable", Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable,
Action = () => Action = () =>
{ {
importBeatmapsButton.Enabled.Value = false; importBeatmapsButton.Enabled.Value = false;
@ -48,7 +49,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Add(deleteBeatmapsButton = new DangerousSettingsButton Add(deleteBeatmapsButton = new DangerousSettingsButton
{ {
Text = "Delete ALL beatmaps", Text = MaintenanceSettingsStrings.DeleteAllBeatmaps,
Action = () => Action = () =>
{ {
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
Add(importScoresButton = new SettingsButton Add(importScoresButton = new SettingsButton
{ {
Text = "Import scores from stable", Text = MaintenanceSettingsStrings.ImportScoresFromStable,
Action = () => Action = () =>
{ {
importScoresButton.Enabled.Value = false; importScoresButton.Enabled.Value = false;
@ -74,7 +75,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Add(deleteScoresButton = new DangerousSettingsButton Add(deleteScoresButton = new DangerousSettingsButton
{ {
Text = "Delete ALL scores", Text = MaintenanceSettingsStrings.DeleteAllScores,
Action = () => Action = () =>
{ {
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
@ -89,7 +90,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
Add(importSkinsButton = new SettingsButton Add(importSkinsButton = new SettingsButton
{ {
Text = "Import skins from stable", Text = MaintenanceSettingsStrings.ImportSkinsFromStable,
Action = () => Action = () =>
{ {
importSkinsButton.Enabled.Value = false; importSkinsButton.Enabled.Value = false;
@ -100,7 +101,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Add(deleteSkinsButton = new DangerousSettingsButton Add(deleteSkinsButton = new DangerousSettingsButton
{ {
Text = "Delete ALL skins", Text = MaintenanceSettingsStrings.DeleteAllSkins,
Action = () => Action = () =>
{ {
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
@ -117,7 +118,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
Add(importCollectionsButton = new SettingsButton Add(importCollectionsButton = new SettingsButton
{ {
Text = "Import collections from stable", Text = MaintenanceSettingsStrings.ImportCollectionsFromStable,
Action = () => Action = () =>
{ {
importCollectionsButton.Enabled.Value = false; importCollectionsButton.Enabled.Value = false;
@ -128,7 +129,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Add(new DangerousSettingsButton Add(new DangerousSettingsButton
{ {
Text = "Delete ALL collections", Text = MaintenanceSettingsStrings.DeleteAllCollections,
Action = () => Action = () =>
{ {
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(collectionManager.DeleteAll)); dialogOverlay?.Push(new DeleteAllBeatmapsDialog(collectionManager.DeleteAll));
@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
restoreButton = new SettingsButton restoreButton = new SettingsButton
{ {
Text = "Restore all hidden difficulties", Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties,
Action = () => Action = () =>
{ {
restoreButton.Enabled.Value = false; restoreButton.Enabled.Value = false;
@ -153,7 +154,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
}, },
undeleteButton = new SettingsButton undeleteButton = new SettingsButton
{ {
Text = "Restore all recently deleted beatmaps", Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps,
Action = () => Action = () =>
{ {
undeleteButton.Enabled.Value = false; undeleteButton.Enabled.Value = false;

View File

@ -3,6 +3,8 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Overlays.Settings.Sections.Maintenance;
using osuTK; using osuTK;
@ -10,7 +12,7 @@ namespace osu.Game.Overlays.Settings.Sections
{ {
public class MaintenanceSection : SettingsSection public class MaintenanceSection : SettingsSection
{ {
public override string Header => "Maintenance"; public override LocalisableString Header => MaintenanceSettingsStrings.MaintenanceSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -5,12 +5,13 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Online namespace osu.Game.Overlays.Settings.Sections.Online
{ {
public class AlertsAndPrivacySettings : SettingsSubsection public class AlertsAndPrivacySettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Alerts and Privacy"; protected override LocalisableString Header => OnlineSettingsStrings.AlertsAndPrivacyHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -19,12 +20,12 @@ namespace osu.Game.Overlays.Settings.Sections.Online
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show a notification when someone mentions your name", LabelText = OnlineSettingsStrings.NotifyOnMentioned,
Current = config.GetBindable<bool>(OsuSetting.NotifyOnUsernameMentioned) Current = config.GetBindable<bool>(OsuSetting.NotifyOnUsernameMentioned)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show a notification when you receive a private message", LabelText = OnlineSettingsStrings.NotifyOnPrivateMessage,
Current = config.GetBindable<bool>(OsuSetting.NotifyOnPrivateMessage) Current = config.GetBindable<bool>(OsuSetting.NotifyOnPrivateMessage)
}, },
}; };

View File

@ -5,12 +5,13 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Online namespace osu.Game.Overlays.Settings.Sections.Online
{ {
public class IntegrationSettings : SettingsSubsection public class IntegrationSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Integrations"; protected override LocalisableString Header => OnlineSettingsStrings.IntegrationsHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online
{ {
new SettingsEnumDropdown<DiscordRichPresenceMode> new SettingsEnumDropdown<DiscordRichPresenceMode>
{ {
LabelText = "Discord Rich Presence", LabelText = OnlineSettingsStrings.DiscordRichPresence,
Current = config.GetBindable<DiscordRichPresenceMode>(OsuSetting.DiscordRichPresence) Current = config.GetBindable<DiscordRichPresenceMode>(OsuSetting.DiscordRichPresence)
} }
}; };

View File

@ -5,12 +5,13 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Online namespace osu.Game.Overlays.Settings.Sections.Online
{ {
public class WebSettings : SettingsSubsection public class WebSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Web"; protected override LocalisableString Header => OnlineSettingsStrings.WebHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -19,24 +20,24 @@ namespace osu.Game.Overlays.Settings.Sections.Online
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Warn about opening external links", LabelText = OnlineSettingsStrings.ExternalLinkWarning,
Current = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning) Current = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Prefer downloads without video", LabelText = OnlineSettingsStrings.PreferNoVideo,
Keywords = new[] { "no-video" }, Keywords = new[] { "no-video" },
Current = config.GetBindable<bool>(OsuSetting.PreferNoVideo) Current = config.GetBindable<bool>(OsuSetting.PreferNoVideo)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Automatically download beatmaps when spectating", LabelText = OnlineSettingsStrings.AutomaticallyDownloadWhenSpectating,
Keywords = new[] { "spectator" }, Keywords = new[] { "spectator" },
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating), Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating),
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show explicit content in search results", LabelText = OnlineSettingsStrings.ShowExplicitContent,
Keywords = new[] { "nsfw", "18+", "offensive" }, Keywords = new[] { "nsfw", "18+", "offensive" },
Current = config.GetBindable<bool>(OsuSetting.ShowOnlineExplicitContent), Current = config.GetBindable<bool>(OsuSetting.ShowOnlineExplicitContent),
} }

View File

@ -3,13 +3,15 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.Online; using osu.Game.Overlays.Settings.Sections.Online;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class OnlineSection : SettingsSection public class OnlineSection : SettingsSection
{ {
public override string Header => "Online"; public override LocalisableString Header => OnlineSettingsStrings.OnlineSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -13,6 +13,7 @@ using osu.Framework.Localisation;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Skinning.Editor; using osu.Game.Skinning.Editor;
using osuTK; using osuTK;
@ -23,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections
{ {
private SkinSettingsDropdown skinDropdown; private SkinSettingsDropdown skinDropdown;
public override string Header => "Skin"; public override LocalisableString Header => SkinSettingsStrings.SkinSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {
@ -69,34 +70,34 @@ namespace osu.Game.Overlays.Settings.Sections
skinDropdown = new SkinSettingsDropdown(), skinDropdown = new SkinSettingsDropdown(),
new SettingsButton new SettingsButton
{ {
Text = "Skin layout editor", Text = SkinSettingsStrings.SkinLayoutEditor,
Action = () => skinEditor?.Toggle(), Action = () => skinEditor?.Toggle(),
}, },
new ExportSkinButton(), new ExportSkinButton(),
new SettingsSlider<float, SizeSlider> new SettingsSlider<float, SizeSlider>
{ {
LabelText = "Gameplay cursor size", LabelText = SkinSettingsStrings.GameplayCursorSize,
Current = config.GetBindable<float>(OsuSetting.GameplayCursorSize), Current = config.GetBindable<float>(OsuSetting.GameplayCursorSize),
KeyboardStep = 0.01f KeyboardStep = 0.01f
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Adjust gameplay cursor size based on current beatmap", LabelText = SkinSettingsStrings.AutoCursorSize,
Current = config.GetBindable<bool>(OsuSetting.AutoCursorSize) Current = config.GetBindable<bool>(OsuSetting.AutoCursorSize)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Beatmap skins", LabelText = SkinSettingsStrings.BeatmapSkins,
Current = config.GetBindable<bool>(OsuSetting.BeatmapSkins) Current = config.GetBindable<bool>(OsuSetting.BeatmapSkins)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Beatmap colours", LabelText = SkinSettingsStrings.BeatmapColours,
Current = config.GetBindable<bool>(OsuSetting.BeatmapColours) Current = config.GetBindable<bool>(OsuSetting.BeatmapColours)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Beatmap hitsounds", LabelText = SkinSettingsStrings.BeatmapHitsounds,
Current = config.GetBindable<bool>(OsuSetting.BeatmapHitsounds) Current = config.GetBindable<bool>(OsuSetting.BeatmapHitsounds)
}, },
}; };
@ -200,7 +201,7 @@ namespace osu.Game.Overlays.Settings.Sections
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Text = "Export selected skin"; Text = SkinSettingsStrings.ExportSkinButton;
Action = export; Action = export;
currentSkin = skins.CurrentSkin.GetBoundCopy(); currentSkin = skins.CurrentSkin.GetBoundCopy();

View File

@ -6,12 +6,13 @@ using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.UserInterface namespace osu.Game.Overlays.Settings.Sections.UserInterface
{ {
public class GeneralSettings : SettingsSubsection public class GeneralSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "General"; protected override LocalisableString Header => UserInterfaceStrings.GeneralHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -20,23 +21,23 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Rotate cursor when dragging", LabelText = UserInterfaceStrings.CursorRotation,
Current = config.GetBindable<bool>(OsuSetting.CursorRotation) Current = config.GetBindable<bool>(OsuSetting.CursorRotation)
}, },
new SettingsSlider<float, SizeSlider> new SettingsSlider<float, SizeSlider>
{ {
LabelText = "Menu cursor size", LabelText = UserInterfaceStrings.MenuCursorSize,
Current = config.GetBindable<float>(OsuSetting.MenuCursorSize), Current = config.GetBindable<float>(OsuSetting.MenuCursorSize),
KeyboardStep = 0.01f KeyboardStep = 0.01f
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Parallax", LabelText = UserInterfaceStrings.Parallax,
Current = config.GetBindable<bool>(OsuSetting.MenuParallax) Current = config.GetBindable<bool>(OsuSetting.MenuParallax)
}, },
new SettingsSlider<float, TimeSlider> new SettingsSlider<float, TimeSlider>
{ {
LabelText = "Hold-to-confirm activation time", LabelText = UserInterfaceStrings.HoldToConfirmActivationTime,
Current = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay), Current = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay),
KeyboardStep = 50 KeyboardStep = 50
}, },

View File

@ -6,6 +6,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Localisation;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Users; using osu.Game.Users;
@ -13,7 +14,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
{ {
public class MainMenuSettings : SettingsSubsection public class MainMenuSettings : SettingsSubsection
{ {
protected override LocalisableString Header => "Main Menu"; protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader;
private IBindable<User> user; private IBindable<User> user;
@ -28,27 +29,27 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Interface voices", LabelText = UserInterfaceStrings.InterfaceVoices,
Current = config.GetBindable<bool>(OsuSetting.MenuVoice) Current = config.GetBindable<bool>(OsuSetting.MenuVoice)
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "osu! music theme", LabelText = UserInterfaceStrings.OsuMusicTheme,
Current = config.GetBindable<bool>(OsuSetting.MenuMusic) Current = config.GetBindable<bool>(OsuSetting.MenuMusic)
}, },
new SettingsEnumDropdown<IntroSequence> new SettingsEnumDropdown<IntroSequence>
{ {
LabelText = "Intro sequence", LabelText = UserInterfaceStrings.IntroSequence,
Current = config.GetBindable<IntroSequence>(OsuSetting.IntroSequence), Current = config.GetBindable<IntroSequence>(OsuSetting.IntroSequence),
}, },
backgroundSourceDropdown = new SettingsEnumDropdown<BackgroundSource> backgroundSourceDropdown = new SettingsEnumDropdown<BackgroundSource>
{ {
LabelText = "Background source", LabelText = UserInterfaceStrings.BackgroundSource,
Current = config.GetBindable<BackgroundSource>(OsuSetting.MenuBackgroundSource), Current = config.GetBindable<BackgroundSource>(OsuSetting.MenuBackgroundSource),
}, },
new SettingsEnumDropdown<SeasonalBackgroundMode> new SettingsEnumDropdown<SeasonalBackgroundMode>
{ {
LabelText = "Seasonal backgrounds", LabelText = UserInterfaceStrings.SeasonalBackgrounds,
Current = config.GetBindable<SeasonalBackgroundMode>(OsuSetting.SeasonalBackgroundMode), Current = config.GetBindable<SeasonalBackgroundMode>(OsuSetting.SeasonalBackgroundMode),
} }
}; };
@ -60,9 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
user.BindValueChanged(u => user.BindValueChanged(u =>
{ {
const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : default;
backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? not_supporter_note : string.Empty;
}, true); }, true);
} }
} }

View File

@ -8,6 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.UserInterface namespace osu.Game.Overlays.Settings.Sections.UserInterface
{ {
@ -16,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
private Bindable<double> minStars; private Bindable<double> minStars;
private Bindable<double> maxStars; private Bindable<double> maxStars;
protected override LocalisableString Header => "Song Select"; protected override LocalisableString Header => UserInterfaceStrings.SongSelectHeader;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
@ -31,31 +32,31 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
{ {
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Right mouse drag to absolute scroll", LabelText = UserInterfaceStrings.RightMouseScroll,
Current = config.GetBindable<bool>(OsuSetting.SongSelectRightMouseScroll), Current = config.GetBindable<bool>(OsuSetting.SongSelectRightMouseScroll),
}, },
new SettingsCheckbox new SettingsCheckbox
{ {
LabelText = "Show converted beatmaps", LabelText = UserInterfaceStrings.ShowConvertedBeatmaps,
Current = config.GetBindable<bool>(OsuSetting.ShowConvertedBeatmaps), Current = config.GetBindable<bool>(OsuSetting.ShowConvertedBeatmaps),
}, },
new SettingsSlider<double, StarsSlider> new SettingsSlider<double, StarsSlider>
{ {
LabelText = "Display beatmaps from", LabelText = UserInterfaceStrings.StarsMinimum,
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum), Current = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
KeyboardStep = 0.1f, KeyboardStep = 0.1f,
Keywords = new[] { "minimum", "maximum", "star", "difficulty" } Keywords = new[] { "minimum", "maximum", "star", "difficulty" }
}, },
new SettingsSlider<double, MaximumStarsSlider> new SettingsSlider<double, MaximumStarsSlider>
{ {
LabelText = "up to", LabelText = UserInterfaceStrings.StarsMaximum,
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum), Current = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
KeyboardStep = 0.1f, KeyboardStep = 0.1f,
Keywords = new[] { "minimum", "maximum", "star", "difficulty" } Keywords = new[] { "minimum", "maximum", "star", "difficulty" }
}, },
new SettingsEnumDropdown<RandomSelectAlgorithm> new SettingsEnumDropdown<RandomSelectAlgorithm>
{ {
LabelText = "Random selection algorithm", LabelText = UserInterfaceStrings.RandomSelectionAlgorithm,
Current = config.GetBindable<RandomSelectAlgorithm>(OsuSetting.RandomSelectAlgorithm), Current = config.GetBindable<RandomSelectAlgorithm>(OsuSetting.RandomSelectAlgorithm),
} }
}; };
@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
private class MaximumStarsSlider : StarsSlider private class MaximumStarsSlider : StarsSlider
{ {
public override LocalisableString TooltipText => Current.IsDefault ? "no limit" : base.TooltipText; public override LocalisableString TooltipText => Current.IsDefault ? UserInterfaceStrings.NoLimit : base.TooltipText;
} }
private class StarsSlider : OsuSliderBar<double> private class StarsSlider : OsuSliderBar<double>

View File

@ -3,13 +3,15 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Overlays.Settings.Sections.UserInterface; using osu.Game.Overlays.Settings.Sections.UserInterface;
namespace osu.Game.Overlays.Settings.Sections namespace osu.Game.Overlays.Settings.Sections
{ {
public class UserInterfaceSection : SettingsSection public class UserInterfaceSection : SettingsSection
{ {
public override string Header => "User Interface"; public override LocalisableString Header => UserInterfaceStrings.UserInterfaceSectionHeader;
public override Drawable CreateIcon() => new SpriteIcon public override Drawable CreateIcon() => new SpriteIcon
{ {

View File

@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osuTK.Graphics; using osuTK.Graphics;
@ -19,10 +20,10 @@ namespace osu.Game.Overlays.Settings
protected override Container<Drawable> Content => FlowContent; protected override Container<Drawable> Content => FlowContent;
public abstract Drawable CreateIcon(); public abstract Drawable CreateIcon();
public abstract string Header { get; } public abstract LocalisableString Header { get; }
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>(); public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
public virtual IEnumerable<string> FilterTerms => new[] { Header }; public virtual IEnumerable<string> FilterTerms => new[] { Header.ToString() };
private const int header_size = 26; private const int header_size = 26;
private const int margin = 20; private const int margin = 20;

View File

@ -24,6 +24,11 @@ namespace osu.Game.Overlays.Settings
protected abstract LocalisableString Header { get; } protected abstract LocalisableString Header { get; }
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>(); public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
// FilterTerms should contains both original string and localised string for user to search.
// Since LocalisableString is unable to get original string at this time (2021-08-14),
// only call .ToString() to use localised one.
// TODO: Update here when FilterTerms accept LocalisableString.
public virtual IEnumerable<string> FilterTerms => new[] { Header.ToString() }; public virtual IEnumerable<string> FilterTerms => new[] { Header.ToString() };
public bool MatchingFilter public bool MatchingFilter

View File

@ -4,6 +4,7 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Screens.Play;
namespace osu.Game.Performance namespace osu.Game.Performance
{ {
@ -12,9 +13,9 @@ namespace osu.Game.Performance
private readonly IBindable<bool> localUserPlaying = new Bindable<bool>(); private readonly IBindable<bool> localUserPlaying = new Bindable<bool>();
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGame game) private void load(ILocalUserPlayInfo localUserInfo)
{ {
localUserPlaying.BindTo(game.LocalUserPlaying); localUserPlaying.BindTo(localUserInfo.IsPlaying);
} }
protected override void LoadComplete() protected override void LoadComplete()

View File

@ -0,0 +1,54 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Difficulty.Skills
{
/// <summary>
/// Used to processes strain values of <see cref="DifficultyHitObject"/>s, keep track of strain levels caused by the processed objects
/// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
/// </summary>
public abstract class StrainDecaySkill : StrainSkill
{
/// <summary>
/// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
/// </summary>
protected abstract double SkillMultiplier { get; }
/// <summary>
/// Determines how quickly strain decays for the given skill.
/// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
/// </summary>
protected abstract double StrainDecayBase { get; }
/// <summary>
/// The current strain level.
/// </summary>
protected double CurrentStrain { get; private set; } = 1;
protected StrainDecaySkill(Mod[] mods)
: base(mods)
{
}
protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime);
protected override double StrainValueAt(DifficultyHitObject current)
{
CurrentStrain *= strainDecay(current.DeltaTime);
CurrentStrain += StrainValueOf(current) * SkillMultiplier;
return CurrentStrain;
}
/// <summary>
/// Calculates the strain value of a <see cref="DifficultyHitObject"/>. This value is affected by previously processed objects.
/// </summary>
protected abstract double StrainValueOf(DifficultyHitObject current);
private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
}
}

View File

@ -15,27 +15,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills
/// </summary> /// </summary>
public abstract class StrainSkill : Skill public abstract class StrainSkill : Skill
{ {
/// <summary>
/// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
/// </summary>
protected abstract double SkillMultiplier { get; }
/// <summary>
/// Determines how quickly strain decays for the given skill.
/// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
/// </summary>
protected abstract double StrainDecayBase { get; }
/// <summary> /// <summary>
/// The weight by which each strain value decays. /// The weight by which each strain value decays.
/// </summary> /// </summary>
protected virtual double DecayWeight => 0.9; protected virtual double DecayWeight => 0.9;
/// <summary>
/// The current strain level.
/// </summary>
protected double CurrentStrain { get; private set; } = 1;
/// <summary> /// <summary>
/// The length of each strain section. /// The length of each strain section.
/// </summary> /// </summary>
@ -52,6 +36,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills
{ {
} }
/// <summary>
/// Returns the strain value at <see cref="DifficultyHitObject"/>. This value is calculated with or without respect to previous objects.
/// </summary>
protected abstract double StrainValueAt(DifficultyHitObject current);
/// <summary> /// <summary>
/// Process a <see cref="DifficultyHitObject"/> and update current strain values accordingly. /// Process a <see cref="DifficultyHitObject"/> and update current strain values accordingly.
/// </summary> /// </summary>
@ -68,10 +57,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
currentSectionEnd += SectionLength; currentSectionEnd += SectionLength;
} }
CurrentStrain *= strainDecay(current.DeltaTime); currentSectionPeak = Math.Max(StrainValueAt(current), currentSectionPeak);
CurrentStrain += StrainValueOf(current) * SkillMultiplier;
currentSectionPeak = Math.Max(CurrentStrain, currentSectionPeak);
} }
/// <summary> /// <summary>
@ -88,9 +74,9 @@ namespace osu.Game.Rulesets.Difficulty.Skills
/// <param name="time">The beginning of the new section in milliseconds.</param> /// <param name="time">The beginning of the new section in milliseconds.</param>
private void startNewSectionFrom(double time) private void startNewSectionFrom(double time)
{ {
// The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries. // The maximum strain of the new section is not zero by default
// This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level. // This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level.
currentSectionPeak = GetPeakStrain(time); currentSectionPeak = CalculateInitialStrain(time);
} }
/// <summary> /// <summary>
@ -98,7 +84,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
/// </summary> /// </summary>
/// <param name="time">The time to retrieve the peak strain at.</param> /// <param name="time">The time to retrieve the peak strain at.</param>
/// <returns>The peak strain.</returns> /// <returns>The peak strain.</returns>
protected virtual double GetPeakStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); protected abstract double CalculateInitialStrain(double time);
/// <summary> /// <summary>
/// Returns a live enumerable of the peak strains for each <see cref="SectionLength"/> section of the beatmap, /// Returns a live enumerable of the peak strains for each <see cref="SectionLength"/> section of the beatmap,
@ -124,12 +110,5 @@ namespace osu.Game.Rulesets.Difficulty.Skills
return difficulty; return difficulty;
} }
/// <summary>
/// Calculates the strain value of a <see cref="DifficultyHitObject"/>. This value is affected by previously processed objects.
/// </summary>
protected abstract double StrainValueOf(DifficultyHitObject current);
private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
} }
} }

View File

@ -91,7 +91,13 @@ namespace osu.Game.Rulesets.Mods
{ {
// This is required as SettingsItem relies heavily on this bindable for internal use. // This is required as SettingsItem relies heavily on this bindable for internal use.
// The actual update flow is done via the bindable provided in the constructor. // The actual update flow is done via the bindable provided in the constructor.
public Bindable<float?> Current { get; set; } = new Bindable<float?>(); private readonly BindableWithCurrent<float?> current = new BindableWithCurrent<float?>();
public Bindable<float?> Current
{
get => current.Current;
set => current.Current = value;
}
public SliderControl(BindableNumber<float> currentNumber) public SliderControl(BindableNumber<float> currentNumber)
{ {

View File

@ -41,11 +41,13 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
protected override void PopIn() protected override void PopIn()
{ {
base.PopIn();
Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint); Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint);
} }
protected override void PopOut() protected override void PopOut()
{ {
base.PopOut();
Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine);
} }

View File

@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
/// <param name="score">The score containing the player's replay.</param> /// <param name="score">The score containing the player's replay.</param>
/// <param name="spectatorPlayerClock">The clock controlling the gameplay running state.</param> /// <param name="spectatorPlayerClock">The clock controlling the gameplay running state.</param>
public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock) public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock)
: base(score) : base(score, new PlayerConfiguration { AllowUserInteraction = false })
{ {
this.spectatorPlayerClock = spectatorPlayerClock; this.spectatorPlayerClock = spectatorPlayerClock;
} }
@ -34,6 +34,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
private void load() private void load()
{ {
spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames);
HUDOverlay.PlayerSettingsOverlay.Expire();
HUDOverlay.HoldToQuit.Expire();
} }
protected override void UpdateAfterChildren() protected override void UpdateAfterChildren()

View File

@ -3,6 +3,7 @@
using System; using System;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
@ -19,6 +20,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
{ {
} }
[BackgroundDependencyLoader]
private void load()
{
PlayerSettings.Expire();
}
protected override void LogoArriving(OsuLogo logo, bool resuming) protected override void LogoArriving(OsuLogo logo, bool resuming)
{ {
} }

View File

@ -0,0 +1,17 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
namespace osu.Game.Screens.Play
{
[Cached]
public interface ILocalUserPlayInfo
{
/// <summary>
/// Whether the local user is currently playing.
/// </summary>
IBindable<bool> IsPlaying { get; }
}
}

View File

@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play
{ {
[Cached] [Cached]
[Cached(typeof(ISamplePlaybackDisabler))] [Cached(typeof(ISamplePlaybackDisabler))]
public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler, ILocalUserPlayInfo
{ {
/// <summary> /// <summary>
/// The delay upon completion of the beatmap before displaying the results screen. /// The delay upon completion of the beatmap before displaying the results screen.
@ -1052,5 +1052,7 @@ namespace osu.Game.Screens.Play
#endregion #endregion
IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled; IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled;
IBindable<bool> ILocalUserPlayInfo.IsPlaying => LocalUserPlaying;
} }
} }

View File

@ -20,6 +20,11 @@ namespace osu.Game.Screens.Play
/// </summary> /// </summary>
public bool AllowRestart { get; set; } = true; public bool AllowRestart { get; set; } = true;
/// <summary>
/// Whether the player should be able to interact with this player instance.
/// </summary>
public bool AllowUserInteraction { get; set; } = true;
/// <summary> /// <summary>
/// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard.
/// </summary> /// </summary>

View File

@ -46,9 +46,14 @@ namespace osu.Game.Screens.Play
protected override bool PlayResumeSound => false; protected override bool PlayResumeSound => false;
protected BeatmapMetadataDisplay MetadataInfo; protected BeatmapMetadataDisplay MetadataInfo { get; private set; }
protected VisualSettings VisualSettings; /// <summary>
/// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader.
/// </summary>
protected FillFlowContainer<PlayerSettingsGroup> PlayerSettings { get; private set; }
protected VisualSettings VisualSettings { get; private set; }
protected Task LoadTask { get; private set; } protected Task LoadTask { get; private set; }
@ -140,7 +145,7 @@ namespace osu.Game.Screens.Play
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
}, },
new FillFlowContainer<PlayerSettingsGroup> PlayerSettings = new FillFlowContainer<PlayerSettingsGroup>
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,

View File

@ -119,13 +119,14 @@ namespace osu.Game.Screens.Play
if (drawableRuleset != null) if (drawableRuleset != null)
{ {
AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded); if (player?.Configuration.AllowUserInteraction == true)
((IBindable<bool>)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded);
referenceClock = drawableRuleset.FrameStableClock; referenceClock = drawableRuleset.FrameStableClock;
Objects = drawableRuleset.Objects; Objects = drawableRuleset.Objects;
} }
config.BindWith(OsuSetting.ShowDifficultyGraph, ShowGraph); config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph);
graph.FillColour = bar.FillColour = colours.BlueLighter; graph.FillColour = bar.FillColour = colours.BlueLighter;
} }

View File

@ -23,7 +23,8 @@ namespace osu.Game.Screens.Play
protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap
public SpectatorPlayer(Score score) public SpectatorPlayer(Score score, PlayerConfiguration configuration = null)
: base(configuration)
{ {
this.score = score; this.score = score;
} }

View File

@ -304,6 +304,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AABB/@EntryIndexedValue">AABB</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AABB/@EntryIndexedValue">AABB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BPM/@EntryIndexedValue">BPM</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BPM/@EntryIndexedValue">BPM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FPS/@EntryIndexedValue">FPS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GL/@EntryIndexedValue">GL</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GL/@EntryIndexedValue">GL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GLSL/@EntryIndexedValue">GLSL</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GLSL/@EntryIndexedValue">GLSL</s:String>