From 711bdd72c6ad5526f7d2bd2a4b892ea2c787da3d Mon Sep 17 00:00:00 2001 From: Aidenkrz <28298836+Aidenkrz@users.noreply.github.com> Date: Thu, 23 Apr 2026 14:20:55 -0500 Subject: [PATCH 1/4] TTS --- Content.Client/Audio/ContentAudioSystem.cs | 2 + .../Lobby/UI/HumanoidProfileEditor.TTS.cs | 85 + .../Lobby/UI/HumanoidProfileEditor.xaml | 7 + .../Lobby/UI/HumanoidProfileEditor.xaml.cs | 18 + Content.Client/Options/UI/Tabs/AudioTab.xaml | 2 + .../Options/UI/Tabs/AudioTab.xaml.cs | 12 + Content.Client/TTS/TTSSystem.cs | 173 ++ .../Tests/Preferences/ServerDbSqliteTests.cs | 1 + .../Postgres/20260423184735_TTS.Designer.cs | 2305 +++++++++++++++++ .../Migrations/Postgres/20260423184735_TTS.cs | 40 + .../PostgresServerDbContextModelSnapshot.cs | 13 +- .../Sqlite/20260423184717_TTS.Designer.cs | 2219 ++++++++++++++++ .../Migrations/Sqlite/20260423184717_TTS.cs | 29 + .../SqliteServerDbContextModelSnapshot.cs | 7 +- Content.Server.Database/Model.cs | 1 + Content.Server/Chat/Systems/ChatSystem.cs | 10 +- Content.Server/Database/ServerDbBase.cs | 5 + .../Systems/HumanoidAppearanceSystem.cs | 1 + Content.Server/IoC/ServerContentIoC.cs | 2 + .../Radio/EntitySystems/RadioSystem.cs | 5 + Content.Server/Radio/RadioEvent.cs | 11 + Content.Server/TTS/TTSManager.cs | 551 ++++ Content.Server/TTS/TTSSystem.Sanitize.cs | 207 ++ Content.Server/TTS/TTSSystem.cs | 244 ++ Content.Shared/CCVar/CCVars.TTS.cs | 79 + .../Humanoid/HumanoidAppearanceComponent.cs | 11 +- .../SharedHumanoidAppearanceSystem.cs | 19 + .../Preferences/HumanoidCharacterProfile.cs | 30 +- Content.Shared/TTS/PlayTTSEvent.cs | 13 + Content.Shared/TTS/RequestPreviewTTSEvent.cs | 10 + Content.Shared/TTS/SharedVoiceMaskSystem.cs | 14 + Content.Shared/TTS/TTSComponent.cs | 13 + Content.Shared/TTS/TTSVoicePrototype.cs | 23 + Resources/Locale/en-US/tts/ui.ftl | 5 + Resources/Locale/en-US/tts/voices.ftl | 3 + Resources/Locale/uk-UA/_Pirate/tts/ui.ftl | 4 + Resources/Locale/uk-UA/_Pirate/tts/voices.ftl | 3 + .../Prototypes/Entities/Mobs/Species/base.yml | 1 + Resources/Prototypes/TTS/voices.yml | 81 + 39 files changed, 6245 insertions(+), 14 deletions(-) create mode 100644 Content.Client/Lobby/UI/HumanoidProfileEditor.TTS.cs create mode 100644 Content.Client/TTS/TTSSystem.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20260423184735_TTS.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20260423184735_TTS.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20260423184717_TTS.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20260423184717_TTS.cs create mode 100644 Content.Server/TTS/TTSManager.cs create mode 100644 Content.Server/TTS/TTSSystem.Sanitize.cs create mode 100644 Content.Server/TTS/TTSSystem.cs create mode 100644 Content.Shared/CCVar/CCVars.TTS.cs create mode 100644 Content.Shared/TTS/PlayTTSEvent.cs create mode 100644 Content.Shared/TTS/RequestPreviewTTSEvent.cs create mode 100644 Content.Shared/TTS/SharedVoiceMaskSystem.cs create mode 100644 Content.Shared/TTS/TTSComponent.cs create mode 100644 Content.Shared/TTS/TTSVoicePrototype.cs create mode 100644 Resources/Locale/en-US/tts/ui.ftl create mode 100644 Resources/Locale/en-US/tts/voices.ftl create mode 100644 Resources/Locale/uk-UA/_Pirate/tts/ui.ftl create mode 100644 Resources/Locale/uk-UA/_Pirate/tts/voices.ftl create mode 100644 Resources/Prototypes/TTS/voices.yml diff --git a/Content.Client/Audio/ContentAudioSystem.cs b/Content.Client/Audio/ContentAudioSystem.cs index 3c8bbe598cb..137ac975554 100644 --- a/Content.Client/Audio/ContentAudioSystem.cs +++ b/Content.Client/Audio/ContentAudioSystem.cs @@ -30,6 +30,8 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem public const float LobbyMultiplier = 3f; public const float InterfaceMultiplier = 2f; public const float SalvageMultiplier = 1f; // Frontier + public const float TtsMultiplier = 3f; // TTS + public const float TtsRadioMultiplier = 3f; // TTS public override void Initialize() { diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.TTS.cs b/Content.Client/Lobby/UI/HumanoidProfileEditor.TTS.cs new file mode 100644 index 00000000000..ffea570461a --- /dev/null +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.TTS.cs @@ -0,0 +1,85 @@ +using System.Linq; +using Content.Client.TTS; +using Content.Shared.Preferences; +using Content.Shared.TTS; +using Robust.Shared.Random; + +namespace Content.Client.Lobby.UI; + +public sealed partial class HumanoidProfileEditor +{ + private IRobustRandom _random = default!; + private TTSSystem _ttsSys = default!; + private List _voiceList = default!; + private readonly List _sampleText = new() + { + "Hello station, I have teleported the janitor.", + "Yes, Ms. Sarah, about the theater issue -- will Engineering be dealing with it?", + "Since Samuel was detained should we change it to a code green?", + "He wants to do an interview, where are you?", + "Samuel Rodriguez broke the door to the bridge with an e-mag!", + "I want to give credit where it's due -- the newspaper is working, and it's doing quite well. I like it.", + "Praise and glory from NT.", + "Will someone build a podium in the theater?", + "Clown, I'm about to be interviewed, I'll be gone about 10 minutes.", + "Chief, I'm about to be interviewed, I'll be gone for about 10 minutes.", + "As far as I understand, the anomaly broke the barrier between the Singularity and the station.", + }; + + private void InitializeVoice() + { + _random = IoCManager.Resolve(); + _ttsSys = _entManager.System(); + _voiceList = _prototypeManager + .EnumeratePrototypes() + .Where(o => o.CanSelect) + .OrderBy(o => Loc.GetString(o.Name)) + .ToList(); + + VoiceButton.OnItemSelected += args => + { + VoiceButton.SelectId(args.Id); + SetVoice(_voiceList[args.Id].ID); + }; + + VoicePlayButton.OnPressed += _ => { PlayTTS(); }; + } + + private void UpdateTTSVoicesControls() + { + if (Profile is null) + return; + + VoiceButton.Clear(); + + var firstVoiceChoiceId = 1; + for (var i = 0; i < _voiceList.Count; i++) + { + var voice = _voiceList[i]; + if (!HumanoidCharacterProfile.CanHaveVoice(voice, Profile.Sex)) + continue; + + var name = Loc.GetString(voice.Name); + VoiceButton.AddItem(name, i); + + if (firstVoiceChoiceId == 1) + firstVoiceChoiceId = i; + + } + + var voiceChoiceId = _voiceList.FindIndex(x => x.ID == Profile.Voice); + if (!VoiceButton.TrySelectId(voiceChoiceId) && + VoiceButton.TrySelectId(firstVoiceChoiceId)) + { + SetVoice(_voiceList[firstVoiceChoiceId].ID); + } + } + + private void PlayTTS() + { + if (Profile is null) + return; + + _ttsSys.RequestPreviewTTS(Profile.Voice); + } +} diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml index ba34d5b976d..bdfe85e9859 100644 --- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml @@ -104,6 +104,13 @@ + + +