Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Supermatter Updates From Impstation #1719

Merged
merged 9 commits into from
Feb 17, 2025
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Content.Shared._EE.Supermatter.Components;

namespace Content.Client._EE.Supermatter.Consoles;

public sealed class SupermatterConsoleBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private SupermatterConsoleWindow? _menu;

public SupermatterConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { }

protected override void Open()
{
_menu = new SupermatterConsoleWindow(this, Owner);
_menu.OpenCentered();
_menu.OnClose += Close;
}

protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);

var castState = (SupermatterConsoleBoundInterfaceState)state;
_menu?.UpdateUI(castState.Supermatters, castState.FocusData);
}

public void SendFocusChangeMessage(NetEntity? netEntity)
{
SendMessage(new SupermatterConsoleFocusChangeMessage(netEntity));
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;

_menu?.Dispose();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.Pinpointer.UI"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'supermatter-console-window-title'}"
Resizable="True"
SetSize="700 400"
MinSize="700 400">
<BoxContainer Orientation="Vertical">
<!-- Main display -->
<BoxContainer Orientation="Horizontal" VerticalExpand="True" HorizontalExpand="True">
<!-- Supermatter list -->
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" Margin="10 0 10 10">
<!-- Supermatters (entries added by C# code) -->
<BoxContainer VerticalExpand="True" HorizontalExpand="True" Margin="0 10 0 0">
<ScrollContainer HorizontalExpand="True">
<BoxContainer Name="SupermattersTable" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" Margin="0 0 0 10" />
</ScrollContainer>
</BoxContainer>
</BoxContainer>
</BoxContainer>

<!-- Footer -->
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'supermatter-console-window-flavor-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'supermatter-console-window-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared._EE.Supermatter.Components;
using Content.Shared._EE.Supermatter.Monitor;
using Content.Shared.Pinpointer;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace Content.Client._EE.Supermatter.Consoles;

[GenerateTypedNameReferences]
public sealed partial class SupermatterConsoleWindow : FancyWindow
{
private readonly IEntityManager _entManager;
private readonly SpriteSystem _spriteSystem;
private readonly SharedNavMapSystem _navMapSystem;

private EntityUid? _owner;
private NetEntity? _trackedEntity;

private SupermatterConsoleEntry[]? _supermatters = null;
private IEnumerable<SupermatterConsoleEntry>? _activeAlerts = null;

public event Action<NetEntity?>? SendFocusChangeMessageAction;

private bool _autoScrollActive = false;
private bool _autoScrollAwaitsUpdate = false;

// Colors
private Color _wallColor = new Color(64, 64, 64);
private Color _tileColor = new Color(28, 28, 28);
private Color _monitorBlipColor = Color.Cyan;
private Color _untrackedEntColor = Color.DimGray;
private Color _regionBaseColor = new Color(154, 154, 154);
private Color _inactiveColor = StyleNano.DisabledFore;
private Color _statusTextColor = StyleNano.GoodGreenFore;
private Color _goodColor = Color.LimeGreen;
private Color _warningColor = new Color(255, 182, 72);
private Color _dangerColor = new Color(255, 67, 67);

public SupermatterConsoleWindow(SupermatterConsoleBoundUserInterface userInterface, EntityUid? owner)
{
RobustXamlLoader.Load(this);
_entManager = IoCManager.Resolve<IEntityManager>();
_spriteSystem = _entManager.System<SpriteSystem>();
_navMapSystem = _entManager.System<SharedNavMapSystem>();

// Pass the owner to nav map
_owner = owner;

// Set supermatter monitoring message action
SendFocusChangeMessageAction += userInterface.SendFocusChangeMessage;
}

public void UpdateUI(SupermatterConsoleEntry[] supermatters, SupermatterFocusData? focusData)
{
if (_owner == null)
return;

if (!_entManager.TryGetComponent<SupermatterConsoleComponent>(_owner.Value, out var console))
return;

if (_trackedEntity != focusData?.NetEntity)
{
SendFocusChangeMessageAction?.Invoke(_trackedEntity);
focusData = null;
}

// Retain supermatter data for use inbetween updates
_supermatters = supermatters;

// Clear excess children from the tables
var supermattersCount = _supermatters.Count();

while (SupermattersTable.ChildCount > supermattersCount)
SupermattersTable.RemoveChild(SupermattersTable.GetChild(SupermattersTable.ChildCount - 1));

// Update all entries in each table
for (int index = 0; index < _supermatters.Count(); index++)
{
var entry = _supermatters.ElementAt(index);
UpdateUIEntry(entry, index, SupermattersTable, console, focusData);
}

// If no alerts are active, display a message
if (supermattersCount == 0)
{
var label = new RichTextLabel()
{
HorizontalExpand = true,
VerticalExpand = true,
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
};

label.SetMarkup(Loc.GetString("supermatter-console-window-no-supermatters"));

SupermattersTable.AddChild(label);
}

// Auto-scroll re-enable
if (_autoScrollAwaitsUpdate)
{
_autoScrollActive = true;
_autoScrollAwaitsUpdate = false;
}
}

private void UpdateUIEntry(SupermatterConsoleEntry entry, int index, Control table, SupermatterConsoleComponent console, SupermatterFocusData? focusData = null)
{
// Make new UI entry if required
if (index >= table.ChildCount)
{
var newEntryContainer = new SupermatterEntryContainer(entry.NetEntity);

// On click
newEntryContainer.FocusButton.OnButtonUp += args =>
{
if (_trackedEntity == newEntryContainer.NetEntity)
{
_trackedEntity = null;
}

else
{
_trackedEntity = newEntryContainer.NetEntity;
}

// Send message to console that the focus has changed
SendFocusChangeMessageAction?.Invoke(_trackedEntity);
};

// Add the entry to the current table
table.AddChild(newEntryContainer);
}

// Update values and UI elements
var tableChild = table.GetChild(index);

if (tableChild is not SupermatterEntryContainer)
{
table.RemoveChild(tableChild);
UpdateUIEntry(entry, index, table, console, focusData);

return;
}

var entryContainer = (SupermatterEntryContainer)tableChild;

entryContainer.UpdateEntry(entry, entry.NetEntity == _trackedEntity, focusData);
}

protected override void FrameUpdate(FrameEventArgs args)
{
AutoScrollToFocus();
}

private void ActivateAutoScrollToFocus()
{
_autoScrollActive = false;
_autoScrollAwaitsUpdate = true;
}

private void AutoScrollToFocus()
{
if (!_autoScrollActive)
return;

var scroll = SupermattersTable.Parent as ScrollContainer;
if (scroll == null)
return;

if (!TryGetVerticalScrollbar(scroll, out var vScrollbar))
return;

if (!TryGetNextScrollPosition(out float? nextScrollPosition))
return;

vScrollbar.ValueTarget = nextScrollPosition.Value;

if (MathHelper.CloseToPercent(vScrollbar.Value, vScrollbar.ValueTarget))
_autoScrollActive = false;
}

private bool TryGetVerticalScrollbar(ScrollContainer scroll, [NotNullWhen(true)] out VScrollBar? vScrollBar)
{
vScrollBar = null;

foreach (var child in scroll.Children)
{
if (child is not VScrollBar)
continue;

var castChild = child as VScrollBar;

if (castChild != null)
{
vScrollBar = castChild;
return true;
}
}

return false;
}

private bool TryGetNextScrollPosition([NotNullWhen(true)] out float? nextScrollPosition)
{
nextScrollPosition = null;

var scroll = SupermattersTable.Parent as ScrollContainer;
if (scroll == null)
return false;

var container = scroll.Children.ElementAt(0) as BoxContainer;
if (container == null || container.Children.Count() == 0)
return false;

// Exit if the heights of the children haven't been initialized yet
if (!container.Children.Any(x => x.Height > 0))
return false;

nextScrollPosition = 0;

foreach (var control in container.Children)
{
if (control == null || control is not SupermatterEntryContainer)
continue;

if (((SupermatterEntryContainer)control).NetEntity == _trackedEntity)
return true;

nextScrollPosition += control.Height;
}

// Failed to find control
nextScrollPosition = null;

return false;
}

private SupermatterStatusType GetStatus(NetEntity netEntity)
{
var status = _supermatters?.FirstOrNull(x => x.NetEntity == netEntity)?.EntityStatus;

if (status == null)
return SupermatterStatusType.Error;

return status.Value;
}
}
Loading
Loading