Add UI click sounds (#22410)

* Add UI click sounds

* tweaks

* Significant cleanup

* Audio options and numerous fixes

* Fix the remaining UI elements

* new click sound

---------

Co-authored-by: Kara <lunarautomaton6@gmail.com>
This commit is contained in:
metalgearsloth
2023-12-29 15:43:36 +11:00
committed by GitHub
parent 5f7e92a2d7
commit 4023134cf0
19 changed files with 179 additions and 21 deletions

View File

@@ -0,0 +1,98 @@
using Content.Shared.CCVar;
using Robust.Client.Audio;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controllers;
using Robust.Shared.Audio.Sources;
using Robust.Shared.Configuration;
namespace Content.Client.Audio;
public sealed class AudioUIController : UIController
{
[Dependency] private readonly IAudioManager _audioManager = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IResourceCache _cache = default!;
private float _interfaceGain;
private IAudioSource? _clickSource;
private IAudioSource? _hoverSource;
private const float ClickGain = 0.25f;
private const float HoverGain = 0.05f;
public override void Initialize()
{
base.Initialize();
/*
* This exists to load UI sounds outside of the game sim.
*/
// No unsub coz never shuts down until program exit.
_configManager.OnValueChanged(CCVars.UIClickSound, SetClickSound, true);
_configManager.OnValueChanged(CCVars.UIHoverSound, SetHoverSound, true);
_configManager.OnValueChanged(CCVars.InterfaceVolume, SetInterfaceVolume, true);
}
private void SetInterfaceVolume(float obj)
{
_interfaceGain = obj;
if (_clickSource != null)
{
_clickSource.Gain = ClickGain * _interfaceGain;
}
if (_hoverSource != null)
{
_hoverSource.Gain = HoverGain * _interfaceGain;
}
}
private void SetClickSound(string value)
{
if (!string.IsNullOrEmpty(value))
{
var resource = _cache.GetResource<AudioResource>(value);
var source =
_audioManager.CreateAudioSource(resource);
if (source != null)
{
source.Gain = ClickGain * _interfaceGain;
source.Global = true;
}
_clickSource = source;
UIManager.SetClickSound(source);
}
else
{
UIManager.SetClickSound(null);
}
}
private void SetHoverSound(string value)
{
if (!string.IsNullOrEmpty(value))
{
var hoverResource = _cache.GetResource<AudioResource>(value);
var hoverSource =
_audioManager.CreateAudioSource(hoverResource);
if (hoverSource != null)
{
hoverSource.Gain = HoverGain * _interfaceGain;
hoverSource.Global = true;
}
_hoverSource = hoverSource;
UIManager.SetHoverSound(hoverSource);
}
else
{
UIManager.SetHoverSound(null);
}
}
}

View File

@@ -1,15 +1,18 @@
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.CCVar;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Robust.Client.GameObjects; using Robust.Client.Audio;
using Robust.Shared; using Robust.Client.ResourceManagement;
using Robust.Shared.Audio; using Robust.Client.UserInterface;
using AudioComponent = Robust.Shared.Audio.Components.AudioComponent; using AudioComponent = Robust.Shared.Audio.Components.AudioComponent;
namespace Content.Client.Audio; namespace Content.Client.Audio;
public sealed partial class ContentAudioSystem : SharedContentAudioSystem public sealed partial class ContentAudioSystem : SharedContentAudioSystem
{ {
[Dependency] private readonly IAudioManager _audioManager = default!;
[Dependency] private readonly IResourceCache _cache = default!;
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
// Need how much volume to change per tick and just remove it when it drops below "0" // Need how much volume to change per tick and just remove it when it drops below "0"
private readonly Dictionary<EntityUid, float> _fadingOut = new(); private readonly Dictionary<EntityUid, float> _fadingOut = new();
@@ -32,6 +35,7 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem
public const float AmbienceMultiplier = 3f; public const float AmbienceMultiplier = 3f;
public const float AmbientMusicMultiplier = 3f; public const float AmbientMusicMultiplier = 3f;
public const float LobbyMultiplier = 3f; public const float LobbyMultiplier = 3f;
public const float InterfaceMultiplier = 2f;
public override void Initialize() public override void Initialize()
{ {

View File

@@ -394,7 +394,7 @@ namespace Content.Client.Construction.UI
if (IsAtFront) if (IsAtFront)
{ {
WindowOpen = false; WindowOpen = false;
_uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.Pressed = false; // This does not call CraftingButtonToggled _uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.SetClickPressed(false); // This does not call CraftingButtonToggled
} }
else else
_constructionView.MoveToFront(); _constructionView.MoveToFront();
@@ -402,7 +402,7 @@ namespace Content.Client.Construction.UI
else else
{ {
WindowOpen = true; WindowOpen = true;
_uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.Pressed = true; // This does not call CraftingButtonToggled _uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.SetClickPressed(true); // This does not call CraftingButtonToggled
} }
} }

View File

@@ -74,6 +74,19 @@
<Label Name="LobbyVolumeLabel" MinSize="48 0" Align="Right" /> <Label Name="LobbyVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/> <Control MinSize="4 0"/>
</BoxContainer> </BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-interface-volume'}" HorizontalExpand="True" />
<Control MinSize="8 0" />
<Slider Name="InterfaceVolumeSlider"
MinValue="0"
MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" />
<Control MinSize="8 0" />
<Label Name="InterfaceVolumeLabel" MinSize="48 0" Align="Right" />
<Control MinSize="4 0"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0"> <BoxContainer Orientation="Horizontal" Margin="5 0 0 0">
<Label Text="{Loc 'ui-options-ambience-max-sounds'}" HorizontalExpand="True" /> <Label Text="{Loc 'ui-options-ambience-max-sounds'}" HorizontalExpand="True" />
<Control MinSize="8 0" /> <Control MinSize="8 0" />

View File

@@ -2,13 +2,10 @@ using Content.Client.Audio;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Robust.Client.Audio; using Robust.Client.Audio;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared; using Robust.Shared;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Range = Robust.Client.UserInterface.Controls.Range; using Range = Robust.Client.UserInterface.Controls.Range;
@@ -39,6 +36,7 @@ namespace Content.Client.Options.UI.Tabs
AmbienceVolumeSlider.OnValueChanged += OnAmbienceVolumeSliderChanged; AmbienceVolumeSlider.OnValueChanged += OnAmbienceVolumeSliderChanged;
AmbienceSoundsSlider.OnValueChanged += OnAmbienceSoundsSliderChanged; AmbienceSoundsSlider.OnValueChanged += OnAmbienceSoundsSliderChanged;
LobbyVolumeSlider.OnValueChanged += OnLobbyVolumeSliderChanged; LobbyVolumeSlider.OnValueChanged += OnLobbyVolumeSliderChanged;
InterfaceVolumeSlider.OnValueChanged += OnInterfaceVolumeSliderChanged;
LobbyMusicCheckBox.OnToggled += OnLobbyMusicCheckToggled; LobbyMusicCheckBox.OnToggled += OnLobbyMusicCheckToggled;
RestartSoundsCheckBox.OnToggled += OnRestartSoundsCheckToggled; RestartSoundsCheckBox.OnToggled += OnRestartSoundsCheckToggled;
EventMusicCheckBox.OnToggled += OnEventMusicCheckToggled; EventMusicCheckBox.OnToggled += OnEventMusicCheckToggled;
@@ -59,6 +57,7 @@ namespace Content.Client.Options.UI.Tabs
AmbientMusicVolumeSlider.OnValueChanged -= OnAmbientMusicVolumeSliderChanged; AmbientMusicVolumeSlider.OnValueChanged -= OnAmbientMusicVolumeSliderChanged;
AmbienceVolumeSlider.OnValueChanged -= OnAmbienceVolumeSliderChanged; AmbienceVolumeSlider.OnValueChanged -= OnAmbienceVolumeSliderChanged;
LobbyVolumeSlider.OnValueChanged -= OnLobbyVolumeSliderChanged; LobbyVolumeSlider.OnValueChanged -= OnLobbyVolumeSliderChanged;
InterfaceVolumeSlider.OnValueChanged -= OnInterfaceVolumeSliderChanged;
base.Dispose(disposing); base.Dispose(disposing);
} }
@@ -67,6 +66,11 @@ namespace Content.Client.Options.UI.Tabs
UpdateChanges(); UpdateChanges();
} }
private void OnInterfaceVolumeSliderChanged(Range obj)
{
UpdateChanges();
}
private void OnAmbientMusicVolumeSliderChanged(Range obj) private void OnAmbientMusicVolumeSliderChanged(Range obj)
{ {
UpdateChanges(); UpdateChanges();
@@ -120,6 +124,7 @@ namespace Content.Client.Options.UI.Tabs
_cfg.SetCVar(CCVars.AmbienceVolume, AmbienceVolumeSlider.Value / 100f * ContentAudioSystem.AmbienceMultiplier); _cfg.SetCVar(CCVars.AmbienceVolume, AmbienceVolumeSlider.Value / 100f * ContentAudioSystem.AmbienceMultiplier);
_cfg.SetCVar(CCVars.AmbientMusicVolume, AmbientMusicVolumeSlider.Value / 100f * ContentAudioSystem.AmbientMusicMultiplier); _cfg.SetCVar(CCVars.AmbientMusicVolume, AmbientMusicVolumeSlider.Value / 100f * ContentAudioSystem.AmbientMusicMultiplier);
_cfg.SetCVar(CCVars.LobbyMusicVolume, LobbyVolumeSlider.Value / 100f * ContentAudioSystem.LobbyMultiplier); _cfg.SetCVar(CCVars.LobbyMusicVolume, LobbyVolumeSlider.Value / 100f * ContentAudioSystem.LobbyMultiplier);
_cfg.SetCVar(CCVars.InterfaceVolume, InterfaceVolumeSlider.Value / 100f * ContentAudioSystem.InterfaceMultiplier);
_cfg.SetCVar(CCVars.MaxAmbientSources, (int)AmbienceSoundsSlider.Value); _cfg.SetCVar(CCVars.MaxAmbientSources, (int)AmbienceSoundsSlider.Value);
@@ -143,6 +148,7 @@ namespace Content.Client.Options.UI.Tabs
AmbienceVolumeSlider.Value = _cfg.GetCVar(CCVars.AmbienceVolume) * 100f / ContentAudioSystem.AmbienceMultiplier; AmbienceVolumeSlider.Value = _cfg.GetCVar(CCVars.AmbienceVolume) * 100f / ContentAudioSystem.AmbienceMultiplier;
AmbientMusicVolumeSlider.Value = _cfg.GetCVar(CCVars.AmbientMusicVolume) * 100f / ContentAudioSystem.AmbientMusicMultiplier; AmbientMusicVolumeSlider.Value = _cfg.GetCVar(CCVars.AmbientMusicVolume) * 100f / ContentAudioSystem.AmbientMusicMultiplier;
LobbyVolumeSlider.Value = _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier; LobbyVolumeSlider.Value = _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier;
InterfaceVolumeSlider.Value = _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier;
AmbienceSoundsSlider.Value = _cfg.GetCVar(CCVars.MaxAmbientSources); AmbienceSoundsSlider.Value = _cfg.GetCVar(CCVars.MaxAmbientSources);
@@ -166,6 +172,8 @@ namespace Content.Client.Options.UI.Tabs
Math.Abs(AmbientMusicVolumeSlider.Value - _cfg.GetCVar(CCVars.AmbientMusicVolume) * 100f / ContentAudioSystem.AmbientMusicMultiplier) < 0.01f; Math.Abs(AmbientMusicVolumeSlider.Value - _cfg.GetCVar(CCVars.AmbientMusicVolume) * 100f / ContentAudioSystem.AmbientMusicMultiplier) < 0.01f;
var isLobbyVolumeSame = var isLobbyVolumeSame =
Math.Abs(LobbyVolumeSlider.Value - _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier) < 0.01f; Math.Abs(LobbyVolumeSlider.Value - _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier) < 0.01f;
var isInterfaceVolumeSame =
Math.Abs(InterfaceVolumeSlider.Value - _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier) < 0.01f;
var isAmbientSoundsSame = (int)AmbienceSoundsSlider.Value == _cfg.GetCVar(CCVars.MaxAmbientSources); var isAmbientSoundsSame = (int)AmbienceSoundsSlider.Value == _cfg.GetCVar(CCVars.MaxAmbientSources);
var isLobbySame = LobbyMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.LobbyMusicEnabled); var isLobbySame = LobbyMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.LobbyMusicEnabled);
@@ -173,7 +181,7 @@ namespace Content.Client.Options.UI.Tabs
var isEventSame = EventMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.EventMusicEnabled); var isEventSame = EventMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.EventMusicEnabled);
var isAdminSoundsSame = AdminSoundsCheckBox.Pressed == _cfg.GetCVar(CCVars.AdminSoundsEnabled); var isAdminSoundsSame = AdminSoundsCheckBox.Pressed == _cfg.GetCVar(CCVars.AdminSoundsEnabled);
var isEverythingSame = isMasterVolumeSame && isMidiVolumeSame && isAmbientVolumeSame && isAmbientMusicVolumeSame && isAmbientSoundsSame && isLobbySame && isRestartSoundsSame && isEventSame var isEverythingSame = isMasterVolumeSame && isMidiVolumeSame && isAmbientVolumeSame && isAmbientMusicVolumeSame && isAmbientSoundsSame && isLobbySame && isRestartSoundsSame && isEventSame
&& isAdminSoundsSame && isLobbyVolumeSame; && isAdminSoundsSame && isLobbyVolumeSame && isInterfaceVolumeSame;
ApplyButton.Disabled = isEverythingSame; ApplyButton.Disabled = isEverythingSame;
ResetButton.Disabled = isEverythingSame; ResetButton.Disabled = isEverythingSame;
MasterVolumeLabel.Text = MasterVolumeLabel.Text =
@@ -186,6 +194,8 @@ namespace Content.Client.Options.UI.Tabs
Loc.GetString("ui-options-volume-percent", ("volume", AmbienceVolumeSlider.Value / 100)); Loc.GetString("ui-options-volume-percent", ("volume", AmbienceVolumeSlider.Value / 100));
LobbyVolumeLabel.Text = LobbyVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", LobbyVolumeSlider.Value / 100)); Loc.GetString("ui-options-volume-percent", ("volume", LobbyVolumeSlider.Value / 100));
InterfaceVolumeLabel.Text =
Loc.GetString("ui-options-volume-percent", ("volume", InterfaceVolumeSlider.Value / 100));
AmbienceSoundsLabel.Text = ((int)AmbienceSoundsSlider.Value).ToString(); AmbienceSoundsLabel.Text = ((int)AmbienceSoundsSlider.Value).ToString();
} }
} }

