Skip to content

Commit e710d6a

Browse files
Augment audio system with the ability to have captions
1 parent 3f73593 commit e710d6a

File tree

6 files changed

+115
-0
lines changed

6 files changed

+115
-0
lines changed

Robust.Client/Audio/AudioSystem.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public sealed partial class AudioSystem : SharedAudioSystem
4343
[Dependency] private readonly SharedMapSystem _maps = default!;
4444
[Dependency] private readonly SharedTransformSystem _xformSys = default!;
4545
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
46+
[Dependency] private readonly IEntityManager _entityManager = default!;
47+
48+
public event Action<CaptionComponent>? OnSubtitledAudioStart;
49+
public event Action<CaptionComponent>? OnSubtitledAudioEnd;
4650

4751
/// <summary>
4852
/// Per-tick cache of relevant streams.
@@ -172,17 +176,23 @@ public void SetMasterVolume(float value)
172176

173177
private void OnAudioPaused(EntityUid uid, AudioComponent component, ref EntityPausedEvent args)
174178
{
179+
if (_entityManager.TryGetComponent(uid, out CaptionComponent? caption))
180+
OnSubtitledAudioEnd?.Invoke(caption);
175181
component.Pause();
176182
}
177183

178184
protected override void OnAudioUnpaused(EntityUid uid, AudioComponent component, ref EntityUnpausedEvent args)
179185
{
186+
if (_entityManager.TryGetComponent(uid, out CaptionComponent? caption))
187+
OnSubtitledAudioStart?.Invoke(caption);
180188
base.OnAudioUnpaused(uid, component, ref args);
181189
component.StartPlaying();
182190
}
183191

184192
private void OnAudioStartup(EntityUid uid, AudioComponent component, ComponentStartup args)
185193
{
194+
if (_entityManager.TryGetComponent(uid, out CaptionComponent? caption))
195+
OnSubtitledAudioStart?.Invoke(caption);
186196
if (!Timing.ApplyingState && !Timing.IsFirstTimePredicted)
187197
{
188198
return;
@@ -247,6 +257,8 @@ private void OnAudioShutdown(EntityUid uid, AudioComponent component, ComponentS
247257
component.Source.Dispose();
248258

249259
RemoveAudioLimit(component.FileName);
260+
if (_entityManager.TryGetComponent(uid, out CaptionComponent? caption))
261+
OnSubtitledAudioEnd?.Invoke(caption);
250262
}
251263

252264
private void OnAudioAttenuation(int obj)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Numerics;
2+
using Robust.Client.GameObjects;
3+
using Robust.Shared.ComponentTrees;
4+
using Robust.Shared.GameObjects;
5+
using Robust.Shared.Maths;
6+
using Robust.Shared.Physics;
7+
using Robust.Shared.Audio.Components;
8+
using Robust.Shared.IoC;
9+
10+
namespace Robust.Client.ComponentTrees;
11+
12+
public sealed class CaptionTreeSystem : ComponentTreeSystem<CaptionTreeComponent, CaptionComponent>
13+
{
14+
[Dependency] private readonly IEntityManager _entityManager = default!;
15+
16+
#region Component Tree Overrides
17+
protected override bool DoFrameUpdate => false;
18+
protected override bool DoTickUpdate => true;
19+
protected override bool Recursive => true;
20+
protected override int InitialCapacity => 128;
21+
22+
protected override Box2 ExtractAabb(in ComponentTreeEntry<CaptionComponent> entry, Vector2 pos, Angle rot)
23+
{
24+
if (_entityManager.TryGetComponent(entry.Uid, out AudioComponent? audio))
25+
{
26+
var radius = audio.MaxDistance;
27+
var radiusVec = new Vector2(radius, radius);
28+
return new Box2(pos - radiusVec, pos + radiusVec);
29+
}
30+
return default;
31+
}
32+
33+
protected override Box2 ExtractAabb(in ComponentTreeEntry<CaptionComponent> entry)
34+
{
35+
if (entry.Component.TreeUid == null)
36+
return default;
37+
38+
var pos = XformSystem.GetRelativePosition(
39+
entry.Transform,
40+
entry.Component.TreeUid.Value,
41+
GetEntityQuery<TransformComponent>());
42+
43+
return ExtractAabb(in entry, pos, default);
44+
}
45+
#endregion
46+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Robust.Shared.GameObjects;
2+
using Robust.Shared.Localization;
3+
using Robust.Shared.ViewVariables;
4+
using Robust.Shared.Physics;
5+
using Robust.Shared.ComponentTrees;
6+
using Robust.Shared.Serialization.Manager.Attributes;
7+
using Robust.Shared.GameStates;
8+
9+
namespace Robust.Shared.Audio.Components;
10+
11+
/// <summary>
12+
/// Stores the caption data for an audio entity.
13+
/// </summary>
14+
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
15+
public sealed partial class CaptionComponent : Component, IComponentTreeEntry<CaptionComponent>
16+
{
17+
[DataField, AutoNetworkedField]
18+
public LocId? Caption { get; set; }
19+
20+
[ViewVariables(VVAccess.ReadOnly)]
21+
public string? LocalizedCaption => Caption != null ? Loc.GetString(Caption) : null;
22+
23+
public EntityUid? TreeUid { get; set; }
24+
25+
public DynamicTree<ComponentTreeEntry<CaptionComponent>>? Tree { get; set; }
26+
27+
public bool AddToTree => true;
28+
29+
public bool TreeUpdateQueued { get; set; }
30+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Robust.Shared.Physics;
2+
using Robust.Shared.ComponentTrees;
3+
using Robust.Shared.GameObjects;
4+
5+
namespace Robust.Shared.Audio.Components;
6+
7+
/// <summary>
8+
/// Samples nearby <see cref="CaptionComponent"/>.
9+
/// </summary>
10+
[RegisterComponent]
11+
public sealed partial class CaptionTreeComponent : Component, IComponentTreeComponent<CaptionComponent>
12+
{
13+
public DynamicTree<ComponentTreeEntry<CaptionComponent>> Tree { get; set; } = default!;
14+
}

Robust.Shared/Audio/SoundCollectionPrototype.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Robust.Shared.Serialization.Manager.Attributes;
44
using Robust.Shared.Utility;
55
using Robust.Shared.ViewVariables;
6+
using Robust.Shared.Localization;
67

78
namespace Robust.Shared.Audio;
89

@@ -13,6 +14,9 @@ public sealed partial class SoundCollectionPrototype : IPrototype
1314
[IdDataField]
1415
public string ID { get; private set; } = default!;
1516

17+
[DataField]
18+
public LocId? Caption { get; private set; }
19+
1620
[DataField("files")]
1721
public List<ResPath> PickFiles { get; private set; } = new();
1822
}

Robust.Shared/Audio/Systems/SharedAudioSystem.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,15 @@ protected Entity<AudioComponent> SetupAudio(ResolvedSoundSpecifier? specifier, A
332332
comp.FileName = fileName ?? string.Empty;
333333
comp.Params = audioParams.Value;
334334
comp.AudioStart = Timing.CurTime;
335+
if (specifier is ResolvedCollectionSpecifier collection && collection.Collection is string collectionID)
336+
{
337+
var caption = ProtoMan.Index<SoundCollectionPrototype>(collectionID).Caption;
338+
if (caption is not null)
339+
{
340+
var capt = AddComp<CaptionComponent>(uid);
341+
capt.Caption = caption;
342+
}
343+
}
335344

336345
if (!audioParams.Value.Loop)
337346
{

0 commit comments

Comments
 (0)