Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,25 @@ public sealed class RadioDeviceSystem : SharedRadioDeviceSystem
/// <inheritdoc/>
public override void Initialize()
{
// BEGIN DeltaV - Update intercom UI on RadioMicrophone/Speaker component statechange
base.Initialize();
SubscribeLocalEvent<RadioMicrophoneComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
SubscribeLocalEvent<RadioSpeakerComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
// END DeltaV
SubscribeLocalEvent<IntercomComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
}

private void OnAfterHandleState(Entity<IntercomComponent> ent, ref AfterAutoHandleStateEvent args)
// DeltaV - Made generic. `component` unused, but required for subscriptions.
private void OnAfterHandleState<TComp>(EntityUid uid, TComp component, AfterAutoHandleStateEvent args) where TComp : IComponent
{
// BEGIN DeltaV
IntercomComponent? intercom = null;
if (!Resolve(uid, ref intercom, false))
return;

var ent = new Entity<IntercomComponent>(uid, intercom);
// END DeltaV

if (_ui.TryGetOpenUi<IntercomBoundUserInterface>(ent.Owner, IntercomUiKey.Key, out var bui))
bui.Update(ent);
}
Expand Down
15 changes: 13 additions & 2 deletions Content.Client/Radio/Ui/IntercomBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ protected override void Open()

if (EntMan.TryGetComponent(Owner, out IntercomComponent? intercom))
{
_menu.Update((Owner, intercom));
// BEGIN DeltaV - Add microphone and speaker component parameters to Update
EntMan.TryGetComponent(Owner, out RadioMicrophoneComponent? microphone);
EntMan.TryGetComponent(Owner, out RadioSpeakerComponent? speaker);
_menu.Update(Owner, intercom, microphone, speaker);
// END DeltaV
}

_menu.OnMicPressed += enabled =>
Expand All @@ -44,6 +48,13 @@ protected override void Open()

public void Update(Entity<IntercomComponent> ent)
{
_menu?.Update(ent);
// BEGIN DeltaV - Add microphone and speaker component parameters to Update
if (_menu == null)
return;

EntMan.TryGetComponent(Owner, out RadioMicrophoneComponent? microphone);
EntMan.TryGetComponent(Owner, out RadioSpeakerComponent? speaker);
_menu.Update(Owner, ent.Comp, microphone, speaker);
// END DeltaV
}
}
54 changes: 43 additions & 11 deletions Content.Client/Radio/Ui/IntercomMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System.Threading.Channels;
using System.Linq; // DeltaV - Used for `.First()` on channel sets.
// using System.Threading.Channels; // DeltaV - Unused.
using Content.Client.UserInterface.Controls;
using Content.Shared._DV.Radio.Components; // DeltaV - To use DVRadioToggleable type
using Content.Shared.Radio.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls; // DeltaV - To use Button type
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
Expand All @@ -28,31 +31,60 @@ public IntercomMenu()
SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed);
}

public void Update(Entity<IntercomComponent> entity)
/// <summary>
/// DeltaV - Sets button's state based on component's presence and enabled-status.
/// </summary>
/// <param name="button">The button which state depends on the component</param>
/// <param name="component">The component which defines the button's state</param>
private void UpdateToggleButton(Button button, DVRadioToggleable? component)
{
MicButton.Pressed = entity.Comp.MicrophoneEnabled;
SpeakerButton.Pressed = entity.Comp.SpeakerEnabled;
if (component == null)
{
button.Disabled = true;
return;
}

button.Disabled = false;
button.Pressed = component.Enabled;
}

