using Content.Client.Computer; using Content.Client.UserInterface; using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Components; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Map; using Robust.Shared.Utility; namespace Content.Client.Shuttles.UI; [GenerateTypedNameReferences] public sealed partial class ShuttleConsoleWindow : FancyWindow, IComputerWindow { private readonly IEntityManager _entManager; private EntityUid? _shuttleUid; /// /// Currently selected dock button for camera. /// private BaseButton? _selectedDock; /// /// Stored by grid entityid then by states /// private Dictionary> _docks = new(); public Action? ShuttleModePressed; public Action? UndockPressed; public Action? StartAutodockPressed; public Action? StopAutodockPressed; public ShuttleConsoleWindow() { RobustXamlLoader.Load(this); _entManager = IoCManager.Resolve(); OnRadarRangeChange(RadarScreen.RadarRange); RadarScreen.OnRadarRangeChanged += OnRadarRangeChange; IFFToggle.OnToggled += OnIFFTogglePressed; IFFToggle.Pressed = RadarScreen.ShowIFF; DockToggle.OnToggled += OnDockTogglePressed; DockToggle.Pressed = RadarScreen.ShowDocks; ShuttleModeDisplay.OnToggled += OnShuttleModePressed; UndockButton.OnPressed += OnUndockPressed; } private void OnRadarRangeChange(float value) { RadarRange.Text = $"{value:0}"; } private void OnShuttleModePressed(BaseButton.ButtonEventArgs obj) { ShuttleModePressed?.Invoke(obj.Button.Pressed ? ShuttleMode.Strafing : ShuttleMode.Cruise); } private void OnIFFTogglePressed(BaseButton.ButtonEventArgs args) { RadarScreen.ShowIFF ^= true; args.Button.Pressed = RadarScreen.ShowIFF; } private void OnDockTogglePressed(BaseButton.ButtonEventArgs args) { RadarScreen.ShowDocks ^= true; args.Button.Pressed = RadarScreen.ShowDocks; } private void OnUndockPressed(BaseButton.ButtonEventArgs args) { if (DockingScreen.ViewedDock == null) return; UndockPressed?.Invoke(DockingScreen.ViewedDock.Value); } public void SetMatrix(EntityCoordinates? coordinates, Angle? angle) { _shuttleUid = coordinates?.EntityId; RadarScreen.SetMatrix(coordinates, angle); } public void UpdateState(ShuttleConsoleBoundInterfaceState scc) { UpdateDocks(scc.Docks); RadarScreen.UpdateState(scc); MaxRadarRange.Text = $"{scc.MaxRange:0}"; ShuttleModeDisplay.Pressed = scc.Mode == ShuttleMode.Strafing; } #region Docking private void UpdateDocks(List docks) { // TODO: We should check for changes so any existing highlighted doesn't delete. // We also need to make up some pseudonumber as well for these. _docks.Clear(); foreach (var dock in docks) { var grid = _docks.GetOrNew(dock.Coordinates.EntityId); grid.Add(dock); } DockPorts.DisposeAllChildren(); DockingScreen.Docks = _docks; // TODO: Show Placeholder if (_shuttleUid != null && _docks.TryGetValue(_shuttleUid.Value, out var gridDocks)) { var index = 1; foreach (var state in gridDocks) { var pressed = state.Entity == DockingScreen.ViewedDock; string suffix; if (state.Connected) { suffix = Loc.GetString("shuttle-console-docked", ("index", index)); } else { suffix = $"{index}"; } var button = new Button() { Text = Loc.GetString("shuttle-console-dock-button", ("suffix", suffix)), ToggleMode = true, Pressed = pressed, }; if (pressed) { _selectedDock = button; } button.OnMouseEntered += args => OnDockMouseEntered(args, state); button.OnMouseExited += args => OnDockMouseExited(args, state); button.OnToggled += args => OnDockToggled(args, state); DockPorts.AddChild(button); index++; } } } private void OnDockMouseEntered(GUIMouseHoverEventArgs obj, DockingInterfaceState state) { RadarScreen.HighlightedDock = state.Entity; } private void OnDockMouseExited(GUIMouseHoverEventArgs obj, DockingInterfaceState state) { RadarScreen.HighlightedDock = null; } /// /// Shows a docking camera instead of radar screen. /// private void OnDockToggled(BaseButton.ButtonEventArgs obj, DockingInterfaceState state) { var ent = state.Entity; if (_selectedDock != null) { // If it got untoggled via other means then we'll stop viewing the old dock. if (DockingScreen.ViewedDock != null && DockingScreen.ViewedDock != state.Entity) { StopAutodockPressed?.Invoke(DockingScreen.ViewedDock.Value); } _selectedDock.Pressed = false; _selectedDock = null; } if (!obj.Button.Pressed) { if (DockingScreen.ViewedDock != null) { StopAutodockPressed?.Invoke(DockingScreen.ViewedDock.Value); DockingScreen.ViewedDock = null; } UndockButton.Disabled = true; DockingScreen.Visible = false; RadarScreen.Visible = true; } else { if (_shuttleUid != null) { DockingScreen.Coordinates = state.Coordinates; DockingScreen.Angle = state.Angle; } else { DockingScreen.Coordinates = null; DockingScreen.Angle = null; } UndockButton.Disabled = false; RadarScreen.Visible = false; DockingScreen.Visible = true; DockingScreen.ViewedDock = ent; StartAutodockPressed?.Invoke(ent); DockingScreen.GridEntity = _shuttleUid; _selectedDock = obj.Button; } } public override void Close() { base.Close(); if (DockingScreen.ViewedDock != null) { StopAutodockPressed?.Invoke(DockingScreen.ViewedDock.Value); } } #endregion protected override void Draw(DrawingHandleScreen handle) { base.Draw(handle); if (!_entManager.TryGetComponent(_shuttleUid, out var gridBody) || !_entManager.TryGetComponent(_shuttleUid, out var gridXform)) { return; } var (_, worldRot, worldMatrix) = gridXform.GetWorldPositionRotationMatrix(); var worldPos = worldMatrix.Transform(gridBody.LocalCenter); // Get the positive reduced angle. var displayRot = -worldRot.Reduced(); GridPosition.Text = $"{worldPos.X:0.0}, {worldPos.Y:0.0}"; GridOrientation.Text = $"{displayRot.Degrees:0.0}"; var gridVelocity = gridBody.LinearVelocity; gridVelocity = displayRot.RotateVec(gridVelocity); // Get linear velocity relative to the console entity GridLinearVelocity.Text = $"{gridVelocity.X:0.0}, {gridVelocity.Y:0.0}"; GridAngularVelocity.Text = $"{-gridBody.AngularVelocity:0.0}"; } }