diff --git a/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs b/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs index f818f0595a..8b37687a24 100644 --- a/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs +++ b/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs @@ -27,7 +27,7 @@ namespace Content.Client.Medical.CrewMonitoring switch (state) { case CrewMonitoringState st: - _menu?.ShowSensors(st.Sensors, st.WorldPosition, st.WorldRotation, st.Snap, st.Precision); + _menu?.ShowSensors(st.Sensors, st.WorldPosition, st.Snap, st.Precision); break; } } diff --git a/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs b/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs index 5bc0289334..ff9c6529c2 100644 --- a/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs +++ b/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs @@ -1,11 +1,13 @@ using Content.Client.UserInterface.Controls; using Content.Shared.Medical.SuitSensor; using Robust.Client.AutoGenerated; +using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Map; +using Robust.Shared.Timing; using static Robust.Client.UserInterface.Controls.BoxContainer; namespace Content.Client.Medical.CrewMonitoring @@ -14,15 +16,18 @@ namespace Content.Client.Medical.CrewMonitoring public sealed partial class CrewMonitoringWindow : DefaultWindow { private List _rowsContent = new(); + private List<(DirectionIcon Icon, Vector2 Position)> _directionIcons = new(); + private readonly IEyeManager _eye; public static int IconSize = 16; // XAML has a `VSeparationOverride` of 20 for each row. public CrewMonitoringWindow() { RobustXamlLoader.Load(this); + _eye = IoCManager.Resolve(); } - public void ShowSensors(List stSensors, Vector2 worldPosition, Angle worldRotation, bool snap, float precision) + public void ShowSensors(List stSensors, Vector2 worldPosition, bool snap, float precision) { ClearAllSensors(); @@ -61,13 +66,13 @@ namespace Content.Client.Medical.CrewMonitoring // add users positions // format: (x, y) - var box = GetPositionBox(sensor.Coordinates, worldPosition, worldRotation, snap, precision); + var box = GetPositionBox(sensor.Coordinates, worldPosition, snap, precision); SensorsTable.AddChild(box); _rowsContent.Add(box); } } - private BoxContainer GetPositionBox(MapCoordinates? coordinates, Vector2 sensorPosition, Angle sensorRotation, bool snap, float precision) + private BoxContainer GetPositionBox(MapCoordinates? coordinates, Vector2 sensorPosition, bool snap, float precision) { var box = new BoxContainer() { Orientation = LayoutOrientation.Horizontal }; @@ -85,19 +90,30 @@ namespace Content.Client.Medical.CrewMonitoring { // todo: add locations names (kitchen, bridge, etc) var pos = (Vector2i) coordinates.Value.Position; - var relPos = coordinates.Value.Position - sensorPosition; - var dirIcon = new DirectionIcon(relPos, sensorRotation, snap, minDistance: precision) + var dirIcon = new DirectionIcon(snap, precision) { SetSize = (IconSize, IconSize), Margin = new(0, 0, 4, 0) }; box.AddChild(dirIcon); box.AddChild(new Label() { Text = pos.ToString() }); + _directionIcons.Add((dirIcon, coordinates.Value.Position - sensorPosition)); } return box; } + protected override void FrameUpdate(FrameEventArgs args) + { + // the window is separate from any specific viewport, so there is no real way to get an eye-rotation without + // using IEyeManager. Eventually this will have to be reworked for a station AI with multi-viewports. + + foreach (var (icon, pos) in _directionIcons) + { + icon.UpdateDirection(pos, -_eye.CurrentEye.Rotation); + } + } + private void ClearAllSensors() { foreach (var child in _rowsContent) diff --git a/Content.Client/UserInterface/Controls/DirectionIcon.cs b/Content.Client/UserInterface/Controls/DirectionIcon.cs index 6652cdc0e5..cdc567be3d 100644 --- a/Content.Client/UserInterface/Controls/DirectionIcon.cs +++ b/Content.Client/UserInterface/Controls/DirectionIcon.cs @@ -16,6 +16,8 @@ public sealed class DirectionIcon : TextureRect public static string StyleClassDirectionIconUnknown = "direction-icon-unknown"; // unknown direction / error private Angle? _rotation; + private bool _snap; + float _minDistance; public Angle? Rotation { @@ -33,29 +35,27 @@ public sealed class DirectionIcon : TextureRect SetOnlyStyleClass(StyleClassDirectionIconUnknown); } - public DirectionIcon(Direction direction) : this() + public DirectionIcon(bool snap = true, float minDistance = 0.1f) : this() + { + _snap = snap; + _minDistance = minDistance; + } + + public void UpdateDirection(Direction direction) { Rotation = direction.ToAngle(); } - /// - /// Creates an icon with an arrow pointing in some direction. - /// - /// The direction - /// The relative angle. This may be the players eye rotation, the grid rotation, or - /// maybe the world rotation of the entity that owns some BUI - /// If true, will snap the nearest cardinal or diagonal direction - /// If the distance is less than this, the arrow icon will be replaced by some other indicator - public DirectionIcon(Vector2 direction, Angle relativeAngle, bool snap, float minDistance = 0.1f) : this() + public void UpdateDirection(Vector2 direction, Angle relativeAngle) { - if (direction.EqualsApprox(Vector2.Zero, minDistance)) + if (direction.EqualsApprox(Vector2.Zero, _minDistance)) { SetOnlyStyleClass(StyleClassDirectionIconHere); return; } var rotation = direction.ToWorldAngle() - relativeAngle; - Rotation = snap ? rotation.GetDir().ToAngle() : rotation; + Rotation = _snap ? rotation.GetDir().ToAngle() : rotation; } protected override void Draw(DrawingHandleScreen handle) diff --git a/Content.Server/Medical/CrewMonitoring/CrewMonitoringConsoleSystem.cs b/Content.Server/Medical/CrewMonitoring/CrewMonitoringConsoleSystem.cs index 4456ba6ddb..21beee0fbf 100644 --- a/Content.Server/Medical/CrewMonitoring/CrewMonitoringConsoleSystem.cs +++ b/Content.Server/Medical/CrewMonitoring/CrewMonitoringConsoleSystem.cs @@ -3,8 +3,6 @@ using Content.Server.DeviceNetwork.Systems; using Content.Server.Medical.SuitSensors; using Content.Server.UserInterface; using Content.Shared.Medical.CrewMonitoring; -using Content.Shared.Movement.Components; -using Robust.Shared.Map; using Robust.Shared.Timing; namespace Content.Server.Medical.CrewMonitoring @@ -12,8 +10,8 @@ namespace Content.Server.Medical.CrewMonitoring public sealed class CrewMonitoringConsoleSystem : EntitySystem { [Dependency] private readonly SuitSensorSystem _sensors = default!; + [Dependency] private readonly SharedTransformSystem _xform = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly IMapManager _mapManager = default!; private const float UpdateRate = 3f; private float _updateDif; @@ -67,20 +65,10 @@ namespace Content.Server.Medical.CrewMonitoring if (ui == null) return; - // For directional arrows, we need to fetch the monitor's transform data - var xform = Transform(uid); - var (worldPos, worldRot) = xform.GetWorldPositionRotation(); - - // In general, the directions displayed depend on either the orientation of the grid, or the orientation of - // the monitor. But in the special case where the monitor IS a player (i.e., admin ghost), we base it off - // the players eye rotation. We don't know what that is for sure, but we know their last grid angle, which - // should work well enough? - if (_mapManager.TryGetGrid(xform.GridUid, out var grid)) - worldRot = grid.WorldRotation; - // update all sensors info + var worldPos = _xform.GetWorldPosition(uid); var allSensors = component.ConnectedSensors.Values.ToList(); - var uiState = new CrewMonitoringState(allSensors, worldPos, worldRot, component.Snap, component.Precision); + var uiState = new CrewMonitoringState(allSensors, worldPos, component.Snap, component.Precision); ui.SetState(uiState); } diff --git a/Content.Shared/Medical/CrewMonitoring/CrewMonitoringShared.cs b/Content.Shared/Medical/CrewMonitoring/CrewMonitoringShared.cs index d1ee5edd96..ddf943e58d 100644 --- a/Content.Shared/Medical/CrewMonitoring/CrewMonitoringShared.cs +++ b/Content.Shared/Medical/CrewMonitoring/CrewMonitoringShared.cs @@ -14,15 +14,13 @@ namespace Content.Shared.Medical.CrewMonitoring { public List Sensors; public readonly Vector2 WorldPosition; - public readonly Angle WorldRotation; public readonly bool Snap; public readonly float Precision; - public CrewMonitoringState(List sensors, Vector2 worldPosition, Angle worldRot, bool snap, float precision) + public CrewMonitoringState(List sensors, Vector2 worldPosition, bool snap, float precision) { Sensors = sensors; WorldPosition = worldPosition; - WorldRotation = worldRot; Snap = snap; Precision = precision; }