CatStation/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
āda d33e63a5a2
New Agent Id UI (#39769)
* icon group prototype

* prototype v2

* agent id uses groups

* working UI using groups

* UI work, new header

* formatting and misc work

* fix some texture scaling

* aesthetics

* tabs, scrollbar, MinSize

* commit

* commit

* commit

* commit

* Revert "commit"

This reverts commit 8f29ae30c69670c6dc8d5fba3dd6bd98f574830d.

* we're back

* well enough

* Final visuals for the Id (for now)

* code cleaning

* minor cleanup

* self review

* id card system changes

* try index -> resolve

* DisposeAllChildren -> RemoveAllChildren

* fix the id cards

* all pretty

* unneeded

* merge

* Review by Fildrance

* Review by Pok

* fix

* cleanup

* refactor: revert icon setsize changes back to good old '32', made container button be resizable for localization reasons

* jobIconGroup

---------

Co-authored-by: iaada <iaada@users.noreply.github.com>
Co-authored-by: Pok245 <113675512+Pok27@users.noreply.github.com>
Co-authored-by: Fildrance <fildrance@gmail.com>
2026-07-18 19:51:36 +00:00

183 lines
6.1 KiB
C#

using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Access.Components;
using Content.Shared.CCVar;
using Content.Shared.StatusIcon;
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.Configuration;
using Robust.Shared.Prototypes;
using System.Numerics;
namespace Content.Client.Access.UI;
[GenerateTypedNameReferences]
public sealed partial class AgentIDCardWindow : FancyWindow
{
[Dependency] private IConfigurationManager _cfgManager = default!;
[Dependency] private IEntitySystemManager _entitySystem = default!;
[Dependency] private IPrototypeManager _prototypeManager = default!;
private readonly SpriteSystem _spriteSystem;
public event Action<string>? OnNameChanged;
public event Action<string>? OnJobChanged;
public event Action<ProtoId<JobIconPrototype>>? OnJobIconChanged;
public AgentIDCardWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
NameLineEdit.OnTextEntered += e => CommitName(e.Text);
NameLineEdit.OnFocusExit += e => CommitName(e.Text);
JobLineEdit.OnTextEntered += e => CommitJob(e.Text);
JobLineEdit.OnFocusExit += e => CommitJob(e.Text);
NameLineEdit.IsValid = s => s.Length <= _cfgManager.GetCVar(CCVars.MaxNameLength);
JobLineEdit.IsValid = s => s.Length <= _cfgManager.GetCVar(CCVars.MaxIdJobLength);
AgentTabs.SetTabTitle(0, Loc.GetString("agent-id-ui-tab-settings"));
AgentTabs.SetTabTitle(1, Loc.GetString("agent-id-ui-tab-job-icons"));
}
/// <summary>
/// Creates the job icons tab.
/// </summary>
public void SetAllowedIcons(IReadOnlyList<ProtoId<JobIconGroupPrototype>> jobGroups, ProtoId<JobIconPrototype> currentIcon)
{
JobGroupGrid.DisposeAllChildren();
IconGrid.DisposeAllChildren();
var jobGroupButtonGroup = new ButtonGroup();
ContainerButton? firstGroupButton = null;
IReadOnlyList<ProtoId<JobIconPrototype>>? firstGroupIcons = null;
ContainerButton? matchingGroupButton = null;
IReadOnlyList<ProtoId<JobIconPrototype>>? matchingGroupIcons = null;
foreach (var group in jobGroups)
{
if (!_prototypeManager.TryIndex(group, out var groupProto))
continue;
var groupButton = CreateGroupButton(groupProto, jobGroupButtonGroup);
groupButton.OnPressed += _ => SetJobIcons(groupProto.Icons);
JobGroupGrid.AddChild(groupButton);
firstGroupButton ??= groupButton;
firstGroupIcons ??= groupProto.Icons;
// Prefer the group that actually contains the card's current icon so
// the opened window shows the relevant set rather than always the first.
if (matchingGroupButton == null && groupProto.Icons.Contains(currentIcon))
{
matchingGroupButton = groupButton;
matchingGroupIcons = groupProto.Icons;
}
}
var selectedButton = matchingGroupButton ?? firstGroupButton;
var selectedIcons = matchingGroupIcons ?? firstGroupIcons;
if (selectedButton == null || selectedIcons == null)
return;
selectedButton.Pressed = true;
SetJobIcons(selectedIcons);
}
/// <summary>
/// Creates the job icon subgroup within the job icons tab.
/// </summary>
private void SetJobIcons(IReadOnlyList<ProtoId<JobIconPrototype>> jobIcons)
{
IconGrid.DisposeAllChildren();
foreach (var icon in jobIcons)
{
if (!_prototypeManager.TryIndex(icon, out var iconProto))
continue;
var texture = _spriteSystem.Frame0(iconProto.Icon);
// Create new button
var jobIconButton = new TextureButton
{
Access = AccessLevel.Public,
ToolTip = Loc.GetString(iconProto.JobName),
TextureNormal = texture,
SetSize = new Vector2(32, 32),
};
// Finish button and add to UI
jobIconButton.OnPressed += _ => OnJobIconChanged?.Invoke(iconProto.ID);
IconGrid.AddChild(jobIconButton);
}
}
public void Update(IdCardComponent card)
{
var name = card.FullName ?? string.Empty;
var job = card.LocalizedJobTitle ?? string.Empty;
NameLineEdit.Text = name;
CurrentName.Text = name;
JobLineEdit.Text = job;
CurrentJob.Text = job;
var jobIconProto = _prototypeManager.Index(card.JobIcon);
CurrentJobIcon.Texture = _spriteSystem.Frame0(jobIconProto.Icon);
}
private ContainerButton CreateGroupButton(JobIconGroupPrototype groupProto, ButtonGroup buttonGroup)
{
var button = new ContainerButton
{
Access = AccessLevel.Public,
Group = buttonGroup,
ToggleMode = true,
StyleClasses = { StyleClass.ButtonOpenBoth },
Margin = new Thickness(8, 2)
};
button.AddChild(new BoxContainer
{
SeparationOverride = 8,
Children =
{
new TextureRect
{
Texture = _spriteSystem.Frame0(groupProto.Sprite),
Stretch = TextureRect.StretchMode.KeepAspectCentered,
SetSize = new Vector2(32, 32),
VerticalAlignment = VAlignment.Center,
},
new Label
{
Text = Loc.GetString(groupProto.GroupName),
HorizontalExpand = true,
VerticalAlignment = VAlignment.Center,
},
},
});
return button;
}
private void CommitJob(string job)
{
OnJobChanged?.Invoke(job);
}
private void CommitName(string name)
{
OnNameChanged?.Invoke(name);
}
}