fix: теперь в лобби можно прослушать голос
This commit is contained in:
@@ -126,8 +126,8 @@
|
|||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<Label Text="{Loc 'humanoid-profile-editor-species-label'}" />
|
<Label Text="{Loc 'humanoid-profile-editor-species-label'}" />
|
||||||
<Control HorizontalExpand="True"/>
|
<Control HorizontalExpand="True"/>
|
||||||
<TextureButton Name="SpeciesInfoButton" Scale="0.3 0.3" VerticalAlignment="Center"></TextureButton>
|
|
||||||
<OptionButton Name="CSpeciesButton" />
|
<OptionButton Name="CSpeciesButton" />
|
||||||
|
<TextureButton Name="SpeciesInfoButton" Scale="0.5 0.5" VerticalAlignment="Center"></TextureButton>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</prefUi:HighlightedContainer>
|
</prefUi:HighlightedContainer>
|
||||||
<!-- Show clothing -->
|
<!-- Show clothing -->
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
private Button _nameRandomButton => CNameRandomize;
|
private Button _nameRandomButton => CNameRandomize;
|
||||||
private Button _nameClownRandomButton => CClownNameRandomize;
|
private Button _nameClownRandomButton => CClownNameRandomize;
|
||||||
private Button _nameMimeRandomButton => CMimeNameRandomize;
|
private Button _nameMimeRandomButton => CMimeNameRandomize;
|
||||||
private Button _nameBorgRandomButton => CBorgNameRandomize;
|
private Button _nameBorgRandomButton => CBorgNameRandomize;
|
||||||
private Button _randomizeEverythingButton => CRandomizeEverything;
|
private Button _randomizeEverythingButton => CRandomizeEverything;
|
||||||
private RichTextLabel _warningLabel => CWarningLabel;
|
private RichTextLabel _warningLabel => CWarningLabel;
|
||||||
private Button _saveButton => CSaveButton;
|
private Button _saveButton => CSaveButton;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ using Content.Shared.Preferences;
|
|||||||
using Content.Shared._White.TTS;
|
using Content.Shared._White.TTS;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
namespace Content.Client.Preferences.UI;
|
namespace Content.Client.Preferences.UI;
|
||||||
|
|
||||||
public sealed partial class HumanoidProfileEditor
|
public sealed partial class HumanoidProfileEditor
|
||||||
@@ -12,6 +14,7 @@ public sealed partial class HumanoidProfileEditor
|
|||||||
private TTSManager _ttsMgr = default!;
|
private TTSManager _ttsMgr = default!;
|
||||||
private TTSSystem _ttsSys = default!;
|
private TTSSystem _ttsSys = default!;
|
||||||
private List<TTSVoicePrototype> _voiceList = default!;
|
private List<TTSVoicePrototype> _voiceList = default!;
|
||||||
|
|
||||||
private readonly List<string> _sampleText = new()
|
private readonly List<string> _sampleText = new()
|
||||||
{
|
{
|
||||||
"Помогите, клоун насилует в технических тоннелях!",
|
"Помогите, клоун насилует в технических тоннелях!",
|
||||||
@@ -35,7 +38,6 @@ public sealed partial class HumanoidProfileEditor
|
|||||||
};
|
};
|
||||||
|
|
||||||
_voicePlayButton.OnPressed += _ => { PlayTTS(); };
|
_voicePlayButton.OnPressed += _ => { PlayTTS(); };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTTSVoicesControls()
|
private void UpdateTTSVoicesControls()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace Content.Client._White.TTS;
|
|||||||
public sealed class TTSManager
|
public sealed class TTSManager
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
||||||
|
[Dependency] private readonly EntityManager _entityManager = default!;
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
@@ -16,7 +17,8 @@ public sealed class TTSManager
|
|||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public void RequestTTS(EntityUid uid, string text, string voiceId)
|
public void RequestTTS(EntityUid uid, string text, string voiceId)
|
||||||
{
|
{
|
||||||
var msg = new MsgRequestTTS() { Text = text, Uid = uid, VoiceId = voiceId };
|
var netEntity = _entityManager.GetNetEntity(uid);
|
||||||
|
var msg = new MsgRequestTTS() { Text = text, Uid = netEntity, VoiceId = voiceId };
|
||||||
_netMgr.ClientSendMessage(msg);
|
_netMgr.ClientSendMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ using Content.Shared.Physics;
|
|||||||
using Content.Shared._White;
|
using Content.Shared._White;
|
||||||
using Content.Shared._White.TTS;
|
using Content.Shared._White.TTS;
|
||||||
using Robust.Client.Audio;
|
using Robust.Client.Audio;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Shared.Audio.Sources;
|
using Robust.Shared.Audio.Sources;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -25,16 +26,16 @@ public sealed class TTSSystem : EntitySystem
|
|||||||
[Dependency] private readonly IEyeManager _eye = default!;
|
[Dependency] private readonly IEyeManager _eye = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _broadPhase = default!;
|
[Dependency] private readonly SharedPhysicsSystem _broadPhase = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transform = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private float _volume;
|
||||||
private float _volume = 0.0f;
|
private const int TTSCollisionMask = (int)CollisionGroup.Impassable;
|
||||||
|
|
||||||
private readonly HashSet<AudioStream> _currentStreams = new();
|
private readonly HashSet<AudioStream> _currentStreams = new();
|
||||||
private readonly Dictionary<EntityUid, Queue<AudioStream>> _entityQueues = new();
|
private readonly Dictionary<EntityUid, Queue<AudioStream>> _entityQueues = new();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
_sawmill = Logger.GetSawmill("tts");
|
|
||||||
_cfg.OnValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged, true);
|
_cfg.OnValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged, true);
|
||||||
SubscribeNetworkEvent<PlayTTSEvent>(OnPlayTTS);
|
SubscribeNetworkEvent<PlayTTSEvent>(OnPlayTTS);
|
||||||
}
|
}
|
||||||
@@ -64,26 +65,27 @@ public sealed class TTSSystem : EntitySystem
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapPos = xform.MapPosition;
|
var mapPos = _transform.GetMapCoordinates(xform);
|
||||||
if (mapPos.MapId != MapId.Nullspace)
|
if (mapPos.MapId != MapId.Nullspace)
|
||||||
{
|
{
|
||||||
stream.Source.Position = mapPos.Position;
|
stream.Source.Position = mapPos.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapPos.MapId == _eye.CurrentMap)
|
if (mapPos.MapId != _eye.CurrentMap)
|
||||||
{
|
{
|
||||||
var collisionMask = (int) CollisionGroup.Impassable;
|
continue;
|
||||||
var sourceRelative = ourPos - mapPos.Position;
|
|
||||||
var occlusion = 0f;
|
|
||||||
if (sourceRelative.Length() > 0)
|
|
||||||
{
|
|
||||||
occlusion = _broadPhase.IntersectRayPenetration(mapPos.MapId,
|
|
||||||
new CollisionRay(mapPos.Position, sourceRelative.Normalized(), collisionMask),
|
|
||||||
sourceRelative.Length(), stream.Uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.Source.Occlusion = occlusion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sourceRelative = ourPos - mapPos.Position;
|
||||||
|
var occlusion = 0f;
|
||||||
|
if (sourceRelative.Length() > 0)
|
||||||
|
{
|
||||||
|
occlusion = _broadPhase.IntersectRayPenetration(mapPos.MapId,
|
||||||
|
new CollisionRay(mapPos.Position, sourceRelative.Normalized(), TTSCollisionMask),
|
||||||
|
sourceRelative.Length(), stream.Uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Source.Occlusion = occlusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var audioStream in streamToRemove)
|
foreach (var audioStream in streamToRemove)
|
||||||
@@ -178,7 +180,7 @@ public sealed class TTSSystem : EntitySystem
|
|||||||
if (!_entity.TryGetComponent<TransformComponent>(stream.Uid, out var xform))
|
if (!_entity.TryGetComponent<TransformComponent>(stream.Uid, out var xform))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stream.Source.Position = xform.WorldPosition;
|
stream.Source.Position = _transform.GetWorldPosition(xform);
|
||||||
stream.Source.StartPlaying();
|
stream.Source.StartPlaying();
|
||||||
_currentStreams.Add(stream);
|
_currentStreams.Add(stream);
|
||||||
}
|
}
|
||||||
@@ -204,16 +206,10 @@ public sealed class TTSSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
private sealed class AudioStream
|
private sealed class AudioStream(EntityUid uid, IAudioSource source)
|
||||||
{
|
{
|
||||||
public EntityUid Uid { get; }
|
public EntityUid Uid { get; } = uid;
|
||||||
|
|
||||||
public IAudioSource Source { get; }
|
public IAudioSource Source { get; } = source;
|
||||||
|
|
||||||
public AudioStream(EntityUid uid, IAudioSource source)
|
|
||||||
{
|
|
||||||
Uid = uid;
|
|
||||||
Source = source;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ public sealed partial class TTSSystem : EntitySystem
|
|||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
|
|
||||||
private const int MaxMessageChars = 100 * 2; // same as SingleBubbleCharLimit * 2
|
private const int MaxMessageChars = 100 * 2; // same as SingleBubbleCharLimit * 2
|
||||||
private bool _isEnabled = false;
|
private bool _isEnabled;
|
||||||
private string _apiUrl = string.Empty;
|
private string _apiUrl = string.Empty;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -122,9 +122,12 @@ public sealed partial class TTSSystem : EntitySystem
|
|||||||
!_prototypeManager.TryIndex(ev.VoiceId, out var protoVoice))
|
!_prototypeManager.TryIndex(ev.VoiceId, out var protoVoice))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var soundData = await GenerateTTS(ev.Uid, ev.Text, protoVoice.Speaker);
|
var soundData = await GenerateTTS(GetEntity(ev.Uid), ev.Text, protoVoice.Speaker);
|
||||||
if (soundData != null)
|
if (soundData != null)
|
||||||
RaiseNetworkEvent(new PlayTTSEvent(GetNetEntity(ev.Uid), soundData, false), Filter.SinglePlayer(session), false);
|
{
|
||||||
|
RaiseNetworkEvent(new PlayTTSEvent(ev.Uid, soundData, false), Filter.SinglePlayer(session),
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnEntitySpoke(EntityUid uid, SharedTTSComponent component, EntitySpokeEvent args)
|
private async void OnEntitySpoke(EntityUid uid, SharedTTSComponent component, EntitySpokeEvent args)
|
||||||
@@ -189,16 +192,9 @@ public sealed partial class TTSSystem : EntitySystem
|
|||||||
if (distance > (ChatSystem.VoiceRange * ChatSystem.VoiceRange))
|
if (distance > (ChatSystem.VoiceRange * ChatSystem.VoiceRange))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
EntityEventArgs actualEvent;
|
EntityEventArgs actualEvent = distance > ChatSystem.WhisperClearRange
|
||||||
|
? obfTtsEvent
|
||||||
if (distance > ChatSystem.WhisperClearRange)
|
: ttsEvent;
|
||||||
{
|
|
||||||
actualEvent = obfTtsEvent;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
actualEvent = ttsEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
RaiseNetworkEvent(actualEvent, Filter.SinglePlayer(session), false);
|
RaiseNetworkEvent(actualEvent, Filter.SinglePlayer(session), false);
|
||||||
}
|
}
|
||||||
@@ -209,7 +205,9 @@ public sealed partial class TTSSystem : EntitySystem
|
|||||||
_ttsManager.ResetCache();
|
_ttsManager.ResetCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<byte[]?> GenerateTTS(EntityUid? uid, string text, string speaker, string? speechPitch = null, string? speechRate = null, string? effect = null)
|
// ReSharper disable once InconsistentNaming
|
||||||
|
private async Task<byte[]?> GenerateTTS(EntityUid? uid, string text, string speaker, string? speechPitch = null,
|
||||||
|
string? speechRate = null, string? effect = null)
|
||||||
{
|
{
|
||||||
var textSanitized = Sanitize(text);
|
var textSanitized = Sanitize(text);
|
||||||
if (textSanitized == "")
|
if (textSanitized == "")
|
||||||
@@ -240,14 +238,8 @@ public sealed partial class TTSSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class TransformSpeakerVoiceEvent : EntityEventArgs
|
public sealed class TransformSpeakerVoiceEvent(EntityUid sender, string voiceId) : EntityEventArgs
|
||||||
{
|
{
|
||||||
public EntityUid Sender;
|
public EntityUid Sender = sender;
|
||||||
public string VoiceId;
|
public string VoiceId = voiceId;
|
||||||
|
|
||||||
public TransformSpeakerVoiceEvent(EntityUid sender, string voiceId)
|
|
||||||
{
|
|
||||||
Sender = sender;
|
|
||||||
VoiceId = voiceId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,13 @@ public sealed class MsgRequestTTS : NetMessage
|
|||||||
{
|
{
|
||||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||||
|
|
||||||
public EntityUid Uid { get; set; } = EntityUid.Invalid;
|
public NetEntity Uid { get; set; } = NetEntity.Invalid;
|
||||||
public string Text { get; set; } = string.Empty;
|
public string Text { get; set; } = string.Empty;
|
||||||
public ProtoId<TTSVoicePrototype> VoiceId { get; set; } = string.Empty;
|
public ProtoId<TTSVoicePrototype> VoiceId { get; set; } = string.Empty;
|
||||||
|
|
||||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||||
{
|
{
|
||||||
Uid = new EntityUid(buffer.ReadInt32());
|
Uid = new NetEntity(buffer.ReadInt32());
|
||||||
Text = buffer.ReadString();
|
Text = buffer.ReadString();
|
||||||
VoiceId = buffer.ReadString();
|
VoiceId = buffer.ReadString();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user