ItemStatusPanel.xaml.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using Content.Client.Items;
  2. using Content.Shared.Hands.Components;
  3. using Content.Shared.IdentityManagement;
  4. using Content.Shared.Inventory.VirtualItem;
  5. using Robust.Client.AutoGenerated;
  6. using Robust.Client.Graphics;
  7. using Robust.Client.UserInterface;
  8. using Robust.Client.UserInterface.XAML;
  9. using Robust.Shared.Timing;
  10. using Robust.Shared.Utility;
  11. namespace Content.Client.UserInterface.Systems.Inventory.Controls;
  12. [GenerateTypedNameReferences]
  13. public sealed partial class ItemStatusPanel : Control
  14. {
  15. [Dependency] private readonly IEntityManager _entityManager = default!;
  16. [ViewVariables] private EntityUid? _entity;
  17. // Tracked so we can re-run SetSide() if the theme changes.
  18. private HandUILocation _side;
  19. public ItemStatusPanel()
  20. {
  21. RobustXamlLoader.Load(this);
  22. IoCManager.InjectDependencies(this);
  23. }
  24. public void SetSide(HandUILocation location)
  25. {
  26. // AN IMPORTANT REMINDER ABOUT THIS CODE:
  27. // In the UI, the RIGHT hand is on the LEFT on the screen.
  28. // So that a character facing DOWN matches the hand positions.
  29. Texture? texture;
  30. Texture? textureHighlight;
  31. StyleBox.Margin cutOut;
  32. StyleBox.Margin flat;
  33. Thickness contentMargin;
  34. switch (location)
  35. {
  36. case HandUILocation.Right:
  37. texture = Theme.ResolveTexture("item_status_right");
  38. textureHighlight = Theme.ResolveTexture("item_status_right_highlight");
  39. cutOut = StyleBox.Margin.Left;
  40. flat = StyleBox.Margin.Right;
  41. contentMargin = MarginFromThemeColor("_itemstatus_content_margin_right");
  42. break;
  43. case HandUILocation.Left:
  44. texture = Theme.ResolveTexture("item_status_left");
  45. textureHighlight = Theme.ResolveTexture("item_status_left_highlight");
  46. cutOut = StyleBox.Margin.Right;
  47. flat = StyleBox.Margin.Left;
  48. contentMargin = MarginFromThemeColor("_itemstatus_content_margin_left");
  49. break;
  50. default:
  51. throw new ArgumentOutOfRangeException(nameof(location), location, null);
  52. }
  53. Contents.Margin = contentMargin;
  54. var panel = (StyleBoxTexture)Panel.PanelOverride!;
  55. panel.Texture = texture;
  56. panel.SetPatchMargin(flat, 4);
  57. panel.SetPatchMargin(cutOut, 7);
  58. var panelHighlight = (StyleBoxTexture)HighlightPanel.PanelOverride!;
  59. panelHighlight.Texture = textureHighlight;
  60. panelHighlight.SetPatchMargin(flat, 4);
  61. panelHighlight.SetPatchMargin(cutOut, 7);
  62. _side = location;
  63. }
  64. private Thickness MarginFromThemeColor(string itemName)
  65. {
  66. // This is the worst thing I've ever programmed
  67. // (can you tell I'm a graphics programmer?)
  68. // (the margin needs to change depending on the UI theme, so we use a fake color entry to store the value)
  69. var color = Theme.ResolveColorOrSpecified(itemName);
  70. return new Thickness(color.RByte, color.GByte, color.BByte, color.AByte);
  71. }
  72. protected override void OnThemeUpdated()
  73. {
  74. SetSide(_side);
  75. }
  76. protected override void FrameUpdate(FrameEventArgs args)
  77. {
  78. base.FrameUpdate(args);
  79. UpdateItemName();
  80. }
  81. public void Update(EntityUid? entity)
  82. {
  83. ItemNameLabel.Visible = entity != null;
  84. NoItemLabel.Visible = entity == null;
  85. if (entity == null)
  86. {
  87. ItemNameLabel.Text = "";
  88. ClearOldStatus();
  89. _entity = null;
  90. return;
  91. }
  92. if (entity != _entity)
  93. {
  94. _entity = entity.Value;
  95. BuildNewEntityStatus();
  96. UpdateItemName();
  97. }
  98. }
  99. public void UpdateHighlight(bool highlight)
  100. {
  101. HighlightPanel.Visible = highlight;
  102. }
  103. private void UpdateItemName()
  104. {
  105. if (_entity == null)
  106. return;
  107. if (!_entityManager.TryGetComponent<MetaDataComponent>(_entity, out var meta) || meta.Deleted)
  108. {
  109. Update(null);
  110. return;
  111. }
  112. if (_entityManager.TryGetComponent(_entity, out VirtualItemComponent? virtualItem)
  113. && _entityManager.EntityExists(virtualItem.BlockingEntity))
  114. {
  115. // Uses identity because we can be blocked by pulling someone
  116. ItemNameLabel.Text = Identity.Name(virtualItem.BlockingEntity, _entityManager);
  117. }
  118. else
  119. {
  120. ItemNameLabel.Text = Identity.Name(_entity.Value, _entityManager);
  121. }
  122. }
  123. private void ClearOldStatus()
  124. {
  125. StatusContents.RemoveAllChildren();
  126. }
  127. private void BuildNewEntityStatus()
  128. {
  129. DebugTools.AssertNotNull(_entity);
  130. ClearOldStatus();
  131. var collectMsg = new ItemStatusCollectMessage();
  132. _entityManager.EventBus.RaiseLocalEvent(_entity!.Value, collectMsg, true);
  133. foreach (var control in collectMsg.Controls)
  134. {
  135. StatusContents.AddChild(control);
  136. }
  137. }
  138. }