using System; using System.Collections.Generic; using Content.Client.Items.Components; using Content.Client.Resources; using Content.Client.Stylesheets; using Content.Shared.Hands.Components; using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Timing; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; using static Content.Client.IoC.StaticIoC; using static Robust.Client.UserInterface.Controls.BoxContainer; namespace Content.Client.Items.UI { public class ItemStatusPanel : Control { [Dependency] private readonly IEntityManager _entityManager = default!; [ViewVariables] private readonly List<(IItemStatus, Control)> _activeStatusComponents = new(); [ViewVariables] private readonly Label _itemNameLabel; [ViewVariables] private readonly BoxContainer _statusContents; [ViewVariables] private readonly PanelContainer _panel; [ViewVariables] private IEntity? _entity; public ItemStatusPanel(Texture texture, StyleBox.Margin cutout, StyleBox.Margin flat, Label.AlignMode textAlign) { IoCManager.InjectDependencies(this); var panel = new StyleBoxTexture { Texture = texture }; panel.SetContentMarginOverride(StyleBox.Margin.Vertical, 4); panel.SetContentMarginOverride(StyleBox.Margin.Horizontal, 6); panel.SetPatchMargin(flat, 2); panel.SetPatchMargin(cutout, 13); AddChild(_panel = new PanelContainer { PanelOverride = panel, ModulateSelfOverride = Color.White.WithAlpha(0.9f), Children = { new BoxContainer { Orientation = LayoutOrientation.Vertical, SeparationOverride = 0, Children = { (_statusContents = new BoxContainer { Orientation = LayoutOrientation.Vertical }), (_itemNameLabel = new Label { ClipText = true, StyleClasses = {StyleNano.StyleClassItemStatus}, Align = textAlign }) } } } }); VerticalAlignment = VAlignment.Bottom; // TODO: Depending on if its a two-hand panel or not MinSize = (150, 0); } /// /// Creates a new instance of /// based on whether or not it is being created for the right /// or left hand. /// /// /// The location of the hand that this panel is for /// /// the new instance public static ItemStatusPanel FromSide(HandLocation location) { string texture; StyleBox.Margin cutOut; StyleBox.Margin flat; Label.AlignMode textAlign; switch (location) { case HandLocation.Left: texture = "/Textures/Interface/Nano/item_status_right.svg.96dpi.png"; cutOut = StyleBox.Margin.Left | StyleBox.Margin.Top; flat = StyleBox.Margin.Right | StyleBox.Margin.Bottom; textAlign = Label.AlignMode.Right; break; case HandLocation.Middle: texture = "/Textures/Interface/Nano/item_status_middle.svg.96dpi.png"; cutOut = StyleBox.Margin.Right | StyleBox.Margin.Top; flat = StyleBox.Margin.Left | StyleBox.Margin.Bottom; textAlign = Label.AlignMode.Left; break; case HandLocation.Right: texture = "/Textures/Interface/Nano/item_status_left.svg.96dpi.png"; cutOut = StyleBox.Margin.Right | StyleBox.Margin.Top; flat = StyleBox.Margin.Left | StyleBox.Margin.Bottom; textAlign = Label.AlignMode.Left; break; default: throw new ArgumentOutOfRangeException(nameof(location), location, null); } return new ItemStatusPanel(ResC.GetTexture(texture), cutOut, flat, textAlign); } protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); UpdateItemName(); } public void Update(IEntity? entity) { if (entity == null) { ClearOldStatus(); _entity = null; _panel.Visible = false; return; } if (entity != _entity) { _entity = entity; BuildNewEntityStatus(); UpdateItemName(); } _panel.Visible = true; } private void UpdateItemName() { if (_entity == null) return; if (_entity.TryGetComponent(out HandVirtualItemComponent? virtualItem) && _entityManager.TryGetEntity(virtualItem.BlockingEntity, out var blockEnt)) { _itemNameLabel.Text = blockEnt.Name; } else { _itemNameLabel.Text = _entity.Name; } } private void ClearOldStatus() { _statusContents.RemoveAllChildren(); foreach (var (itemStatus, control) in _activeStatusComponents) { itemStatus.DestroyControl(control); } _activeStatusComponents.Clear(); } private void BuildNewEntityStatus() { DebugTools.AssertNotNull(_entity); ClearOldStatus(); foreach (var statusComponent in _entity!.GetAllComponents()) { var control = statusComponent.MakeControl(); _statusContents.AddChild(control); _activeStatusComponents.Add((statusComponent, control)); } var collectMsg = new ItemStatusCollectMessage(); _entity.EntityManager.EventBus.RaiseLocalEvent(_entity.Uid, collectMsg); foreach (var control in collectMsg.Controls) { _statusContents.AddChild(control); } } } }