View File

@@ -285,7 +285,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
private void OnWindowOpened() private void OnWindowOpened()
{ {
if (ActionButton != null) if (ActionButton != null)
ActionButton.Pressed = true; ActionButton.SetClickPressed(true);
SearchAndDisplay(); SearchAndDisplay();
} }
@@ -293,7 +293,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
private void OnWindowClosed() private void OnWindowClosed()
{ {
if (ActionButton != null) if (ActionButton != null)
ActionButton.Pressed = false; ActionButton.SetClickPressed(false);
} }
public void OnStateExited(GameplayState state) public void OnStateExited(GameplayState state)

View File

@@ -355,6 +355,7 @@ public sealed class ActionButton : Control, IEntityControl
{ {
base.MouseEntered(); base.MouseEntered();
UserInterfaceManager.HoverSound();
_beingHovered = true; _beingHovered = true;
DrawModeChanged(); DrawModeChanged();
} }

View File

@@ -127,14 +127,12 @@ public sealed class AdminUIController : UIController, IOnStateEntered<GameplaySt
private void OnWindowOpen() private void OnWindowOpen()
{ {
if (AdminButton != null) AdminButton?.SetClickPressed(true);
AdminButton.Pressed = true;
} }
private void OnWindowClosed() private void OnWindowClosed()
{ {
if (AdminButton != null) AdminButton?.SetClickPressed(false);
AdminButton.Pressed = false;
} }
private void OnWindowDisposed() private void OnWindowDisposed()

