Files
tbd-station-14/Content.Client/UserInterface/Systems/Inventory/Controls/ItemStatusPanel.xaml.cs
Pieter-Jan Briers 7b90c08a2c Various item status fixes/tweaks (#27267)
* Always display item status panel fully

Initial feedback from the UI changes seems to be that a lot of people go "why is there empty space" so let's fix that.

* Fix item status middle hand being on the wrong side

I think I switched this around when fixing the left/right being inverted in the UI code.

* Minor status panel UI tweaks

Bottom-align contents now that the panel itself doesn't dynamically expand, prevent weird gaps.

Clip contents for panel

* Fix clipping on implanters and network configurators.

Made them take less space. For implanters the name has to be cut off, which I did by adding a new ClipControl to achieve that in rich text.

* Update visibility of item status panels based on whether you have hands at all.

This avoids UI for borgs looking silly.

Added a new "HandUILocation" enum that doesn't have middle hands to avoid confusion in UI code.

* Use BulletRender for laser guns too.

Provides all the benefits like fixing layout overflow and allowing multi-line stuff. Looks great now.

This involved generalizing BulletRender a bit so it can be used for not-just-bullets.

* Fix geiger word wrapping if you're really fucked
2024-04-25 00:01:31 +10:00

168 lines
5.0 KiB
C#

using Content.Client.Items;
using Content.Shared.Hands.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Inventory.VirtualItem;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.UserInterface.Systems.Inventory.Controls;
[GenerateTypedNameReferences]
public sealed partial class ItemStatusPanel : Control
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[ViewVariables] private EntityUid? _entity;
// Tracked so we can re-run SetSide() if the theme changes.
private HandUILocation _side;
public ItemStatusPanel()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
}
public void SetSide(HandUILocation location)
{
// AN IMPORTANT REMINDER ABOUT THIS CODE:
// In the UI, the RIGHT hand is on the LEFT on the screen.
// So that a character facing DOWN matches the hand positions.
Texture? texture;
Texture? textureHighlight;
StyleBox.Margin cutOut;
StyleBox.Margin flat;
Thickness contentMargin;
switch (location)
{
case HandUILocation.Right:
texture = Theme.ResolveTexture("item_status_right");
textureHighlight = Theme.ResolveTexture("item_status_right_highlight");
cutOut = StyleBox.Margin.Left;
flat = StyleBox.Margin.Right;
contentMargin = MarginFromThemeColor("_itemstatus_content_margin_right");
break;
case HandUILocation.Left:
texture = Theme.ResolveTexture("item_status_left");
textureHighlight = Theme.ResolveTexture("item_status_left_highlight");
cutOut = StyleBox.Margin.Right;
flat = StyleBox.Margin.Left;
contentMargin = MarginFromThemeColor("_itemstatus_content_margin_left");
break;
default:
throw new ArgumentOutOfRangeException(nameof(location), location, null);
}
Contents.Margin = contentMargin;
var panel = (StyleBoxTexture) Panel.PanelOverride!;
panel.Texture = texture;
panel.SetPatchMargin(flat, 4);
panel.SetPatchMargin(cutOut, 7);
var panelHighlight = (StyleBoxTexture) HighlightPanel.PanelOverride!;
panelHighlight.Texture = textureHighlight;
panelHighlight.SetPatchMargin(flat, 4);
panelHighlight.SetPatchMargin(cutOut, 7);
_side = location;
}
private Thickness MarginFromThemeColor(string itemName)
{
// This is the worst thing I've ever programmed
// (can you tell I'm a graphics programmer?)
// (the margin needs to change depending on the UI theme, so we use a fake color entry to store the value)
var color = Theme.ResolveColorOrSpecified(itemName);
return new Thickness(color.RByte, color.GByte, color.BByte, color.AByte);
}
protected override void OnThemeUpdated()
{
SetSide(_side);
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateItemName();
}
public void Update(EntityUid? entity)
{
ItemNameLabel.Visible = entity != null;
NoItemLabel.Visible = entity == null;
if (entity == null)
{
ItemNameLabel.Text = "";
ClearOldStatus();
_entity = null;
return;
}
if (entity != _entity)
{
_entity = entity.Value;
BuildNewEntityStatus();
UpdateItemName();
}
}
public void UpdateHighlight(bool highlight)
{
HighlightPanel.Visible = highlight;
}
private void UpdateItemName()
{
if (_entity == null)
return;
if (!_entityManager.TryGetComponent<MetaDataComponent>(_entity, out var meta) || meta.Deleted)
{
Update(null);
return;
}
if (_entityManager.TryGetComponent(_entity, out VirtualItemComponent? virtualItem)
&& _entityManager.EntityExists(virtualItem.BlockingEntity))
{
// Uses identity because we can be blocked by pulling someone
ItemNameLabel.Text = Identity.Name(virtualItem.BlockingEntity, _entityManager);
}
else
{
ItemNameLabel.Text = Identity.Name(_entity.Value, _entityManager);
}
}
private void ClearOldStatus()
{
StatusContents.RemoveAllChildren();
}
private void BuildNewEntityStatus()
{
DebugTools.AssertNotNull(_entity);
ClearOldStatus();
var collectMsg = new ItemStatusCollectMessage();
_entityManager.EventBus.RaiseLocalEvent(_entity!.Value, collectMsg, true);
foreach (var control in collectMsg.Controls)
{
StatusContents.AddChild(control);
}
}
}