Predict vending machine UI (#33412)

This commit is contained in:
metalgearsloth
2025-03-02 13:47:52 +11:00
committed by GitHub
parent ba1504d0d6
commit a8ebcac5c9
15 changed files with 542 additions and 318 deletions

View File

@@ -1,3 +1,4 @@
using System.Linq;
using System.Numerics;
using Content.Shared.VendingMachines;
using Robust.Client.AutoGenerated;
@@ -19,11 +20,16 @@ namespace Content.Client.VendingMachines.UI
[Dependency] private readonly IEntityManager _entityManager = default!;
private readonly Dictionary<EntProtoId, EntityUid> _dummies = [];
private readonly Dictionary<EntProtoId, (ListContainerButton Button, VendingMachineItem Item)> _listItems = new();
private readonly Dictionary<EntProtoId, uint> _amounts = new();
/// <summary>
/// Whether the vending machine is able to be interacted with or not.
/// </summary>
private bool _enabled;
public event Action<GUIBoundKeyEventArgs, ListData>? OnItemSelected;
private readonly StyleBoxFlat _styleBox = new() { BackgroundColor = new Color(70, 73, 102) };
public VendingMachineMenu()
{
MinSize = SetSize = new Vector2(250, 150);
@@ -68,18 +74,23 @@ namespace Content.Client.VendingMachines.UI
if (data is not VendorItemsListData { ItemProtoID: var protoID, ItemText: var text })
return;
button.AddChild(new VendingMachineItem(protoID, text));
button.ToolTip = text;
button.StyleBoxOverride = _styleBox;
var item = new VendingMachineItem(protoID, text);
_listItems[protoID] = (button, item);
button.AddChild(item);
button.AddStyleClass("ButtonSquare");
button.Disabled = !_enabled || _amounts[protoID] == 0;
}
/// <summary>
/// Populates the list of available items on the vending machine interface
/// and sets icons based on their prototypes
/// </summary>
public void Populate(List<VendingMachineInventoryEntry> inventory)
public void Populate(List<VendingMachineInventoryEntry> inventory, bool enabled)
{
_enabled = enabled;
_listItems.Clear();
_amounts.Clear();
if (inventory.Count == 0 && VendingContents.Visible)
{
SearchBar.Visible = false;
@@ -109,7 +120,10 @@ namespace Content.Client.VendingMachines.UI
var entry = inventory[i];
if (!_prototypeManager.TryIndex(entry.ID, out var prototype))
{
_amounts[entry.ID] = 0;
continue;
}
if (!_dummies.TryGetValue(entry.ID, out var dummy))
{
@@ -119,11 +133,15 @@ namespace Content.Client.VendingMachines.UI
var itemName = Identity.Name(dummy, _entityManager);
var itemText = $"{itemName} [{entry.Amount}]";
_amounts[entry.ID] = entry.Amount;
if (itemText.Length > longestEntry.Length)
longestEntry = itemText;
listData.Add(new VendorItemsListData(prototype.ID, itemText, i));
listData.Add(new VendorItemsListData(prototype.ID, i)
{
ItemText = itemText,
});
}
VendingContents.PopulateList(listData);
@@ -131,12 +149,43 @@ namespace Content.Client.VendingMachines.UI
SetSizeAfterUpdate(longestEntry.Length, inventory.Count);
}
/// <summary>
/// Updates text entries for vending data in place without modifying the list controls.
/// </summary>
public void UpdateAmounts(List<VendingMachineInventoryEntry> cachedInventory, bool enabled)
{
_enabled = enabled;
foreach (var proto in _dummies.Keys)
{
if (!_listItems.TryGetValue(proto, out var button))
continue;
var dummy = _dummies[proto];
var amount = cachedInventory.First(o => o.ID == proto).Amount;
// Could be better? Problem is all inventory entries get squashed.
var text = GetItemText(dummy, amount);
button.Item.SetText(text);
button.Button.Disabled = !enabled || amount == 0;
}
}
private string GetItemText(EntityUid dummy, uint amount)
{
var itemName = Identity.Name(dummy, _entityManager);
return $"{itemName} [{amount}]";
}
private void SetSizeAfterUpdate(int longestEntryLength, int contentCount)
{
SetSize = new Vector2(Math.Clamp((longestEntryLength + 2) * 12, 250, 400),
Math.Clamp(contentCount * 50, 150, 350));
}
}
}
public record VendorItemsListData(EntProtoId ItemProtoID, string ItemText, int ItemIndex) : ListData;
public record VendorItemsListData(EntProtoId ItemProtoID, int ItemIndex) : ListData
{
public string ItemText = string.Empty;
}
}