Skip to content
Closed
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,12 @@
using Content.Client._EE.Supermatter.Systems;
using Content.Shared._EE.Supermatter.Components;

namespace Content.Client._EE.Supermatter.Components;

[RegisterComponent]
[Access(typeof(SupermatterVisualizerSystem))]
public sealed partial class SupermatterVisualsComponent : Component
{
[DataField("crystal", required: true)]
public Dictionary<SupermatterCrystalState, PrototypeLayerData> CrystalVisuals = default!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Content.Shared._EE.Supermatter.Components;

namespace Content.Client._EE.Supermatter.Consoles;

public sealed class SupermatterConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
[ViewVariables]
private SupermatterConsoleWindow? _menu;

protected override void Open()
{
base.Open();

_menu = new SupermatterConsoleWindow(this, Owner);
_menu.OpenCentered();
_menu.OnClose += Close;
}

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

if (_menu == null || state is not SupermatterConsoleBoundInterfaceState msg)
return;

_menu?.UpdateUI(msg.Supermatters, msg.FocusData);
}

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

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

_menu?.Parent?.RemoveChild(_menu);
}
}

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,216 @@
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.Client.UserInterface.Controls;
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;
using Content.Client._EE.Supermatter.Consoles;

namespace Content.Client._EE.Supermatter.Consoles;

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

private readonly EntityUid? _owner;
private NetEntity? _trackedEntity;
private SupermatterConsoleEntry[]? _supermatters = null;

public event Action<NetEntity?>? SendFocusChangeMessageAction;

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

public SupermatterConsoleWindow(SupermatterConsoleBoundUserInterface userInterface, EntityUid? owner)
{
RobustXamlLoader.Load(this);
_entManager = IoCManager.Resolve<IEntityManager>();
_owner = owner;

// Set the tracked supermatter for persistence
if (_entManager.TryGetComponent<SupermatterConsoleComponent>(_owner, out var console))
_trackedEntity = console.FocusSupermatter;

// 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.Length;

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

// Update all entries in each table
for (var index = 0; index < _supermatters.Length; 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 AutoScrollToFocus()
{
if (!_autoScrollActive)
return;

if (SupermattersTable.Parent is not ScrollContainer scroll)
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 static bool TryGetVerticalScrollbar(ScrollContainer scroll, [NotNullWhen(true)] out VScrollBar? vScrollBar)
{
vScrollBar = null;

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

vScrollBar = castChild;
return true;
}

return false;
}

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

if (SupermattersTable.Parent is not ScrollContainer scroll)
return false;

if (scroll.Children.ElementAt(0) is not BoxContainer container ||
!container.Children.Any())
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;
}
}
Loading
Loading