View File

@@ -121,6 +121,7 @@ public sealed class AHelpUIController: UIController, IOnSystemChanged<BwoinkSyst
LobbyAHelpButton.Pressed = pressed; LobbyAHelpButton.Pressed = pressed;
} }
UIManager.ClickSound();
UnreadAHelpRead(); UnreadAHelpRead();
} }

View File

@@ -184,7 +184,7 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
if (CharacterButton != null) if (CharacterButton != null)
{ {
CharacterButton.Pressed = !_window.IsOpen; CharacterButton.SetClickPressed(!_window.IsOpen);
} }
if (_window.IsOpen) if (_window.IsOpen)

View File

@@ -51,8 +51,8 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
EscapeButton.OnPressed += EscapeButtonOnOnPressed; EscapeButton.OnPressed += EscapeButtonOnOnPressed;
} }
private void ActivateButton() => EscapeButton!.Pressed = true; private void ActivateButton() => EscapeButton!.SetClickPressed(true);
private void DeactivateButton() => EscapeButton!.Pressed = false; private void DeactivateButton() => EscapeButton!.SetClickPressed(false);
public void OnStateEntered(GameplayState state) public void OnStateEntered(GameplayState state)
{ {

View File

@@ -139,12 +139,13 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
if (_guideWindow.IsOpen) if (_guideWindow.IsOpen)
{ {
UIManager.ClickSound();
_guideWindow.Close(); _guideWindow.Close();
return; return;
} }
if (GuidebookButton != null) if (GuidebookButton != null)
GuidebookButton.Pressed = !_guideWindow.IsOpen; GuidebookButton.SetClickPressed(!_guideWindow.IsOpen);
if (guides == null) if (guides == null)
{ {

View File

@@ -243,7 +243,9 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
} }
UpdateInventoryHotbar(_playerInventory); UpdateInventoryHotbar(_playerInventory);
_inventoryHotbar.Visible = !_inventoryHotbar.Visible; var shouldBeVisible = !_inventoryHotbar.Visible;
_inventoryHotbar.Visible = shouldBeVisible;
} }
// Neuron Activation // Neuron Activation

