diff --git a/Content.Client/Silicons/Borgs/BorgVoiceBoundUserInterface.cs b/Content.Client/Silicons/Borgs/BorgVoiceBoundUserInterface.cs new file mode 100644 index 0000000000..00242099c5 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgVoiceBoundUserInterface.cs @@ -0,0 +1,53 @@ +using Content.Client._Sunrise.TTS; +using Content.Shared._Sunrise.TTS; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface; + +namespace Content.Client.Silicons.Borgs; + +public sealed class BorgVoiceBoundUserInterface : BoundUserInterface +{ + private BorgVoiceWindow? _window; + + public BorgVoiceBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + IoCManager.InjectDependencies(this); + } + + protected override void Open() + { + base.Open(); + + _window = this.CreateWindow(); + _window.OnVoiceSelected += OnVoiceSelected; + _window.OnVoicePreview += OnVoicePreview; + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not BorgVoiceChangeState borgState || _window == null) + return; + + _window.UpdateState(borgState); + } + + private void OnVoiceSelected(string voiceId) + { + SendMessage(new BorgVoiceChangeMessage(voiceId)); + } + + private void OnVoicePreview(string voiceId) + { + EntMan.System().RequestPreviewTts(voiceId); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _window?.Dispose(); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgVoiceWindow.cs b/Content.Client/Silicons/Borgs/BorgVoiceWindow.cs new file mode 100644 index 0000000000..bbc786d440 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgVoiceWindow.cs @@ -0,0 +1,85 @@ +using System.Linq; +using Content.Shared._Sunrise.TTS; +using Content.Shared.Humanoid; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Localization; +using Robust.Shared.Prototypes; + +namespace Content.Client.Silicons.Borgs; + +[GenerateTypedNameReferences] +public sealed partial class BorgVoiceWindow : DefaultWindow +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public event Action? OnVoiceSelected; + public event Action? OnVoicePreview; + + private readonly List _voiceList = new(); + + public BorgVoiceWindow() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + Title = Loc.GetString("borg-voice-window-title"); + + LoadVoiceList(); + SetupButtons(); + } + + private void LoadVoiceList() + { + _voiceList.Clear(); + _voiceList.AddRange(_prototypeManager + .EnumeratePrototypes() + .Where(v => v.RoundStart) + .OrderBy(v => Loc.GetString(v.Name))); + } + + private void SetupButtons() + { + VoiceOptionButton.OnItemSelected += args => + { + VoiceOptionButton.SelectId(args.Id); + var voice = _voiceList[args.Id]; + OnVoiceSelected?.Invoke(voice.ID); + }; + + VoicePlayButton.OnPressed += _ => + { + if (VoiceOptionButton.SelectedId != null) + { + var voice = _voiceList[VoiceOptionButton.SelectedId]; + OnVoicePreview?.Invoke(voice.ID); + } + }; + } + + public void UpdateState(BorgVoiceChangeState state) + { + VoiceOptionButton.Clear(); + + var selectedIndex = 0; + for (var i = 0; i < _voiceList.Count; i++) + { + var voice = _voiceList[i]; + var name = Loc.GetString(voice.Name); + + VoiceOptionButton.AddItem(name, i); + + if (voice.ID == state.CurrentVoiceId) + { + selectedIndex = i; + } + } + + if (_voiceList.Count > 0) + { + VoiceOptionButton.SelectId(selectedIndex); + } + } +} diff --git a/Content.Client/Silicons/Borgs/BorgVoiceWindow.xaml b/Content.Client/Silicons/Borgs/BorgVoiceWindow.xaml new file mode 100644 index 0000000000..3b344b14f7 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgVoiceWindow.xaml @@ -0,0 +1,23 @@ + + +