// BEGIN DeltaV - Add microphone and speaker component parameters to Update
public void Update(EntityUid uid, IntercomComponent intercom, RadioMicrophoneComponent? microphone, RadioSpeakerComponent? speaker)
{
if (intercom.SupportedChannels.Count == 0)
{
MicButton.Disabled = true;
SpeakerButton.Disabled = true;
ChannelOptions.Disabled = true;
}
else
{
UpdateToggleButton(MicButton, microphone);
UpdateToggleButton(SpeakerButton, speaker);
}

MicButton.Disabled = entity.Comp.SupportedChannels.Count == 0;
SpeakerButton.Disabled = entity.Comp.SupportedChannels.Count == 0;
ChannelOptions.Disabled = entity.Comp.SupportedChannels.Count == 0;
var currentChannel =
microphone?.BroadcastChannel ??
speaker?.Channels.First() ??
intercom.SupportedChannels.First();
// END DeltaV

ChannelOptions.Clear();
_channels.Clear();
for (var i = 0; i < entity.Comp.SupportedChannels.Count; i++)
for (var i = 0; i < intercom.SupportedChannels.Count; i++) // DeltaV - Add microphone and speaker component parameters to Update
{
var channel = entity.Comp.SupportedChannels[i];
var channel = intercom.SupportedChannels[i]; // DeltaV - Add microphone and speaker component parameters to Update
if (!_prototype.Resolve(channel, out var prototype))
continue;

_channels.Add(channel);
ChannelOptions.AddItem(Loc.GetString(prototype.Name), i);

if (channel == entity.Comp.CurrentChannel)
if (channel == currentChannel) // DeltaV - Add microphone and speaker component parameters to Update
ChannelOptions.Select(i);
}

if (entity.Comp.SupportedChannels.Count == 0)
if (intercom.SupportedChannels.Count == 0) // DeltaV - Add microphone and speaker component parameters to Update
{
ChannelOptions.AddItem(Loc.GetString("intercom-options-none"), 0);
ChannelOptions.Select(0);
Expand Down
116 changes: 116 additions & 0 deletions Content.Client/_DV/Radio/RadioVisualsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using System.Linq;
using Content.Client.Items.Systems;
using Content.Shared._DV.Radio.Components;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Item;
using Content.Shared.Radio;
using Robust.Client.GameObjects;
namespace Content.Client._DV.Radio;

/// <summary>
/// System for displaying Broadcasting or Speaker layers on radio sprites and in hand items.
/// </summary>
public sealed class RadioVisualsSystem : EntitySystem
{
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly SharedItemSystem _item = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<DVRadioVisualsComponent, AppearanceChangeEvent>(OnAppearanceChange);
SubscribeLocalEvent<DVRadioVisualsComponent, GetInhandVisualsEvent>(OnGetHeldVisuals, after: [typeof(ItemSystem)]);
}

#region Sprite
/// <summary>
/// Handler for <see cref="AppearanceChangeEvent"/>.
/// </summary>
private void OnAppearanceChange(Entity<DVRadioVisualsComponent> entity,
ref AppearanceChangeEvent args)
{
OnComponentAppearanceChange(entity, args, RadioDeviceVisuals.Broadcasting, entity.Comp.MicrophoneSpriteLayer);
OnComponentAppearanceChange(entity, args, RadioDeviceVisuals.Speaker, entity.Comp.SpeakerSpriteLayer);

// update clothing & in-hand visuals.
_item.VisualsChanged(entity);
}

/// <summary>
/// Sets visibility of a sprite layer based on data in <see cref="AppearanceComponent"/>.
/// </summary>
/// <param name="entity">The radio entity.</param>
/// <param name="args"></param>
/// <param name="visualsKey">Enum key from Appearance. Its value determines the layer's visibility.</param>
/// <param name="spriteLayerKey">Key of the <see cref="SpriteComponent"/>'s layer, visibility of which will be toggled.</param>
private void OnComponentAppearanceChange(Entity<DVRadioVisualsComponent> entity,
AppearanceChangeEvent args,
RadioDeviceVisuals visualsKey,
string? spriteLayerKey)
{
if (args.Sprite == null || spriteLayerKey == null)
return;

if(!_sprite.LayerMapTryGet((entity, args.Sprite), spriteLayerKey, out var layerIndex, false))
return;

_appearance.TryGetData<bool>(entity, visualsKey, out var enabled, args.Component);

_sprite.LayerSetVisible((entity, args.Sprite), layerIndex, enabled);
}
#endregion

#region Held
/// <summary>
/// Handler for <see cref="GetInhandVisualsEvent"/>.
/// </summary>
private void OnGetHeldVisuals(Entity<DVRadioVisualsComponent> entity, ref GetInhandVisualsEvent args)
{
if (!TryComp(entity, out AppearanceComponent? appearance))
return;

OnGetComponentHeldVisuals(entity, appearance, args, RadioDeviceVisuals.Broadcasting, entity.Comp.MicrophoneInhandVisuals);
OnGetComponentHeldVisuals(entity, appearance, args, RadioDeviceVisuals.Speaker, entity.Comp.SpeakerInhandVisuals);
}

/// <summary>
/// Adds inhand layers based on data in <see cref="AppearanceComponent"/>.
/// </summary>
/// <param name="uid">The radio entity.</param>
/// <param name="appearance"></param>
/// <param name="args"></param>
/// <param name="visualsKey">Enum key from Appearance. Its value determines if the layers will be added.</param>
/// <param name="locationLayerMap">Map of hand->layers that will be added.</param>
private void OnGetComponentHeldVisuals(
EntityUid uid,
AppearanceComponent appearance,
GetInhandVisualsEvent args,
RadioDeviceVisuals visualsKey,
Dictionary<HandLocation, List<PrototypeLayerData>> locationLayerMap)
{
if(!_appearance.TryGetData<bool>(uid, visualsKey, out var enabled, appearance) ||
!enabled)
return;

if (!locationLayerMap.TryGetValue(args.Location, out var layers))
return;

var handName = args.Location.ToString();
var visualLayerName = Enum.GetName(typeof(RadioDeviceVisuals), visualsKey) ?? visualsKey.ToString();
var defaultKey = $"radio-{visualLayerName}-inhand-{handName}".ToLowerInvariant();
foreach (var (i, layer) in layers.Index())
{
var key = layer.MapKeys?.FirstOrDefault();
if (key == null)
{
key = i == 0 ? defaultKey : $"{defaultKey}-{i}";
}

args.Layers.Add((key, layer));
}
}
#endregion
}
Loading
Loading