SurveillanceCameraMonitorWindow.xaml.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System.Linq;
  2. using Content.Client.Resources;
  3. using Content.Client.Viewport;
  4. using Content.Shared.DeviceNetwork;
  5. using Content.Shared.SurveillanceCamera;
  6. using Robust.Client.AutoGenerated;
  7. using Robust.Client.Graphics;
  8. using Robust.Client.ResourceManagement;
  9. using Robust.Client.UserInterface.Controls;
  10. using Robust.Client.UserInterface.CustomControls;
  11. using Robust.Client.UserInterface.XAML;
  12. using Robust.Shared.Graphics;
  13. using Robust.Shared.Prototypes;
  14. namespace Content.Client.SurveillanceCamera.UI;
  15. [GenerateTypedNameReferences]
  16. public sealed partial class SurveillanceCameraMonitorWindow : DefaultWindow
  17. {
  18. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  19. [Dependency] private readonly IResourceCache _resourceCache = default!;
  20. public event Action<string>? CameraSelected;
  21. public event Action<string>? SubnetOpened;
  22. public event Action? CameraRefresh;
  23. public event Action? SubnetRefresh;
  24. public event Action? CameraSwitchTimer;
  25. public event Action? CameraDisconnect;
  26. private string _currentAddress = string.Empty;
  27. private bool _isSwitching;
  28. private readonly FixedEye _defaultEye = new();
  29. private readonly Dictionary<string, int> _subnetMap = new();
  30. private string? SelectedSubnet
  31. {
  32. get
  33. {
  34. if (SubnetSelector.ItemCount == 0
  35. || SubnetSelector.SelectedMetadata == null)
  36. {
  37. return null;
  38. }
  39. return (string) SubnetSelector.SelectedMetadata;
  40. }
  41. }
  42. public SurveillanceCameraMonitorWindow()
  43. {
  44. RobustXamlLoader.Load(this);
  45. IoCManager.InjectDependencies(this);
  46. // This could be done better. I don't want to deal with stylesheets at the moment.
  47. var texture = _resourceCache.GetTexture("/Textures/Interface/Nano/square_black.png");
  48. var shader = _prototypeManager.Index<ShaderPrototype>("CameraStatic").Instance().Duplicate();
  49. CameraView.ViewportSize = new Vector2i(500, 500);
  50. CameraView.Eye = _defaultEye; // sure
  51. CameraViewBackground.Stretch = TextureRect.StretchMode.Scale;
  52. CameraViewBackground.Texture = texture;
  53. CameraViewBackground.ShaderOverride = shader;
  54. SubnetList.OnItemSelected += OnSubnetListSelect;
  55. SubnetSelector.OnItemSelected += args =>
  56. {
  57. // piss
  58. SubnetOpened!((string) args.Button.GetItemMetadata(args.Id)!);
  59. };
  60. SubnetRefreshButton.OnPressed += _ => SubnetRefresh!();
  61. CameraRefreshButton.OnPressed += _ => CameraRefresh!();
  62. CameraDisconnectButton.OnPressed += _ => CameraDisconnect!();
  63. }
  64. // The UI class should get the eye from the entity, and then
  65. // pass it here so that the UI can change its view.
  66. public void UpdateState(IEye? eye, HashSet<string> subnets, string activeAddress, string activeSubnet, Dictionary<string, string> cameras)
  67. {
  68. _currentAddress = activeAddress;
  69. SetCameraView(eye);
  70. if (subnets.Count == 0)
  71. {
  72. SubnetSelector.AddItem(Loc.GetString("surveillance-camera-monitor-ui-no-subnets"));
  73. SubnetSelector.Disabled = true;
  74. return;
  75. }
  76. if (SubnetSelector.Disabled && subnets.Count != 0)
  77. {
  78. SubnetSelector.Clear();
  79. SubnetSelector.Disabled = false;
  80. }
  81. // That way, we have *a* subnet selected if this is ever opened.
  82. if (string.IsNullOrEmpty(activeSubnet))
  83. {
  84. SubnetOpened!(subnets.First());
  85. return;
  86. }
  87. // if the subnet count is unequal, that means
  88. // we have to rebuild the subnet selector
  89. if (SubnetSelector.ItemCount != subnets.Count)
  90. {
  91. SubnetSelector.Clear();
  92. _subnetMap.Clear();
  93. foreach (var subnet in subnets)
  94. {
  95. var id = AddSubnet(subnet);
  96. _subnetMap.Add(subnet, id);
  97. }
  98. }
  99. if (_subnetMap.TryGetValue(activeSubnet, out var subnetId))
  100. {
  101. SubnetSelector.Select(subnetId);
  102. }
  103. PopulateCameraList(cameras);
  104. }
  105. private void PopulateCameraList(Dictionary<string, string> cameras)
  106. {
  107. SubnetList.Clear();
  108. foreach (var (address, name) in cameras)
  109. {
  110. AddCameraToList(name, address);
  111. }
  112. SubnetList.SortItemsByText();
  113. }
  114. private void SetCameraView(IEye? eye)
  115. {
  116. var eyeChanged = eye != CameraView.Eye || CameraView.Eye == null;
  117. CameraView.Eye = eye ?? _defaultEye;
  118. CameraView.Visible = !eyeChanged && !_isSwitching;
  119. CameraDisconnectButton.Disabled = eye == null;
  120. if (eye != null)
  121. {
  122. if (!eyeChanged)
  123. {
  124. return;
  125. }
  126. _isSwitching = true;
  127. CameraViewBackground.Visible = true;
  128. CameraStatus.Text = Loc.GetString("surveillance-camera-monitor-ui-status",
  129. ("status", Loc.GetString("surveillance-camera-monitor-ui-status-connecting")),
  130. ("address", _currentAddress));
  131. CameraSwitchTimer!();
  132. }
  133. else
  134. {
  135. CameraViewBackground.Visible = true;
  136. CameraStatus.Text = Loc.GetString("surveillance-camera-monitor-ui-status-disconnected");
  137. }
  138. }
  139. public void OnSwitchTimerComplete()
  140. {
  141. _isSwitching = false;
  142. CameraView.Visible = CameraView.Eye != _defaultEye;
  143. CameraViewBackground.Visible = CameraView.Eye == _defaultEye;
  144. CameraStatus.Text = Loc.GetString("surveillance-camera-monitor-ui-status",
  145. ("status", Loc.GetString("surveillance-camera-monitor-ui-status-connected")),
  146. ("address", _currentAddress));
  147. }
  148. private int AddSubnet(string subnet)
  149. {
  150. var name = subnet;
  151. if (_prototypeManager.TryIndex<DeviceFrequencyPrototype>(subnet, out var frequency))
  152. {
  153. name = Loc.GetString(frequency.Name ?? subnet);
  154. }
  155. SubnetSelector.AddItem(name);
  156. SubnetSelector.SetItemMetadata(SubnetSelector.ItemCount - 1, subnet);
  157. return SubnetSelector.ItemCount - 1;
  158. }
  159. private void AddCameraToList(string name, string address)
  160. {
  161. var item = SubnetList.AddItem($"{name}: {address}");
  162. item.Metadata = address;
  163. }
  164. private void OnSubnetListSelect(ItemList.ItemListSelectedEventArgs args)
  165. {
  166. CameraSelected!((string) SubnetList[args.ItemIndex].Metadata!);
  167. }
  168. }