Make vending machine use EntityPrototypeView (#30064)
* Make vendor machines use EntityPrototypeView * Update * 1 * Kill me * For the love of god!!!
This commit is contained in:
16
Content.Client/VendingMachines/UI/VendingMachineItem.xaml
Normal file
16
Content.Client/VendingMachines/UI/VendingMachineItem.xaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<BoxContainer xmlns="https://spacestation14.io"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
SeparationOverride="4">
|
||||||
|
<EntityPrototypeView
|
||||||
|
Name="ItemPrototype"
|
||||||
|
Margin="4 4"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
MinSize="32 32"
|
||||||
|
/>
|
||||||
|
<Label Name="NameLabel"
|
||||||
|
SizeFlagsStretchRatio="3"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
ClipText="True"/>
|
||||||
|
</BoxContainer>
|
||||||
19
Content.Client/VendingMachines/UI/VendingMachineItem.xaml.cs
Normal file
19
Content.Client/VendingMachines/UI/VendingMachineItem.xaml.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.VendingMachines.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class VendingMachineItem : BoxContainer
|
||||||
|
{
|
||||||
|
public VendingMachineItem(EntProtoId entProto, string text)
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
ItemPrototype.SetPrototype(entProto);
|
||||||
|
|
||||||
|
NameLabel.Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,17 +2,10 @@
|
|||||||
xmlns="https://spacestation14.io"
|
xmlns="https://spacestation14.io"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
xmlns:style="clr-namespace:Content.Client.Stylesheets">
|
xmlns:co="clr-namespace:Content.Client.UserInterface.Controls">
|
||||||
<BoxContainer Orientation="Vertical">
|
<BoxContainer Name="MainContainer" Orientation="Vertical">
|
||||||
<LineEdit Name="SearchBar" PlaceHolder="{Loc 'vending-machine-component-search-filter'}" HorizontalExpand="True" Margin ="4 4" Access="Public"/>
|
<LineEdit Name="SearchBar" PlaceHolder="{Loc 'vending-machine-component-search-filter'}" HorizontalExpand="True" Margin ="4 4"/>
|
||||||
<ItemList Name="VendingContents"
|
<co:SearchListContainer Name="VendingContents" VerticalExpand="True" Margin="4 0"/>
|
||||||
SizeFlagsStretchRatio="8"
|
|
||||||
VerticalExpand="True"
|
|
||||||
ItemSeparation="2"
|
|
||||||
Margin="4 0"
|
|
||||||
SelectMode="Button"
|
|
||||||
StyleClasses="transparentBackgroundItemList">
|
|
||||||
</ItemList>
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<BoxContainer Orientation="Vertical">
|
<BoxContainer Orientation="Vertical">
|
||||||
<PanelContainer StyleClasses="LowDivider" />
|
<PanelContainer StyleClasses="LowDivider" />
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Content.Shared.VendingMachines;
|
using Content.Shared.VendingMachines;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Client.Graphics;
|
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
|
using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
|
||||||
using Content.Shared.IdentityManagement;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Shared.Timing;
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
|
||||||
namespace Content.Client.VendingMachines.UI
|
namespace Content.Client.VendingMachines.UI
|
||||||
{
|
{
|
||||||
@@ -16,12 +15,10 @@ namespace Content.Client.VendingMachines.UI
|
|||||||
public sealed partial class VendingMachineMenu : FancyWindow
|
public sealed partial class VendingMachineMenu : FancyWindow
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
||||||
|
|
||||||
private readonly Dictionary<EntProtoId, EntityUid> _dummies = [];
|
public event Action<GUIBoundKeyEventArgs, ListData>? OnItemSelected;
|
||||||
|
|
||||||
public event Action<ItemList.ItemListSelectedEventArgs>? OnItemSelected;
|
private readonly StyleBoxFlat _styleBox = new() { BackgroundColor = new Color(70, 73, 102) };
|
||||||
public event Action<string>? OnSearchChanged;
|
|
||||||
|
|
||||||
public VendingMachineMenu()
|
public VendingMachineMenu()
|
||||||
{
|
{
|
||||||
@@ -29,106 +26,90 @@ namespace Content.Client.VendingMachines.UI
|
|||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
SearchBar.OnTextChanged += _ =>
|
VendingContents.SearchBar = SearchBar;
|
||||||
{
|
VendingContents.DataFilterCondition += DataFilterCondition;
|
||||||
OnSearchChanged?.Invoke(SearchBar.Text);
|
VendingContents.GenerateItem += GenerateButton;
|
||||||
};
|
VendingContents.ItemKeyBindDown += (args, data) => OnItemSelected?.Invoke(args, data);
|
||||||
|
|
||||||
VendingContents.OnItemSelected += args =>
|
|
||||||
{
|
|
||||||
OnItemSelected?.Invoke(args);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
private bool DataFilterCondition(string filter, ListData data)
|
||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
if (data is not VendorItemsListData { ItemText: var text })
|
||||||
|
return false;
|
||||||
|
|
||||||
// Don't clean up dummies during disposal or we'll just have to spawn them again
|
if (string.IsNullOrEmpty(filter))
|
||||||
if (!disposing)
|
return true;
|
||||||
|
|
||||||
|
return text.Contains(filter, StringComparison.CurrentCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateButton(ListData data, ListContainerButton button)
|
||||||
|
{
|
||||||
|
if (data is not VendorItemsListData { ItemProtoID: var protoID, ItemText: var text })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Delete any dummy items we spawned
|
button.AddChild(new VendingMachineItem(protoID, text));
|
||||||
foreach (var entity in _dummies.Values)
|
|
||||||
{
|
button.ToolTip = text;
|
||||||
_entityManager.QueueDeleteEntity(entity);
|
button.StyleBoxOverride = _styleBox;
|
||||||
}
|
|
||||||
_dummies.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates the list of available items on the vending machine interface
|
/// Populates the list of available items on the vending machine interface
|
||||||
/// and sets icons based on their prototypes
|
/// and sets icons based on their prototypes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Populate(List<VendingMachineInventoryEntry> inventory, out List<int> filteredInventory, string? filter = null)
|
public void Populate(List<VendingMachineInventoryEntry> inventory)
|
||||||
{
|
{
|
||||||
filteredInventory = new();
|
if (inventory.Count == 0 && VendingContents.Visible)
|
||||||
|
{
|
||||||
|
SearchBar.Visible = false;
|
||||||
|
VendingContents.Visible = false;
|
||||||
|
|
||||||
if (inventory.Count == 0)
|
var outOfStockLabel = new Label()
|
||||||
{
|
{
|
||||||
VendingContents.Clear();
|
Text = Loc.GetString("vending-machine-component-try-eject-out-of-stock"),
|
||||||
var outOfStockText = Loc.GetString("vending-machine-component-try-eject-out-of-stock");
|
Margin = new Thickness(4, 4),
|
||||||
VendingContents.AddItem(outOfStockText);
|
HorizontalExpand = true,
|
||||||
SetSizeAfterUpdate(outOfStockText.Length, VendingContents.Count);
|
VerticalAlignment = VAlignment.Stretch,
|
||||||
|
HorizontalAlignment = HAlignment.Center
|
||||||
|
};
|
||||||
|
|
||||||
|
MainContainer.AddChild(outOfStockLabel);
|
||||||
|
|
||||||
|
SetSizeAfterUpdate(outOfStockLabel.Text.Length, 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (inventory.Count != VendingContents.Count)
|
|
||||||
{
|
|
||||||
if (inventory.Count > VendingContents.Count)
|
|
||||||
VendingContents.AddItem(string.Empty);
|
|
||||||
else
|
|
||||||
VendingContents.RemoveAt(VendingContents.Count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var longestEntry = string.Empty;
|
var longestEntry = string.Empty;
|
||||||
var spriteSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<SpriteSystem>();
|
var listData = new List<VendorItemsListData>();
|
||||||
|
|
||||||
var filterCount = 0;
|
|
||||||
for (var i = 0; i < inventory.Count; i++)
|
for (var i = 0; i < inventory.Count; i++)
|
||||||
{
|
{
|
||||||
var entry = inventory[i];
|
var entry = inventory[i];
|
||||||
var vendingItem = VendingContents[i - filterCount];
|
|
||||||
vendingItem.Text = string.Empty;
|
|
||||||
vendingItem.Icon = null;
|
|
||||||
|
|
||||||
if (!_dummies.TryGetValue(entry.ID, out var dummy))
|
if (!_prototypeManager.TryIndex(entry.ID, out var prototype))
|
||||||
{
|
|
||||||
dummy = _entityManager.Spawn(entry.ID);
|
|
||||||
_dummies.Add(entry.ID, dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemName = Identity.Name(dummy, _entityManager);
|
|
||||||
Texture? icon = null;
|
|
||||||
if (_prototypeManager.TryIndex<EntityPrototype>(entry.ID, out var prototype))
|
|
||||||
{
|
|
||||||
icon = spriteSystem.GetPrototypeIcon(prototype).Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search filter
|
|
||||||
if (!string.IsNullOrEmpty(filter) &&
|
|
||||||
!itemName.ToLowerInvariant().Contains(filter.Trim().ToLowerInvariant()))
|
|
||||||
{
|
|
||||||
VendingContents.Remove(vendingItem);
|
|
||||||
filterCount++;
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
var itemText = $"{prototype.Name} [{entry.Amount}]";
|
||||||
|
|
||||||
|
if (itemText.Length > longestEntry.Length)
|
||||||
|
longestEntry = itemText;
|
||||||
|
|
||||||
|
listData.Add(new VendorItemsListData(prototype.ID, itemText, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemName.Length > longestEntry.Length)
|
VendingContents.PopulateList(listData);
|
||||||
longestEntry = itemName;
|
|
||||||
|
|
||||||
vendingItem.Text = $"{itemName} [{entry.Amount}]";
|
|
||||||
vendingItem.Icon = icon;
|
|
||||||
filteredInventory.Add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSizeAfterUpdate(longestEntry.Length, inventory.Count);
|
SetSizeAfterUpdate(longestEntry.Length, inventory.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetSizeAfterUpdate(int longestEntryLength, int contentCount)
|
private void SetSizeAfterUpdate(int longestEntryLength, int contentCount)
|
||||||
{
|
{
|
||||||
SetSize = new Vector2(Math.Clamp((longestEntryLength + 2) * 12, 250, 300),
|
SetSize = new Vector2(Math.Clamp((longestEntryLength + 2) * 12, 250, 400),
|
||||||
Math.Clamp(contentCount * 50, 150, 350));
|
Math.Clamp(contentCount * 50, 150, 350));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record VendorItemsListData(EntProtoId ItemProtoID, string ItemText, int ItemIndex) : ListData;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
using Content.Client.VendingMachines.UI;
|
using Content.Client.VendingMachines.UI;
|
||||||
using Content.Shared.VendingMachines;
|
using Content.Shared.VendingMachines;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Input;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
|
|
||||||
@@ -14,9 +17,6 @@ namespace Content.Client.VendingMachines
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private List<VendingMachineInventoryEntry> _cachedInventory = new();
|
private List<VendingMachineInventoryEntry> _cachedInventory = new();
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
private List<int> _cachedFilteredIndex = new();
|
|
||||||
|
|
||||||
public VendingMachineBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
public VendingMachineBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -34,9 +34,10 @@ namespace Content.Client.VendingMachines
|
|||||||
_menu.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
|
_menu.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
|
||||||
|
|
||||||
_menu.OnItemSelected += OnItemSelected;
|
_menu.OnItemSelected += OnItemSelected;
|
||||||
_menu.OnSearchChanged += OnSearchChanged;
|
|
||||||
|
|
||||||
_menu.Populate(_cachedInventory, out _cachedFilteredIndex);
|
_menu.Populate(_cachedInventory);
|
||||||
|
|
||||||
|
_menu.OpenCenteredLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateState(BoundUserInterfaceState state)
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
@@ -48,15 +49,21 @@ namespace Content.Client.VendingMachines
|
|||||||
|
|
||||||
_cachedInventory = newState.Inventory;
|
_cachedInventory = newState.Inventory;
|
||||||
|
|
||||||
_menu?.Populate(_cachedInventory, out _cachedFilteredIndex, _menu.SearchBar.Text);
|
_menu?.Populate(_cachedInventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnItemSelected(ItemList.ItemListSelectedEventArgs args)
|
private void OnItemSelected(GUIBoundKeyEventArgs args, ListData data)
|
||||||
{
|
{
|
||||||
|
if (args.Function != EngineKeyFunctions.UIClick)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data is not VendorItemsListData { ItemIndex: var itemIndex })
|
||||||
|
return;
|
||||||
|
|
||||||
if (_cachedInventory.Count == 0)
|
if (_cachedInventory.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var selectedItem = _cachedInventory.ElementAtOrDefault(_cachedFilteredIndex.ElementAtOrDefault(args.ItemIndex));
|
var selectedItem = _cachedInventory.ElementAtOrDefault(itemIndex);
|
||||||
|
|
||||||
if (selectedItem == null)
|
if (selectedItem == null)
|
||||||
return;
|
return;
|
||||||
@@ -77,10 +84,5 @@ namespace Content.Client.VendingMachines
|
|||||||
_menu.OnClose -= Close;
|
_menu.OnClose -= Close;
|
||||||
_menu.Dispose();
|
_menu.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSearchChanged(string? filter)
|
|
||||||
{
|
|
||||||
_menu?.Populate(_cachedInventory, out _cachedFilteredIndex, filter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user