Skip to content

Commit

Permalink
Merge branch 'master' into plasmaman
Browse files Browse the repository at this point in the history
Signed-off-by: Skubman <[email protected]>
  • Loading branch information
angelofallars authored Jan 18, 2025
2 parents d14271b + d1fefc0 commit 39db850
Show file tree
Hide file tree
Showing 100 changed files with 3,861 additions and 3,234 deletions.
13 changes: 6 additions & 7 deletions Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@ namespace Content.Client.Chemistry.UI
/// Initializes a <see cref="ChemMasterWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public sealed class ChemMasterBoundUserInterface : BoundUserInterface
public sealed class ChemMasterBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
[ViewVariables]
private ChemMasterWindow? _window;

public ChemMasterBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}

/// <summary>
/// Called each time a chem master UI instance is opened. Generates the window and fills it with
/// relevant info. Sets the actions for static buttons.
Expand Down Expand Up @@ -53,7 +49,11 @@ protected override void Open()
_window.PillTypeButtons[i].OnPressed += _ => SendMessage(new ChemMasterSetPillTypeMessage(pillType));
}

_window.OnReagentButtonPressed += (args, button) => SendMessage(new ChemMasterReagentAmountButtonMessage(button.Id, button.Amount, button.IsBuffer));
_window.OnReagentButtonPressed += (_, button, amount) => SendMessage(new ChemMasterReagentAmountButtonMessage(button.Id, amount, button.IsBuffer));
_window.OnSortMethodChanged += sortMethod => SendMessage(new ChemMasterSortMethodUpdated(sortMethod));
_window.OnTransferAmountChanged += amount => SendMessage(new ChemMasterTransferringAmountUpdated(amount));


}

/// <summary>
Expand All @@ -68,7 +68,6 @@ protected override void UpdateState(BoundUserInterfaceState state)
base.UpdateState(state);

var castState = (ChemMasterBoundUserInterfaceState) state;

_window?.UpdateState(castState); // Update window state
}
}
Expand Down
11 changes: 8 additions & 3 deletions Content.Client/Chemistry/UI/ChemMasterWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
MinSize="620 770"
MinSize="500 770"
Title="{Loc 'chem-master-bound-user-interface-title'}">
<TabContainer Name="Tabs" Margin="5 5 7 5">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="5" SeparationOverride="10">
<!-- Input container info -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'chem-master-window-container-label'}" />
<Control HorizontalExpand="True" />
<Button MinSize="80 0" Name="InputEjectButton" Access="Public" Text="{Loc 'chem-master-window-eject-button'}" />
<RichTextLabel Name="InputAmountLabel" Text="{Loc 'chem-master-window-transferring-default-label'}" Margin="0 0 7 0"/>
<LineEdit MinSize="140 0" Name="InputAmountLineEdit" Access="Public" PlaceHolder="{Loc 'chem-master-window-amount-placeholder'}" />
<Button MinSize="80 0" Name="InputEjectButton" Access="Public" Text="{Loc 'chem-master-window-eject-button'}" StyleClasses="OpenLeft" />
</BoxContainer>

<PanelContainer VerticalExpand="True" MinSize="0 300">
Expand All @@ -34,6 +36,7 @@
<Label Text="{Loc 'chem-master-window-buffer-text'}" />
<Control HorizontalExpand="True" />
<Button MinSize="80 0" Name="BufferTransferButton" Access="Public" Text="{Loc 'chem-master-window-transfer-button'}" ToggleMode="True" StyleClasses="OpenRight" />
<OptionButton Name="SortMethod" Access="Public" ToolTip="{Loc 'chem-master-window-sort-method-tooltip'}" StyleClasses="OpenBoth" />
<Button MinSize="80 0" Name="BufferDiscardButton" Access="Public" Text="{Loc 'chem-master-window-discard-button'}" ToggleMode="True" StyleClasses="OpenLeft" />
</BoxContainer>

Expand All @@ -57,6 +60,8 @@
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'chem-master-window-container-label'}" />
<Control HorizontalExpand="True" />
<Label Name="OutputAmountLabel" Text="{Loc 'chem-master-window-transferring-default-label'}" Margin="0 0 7 0"/>
<LineEdit MinSize="140 0" Name="OutputAmountLineEdit" Access="Public" PlaceHolder="{Loc 'chem-master-window-amount-placeholder'}" />
<Button MinSize="80 0" Name="OutputEjectButton" Access="Public" Text="{Loc 'chem-master-window-eject-button'}" />
</BoxContainer>

Expand Down Expand Up @@ -129,4 +134,4 @@
</PanelContainer>
</BoxContainer>
</TabContainer>
</controls:FancyWindow>
</controls:FancyWindow>
222 changes: 184 additions & 38 deletions Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ namespace Content.Client.Chemistry.UI
public sealed partial class ChemMasterWindow : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public event Action<BaseButton.ButtonEventArgs, ReagentButton>? OnReagentButtonPressed;
public event Action<BaseButton.ButtonEventArgs, ReagentButton, int>? OnReagentButtonPressed;
public event Action<int>? OnSortMethodChanged;
public event Action<int>? OnTransferAmountChanged;
public readonly Button[] PillTypeButtons;

private Dictionary<string, ReagentCached> _reagents;
private const string TransferringAmountColor = "#ffa500";
private ReagentSortMethod _currentSortMethod = ReagentSortMethod.Alphabetical;
private ChemMasterBoundUserInterfaceState? _lastState;
private string _lastAmountText = "50";
private int _transferAmount = 50;


private const string PillsRsiPath = "/Textures/Objects/Specific/Chemistry/pills.rsi";

/// <summary>
Expand All @@ -38,6 +48,14 @@ public ChemMasterWindow()
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);

_reagents = new();

InputAmountLineEdit.OnTextEntered += SetAmount;
InputAmountLineEdit.OnFocusExit += SetAmount;

OutputAmountLineEdit.OnTextEntered += SetAmount;
OutputAmountLineEdit.OnFocusExit += SetAmount;

// Pill type selection buttons, in total there are 20 pills.
// Pill rsi file should have states named as pill1, pill2, and so on.
var resourcePath = new ResPath(PillsRsiPath);
Expand Down Expand Up @@ -87,46 +105,118 @@ public ChemMasterWindow()

Tabs.SetTabTitle(0, Loc.GetString("chem-master-window-input-tab"));
Tabs.SetTabTitle(1, Loc.GetString("chem-master-window-output-tab"));

SortMethod.AddItem(
Loc.GetString("chem-master-window-sort-method-Alphabetical-text"),
(int) ReagentSortMethod.Alphabetical);
SortMethod.AddItem(Loc.GetString("chem-master-window-sort-method-Amount-text"), (int) ReagentSortMethod.Amount);
SortMethod.AddItem(Loc.GetString("chem-master-window-sort-method-Time-text"), (int) ReagentSortMethod.Time);
SortMethod.OnItemSelected += HandleChildPressed;

BufferTransferButton.OnPressed += HandleDiscardTransferPress;
BufferDiscardButton.OnPressed += HandleDiscardTransferPress;
}

private void HandleDiscardTransferPress(BaseButton.ButtonEventArgs args)
{
var buttons = BufferInfo.Children
.Where(c => c is Button)
.Cast<Button>();

foreach (var button in buttons)
{
var text = BufferTransferButton.Pressed ? "transfer" : "discard";
button.Text = Loc.GetString($"chem-master-window-{text}-button-text");
}
}

private void HandleSortMethodChange(int newSortMethod)
{
if (newSortMethod == (int) _currentSortMethod)
return;

_currentSortMethod = (ReagentSortMethod) newSortMethod;
SortMethod.SelectId(newSortMethod);
SortUpdated();
}

private void HandleChildPressed(OptionButton.ItemSelectedEventArgs args)
{
HandleSortMethodChange(args.Id);
OnSortMethodChanged?.Invoke(args.Id);
}

private void SortUpdated()
{
if (_lastState == null)
return;

UpdatePanelInfo(_lastState);
}

private bool ValidateAmount(string newText)
{
if (string.IsNullOrWhiteSpace(newText) || !int.TryParse(newText, out int amount))
{
InputAmountLineEdit.SetText(string.Empty);
OutputAmountLineEdit.SetText(string.Empty);
return false;
}

_lastAmountText = newText;
_transferAmount = amount;
OnTransferAmountChanged?.Invoke(amount);
return true;
}

private void SetAmount(LineEdit.LineEditEventArgs args) =>
SetAmountText(args.Text);

private void SetAmountText(string newText)
{
if (newText == _lastAmountText)
return;

if (!ValidateAmount(newText))
return;

var localizedAmount = Loc.GetString(
"chem-master-window-transferring-label",
("quantity", newText),
("color", TransferringAmountColor));

InputAmountLabel.Text = localizedAmount;
OutputAmountLabel.Text = localizedAmount;

InputAmountLineEdit.SetText(string.Empty);
OutputAmountLineEdit.SetText(string.Empty);
}

private ReagentButton MakeReagentButton(string text, ChemMasterReagentAmount amount, ReagentId id, bool isBuffer, string styleClass)
private ReagentButton MakeReagentButton(string text, ReagentId id, bool isBuffer)
{
var reagentTransferButton = new ReagentButton(text, amount, id, isBuffer, styleClass);
var reagentTransferButton = new ReagentButton(text, id, isBuffer);
reagentTransferButton.OnPressed += args
=> OnReagentButtonPressed?.Invoke(args, reagentTransferButton);
=> OnReagentButtonPressed?.Invoke(args, reagentTransferButton, _transferAmount);
return reagentTransferButton;
}
/// <summary>
/// Conditionally generates a set of reagent buttons based on the supplied boolean argument.
/// This was moved outside of BuildReagentRow to facilitate conditional logic, stops indentation depth getting out of hand as well.
/// </summary>
private List<ReagentButton> CreateReagentTransferButtons(ReagentId reagent, bool isBuffer, bool addReagentButtons)
private ReagentButton? CreateReagentTransferButton(ReagentId reagent, bool isBuffer, bool addReagentButtons)
{
if (!addReagentButtons)
return new(); // Return an empty list if reagentTransferButton creation is disabled.
return null; // Return an empty list if reagentTransferButton creation is disabled.

var buttons = new List<ReagentButton>();
var names = Enum.GetNames<ChemMasterReagentAmount>();
var values = Enum.GetValues<ChemMasterReagentAmount>();
var text = BufferTransferButton.Pressed ? "transfer" : "discard";

for (int i = 0; i < names.Length; i++)
{
var isNumber = int.TryParse(names[i].Substring(1), out int number);
var name = isNumber ? number.ToString() : names[i];
var reagentAmount = values[i];

var reagentTransferButton = MakeReagentButton(
name,
reagentAmount,
reagent,
isBuffer,
i != names.Length - 1 ? StyleBase.ButtonOpenBoth : StyleBase.ButtonOpenLeft
);

buttons.Add(reagentTransferButton);
}
var reagentTransferButton = MakeReagentButton(
Loc.GetString($"chem-master-window-{text}-button"),
reagent,
isBuffer
);

return buttons;
return reagentTransferButton;
}

/// <summary>
Expand All @@ -140,8 +230,12 @@ public void UpdateState(BoundUserInterfaceState state)
if (castState.UpdateLabel)
LabelLine = GenerateLabel(castState);

_lastState = castState;

// Ensure the Panel Info is updated, including UI elements for Buffer Volume, Output Container and so on
UpdatePanelInfo(castState);
HandleSortMethodChange(castState.SortMethod);
SetAmountText(castState.TransferringAmount.ToString());

BufferCurrentVolume.Text = $" {castState.BufferCurrentVolume?.Int() ?? 0}u";

Expand Down Expand Up @@ -238,15 +332,57 @@ private void UpdatePanelInfo(ChemMasterBoundUserInterfaceState state)
bufferHBox.AddChild(bufferVol);

// initialises rowCount to allow for striped rows

var rowCount = 0;
foreach (var (reagent, quantity) in state.BufferReagents.OrderBy(x => x.Reagent.Prototype))
var bufferReagents = state.BufferReagents.OrderBy(x => x.Reagent.Prototype);

if (_currentSortMethod == ReagentSortMethod.Amount)
bufferReagents = bufferReagents.OrderByDescending(x => x.Quantity);

if (_currentSortMethod == ReagentSortMethod.Time)
{
bufferReagents = bufferReagents.OrderByDescending(
x =>
{
var exists = _reagents.TryGetValue(x.Reagent.Prototype, out var reagent);
return exists && reagent != null ? reagent.TimeAdded : DateTimeOffset.UtcNow;
});
}

var bufferAsNames = bufferReagents.Select(r => r.Reagent.Prototype).ToHashSet();
var hashSetCachedReagents = _reagents.Keys.ToHashSet();
hashSetCachedReagents.ExceptWith(bufferAsNames);

foreach (var missing in hashSetCachedReagents)
_reagents.Remove(missing);

foreach (var (reagent, quantity) in bufferReagents)
{
var reagentId = reagent;
_prototypeManager.TryIndex(reagentId.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
var reagentColor = proto?.SubstanceColor ?? default(Color);
BufferInfo.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagentId, quantity, true, true));

var exists = _reagents.TryGetValue(reagent.Prototype, out var reagentCached);

if (!exists)
{
reagentCached = new()
{
Id = reagentId,
Quantity = quantity,
TimeAdded = reagentCached?.TimeAdded ?? DateTimeOffset.UtcNow
};

_reagents.Add(reagentId.Prototype, reagentCached);
}
else
{
reagentCached!.Quantity = quantity;
reagentCached!.Id = reagentId;

_reagents[reagentId.Prototype] = reagentCached;
}
}
}

Expand Down Expand Up @@ -316,7 +452,7 @@ private Control BuildReagentRow(Color reagentColor, int rowCount, string name, R
reagentColor = currentRowColor;
}
//this calls the separated button builder, and stores the return to render after labels
var reagentButtonConstructors = CreateReagentTransferButtons(reagent, isBuffer, addReagentButtons);
var reagentButtonConstructor = CreateReagentTransferButton(reagent, isBuffer, addReagentButtons);

// Create the row layout with the color panel
var rowContainer = new BoxContainer
Expand Down Expand Up @@ -348,11 +484,9 @@ private Control BuildReagentRow(Color reagentColor, int rowCount, string name, R
}
};

// Add the reagent buttons after the color panel
foreach (var reagentTransferButton in reagentButtonConstructors)
{
rowContainer.AddChild(reagentTransferButton);
}
if (reagentButtonConstructor != null)
rowContainer.AddChild(reagentButtonConstructor);

//Apply panencontainer to allow for striped rows
return new PanelContainer
{
Expand All @@ -370,16 +504,28 @@ public string LabelLine

public sealed class ReagentButton : Button
{
public ChemMasterReagentAmount Amount { get; set; }
public bool IsBuffer = true;
public ReagentId Id { get; set; }
public ReagentButton(string text, ChemMasterReagentAmount amount, ReagentId id, bool isBuffer, string styleClass)
public ReagentButton(string text, ReagentId id, bool isBuffer)
{
AddStyleClass(styleClass);
AddStyleClass(StyleBase.ButtonOpenLeft);
Text = text;
Amount = amount;
Id = id;
IsBuffer = isBuffer;
}
}

public sealed class ReagentCached
{
public ReagentId Id { get; set; }
public DateTimeOffset TimeAdded { get; set; }
public FixedPoint2 Quantity { get; set; }
}

public enum ReagentSortMethod
{
Time,
Alphabetical,
Amount
}
}
Loading

0 comments on commit 39db850

Please sign in to comment.