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? OnNameChanged; public event Action? OnJobChanged; public event Action>? OnJobIconChanged; public AgentIDCardWindow() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _spriteSystem = _entitySystem.GetEntitySystem(); 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")); } /// /// Creates the job icons tab. /// public void SetAllowedIcons(IReadOnlyList> jobGroups, ProtoId currentIcon) { JobGroupGrid.DisposeAllChildren(); IconGrid.DisposeAllChildren(); var jobGroupButtonGroup = new ButtonGroup(); ContainerButton? firstGroupButton = null; IReadOnlyList>? firstGroupIcons = null; ContainerButton? matchingGroupButton = null; IReadOnlyList>? 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); } /// /// Creates the job icon subgroup within the job icons tab. /// private void SetJobIcons(IReadOnlyList> 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); } }