From abdad3854499e9be3303622328750d2db9036717 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 5 Oct 2026 14:09:33 +0900 Subject: [PATCH 01/11] Add gameplay volume adjustment --- osu.Game/Configuration/OsuConfigManager.cs | 3 ++ osu.Game/Localisation/AudioSettingsStrings.cs | 5 ++++ osu.Game/Localisation/SkinSettingsStrings.cs | 7 ++++- .../Settings/Sections/Audio/VolumeSettings.cs | 12 ++++++-- osu.Game/Rulesets/UI/DrawableRuleset.cs | 8 ++++- .../Play/PlayerSettings/AudioSettings.cs | 29 ++++++++++++------- 6 files changed, 50 insertions(+), 14 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index aab148f25237..dd73e301ebc7 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -103,6 +103,8 @@ protected override void InitialiseDefaults() // Audio SetDefault(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); + SetDefault(OsuSetting.GameplayVolume, 0.6, 0, 1, 0.01); + SetDefault(OsuSetting.MenuVoice, true); SetDefault(OsuSetting.MenuMusic, true); SetDefault(OsuSetting.MenuTips, true); @@ -485,5 +487,6 @@ public enum OsuSetting /// Blocks private messages, multiplayer room invites, and duel requests from people not on the user's friends list. /// PMFriendsOnly, + GameplayVolume, } } diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index c6a6b81c1178..f9926ad0edec 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -54,6 +54,11 @@ public static class AudioSettingsStrings /// public static LocalisableString MusicVolume => new TranslatableString(getKey(@"music_volume"), @"Music"); + /// + /// "Gameplay" + /// + public static LocalisableString GameplayVolume => new TranslatableString(getKey(@"gameplay_volume"), @"Gameplay"); + /// /// "Offset Adjustment" /// diff --git a/osu.Game/Localisation/SkinSettingsStrings.cs b/osu.Game/Localisation/SkinSettingsStrings.cs index c453a09f07fc..43b623f3d24a 100644 --- a/osu.Game/Localisation/SkinSettingsStrings.cs +++ b/osu.Game/Localisation/SkinSettingsStrings.cs @@ -59,6 +59,11 @@ public static class SkinSettingsStrings /// public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds"); - private static string getKey(string key) => $"{prefix}:{key}"; + /// + /// "Gameplay volume" + /// + public static LocalisableString GameplayVolume => new TranslatableString(getKey(@"gameplay_volume"), @"Gameplay volume"); + + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index c0d38e50c151..793c021a4fec 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -36,6 +36,14 @@ private void load(AudioManager audio, OsuConfigManager config) DisplayAsPercentage = true }), new SettingsItemV2(new FormSliderBar + { + Caption = AudioSettingsStrings.MusicVolume, + Current = audio.VolumeTrack, + KeyboardStep = 0.01f, + DisplayAsPercentage = true, + PlaySamplesOnAdjust = false, + }), + new SettingsItemV2(new FormSliderBar { Caption = AudioSettingsStrings.EffectVolume, Current = audio.VolumeSample, @@ -45,8 +53,8 @@ private void load(AudioManager audio, OsuConfigManager config) }), new SettingsItemV2(new FormSliderBar { - Caption = AudioSettingsStrings.MusicVolume, - Current = audio.VolumeTrack, + Caption = AudioSettingsStrings.GameplayVolume, + Current = config.GetBindable(OsuSetting.GameplayVolume), KeyboardStep = 0.01f, DisplayAsPercentage = true, PlaySamplesOnAdjust = false, diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index c599c0da672e..4afa672b942d 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -12,6 +12,7 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; @@ -76,7 +77,7 @@ public abstract partial class DrawableRuleset : DrawableRuleset, IProvi public override IAdjustableAudioComponent Audio => audioContainer; - private readonly AudioContainer audioContainer = new AudioContainer { RelativeSizeAxes = Axes.Both }; + private readonly DrawableAudioMixer audioContainer = new DrawableAudioMixer { RelativeSizeAxes = Axes.Both, Name = "GameplayMixer" }; public override Container FrameStableComponents { get; } = new Container { RelativeSizeAxes = Axes.Both }; @@ -104,6 +105,8 @@ public abstract partial class DrawableRuleset : DrawableRuleset, IProvi private bool frameStablePlayback = true; + private Bindable gameplayVolume; + internal override bool FrameStablePlayback { get => frameStablePlayback; @@ -195,6 +198,9 @@ private void load(CancellationToken? cancellationToken) .WithChild(ResumeOverlay))); } + gameplayVolume = config.GetBindable(OsuSetting.GameplayVolume); + audioContainer.Volume.BindTo(gameplayVolume); + applyRulesetMods(Mods, config); loadObjects(cancellationToken ?? CancellationToken.None); diff --git a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs index 9ff90f6fef72..d3280d6e58f7 100644 --- a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs @@ -16,26 +16,35 @@ public partial class AudioSettings : PlayerSettingsGroup { private Bindable referenceScore { get; } = new Bindable(); - private readonly PlayerCheckbox beatmapHitsoundsToggle; - public AudioSettings() : base(PlayerSettingsOverlayStrings.AudioSettingsTitle) { + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, SessionStatics statics) + { + statics.BindWith(Static.LastLocalUserScore, referenceScore); + Children = new Drawable[] { - beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = SkinSettingsStrings.BeatmapHitsounds }, + new PlayerCheckbox + { + LabelText = SkinSettingsStrings.BeatmapHitsounds, + Current = config.GetBindable(OsuSetting.BeatmapHitsounds), + }, + new PlayerSliderBar + { + LabelText = SkinSettingsStrings.GameplayVolume, + Current = config.GetBindable(OsuSetting.GameplayVolume), + KeyboardStep = 0.01f, + DisplayAsPercentage = true, + }, new BeatmapOffsetControl { ReferenceScore = { BindTarget = referenceScore }, }, }; } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config, SessionStatics statics) - { - beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); - statics.BindWith(Static.LastLocalUserScore, referenceScore); - } } } From 3f00db4c200daa0cb09c030b44be4793b3458304 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Oct 2026 13:33:49 +0900 Subject: [PATCH 02/11] Add gameplay volume to volume overlay --- osu.Game/Overlays/VolumeOverlay.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 8a656f4f2456..e806fa9ecdd6 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Threading; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; @@ -33,11 +34,14 @@ public partial class VolumeOverlay : VisibilityContainer private VolumeMeter volumeMeterMaster = null!; private VolumeMeter volumeMeterEffect = null!; private VolumeMeter volumeMeterMusic = null!; + private VolumeMeter volumeMeterGameplay = null!; + + private Bindable volumeGameplay = null!; private SelectionCycleFillFlowContainer volumeMeters = null!; [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) + private void load(AudioManager audio, OsuColour colours, OsuConfigManager config) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; @@ -69,9 +73,10 @@ private void load(AudioManager audio, OsuColour colours) Spacing = new Vector2(0, offset), Children = new[] { - volumeMeterEffect = new VolumeMeter(AudioSettingsStrings.EffectVolume.ToUpper(), 125, colours.BlueDarker), - volumeMeterMaster = new MasterVolumeMeter(AudioSettingsStrings.MasterVolume.ToUpper(), 150, colours.PinkDarker) { IsMuted = { BindTarget = IsMuted }, }, - volumeMeterMusic = new VolumeMeter(AudioSettingsStrings.MusicVolume.ToUpper(), 125, colours.BlueDarker), + volumeMeterMaster = new MasterVolumeMeter(AudioSettingsStrings.MasterVolume.ToUpper(), 140, colours.PinkDarker) { IsMuted = { BindTarget = IsMuted }, }, + volumeMeterMusic = new VolumeMeter(AudioSettingsStrings.MusicVolume.ToUpper(), 100, colours.BlueDarker), + volumeMeterEffect = new VolumeMeter(AudioSettingsStrings.EffectVolume.ToUpper(), 100, colours.BlueDarker), + volumeMeterGameplay = new VolumeMeter(AudioSettingsStrings.GameplayVolume.ToUpper(), 100, colours.BlueDarker), } }, }, @@ -81,6 +86,7 @@ private void load(AudioManager audio, OsuColour colours) volumeMeterMaster.Bindable.BindTo(audio.Volume); volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); + volumeMeterGameplay.Bindable.BindTo(volumeGameplay = config.GetBindable(OsuSetting.GameplayVolume)); } protected override void LoadComplete() From 2723838df06b70a2ad4a0f7b0f7b4df775e0abc8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Oct 2026 18:12:55 +0900 Subject: [PATCH 03/11] Rename to "hitsound volume" --- osu.Game/Localisation/AudioSettingsStrings.cs | 4 ++-- osu.Game/Localisation/SkinSettingsStrings.cs | 4 ++-- osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs | 2 +- osu.Game/Overlays/VolumeOverlay.cs | 2 +- osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index f9926ad0edec..89d416c9dee0 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -55,9 +55,9 @@ public static class AudioSettingsStrings public static LocalisableString MusicVolume => new TranslatableString(getKey(@"music_volume"), @"Music"); /// - /// "Gameplay" + /// "Hitsound" /// - public static LocalisableString GameplayVolume => new TranslatableString(getKey(@"gameplay_volume"), @"Gameplay"); + public static LocalisableString HitsoundVolume => new TranslatableString(getKey(@"hitsound_volume"), @"Hitsound"); /// /// "Offset Adjustment" diff --git a/osu.Game/Localisation/SkinSettingsStrings.cs b/osu.Game/Localisation/SkinSettingsStrings.cs index 43b623f3d24a..f154808747dd 100644 --- a/osu.Game/Localisation/SkinSettingsStrings.cs +++ b/osu.Game/Localisation/SkinSettingsStrings.cs @@ -60,9 +60,9 @@ public static class SkinSettingsStrings public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds"); /// - /// "Gameplay volume" + /// "Hitsound volume" /// - public static LocalisableString GameplayVolume => new TranslatableString(getKey(@"gameplay_volume"), @"Gameplay volume"); + public static LocalisableString HitsoundVolume => new TranslatableString(getKey(@"hitsound_volume"), @"Hitsound volume"); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 793c021a4fec..7c849d71bac0 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -53,7 +53,7 @@ private void load(AudioManager audio, OsuConfigManager config) }), new SettingsItemV2(new FormSliderBar { - Caption = AudioSettingsStrings.GameplayVolume, + Caption = AudioSettingsStrings.HitsoundVolume, Current = config.GetBindable(OsuSetting.GameplayVolume), KeyboardStep = 0.01f, DisplayAsPercentage = true, diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index e806fa9ecdd6..ce9969cc3f67 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -76,7 +76,7 @@ private void load(AudioManager audio, OsuColour colours, OsuConfigManager config volumeMeterMaster = new MasterVolumeMeter(AudioSettingsStrings.MasterVolume.ToUpper(), 140, colours.PinkDarker) { IsMuted = { BindTarget = IsMuted }, }, volumeMeterMusic = new VolumeMeter(AudioSettingsStrings.MusicVolume.ToUpper(), 100, colours.BlueDarker), volumeMeterEffect = new VolumeMeter(AudioSettingsStrings.EffectVolume.ToUpper(), 100, colours.BlueDarker), - volumeMeterGameplay = new VolumeMeter(AudioSettingsStrings.GameplayVolume.ToUpper(), 100, colours.BlueDarker), + volumeMeterGameplay = new VolumeMeter(AudioSettingsStrings.HitsoundVolume.ToUpper(), 100, colours.BlueDarker), } }, }, diff --git a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs index d3280d6e58f7..e1a8623f5c84 100644 --- a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs @@ -35,7 +35,7 @@ private void load(OsuConfigManager config, SessionStatics statics) }, new PlayerSliderBar { - LabelText = SkinSettingsStrings.GameplayVolume, + LabelText = SkinSettingsStrings.HitsoundVolume, Current = config.GetBindable(OsuSetting.GameplayVolume), KeyboardStep = 0.01f, DisplayAsPercentage = true, From de821c216cab0632783718b58ba85b714de66611 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Oct 2026 22:02:52 +0900 Subject: [PATCH 04/11] We need to keep this reference else it will GC --- osu.Game/Overlays/VolumeOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index ce9969cc3f67..73297021f819 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -36,6 +36,7 @@ public partial class VolumeOverlay : VisibilityContainer private VolumeMeter volumeMeterMusic = null!; private VolumeMeter volumeMeterGameplay = null!; + // ReSharper disable once NotAccessedField.Local private Bindable volumeGameplay = null!; private SelectionCycleFillFlowContainer volumeMeters = null!; From 8bcc424d131b6e8112c0d04b8c8e40ba4d5c07d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Oct 2026 10:43:18 +0900 Subject: [PATCH 05/11] Fix failing test --- osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 1b1ab3799869..44c71bbe0aee 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -255,7 +255,9 @@ public void TestSongSelectScrollHandling() SoloSongSelect songSelect = null; double scrollPosition = 0; + AddStep("move to screen centre", () => InputManager.MoveMouseTo(Game)); AddStep("set game volume to max", () => Game.Dependencies.Get().SetValue(FrameworkSetting.VolumeUniversal, 1d)); + AddStep("set effect volume to max", () => Game.Dependencies.Get().SetValue(FrameworkSetting.VolumeEffect, 1d)); AddUntilStep("wait for volume overlay to hide", () => Game.ChildrenOfType().SingleOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Hidden)); PushAndConfirm(() => songSelect = new SoloSongSelect()); AddUntilStep("wait for song select", () => songSelect.IsLoaded); @@ -294,7 +296,7 @@ public void TestSongSelectScrollHandling() InputManager.ScrollVerticalBy(-1); InputManager.ReleaseKey(Key.AltLeft); }, 5); - AddAssert("game volume decreased", () => Game.Dependencies.Get().Get(FrameworkSetting.VolumeUniversal), () => Is.LessThan(1)); + AddAssert("effect volume decreased", () => Game.Dependencies.Get().Get(FrameworkSetting.VolumeEffect), () => Is.LessThan(1)); AddStep("move to carousel", () => InputManager.MoveMouseTo(songSelect.ChildrenOfType().Single())); AddStep("scroll down", () => InputManager.ScrollVerticalBy(-1)); From 5caf68f9e47c409487c2b5f5ac1701cf18adc34e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Oct 2026 15:45:54 +0900 Subject: [PATCH 06/11] Rename internal variables `gameplay` -> `hitsound` --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Settings/Sections/Audio/VolumeSettings.cs | 2 +- osu.Game/Overlays/VolumeOverlay.cs | 6 +++--- osu.Game/Rulesets/UI/DrawableRuleset.cs | 12 ++++++------ .../Screens/Play/PlayerSettings/AudioSettings.cs | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index dd73e301ebc7..89c9677fe514 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -103,7 +103,7 @@ protected override void InitialiseDefaults() // Audio SetDefault(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); - SetDefault(OsuSetting.GameplayVolume, 0.6, 0, 1, 0.01); + SetDefault(OsuSetting.HitsoundVolume, 0.6, 0, 1, 0.01); SetDefault(OsuSetting.MenuVoice, true); SetDefault(OsuSetting.MenuMusic, true); @@ -487,6 +487,6 @@ public enum OsuSetting /// Blocks private messages, multiplayer room invites, and duel requests from people not on the user's friends list. /// PMFriendsOnly, - GameplayVolume, + HitsoundVolume, } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 7c849d71bac0..6b660e142c9c 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -54,7 +54,7 @@ private void load(AudioManager audio, OsuConfigManager config) new SettingsItemV2(new FormSliderBar { Caption = AudioSettingsStrings.HitsoundVolume, - Current = config.GetBindable(OsuSetting.GameplayVolume), + Current = config.GetBindable(OsuSetting.HitsoundVolume), KeyboardStep = 0.01f, DisplayAsPercentage = true, PlaySamplesOnAdjust = false, diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 73297021f819..790c69fa10b7 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -34,7 +34,7 @@ public partial class VolumeOverlay : VisibilityContainer private VolumeMeter volumeMeterMaster = null!; private VolumeMeter volumeMeterEffect = null!; private VolumeMeter volumeMeterMusic = null!; - private VolumeMeter volumeMeterGameplay = null!; + private VolumeMeter volumeMeterHitsound = null!; // ReSharper disable once NotAccessedField.Local private Bindable volumeGameplay = null!; @@ -77,7 +77,7 @@ private void load(AudioManager audio, OsuColour colours, OsuConfigManager config volumeMeterMaster = new MasterVolumeMeter(AudioSettingsStrings.MasterVolume.ToUpper(), 140, colours.PinkDarker) { IsMuted = { BindTarget = IsMuted }, }, volumeMeterMusic = new VolumeMeter(AudioSettingsStrings.MusicVolume.ToUpper(), 100, colours.BlueDarker), volumeMeterEffect = new VolumeMeter(AudioSettingsStrings.EffectVolume.ToUpper(), 100, colours.BlueDarker), - volumeMeterGameplay = new VolumeMeter(AudioSettingsStrings.HitsoundVolume.ToUpper(), 100, colours.BlueDarker), + volumeMeterHitsound = new VolumeMeter(AudioSettingsStrings.HitsoundVolume.ToUpper(), 100, colours.BlueDarker), } }, }, @@ -87,7 +87,7 @@ private void load(AudioManager audio, OsuColour colours, OsuConfigManager config volumeMeterMaster.Bindable.BindTo(audio.Volume); volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); - volumeMeterGameplay.Bindable.BindTo(volumeGameplay = config.GetBindable(OsuSetting.GameplayVolume)); + volumeMeterHitsound.Bindable.BindTo(volumeGameplay = config.GetBindable(OsuSetting.HitsoundVolume)); } protected override void LoadComplete() diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 4afa672b942d..f8b21075f57a 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -75,9 +75,9 @@ public abstract partial class DrawableRuleset : DrawableRuleset, IProvi public override Container Overlays { get; } = new Container { RelativeSizeAxes = Axes.Both }; - public override IAdjustableAudioComponent Audio => audioContainer; + public override IAdjustableAudioComponent Audio => gameplayMixer; - private readonly DrawableAudioMixer audioContainer = new DrawableAudioMixer { RelativeSizeAxes = Axes.Both, Name = "GameplayMixer" }; + private readonly DrawableAudioMixer gameplayMixer = new DrawableAudioMixer { RelativeSizeAxes = Axes.Both, Name = "GameplayMixer" }; public override Container FrameStableComponents { get; } = new Container { RelativeSizeAxes = Axes.Both }; @@ -105,7 +105,7 @@ public abstract partial class DrawableRuleset : DrawableRuleset, IProvi private bool frameStablePlayback = true; - private Bindable gameplayVolume; + private Bindable hitsoundVolume; internal override bool FrameStablePlayback { @@ -182,7 +182,7 @@ private void load(CancellationToken? cancellationToken) Children = new Drawable[] { FrameStableComponents, - audioContainer.WithChild(KeyBindingInputManager + gameplayMixer.WithChild(KeyBindingInputManager .WithChildren(new Drawable[] { playfieldAdjustmentContainer.WithChild(Playfield), @@ -198,8 +198,8 @@ private void load(CancellationToken? cancellationToken) .WithChild(ResumeOverlay))); } - gameplayVolume = config.GetBindable(OsuSetting.GameplayVolume); - audioContainer.Volume.BindTo(gameplayVolume); + hitsoundVolume = config.GetBindable(OsuSetting.HitsoundVolume); + gameplayMixer.Volume.BindTo(hitsoundVolume); applyRulesetMods(Mods, config); diff --git a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs index e1a8623f5c84..4628b8532705 100644 --- a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs @@ -36,7 +36,7 @@ private void load(OsuConfigManager config, SessionStatics statics) new PlayerSliderBar { LabelText = SkinSettingsStrings.HitsoundVolume, - Current = config.GetBindable(OsuSetting.GameplayVolume), + Current = config.GetBindable(OsuSetting.HitsoundVolume), KeyboardStep = 0.01f, DisplayAsPercentage = true, }, From 27f6e3eaf141ed021d66a592dc35794dcac008d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Oct 2026 18:09:24 +0900 Subject: [PATCH 07/11] Mark hitsounds as such --- osu.Game/Audio/HitSampleInfo.cs | 2 ++ osu.Game/Audio/ISampleInfo.cs | 2 ++ osu.Game/Audio/SampleInfo.cs | 2 ++ osu.Game/Storyboards/StoryboardSample.cs | 2 ++ 4 files changed, 8 insertions(+) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index ff6f3b43bb60..b59ef4198111 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -30,6 +30,8 @@ public class HitSampleInfo : ISampleInfo, IEquatable // new bank used exclusively by taiko for now. public const string BANK_STRONG = @"strong"; + public bool IsHitsound => true; + /// /// All valid sample addition constants. /// diff --git a/osu.Game/Audio/ISampleInfo.cs b/osu.Game/Audio/ISampleInfo.cs index 4f81d37e78e1..c892185dd269 100644 --- a/osu.Game/Audio/ISampleInfo.cs +++ b/osu.Game/Audio/ISampleInfo.cs @@ -13,5 +13,7 @@ public interface ISampleInfo IEnumerable LookupNames { get; } int Volume { get; } + + bool IsHitsound { get; } } } diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 5c46d1a1da47..b6ca56022745 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -14,6 +14,8 @@ public class SampleInfo : ISampleInfo, IEquatable { private readonly string[] sampleNames; + public bool IsHitsound => false; + public SampleInfo(params string[] sampleNames) { this.sampleNames = sampleNames; diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 869e4e2a5d90..4df13c09478e 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -18,6 +18,8 @@ public class StoryboardSampleInfo : IStoryboardElement, ISampleInfo public int Volume { get; } + public bool IsHitsound => false; + public IEnumerable LookupNames => new[] { // Try first with the full name, then attempt with no path From 264489649d3b62b703fc0d164d191867f0fcda14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Oct 2026 18:37:57 +0900 Subject: [PATCH 08/11] Adjust skin lookups --- .../Skins/TestSceneSkinResources.cs | 3 +- .../Screens/Edit/Components/FormSampleSet.cs | 2 +- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 35 +++++++++--------- osu.Game/Skinning/ArgonProSkin.cs | 8 ++--- osu.Game/Skinning/ArgonSkin.cs | 6 ++-- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/Skin.cs | 36 +++++++++++++++---- osu.Game/Skinning/TrianglesSkin.cs | 8 ++--- 8 files changed, 57 insertions(+), 43 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinResources.cs b/osu.Game.Tests/Skins/TestSceneSkinResources.cs index 17e9c9b65411..32d07c90dba8 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinResources.cs @@ -11,7 +11,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.Rendering.Dummy; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; @@ -104,7 +103,7 @@ public TestSkin(SkinInfo skin, IStorageResourceProvider? resources, IResourceSto public override IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); - public override ISample GetSample(ISampleInfo sampleInfo) => Samples.AsNonNull().Get(SAMPLE_NAME); + public override ISample GetSample(ISampleInfo sampleInfo) => GetSample(SAMPLE_NAME, sampleInfo.IsHitsound)!; } } } diff --git a/osu.Game/Screens/Edit/Components/FormSampleSet.cs b/osu.Game/Screens/Edit/Components/FormSampleSet.cs index 854f1d8d2ccd..4326e1ff8bbb 100644 --- a/osu.Game/Screens/Edit/Components/FormSampleSet.cs +++ b/osu.Game/Screens/Edit/Components/FormSampleSet.cs @@ -289,7 +289,7 @@ private void recycleSamples() => Schedule(() => AddInternal(hoverSounds = (ActualFilename.Value == null ? new HoverClickSounds(HoverSampleSet.Button) : new HoverSounds(HoverSampleSet.Button))); - sample = ActualFilename.Value != null ? editorBeatmap?.BeatmapSkin?.Skin.Samples?.Get(ActualFilename.Value) : null; + sample = ActualFilename.Value != null ? editorBeatmap?.BeatmapSkin?.Skin.GetSample(ActualFilename.Value, true) : null; }); protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs index ab871d43bf18..fc81c782c421 100644 --- a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -119,32 +119,29 @@ public IEnumerable GetAvailableSampleSets() [1] = new SampleSet(1), }; - if (Skin.Samples != null) + foreach (string sample in Skin.AllAvailableSamples) { - foreach (string sample in Skin.Samples.GetAvailableResources()) + foreach (string possiblePrefix in possiblePrefixes) { - foreach (string possiblePrefix in possiblePrefixes) - { - if (!sample.StartsWith(possiblePrefix, StringComparison.Ordinal)) - continue; + if (!sample.StartsWith(possiblePrefix, StringComparison.Ordinal)) + continue; - string indexString = Path.GetFileNameWithoutExtension(sample)[possiblePrefix.Length..]; - int? index = null; + string indexString = Path.GetFileNameWithoutExtension(sample)[possiblePrefix.Length..]; + int? index = null; - if (string.IsNullOrEmpty(indexString)) - index = 1; - if (int.TryParse(indexString, out int parsed) && parsed >= 2) - index = parsed; + if (string.IsNullOrEmpty(indexString)) + index = 1; + if (int.TryParse(indexString, out int parsed) && parsed >= 2) + index = parsed; - if (!index.HasValue) - continue; + if (!index.HasValue) + continue; - SampleSet? sampleSet; - if (!sampleSets.TryGetValue(index.Value, out sampleSet)) - sampleSet = sampleSets[index.Value] = new SampleSet(index.Value); + SampleSet? sampleSet; + if (!sampleSets.TryGetValue(index.Value, out sampleSet)) + sampleSet = sampleSets[index.Value] = new SampleSet(index.Value); - sampleSet.Filenames.Add(sample); - } + sampleSet.Filenames.Add(sample); } } diff --git a/osu.Game/Skinning/ArgonProSkin.cs b/osu.Game/Skinning/ArgonProSkin.cs index 6ec9945c0e36..55d6e7e8691f 100644 --- a/osu.Game/Skinning/ArgonProSkin.cs +++ b/osu.Game/Skinning/ArgonProSkin.cs @@ -24,10 +24,10 @@ public class ArgonProSkin : ArgonSkin { foreach (string lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(lookup) - ?? Resources.AudioManager?.Samples.Get(lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/")) - ?? Resources.AudioManager?.Samples.Get(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/")) - ?? Resources.AudioManager?.Samples.Get(lookup); + var sample = GetSample(lookup, sampleInfo.IsHitsound) + ?? GetResourceSample(lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/"), sampleInfo.IsHitsound) + ?? GetResourceSample(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/"), sampleInfo.IsHitsound) + ?? GetResourceSample(lookup, sampleInfo.IsHitsound); if (sample != null) return sample; diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 588c1e9b1cab..f42bd75053d1 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -77,9 +77,9 @@ public ArgonSkin(SkinInfo skin, IStorageResourceProvider resources) { foreach (string lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(lookup) - ?? Resources.AudioManager?.Samples.Get(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/")) - ?? Resources.AudioManager?.Samples.Get(lookup); + var sample = GetSample(lookup, sampleInfo.IsHitsound) + ?? GetResourceSample(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/"), sampleInfo.IsHitsound) + ?? GetResourceSample(lookup, sampleInfo.IsHitsound); if (sample != null) return sample; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index af46bdd5b737..24fb796164ae 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -596,7 +596,7 @@ protected override void ParseConfigurationStream(Stream stream) foreach (string lookup in lookupNames) { - var sample = Samples?.Get(lookup); + var sample = GetSample(lookup, sampleInfo.IsHitsound); if (sample != null) { diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 9f5cc47d447b..d2a0c30893b1 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -40,7 +40,17 @@ public abstract class Skin : IDisposable, ISkin, IHasComboColours, IHasCustomCol /// /// A sample store which can be used to perform user file lookups for this skin. /// - protected internal ISampleStore? Samples { get; private set; } + private ISampleStore? samples; + + private ISampleStore? hitSamples; + + private readonly ISampleStore? resourceHitSamples; + + protected internal ISample? GetSample(string lookup, bool isHitsound) => (isHitsound ? hitSamples : samples)?.Get(lookup); + + public IEnumerable AllAvailableSamples => hitSamples?.GetAvailableResources() ?? Array.Empty(); + + protected internal ISample? GetResourceSample(string lookup, bool isHitsound) => (isHitsound ? resourceHitSamples : resources?.AudioManager?.Samples)?.Get(lookup); public readonly Live SkinInfo; @@ -77,11 +87,12 @@ public abstract class Skin : IDisposable, ISkin, IHasComboColours, IHasCustomCol protected Skin(SkinInfo skin, IStorageResourceProvider? resources, IResourceStore? fallbackStore = null, string configurationFilename = @"skin.ini") { this.resources = resources; - Name = skin.Name; if (resources != null) { + resourceHitSamples = resources.AudioManager?.GetSampleStore(applyGlobalSampleVolume: false); + SkinInfo = skin.ToLive(resources.RealmAccess); store.AddStore(new RealmBackedResourceStore(SkinInfo, resources.Files, resources.RealmAccess)); @@ -146,16 +157,17 @@ protected Skin(SkinInfo skin, IStorageResourceProvider? resources, IResourceStor } /// - /// Recreates . + /// Recreates . /// All users of samples from the skin are expected to manually re-retrieve their samples from this skin after this is called. /// Exposed as public for the purpose of e.g. editing flows where the skin's set of available samples changes. /// In such a scenario a full recycle of the store is required to avoid accidentally retrieving stale samples that don't exist in the skin anymore. /// public void RecycleSamples() { - Samples?.Dispose(); + samples?.Dispose(); + hitSamples?.Dispose(); - var samples = resources?.AudioManager?.GetSampleStore(store); + samples = resources?.AudioManager?.GetSampleStore(store, applyGlobalSampleVolume: true); if (samples != null) { @@ -166,7 +178,16 @@ public void RecycleSamples() samples.AddExtension(@"ogg"); } - Samples = samples; + hitSamples = resources?.AudioManager?.GetSampleStore(store, applyGlobalSampleVolume: false); + + if (hitSamples != null) + { + hitSamples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; + + // osu-stable performs audio lookups in order of wav -> mp3 -> ogg. + // The GetSampleStore() call above internally adds wav and mp3, so ogg is added at the end to ensure expected ordering. + hitSamples.AddExtension(@"ogg"); + } } protected virtual IResourceStore CreateTextureLoaderStore(IStorageResourceProvider resources, IResourceStore storage) @@ -357,7 +378,8 @@ protected virtual void Dispose(bool isDisposing) isDisposed = true; Textures?.Dispose(); - Samples?.Dispose(); + samples?.Dispose(); + hitSamples?.Dispose(); FallbackStore?.Dispose(); store.Dispose(); diff --git a/osu.Game/Skinning/TrianglesSkin.cs b/osu.Game/Skinning/TrianglesSkin.cs index 019dd59b31e6..204a3909cdf4 100644 --- a/osu.Game/Skinning/TrianglesSkin.cs +++ b/osu.Game/Skinning/TrianglesSkin.cs @@ -32,8 +32,6 @@ public class TrianglesSkin : Skin InstantiationInfo = typeof(TrianglesSkin).GetInvariantInstantiationInfo() }; - private readonly IStorageResourceProvider resources; - public TrianglesSkin(IStorageResourceProvider resources) : this(CreateInfo(), resources) { @@ -42,9 +40,7 @@ public TrianglesSkin(IStorageResourceProvider resources) [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] public TrianglesSkin(SkinInfo skin, IStorageResourceProvider resources) : base(skin, resources) - { - this.resources = resources; - } + { } public override Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => Textures?.Get(componentName, wrapModeS, wrapModeT); @@ -52,7 +48,7 @@ public TrianglesSkin(SkinInfo skin, IStorageResourceProvider resources) { foreach (string lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(lookup) ?? resources.AudioManager?.Samples.Get(lookup); + var sample = GetSample(lookup, sampleInfo.IsHitsound) ?? GetResourceSample(lookup, sampleInfo.IsHitsound); if (sample != null) return sample; } From 7ceeab7f84881a52db24217a5ac31f9ad6a22881 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Oct 2026 20:25:15 +0900 Subject: [PATCH 09/11] Adjust naming --- osu.Game.Tests/Skins/TestSceneSkinResources.cs | 2 +- osu.Game/Screens/Edit/Components/FormSampleSet.cs | 2 +- osu.Game/Skinning/ArgonProSkin.cs | 8 ++++---- osu.Game/Skinning/ArgonSkin.cs | 6 +++--- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/Skin.cs | 6 +++--- osu.Game/Skinning/TrianglesSkin.cs | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinResources.cs b/osu.Game.Tests/Skins/TestSceneSkinResources.cs index 32d07c90dba8..88088e5210a3 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinResources.cs @@ -103,7 +103,7 @@ public TestSkin(SkinInfo skin, IStorageResourceProvider? resources, IResourceSto public override IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); - public override ISample GetSample(ISampleInfo sampleInfo) => GetSample(SAMPLE_NAME, sampleInfo.IsHitsound)!; + public override ISample GetSample(ISampleInfo sampleInfo) => GetSampleFromSkinFiles(SAMPLE_NAME, sampleInfo.IsHitsound)!; } } } diff --git a/osu.Game/Screens/Edit/Components/FormSampleSet.cs b/osu.Game/Screens/Edit/Components/FormSampleSet.cs index 4326e1ff8bbb..010ea3d866f3 100644 --- a/osu.Game/Screens/Edit/Components/FormSampleSet.cs +++ b/osu.Game/Screens/Edit/Components/FormSampleSet.cs @@ -289,7 +289,7 @@ private void recycleSamples() => Schedule(() => AddInternal(hoverSounds = (ActualFilename.Value == null ? new HoverClickSounds(HoverSampleSet.Button) : new HoverSounds(HoverSampleSet.Button))); - sample = ActualFilename.Value != null ? editorBeatmap?.BeatmapSkin?.Skin.GetSample(ActualFilename.Value, true) : null; + sample = ActualFilename.Value != null ? editorBeatmap?.BeatmapSkin?.Skin.GetSampleFromSkinFiles(ActualFilename.Value, true) : null; }); protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Skinning/ArgonProSkin.cs b/osu.Game/Skinning/ArgonProSkin.cs index 55d6e7e8691f..c3040290292c 100644 --- a/osu.Game/Skinning/ArgonProSkin.cs +++ b/osu.Game/Skinning/ArgonProSkin.cs @@ -24,10 +24,10 @@ public class ArgonProSkin : ArgonSkin { foreach (string lookup in sampleInfo.LookupNames) { - var sample = GetSample(lookup, sampleInfo.IsHitsound) - ?? GetResourceSample(lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/"), sampleInfo.IsHitsound) - ?? GetResourceSample(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/"), sampleInfo.IsHitsound) - ?? GetResourceSample(lookup, sampleInfo.IsHitsound); + var sample = GetSampleFromSkinFiles(lookup, sampleInfo.IsHitsound) + ?? GetSampleFromResourceFiles(lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/"), sampleInfo.IsHitsound) + ?? GetSampleFromResourceFiles(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/"), sampleInfo.IsHitsound) + ?? GetSampleFromResourceFiles(lookup, sampleInfo.IsHitsound); if (sample != null) return sample; diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index f42bd75053d1..c32872f0dc07 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -77,9 +77,9 @@ public ArgonSkin(SkinInfo skin, IStorageResourceProvider resources) { foreach (string lookup in sampleInfo.LookupNames) { - var sample = GetSample(lookup, sampleInfo.IsHitsound) - ?? GetResourceSample(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/"), sampleInfo.IsHitsound) - ?? GetResourceSample(lookup, sampleInfo.IsHitsound); + var sample = GetSampleFromSkinFiles(lookup, sampleInfo.IsHitsound) + ?? GetSampleFromResourceFiles(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/"), sampleInfo.IsHitsound) + ?? GetSampleFromResourceFiles(lookup, sampleInfo.IsHitsound); if (sample != null) return sample; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 24fb796164ae..3f76a16aadf6 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -596,7 +596,7 @@ protected override void ParseConfigurationStream(Stream stream) foreach (string lookup in lookupNames) { - var sample = GetSample(lookup, sampleInfo.IsHitsound); + var sample = GetSampleFromSkinFiles(lookup, sampleInfo.IsHitsound); if (sample != null) { diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index d2a0c30893b1..1c0104a30b3b 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -46,11 +46,11 @@ public abstract class Skin : IDisposable, ISkin, IHasComboColours, IHasCustomCol private readonly ISampleStore? resourceHitSamples; - protected internal ISample? GetSample(string lookup, bool isHitsound) => (isHitsound ? hitSamples : samples)?.Get(lookup); - public IEnumerable AllAvailableSamples => hitSamples?.GetAvailableResources() ?? Array.Empty(); - protected internal ISample? GetResourceSample(string lookup, bool isHitsound) => (isHitsound ? resourceHitSamples : resources?.AudioManager?.Samples)?.Get(lookup); + protected internal ISample? GetSampleFromSkinFiles(string lookup, bool isHitsound) => (isHitsound ? hitSamples : samples)?.Get(lookup); + + protected internal ISample? GetSampleFromResourceFiles(string lookup, bool isHitsound) => (isHitsound ? resourceHitSamples : resources?.AudioManager?.Samples)?.Get(lookup); public readonly Live SkinInfo; diff --git a/osu.Game/Skinning/TrianglesSkin.cs b/osu.Game/Skinning/TrianglesSkin.cs index 204a3909cdf4..b722257eb0d1 100644 --- a/osu.Game/Skinning/TrianglesSkin.cs +++ b/osu.Game/Skinning/TrianglesSkin.cs @@ -48,7 +48,7 @@ public TrianglesSkin(SkinInfo skin, IStorageResourceProvider resources) { foreach (string lookup in sampleInfo.LookupNames) { - var sample = GetSample(lookup, sampleInfo.IsHitsound) ?? GetResourceSample(lookup, sampleInfo.IsHitsound); + var sample = GetSampleFromSkinFiles(lookup, sampleInfo.IsHitsound) ?? GetSampleFromResourceFiles(lookup, sampleInfo.IsHitsound); if (sample != null) return sample; } From c9b5f357fff65e37c6a77192001ec24ac8b7f7de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Oct 2026 18:00:07 +0900 Subject: [PATCH 10/11] Update framework --- osu.Android.props | 2 +- osu.Game/Skinning/Skin.cs | 6 +++--- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 601eb39a90cf..045c16ba09ab 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - +