using System; using System.Collections.Generic; using Content.Shared.Chemistry.Components; using Robust.Client.AutoGenerated; using Robust.Client.Console; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; namespace Content.Client.Administration.UI.ManageSolutions { /// /// A simple window that displays solutions and their contained reagents. Allows you to edit the reagent quantities and add new reagents. /// [GenerateTypedNameReferences] public sealed partial class EditSolutionsWindow : DefaultWindow { [Dependency] private readonly IClientConsoleHost _consoleHost = default!; [Dependency] private readonly IEntityManager _entityManager = default!; private EntityUid _target = EntityUid.Invalid; private string? _selectedSolution; private AddReagentWindow? _addReagentWindow; private Dictionary? _solutions; public EditSolutionsWindow() { IoCManager.InjectDependencies(this); RobustXamlLoader.Load(this); SolutionOption.OnItemSelected += SolutionSelected; AddButton.OnPressed += OpenAddReagentWindow; } public override void Close() { base.Close(); _addReagentWindow?.Close(); _addReagentWindow?.Dispose(); } public void SetTargetEntity(EntityUid target) { _target = target; var targetName = _entityManager.EntityExists(target) ? IoCManager.Resolve().GetComponent(target).EntityName : string.Empty; Title = Loc.GetString("admin-solutions-window-title", ("targetName", targetName)); } /// /// Update the capacity label and re-create the reagent list /// public void UpdateReagents() { ReagentList.DisposeAllChildren(); if (_selectedSolution == null || _solutions == null) return; if (!_solutions.TryGetValue(_selectedSolution, out var solution)) return; UpdateVolumeBox(solution); UpdateThermalBox(solution); foreach (var reagent in solution) { AddReagentEntry(reagent); } } /// /// Updates the entry displaying the current and maximum volume of the selected solution. /// /// The selected solution. private void UpdateVolumeBox(Solution solution) { VolumeBox.DisposeAllChildren(); var volumeLabel = new Label(); volumeLabel.HorizontalExpand = true; volumeLabel.Margin = new Thickness(0, 4); volumeLabel.Text = Loc.GetString("admin-solutions-window-volume-label", ("currentVolume", solution.CurrentVolume), ("maxVolume", solution.MaxVolume)); var capacityBox = new BoxContainer(); capacityBox.Orientation = BoxContainer.LayoutOrientation.Horizontal; capacityBox.HorizontalExpand = true; capacityBox.Margin = new Thickness(0, 4); var capacityLabel = new Label(); capacityLabel.HorizontalExpand = true; capacityLabel.Margin = new Thickness(0, 1); capacityLabel.Text = Loc.GetString("admin-solutions-window-capacity-label"); var capacitySpin = new FloatSpinBox(1, 2); capacitySpin.HorizontalExpand = true; capacitySpin.Margin = new Thickness(0, 1); capacitySpin.Value = (float) solution.MaxVolume; capacitySpin.OnValueChanged += SetCapacity; capacityBox.AddChild(capacityLabel); capacityBox.AddChild(capacitySpin); VolumeBox.AddChild(volumeLabel); VolumeBox.AddChild(capacityBox); } /// /// Updates the entry displaying the current specific heat, heat capacity, temperature, and thermal energy /// of the selected solution. /// /// The selected solution. private void UpdateThermalBox(Solution solution) { ThermalBox.DisposeAllChildren(); var specificHeatLabel = new Label(); specificHeatLabel.HorizontalExpand = true; specificHeatLabel.Margin = new Thickness(0, 1); specificHeatLabel.Text = Loc.GetString("admin-solutions-window-specific-heat-label", ("specificHeat", solution.SpecificHeat)); var heatCapacityLabel = new Label(); heatCapacityLabel.HorizontalExpand = true; heatCapacityLabel.Margin = new Thickness(0, 1); heatCapacityLabel.Text = Loc.GetString("admin-solutions-window-heat-capacity-label", ("heatCapacity", solution.HeatCapacity)); // Temperature entry: var temperatureBox = new BoxContainer(); temperatureBox.Orientation = BoxContainer.LayoutOrientation.Horizontal; temperatureBox.HorizontalExpand = true; temperatureBox.Margin = new Thickness(0, 1); var temperatureLabel = new Label(); temperatureLabel.HorizontalExpand = true; temperatureLabel.Margin = new Thickness(0, 1); temperatureLabel.Text = Loc.GetString("admin-solutions-window-temperature-label"); var temperatureSpin = new FloatSpinBox(1, 2); temperatureSpin.HorizontalExpand = true; temperatureSpin.Margin = new Thickness(0, 1); temperatureSpin.Value = solution.Temperature; temperatureSpin.OnValueChanged += SetTemperature; temperatureBox.AddChild(temperatureLabel); temperatureBox.AddChild(temperatureSpin); // Thermal energy entry: var thermalEnergyBox = new BoxContainer(); thermalEnergyBox.Orientation = BoxContainer.LayoutOrientation.Horizontal; thermalEnergyBox.HorizontalExpand = true; thermalEnergyBox.Margin = new Thickness(0, 1); var thermalEnergyLabel = new Label(); thermalEnergyLabel.HorizontalExpand = true; thermalEnergyLabel.Margin = new Thickness(0, 1); thermalEnergyLabel.Text = Loc.GetString("admin-solutions-window-thermal-energy-label"); var thermalEnergySpin = new FloatSpinBox(1, 2); thermalEnergySpin.HorizontalExpand = true; thermalEnergySpin.Margin = new Thickness(0, 1); thermalEnergySpin.Value = solution.ThermalEnergy; thermalEnergySpin.OnValueChanged += SetThermalEnergy; thermalEnergyBox.AddChild(thermalEnergyLabel); thermalEnergyBox.AddChild(thermalEnergySpin); ThermalBox.AddChild(specificHeatLabel); ThermalBox.AddChild(heatCapacityLabel); ThermalBox.AddChild(temperatureBox); ThermalBox.AddChild(thermalEnergyBox); } /// /// Add a single reagent entry to the list /// private void AddReagentEntry(Solution.ReagentQuantity reagent) { var box = new BoxContainer(); var spin = new FloatSpinBox(1, 2); spin.Value = reagent.Quantity.Float(); spin.OnValueChanged += (args) => SetReagent(args, reagent.ReagentId); spin.HorizontalExpand = true; box.AddChild(new Label() { Text = reagent.ReagentId , HorizontalExpand = true}); box.AddChild(spin); ReagentList.AddChild(box); } /// /// Execute a command to modify the reagents in the solution. /// private void SetReagent(FloatSpinBox.FloatSpinBoxEventArgs args, string reagentId) { if (_solutions == null || _selectedSolution == null) return; var current = _solutions[_selectedSolution].GetReagentQuantity(reagentId); var delta = args.Value - current.Float(); if (MathF.Abs(delta) < 0.01) return; var command = $"addreagent {_target} {_selectedSolution} {reagentId} {delta}"; _consoleHost.ExecuteCommand(command); } private void SetCapacity(FloatSpinBox.FloatSpinBoxEventArgs args) { if (_solutions == null || _selectedSolution == null) return; var command = $"setsolutioncapacity {_target} {_selectedSolution} {args.Value}"; _consoleHost.ExecuteCommand(command); } /// /// Sets the temperature of the selected solution to a value. /// /// An argument struct containing the value to set the temperature to. private void SetTemperature(FloatSpinBox.FloatSpinBoxEventArgs args) { if (_solutions == null || _selectedSolution == null) return; var command = $"setsolutiontemperature {_target} {_selectedSolution} {args.Value}"; _consoleHost.ExecuteCommand(command); } /// /// Sets the thermal energy of the selected solution to a value. /// /// An argument struct containing the value to set the thermal energy to. private void SetThermalEnergy(FloatSpinBox.FloatSpinBoxEventArgs args) { if (_solutions == null || _selectedSolution == null) return; var command = $"setsolutionthermalenergy {_target} {_selectedSolution} {args.Value}"; _consoleHost.ExecuteCommand(command); } /// /// Open a new window that has options to add new reagents to the solution. /// private void OpenAddReagentWindow(BaseButton.ButtonEventArgs obj) { if (string.IsNullOrEmpty(_selectedSolution)) return; _addReagentWindow?.Close(); _addReagentWindow?.Dispose(); _addReagentWindow = new AddReagentWindow(_target, _selectedSolution); _addReagentWindow.OpenCentered(); } /// /// When a new solution is selected, set _selectedSolution and update the reagent list. /// private void SolutionSelected(OptionButton.ItemSelectedEventArgs args) { SolutionOption.SelectId(args.Id); _selectedSolution = (string?) SolutionOption.SelectedMetadata; _addReagentWindow?.UpdateSolution(_selectedSolution); UpdateReagents(); } /// /// Update the solution options. /// public void UpdateSolutions(Dictionary? solutions) { SolutionOption.Clear(); _solutions = solutions; if (_solutions == null) return; int i = 0; foreach (var solution in _solutions.Keys) { SolutionOption.AddItem(solution, i); SolutionOption.SetItemMetadata(i, solution); if (solution == _selectedSolution) SolutionOption.Select(i); i++; } if (SolutionOption.ItemCount == 0) { // No applicable solutions Close(); Dispose(); } if (_selectedSolution == null || !_solutions.ContainsKey(_selectedSolution)) { // the previously selected solution is no longer valid. SolutionOption.Select(0); _selectedSolution = (string?) SolutionOption.SelectedMetadata; } } } }