Adds Gas Analyzer (#1591)
* -Started Gas Analyzer -TemperatureHelpers * Formatting * Adds PopupTooltip to NotifyManager * Revert Tooltip fuckery * Gas Analyzer gives proper error messages * Localization * Added a very wip gas analyzer ui * UI works, doesn't look good but hey * Safety checks * Fancy WIP gas mix bar * Gas Color * Gas Amount shows only 2 decimal places * -Made bar full width -Moved gas list into a table -Some gas bar things * IDropped something * Description * -Percentage -Padding * ItemStatus * -Proper Danger Warnings -Added Warning danger state * Pressure unit Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using static Content.Shared.GameObjects.Components.SharedGasAnalyzerComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Atmos
|
||||
{
|
||||
public class GasAnalyzerBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
public GasAnalyzerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
private GasAnalyzerWindow _menu;
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
_menu = new GasAnalyzerWindow(this);
|
||||
|
||||
_menu.OnClose += Close;
|
||||
_menu.OpenCentered();
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
_menu.Populate((GasAnalyzerBoundUserInterfaceState) state);
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
SendMessage(new GasAnalyzerRefreshMessage());
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
_menu.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Client.Utility;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Atmos
|
||||
{
|
||||
[RegisterComponent]
|
||||
class GasAnalyzerComponent : SharedGasAnalyzerComponent, IItemStatus
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)] private bool _uiUpdateNeeded;
|
||||
[ViewVariables] public GasAnalyzerDanger Danger { get; private set; }
|
||||
|
||||
Control IItemStatus.MakeControl()
|
||||
{
|
||||
return new StatusControl(this);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
if (!(curState is GasAnalyzerComponentState state))
|
||||
return;
|
||||
|
||||
Danger = state.Danger;
|
||||
_uiUpdateNeeded = true;
|
||||
}
|
||||
|
||||
private sealed class StatusControl : Control
|
||||
{
|
||||
private readonly GasAnalyzerComponent _parent;
|
||||
private readonly RichTextLabel _label;
|
||||
|
||||
public StatusControl(GasAnalyzerComponent parent)
|
||||
{
|
||||
_parent = parent;
|
||||
_label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
|
||||
AddChild(_label);
|
||||
|
||||
parent._uiUpdateNeeded = true;
|
||||
}
|
||||
|
||||
protected override void Update(FrameEventArgs args)
|
||||
{
|
||||
base.Update(args);
|
||||
|
||||
if (!_parent._uiUpdateNeeded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_parent._uiUpdateNeeded = false;
|
||||
var color = _parent.Danger switch
|
||||
{
|
||||
GasAnalyzerDanger.Warning => "orange",
|
||||
GasAnalyzerDanger.Hazard => "red",
|
||||
_ => "green",
|
||||
};
|
||||
_label.SetMarkup(Loc.GetString("Pressure: [color={0}]{1}[/color]",
|
||||
color,
|
||||
Enum.GetName(typeof(GasAnalyzerDanger), _parent.Danger)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
284
Content.Client/GameObjects/Components/Atmos/GasAnalyzerMenu.cs
Normal file
284
Content.Client/GameObjects/Components/Atmos/GasAnalyzerMenu.cs
Normal file
@@ -0,0 +1,284 @@
|
||||
using System;
|
||||
using Content.Client.Animations;
|
||||
using Content.Client.GameObjects.EntitySystems;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Client.Utility;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Content.Shared.Utility;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics.Drawing;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using static Content.Shared.GameObjects.Components.SharedGasAnalyzerComponent;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Atmos
|
||||
{
|
||||
public class GasAnalyzerWindow : BaseWindow
|
||||
{
|
||||
public GasAnalyzerBoundUserInterface Owner { get; }
|
||||
|
||||
private readonly Control _topContainer;
|
||||
private readonly Control _statusContainer;
|
||||
|
||||
private readonly Label _nameLabel;
|
||||
|
||||
public TextureButton CloseButton { get; set; }
|
||||
|
||||
public GasAnalyzerWindow(GasAnalyzerBoundUserInterface owner)
|
||||
{
|
||||
var resourceCache = IoCManager.Resolve<IResourceCache>();
|
||||
|
||||
Owner = owner;
|
||||
var rootContainer = new LayoutContainer { Name = "WireRoot" };
|
||||
AddChild(rootContainer);
|
||||
|
||||
MouseFilter = MouseFilterMode.Stop;
|
||||
|
||||
var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
|
||||
var back = new StyleBoxTexture
|
||||
{
|
||||
Texture = panelTex,
|
||||
Modulate = Color.FromHex("#25252A"),
|
||||
};
|
||||
back.SetPatchMargin(StyleBox.Margin.All, 10);
|
||||
|
||||
var topPanel = new PanelContainer
|
||||
{
|
||||
PanelOverride = back,
|
||||
MouseFilter = MouseFilterMode.Pass
|
||||
};
|
||||
var bottomWrap = new LayoutContainer
|
||||
{
|
||||
Name = "BottomWrap"
|
||||
};
|
||||
|
||||
rootContainer.AddChild(topPanel);
|
||||
rootContainer.AddChild(bottomWrap);
|
||||
|
||||
LayoutContainer.SetAnchorPreset(topPanel, LayoutContainer.LayoutPreset.Wide);
|
||||
LayoutContainer.SetMarginBottom(topPanel, -80);
|
||||
|
||||
LayoutContainer.SetAnchorPreset(bottomWrap, LayoutContainer.LayoutPreset.VerticalCenterWide);
|
||||
LayoutContainer.SetGrowHorizontal(bottomWrap, LayoutContainer.GrowDirection.Both);
|
||||
|
||||
var topContainerWrap = new VBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(_topContainer = new VBoxContainer()),
|
||||
new Control {CustomMinimumSize = (0, 110)}
|
||||
}
|
||||
};
|
||||
|
||||
rootContainer.AddChild(topContainerWrap);
|
||||
|
||||
LayoutContainer.SetAnchorPreset(topContainerWrap, LayoutContainer.LayoutPreset.Wide);
|
||||
|
||||
var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
|
||||
var fontSmall = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 10);
|
||||
|
||||
Button refreshButton;
|
||||
var topRow = new MarginContainer
|
||||
{
|
||||
MarginLeftOverride = 4,
|
||||
MarginTopOverride = 2,
|
||||
MarginRightOverride = 12,
|
||||
MarginBottomOverride = 2,
|
||||
Children =
|
||||
{
|
||||
new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(_nameLabel = new Label
|
||||
{
|
||||
Text = Loc.GetString("Gas Analyzer"),
|
||||
FontOverride = font,
|
||||
FontColorOverride = StyleNano.NanoGold,
|
||||
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
||||
}),
|
||||
new Control
|
||||
{
|
||||
CustomMinimumSize = (20, 0),
|
||||
SizeFlagsHorizontal = SizeFlags.Expand
|
||||
},
|
||||
(refreshButton = new Button {Text = "Refresh"}), //TODO: refresh icon?
|
||||
new Control
|
||||
{
|
||||
CustomMinimumSize = (2, 0),
|
||||
},
|
||||
(CloseButton = new TextureButton
|
||||
{
|
||||
StyleClasses = {SS14Window.StyleClassWindowCloseButton},
|
||||
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
refreshButton.OnPressed += a =>
|
||||
{
|
||||
Owner.Refresh();
|
||||
};
|
||||
|
||||
var middle = new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#202025") },
|
||||
Children =
|
||||
{
|
||||
new MarginContainer
|
||||
{
|
||||
MarginLeftOverride = 8,
|
||||
MarginRightOverride = 8,
|
||||
MarginTopOverride = 4,
|
||||
MarginBottomOverride = 4,
|
||||
Children =
|
||||
{
|
||||
(_statusContainer = new VBoxContainer())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_topContainer.AddChild(topRow);
|
||||
_topContainer.AddChild(new PanelContainer
|
||||
{
|
||||
CustomMinimumSize = (0, 2),
|
||||
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#525252ff") }
|
||||
});
|
||||
_topContainer.AddChild(middle);
|
||||
_topContainer.AddChild(new PanelContainer
|
||||
{
|
||||
CustomMinimumSize = (0, 2),
|
||||
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#525252ff") }
|
||||
});
|
||||
CloseButton.OnPressed += _ => Close();
|
||||
LayoutContainer.SetSize(this, (300, 200));
|
||||
}
|
||||
|
||||
|
||||
public void Populate(GasAnalyzerBoundUserInterfaceState state)
|
||||
{
|
||||
_statusContainer.RemoveAllChildren();
|
||||
if (state.Error != null)
|
||||
{
|
||||
_statusContainer.AddChild(new Label
|
||||
{
|
||||
Text = Loc.GetString("Error: {0}", state.Error),
|
||||
FontColorOverride = Color.Red
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
_statusContainer.AddChild(new Label
|
||||
{
|
||||
Text = Loc.GetString("Pressure: {0:0.##} kPa", state.Pressure)
|
||||
});
|
||||
_statusContainer.AddChild(new Label
|
||||
{
|
||||
Text = Loc.GetString("Temperature: {0:0.#}K ({1:0.#}°C)", state.Pressure, TemperatureHelpers.KelvinToCelsius(state.Pressure))
|
||||
});
|
||||
// Return here cause all that stuff down there is gas stuff (so we don't get the seperators)
|
||||
if (state.Gases.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Seperator
|
||||
_statusContainer.AddChild(new Control
|
||||
{
|
||||
CustomMinimumSize = new Vector2(0, 10)
|
||||
});
|
||||
|
||||
// Add a table with all the gases
|
||||
var tableKey = new VBoxContainer();
|
||||
var tableVal = new VBoxContainer();
|
||||
_statusContainer.AddChild(new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
tableKey,
|
||||
new Control
|
||||
{
|
||||
CustomMinimumSize = new Vector2(20, 0)
|
||||
},
|
||||
tableVal
|
||||
}
|
||||
});
|
||||
// This is the gas bar thingy
|
||||
var height = 30;
|
||||
var minSize = 24; // This basically allows gases which are too small, to be shown properly
|
||||
var gasBar = new HBoxContainer
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
CustomMinimumSize = new Vector2(0, height)
|
||||
};
|
||||
// Seperator
|
||||
_statusContainer.AddChild(new Control
|
||||
{
|
||||
CustomMinimumSize = new Vector2(0, 10)
|
||||
});
|
||||
|
||||
var totalGasAmount = 0f;
|
||||
foreach (var gas in state.Gases)
|
||||
{
|
||||
totalGasAmount += gas.Amount;
|
||||
}
|
||||
|
||||
for (int i = 0; i < state.Gases.Length; i++)
|
||||
{
|
||||
var gas = state.Gases[i];
|
||||
var color = Color.FromHex($"#{gas.Color}", Color.White);
|
||||
// Add to the table
|
||||
tableKey.AddChild(new Label
|
||||
{
|
||||
Text = Loc.GetString(gas.Name)
|
||||
});
|
||||
tableVal.AddChild(new Label
|
||||
{
|
||||
Text = Loc.GetString("{0:0.##} mol", gas.Amount)
|
||||
});
|
||||
|
||||
// Add to the gas bar //TODO: highlight the currently hover one
|
||||
var left = (i == 0) ? 0f : 2f;
|
||||
var right = (i == state.Gases.Length - 1) ? 0f : 2f;
|
||||
gasBar.AddChild(new PanelContainer
|
||||
{
|
||||
ToolTip = Loc.GetString("{0}: {1:0.##} mol ({2:0.#}%)", gas.Name, gas.Amount, (gas.Amount / totalGasAmount) * 100),
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||
SizeFlagsStretchRatio = gas.Amount,
|
||||
MouseFilter = MouseFilterMode.Pass,
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = color,
|
||||
PaddingLeft = left,
|
||||
PaddingRight = right
|
||||
},
|
||||
CustomMinimumSize = new Vector2(minSize, 0)
|
||||
});
|
||||
}
|
||||
_statusContainer.AddChild(gasBar);
|
||||
}
|
||||
|
||||
protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
|
||||
{
|
||||
return DragMode.Move;
|
||||
}
|
||||
|
||||
protected override bool HasPoint(Vector2 point)
|
||||
{
|
||||
// This makes it so our base window won't count for hit tests,
|
||||
// but we will still receive mouse events coming in from Pass mouse filter mode.
|
||||
// So basically, it perfectly shells out the hit tests to the panels we have!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user