Files
ss14-wega/Content.Client/_Wega/Medical/Ui/InjectorFabticatorWindow.xaml.cs
T
2026-06-01 23:58:02 +03:00

284 lines
10 KiB
C#

using System.Linq;
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Injector.Fabticator;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client._Wega.Medical.Ui;
[GenerateTypedNameReferences]
public sealed partial class InjectorFabticatorWindow : FancyWindow
{
[Dependency] private IPrototypeManager _prototypeManager = default!;
[Dependency] private IEntityManager _entityManager = default!;
public event Action? EjectButtonPressed;
public event Action<int, string?>? ProduceButtonPressed;
public event Action<ReagentId, FixedPoint2>? ReagentAdded;
public event Action<ReagentId>? ReagentRemoved;
public event Action<ReagentId, FixedPoint2>? TransferToBufferPressed;
public event Action<ReagentId, FixedPoint2>? TransferToBeakerPressed;
private Dictionary<ReagentId, ReagentPrototype> _beakerReagents = new();
private Dictionary<ReagentId, ReagentPrototype> _bufferReagents = new();
public InjectorFabticatorWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
// Setup button events
TransferToBufferButton.OnPressed += OnTransferToBufferPressed;
TransferToBeakerButton.OnPressed += OnTransferToBeakerPressed;
BeakerTransferAmount.OnValueChanged += OnSpinBoxValueChanged;
BufferTransferAmount.OnValueChanged += OnSpinBoxValueChanged;
EjectButton.OnPressed += _ => EjectButtonPressed?.Invoke();
AddReagentButton.OnPressed += OnAddReagentPressed;
ProduceButton.OnPressed += OnProducePressed;
ReagentAmount.OnValueChanged += OnSpinBoxValueChanged;
BeakerReagentSelector.OnItemSelected += OnBeakerReagentSelected;
BufferReagentSelector.OnItemSelected += OnBufferReagentSelected;
ReagentSelector.OnItemSelected += OnReagentSelected;
}
private void OnTransferToBufferPressed(BaseButton.ButtonEventArgs args)
{
if (BeakerReagentSelector.SelectedId == 0)
return;
var selectedHash = BeakerReagentSelector.SelectedId;
var selectedReagent = _beakerReagents.Keys.FirstOrDefault(id => id.Prototype.GetHashCode() == selectedHash);
var amount = FixedPoint2.New(BeakerTransferAmount.Value);
TransferToBufferPressed?.Invoke(selectedReagent, amount);
}
private void OnTransferToBeakerPressed(BaseButton.ButtonEventArgs args)
{
if (BufferReagentSelector.SelectedId == 0)
return;
var selectedHash = BufferReagentSelector.SelectedId;
var selectedReagent = _bufferReagents.Keys.FirstOrDefault(id => id.Prototype.GetHashCode() == selectedHash);
var amount = FixedPoint2.New(BufferTransferAmount.Value);
TransferToBeakerPressed?.Invoke(selectedReagent, amount);
}
private void OnAddReagentPressed(BaseButton.ButtonEventArgs args)
{
if (ReagentSelector.SelectedId == 0)
return;
var selectedHash = ReagentSelector.SelectedId;
var selectedReagent = _bufferReagents.Keys.FirstOrDefault(id => id.Prototype.GetHashCode() == selectedHash);
var amount = FixedPoint2.New(ReagentAmount.Value);
ReagentAdded?.Invoke(selectedReagent, amount);
}
private void OnProducePressed(BaseButton.ButtonEventArgs args)
{
var amount = ProductionAmount.Value;
var customName = string.IsNullOrWhiteSpace(CustomNameInput.Text) ? null : CustomNameInput.Text;
ProduceButtonPressed?.Invoke((int)amount, customName);
}
private void OnBeakerReagentSelected(OptionButton.ItemSelectedEventArgs args)
{
BeakerReagentSelector.SelectId(args.Id);
}
private void OnBufferReagentSelected(OptionButton.ItemSelectedEventArgs args)
{
BufferReagentSelector.SelectId(args.Id);
}
private void OnReagentSelected(OptionButton.ItemSelectedEventArgs args)
{
ReagentSelector.SelectId(args.Id);
}
public void UpdateState(InjectorFabticatorBoundUserInterfaceState state)
{
// Update beaker slot
if (state.Beaker == null)
{
BeakerSlot.RemoveAllChildren();
BeakerInfoLabel.Text = Loc.GetString("injector-fabticator-no-beaker");
}
else
{
var entityView = new SpriteView
{
Scale = new Vector2(2, 2),
SetSize = new Vector2(64, 64),
Margin = new Thickness(4)
};
entityView.SetEntity(_entityManager.GetEntity(state.Beaker));
BeakerSlot.AddChild(entityView);
if (state.BeakerContainerInfo != null)
{
BeakerInfoLabel.Text = $"{state.BeakerContainerInfo.DisplayName}: " +
$"{state.BeakerContainerInfo.CurrentVolume}/{state.BeakerContainerInfo.MaxVolume}";
UpdateReagentList(BeakerReagentList, state.BeakerContainerInfo.Reagents);
}
}
EjectButton.Disabled = state.Beaker == null;
// Update buffer solution
BufferProgress.Value = (float)(state.BufferVolume / state.BufferMaxVolume * 100);
UpdateReagentList(BufferReagentList, state.BufferSolution?.Contents);
// Update recipe
UpdateReagentList(RecipeReagentList, state.Recipe);
// Update reagent selectors
UpdateReagentSelectors(state);
// Update production controls
var canProduce = state.CanProduce && !state.IsProducing;
CustomNameInput.Editable = !state.IsProducing;
ProduceButton.Disabled = !canProduce;
// Update status
StatusLabel.Text = state.IsProducing
? Loc.GetString("injector-fabticator-status-producing",
("remaining", state.InjectorsToProduce - state.InjectorsProduced))
: Loc.GetString("injector-fabticator-status-ready");
}
private void UpdateReagentSelectors(InjectorFabticatorBoundUserInterfaceState state)
{
// Clear and update buffer reagents
_beakerReagents.Clear();
_bufferReagents.Clear();
ReagentSelector.Clear();
BufferReagentSelector.Clear();
BeakerReagentSelector.Clear();
// Add beaker reagents to beaker transfer selector
if (state.BeakerContainerInfo?.Reagents != null)
{
foreach (var reagent in state.BeakerContainerInfo.Reagents)
{
if (_prototypeManager.TryIndex<ReagentPrototype>(reagent.Reagent.Prototype, out var reagentProto))
{
_beakerReagents[reagent.Reagent] = reagentProto;
BeakerReagentSelector.AddItem(reagentProto.LocalizedName, reagent.Reagent.Prototype.GetHashCode());
}
}
}
// Add buffer reagents to selectors
if (state.BufferSolution?.Contents != null)
{
foreach (var (reagentId, _) in state.BufferSolution.Contents)
{
if (_prototypeManager.TryIndex<ReagentPrototype>(reagentId.Prototype, out var reagentProto))
{
_bufferReagents[reagentId] = reagentProto;
ReagentSelector.AddItem(reagentProto.LocalizedName, reagentId.Prototype.GetHashCode());
BufferReagentSelector.AddItem(reagentProto.LocalizedName, reagentId.Prototype.GetHashCode());
}
}
}
// Update transfer buttons state
TransferToBufferButton.Disabled = BeakerReagentSelector.ItemCount == 0;
TransferToBeakerButton.Disabled = BufferReagentSelector.ItemCount == 0;
AddReagentButton.Disabled = ReagentSelector.ItemCount == 0;
}
private void UpdateReagentList(BoxContainer container, IReadOnlyDictionary<ReagentId, FixedPoint2>? reagents)
{
if (reagents == null)
{
container.RemoveAllChildren();
container.AddChild(new Label { Text = Loc.GetString("injector-fabticator-empty") });
return;
}
// Convert dictionary to a list of ReagentQuantity
var reagentList = reagents.Select(x => new ReagentQuantity(x.Key, x.Value)).ToList();
UpdateReagentList(container, reagentList);
}
private void UpdateReagentList(BoxContainer container, IReadOnlyList<ReagentQuantity>? reagents)
{
container.RemoveAllChildren();
if (reagents == null || reagents.Count == 0)
{
container.AddChild(new Label { Text = Loc.GetString("injector-fabticator-empty") });
return;
}
var groupedReagents = reagents
.GroupBy(r => r.Reagent)
.Select(g => new
{
ReagentId = g.Key,
Quantity = g.Aggregate(FixedPoint2.Zero, (sum, x) => sum + x.Quantity),
Prototype = _prototypeManager.Index<ReagentPrototype>(g.Key.Prototype)
});
foreach (var reagent in groupedReagents)
{
var row = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
HorizontalExpand = true
};
row.AddChild(new Label
{
Text = reagent.Prototype.LocalizedName,
HorizontalExpand = true
});
row.AddChild(new Label
{
Text = $"{reagent.Quantity}u",
Align = Label.AlignMode.Right
});
if (container == RecipeReagentList)
{
var removeButton = new Button
{
Text = Loc.GetString("injector-fabticator-button-remove"),
MinWidth = 80,
Margin = new Thickness(5, 0, 0, 0)
};
removeButton.OnPressed += _ =>
ReagentRemoved?.Invoke(reagent.ReagentId);
row.AddChild(removeButton);
}
container.AddChild(row);
}
}
private void OnSpinBoxValueChanged(FloatSpinBox.FloatSpinBoxEventArgs args)
{
if (args.Value < 1)
{
args.Control.Value = 1;
}
else if (args.Value > 30)
{
args.Control.Value = 30;
}
}
}