using System.Linq; using System.Numerics; using Content.Client.Roles; using Content.Client.Stylesheets; using Content.Client.UserInterface.Controls; using Content.Shared.Implants; using Content.Shared.StatusIcon; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Client.Implants.UI; [GenerateTypedNameReferences] public sealed partial class ChameleonControllerMenu : FancyWindow { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!; private readonly SpriteSystem _sprite; private readonly JobSystem _job; // List of all the job protos that you can select! private IEnumerable _outfits; // Lock the UI until this time public DateTime? _lockedUntil; private static readonly ProtoId UnknownIcon = "JobIconUnknown"; private static readonly LocId UnknownDepartment = "department-Unknown"; public event Action>? OnJobSelected; public ChameleonControllerMenu() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _sprite = _entityManager.System(); _job = _entityManager.System(); _outfits = _prototypeManager.EnumeratePrototypes(); UpdateGrid(); } /// /// Fill the grid with the correct job icons and buttons. /// /// Set to true to disable all the buttons. public void UpdateGrid(bool disabled = false) { Grid.RemoveAllChildren(); // Dictionary to easily put outfits in departments. // Department name -> UI element holding that department. var departments = new Dictionary(); departments.Add(UnknownDepartment, CreateDepartment(UnknownDepartment)); // Go through every outfit and add them to the correct department. foreach (var outfit in _outfits) { _prototypeManager.TryIndex(outfit.Job, out var jobProto); var name = outfit.LoadoutName ?? outfit.Name ?? jobProto?.Name ?? "Prototype has no name or job."; var jobIconId = outfit.Icon ?? jobProto?.Icon ?? UnknownIcon; var jobIconProto = _prototypeManager.Index(jobIconId); var outfitButton = CreateOutfitButton(disabled, name, jobIconProto, outfit.ID); if (outfit.Job != null && _job.TryGetLowestWeightDepartment(outfit.Job, out var departmentPrototype)) { if (!departments.ContainsKey(departmentPrototype.Name)) departments.Add(departmentPrototype.Name, CreateDepartment(departmentPrototype.Name)); departments[departmentPrototype.Name].AddChild(outfitButton); } else { departments[UnknownDepartment].AddChild(outfitButton); } } // Sort the departments by their weight. var departmentList = departments.ToList(); departmentList.Sort((a, b) => a.Value.ChildCount.CompareTo(b.Value.ChildCount)); // Actually add the departments to the window. foreach (var department in departmentList) { Grid.AddChild(department.Value); } } private BoxContainer CreateDepartment(string name) { var departmentContainer = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Vertical, }; departmentContainer.AddChild(new Label { Text = Loc.GetString(name), }); return departmentContainer; } private BoxContainer CreateOutfitButton(bool disabled, string name, JobIconPrototype jobIconProto, ProtoId outfitProto) { var outfitButton = new BoxContainer(); var button = new Button { HorizontalExpand = true, StyleClasses = {StyleBase.ButtonSquare}, ToolTip = Loc.GetString(name), Text = Loc.GetString(name), Margin = new Thickness(0, 0, 15, 0), Disabled = disabled, }; var jobIconTexture = new TextureRect { Texture = _sprite.Frame0(jobIconProto.Icon), TextureScale = new Vector2(2.5f, 2.5f), Stretch = TextureRect.StretchMode.KeepCentered, Margin = new Thickness(0, 0, 5, 0), }; outfitButton.AddChild(jobIconTexture); outfitButton.AddChild(button); button.OnPressed += _ => JobButtonPressed(outfitProto); return outfitButton; } private void JobButtonPressed(ProtoId outfit) { OnJobSelected?.Invoke(outfit); } protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); if (_lockedUntil == null || DateTime.Now < _lockedUntil) return; _lockedUntil = null; UpdateGrid(); } }