View File

@@ -172,10 +172,12 @@ public sealed class SandboxUIController : UIController, IOnStateChanged<Gameplay
return; return;
if (_sandbox.SandboxAllowed && _window.IsOpen != true) if (_sandbox.SandboxAllowed && _window.IsOpen != true)
{ {
UIManager.ClickSound();
_window.OpenCentered(); _window.OpenCentered();
} }
else else
{ {
UIManager.ClickSound();
_window.Close(); _window.Close();
} }
} }

View File

@@ -81,6 +81,12 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<float> LobbyMusicVolume = public static readonly CVarDef<float> LobbyMusicVolume =
CVarDef.Create("ambience.lobby_music_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY); CVarDef.Create("ambience.lobby_music_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY);
/// <summary>
/// UI volume.
/// </summary>
public static readonly CVarDef<float> InterfaceVolume =
CVarDef.Create("audio.interface_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY);
/* /*
* Status * Status
*/ */
@@ -573,6 +579,16 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> DatabaseSynchronous = public static readonly CVarDef<bool> DatabaseSynchronous =
CVarDef.Create("database.sync", false, CVar.SERVERONLY); CVarDef.Create("database.sync", false, CVar.SERVERONLY);
/*
* Interface
*/
public static readonly CVarDef<string> UIClickSound =
CVarDef.Create("interface.click_sound", "/Audio/UserInterface/click.ogg", CVar.REPLICATED);
public static readonly CVarDef<string> UIHoverSound =
CVarDef.Create("interface.hover_sound", "/Audio/UserInterface/hover.ogg", CVar.REPLICATED);
/* /*
* Outline * Outline
*/ */

View File

@@ -0,0 +1,11 @@
- files:
- click.ogg
license: "CC0-1.0"
copyright: "Made by el_boss, edited by mirrorcult"
source: "https://freesound.org/people/el_boss/sounds/677861/"
- files:
- hover.ogg
license: "CC0-1.0"
copyright: "Made by MATRIXXX_, edited by metalgearsloth"
source: "https://freesound.org/people/MATRIXXX_/sounds/703884/"

Binary file not shown.

Binary file not shown.

View File

@@ -27,6 +27,7 @@ ui-options-midi-volume = MIDI (Instrument) Volume:
ui-options-ambient-music-volume = Ambient music volume: ui-options-ambient-music-volume = Ambient music volume:
ui-options-ambience-volume = Ambience volume: ui-options-ambience-volume = Ambience volume:
ui-options-lobby-volume = Lobby & Round-end volume: ui-options-lobby-volume = Lobby & Round-end volume:
ui-options-interface-volume = Interface volume:
ui-options-ambience-max-sounds = Ambience simultaneous sounds: ui-options-ambience-max-sounds = Ambience simultaneous sounds:
ui-options-lobby-music = Lobby & Round-end Music ui-options-lobby-music = Lobby & Round-end Music
ui-options-restart-sounds = Round Restart Sounds ui-options-restart-sounds = Round Restart Sounds