diff --git a/Content.Client/Power/APC/ApcBoundUserInterface.cs b/Content.Client/Power/APC/ApcBoundUserInterface.cs index fd4724c544..453f11a8de 100644 --- a/Content.Client/Power/APC/ApcBoundUserInterface.cs +++ b/Content.Client/Power/APC/ApcBoundUserInterface.cs @@ -1,38 +1,24 @@ -using System; -using Content.Client.Stylesheets; +using Content.Client.Power.APC.UI; using Content.Shared.APC; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.Graphics; -using Robust.Client.UserInterface.Controls; -using Robust.Client.UserInterface.CustomControls; using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using static Robust.Client.UserInterface.Controls.BoxContainer; +using Robust.Shared.ViewVariables; namespace Content.Client.Power.APC { [UsedImplicitly] public class ApcBoundUserInterface : BoundUserInterface { - private ApcWindow? _window; - private BaseButton? _breakerButton; - private Label? _externalPowerStateLabel; - private ProgressBar? _chargeBar; + [ViewVariables] private ApcMenu? _menu; protected override void Open() { base.Open(); - _window = new ApcWindow(); - _window.OnClose += Close; - _window.OpenCentered(); - - _breakerButton = _window.BreakerButton; - _breakerButton.OnPressed += _ => SendMessage(new ApcToggleMainBreakerMessage()); - - _externalPowerStateLabel = _window.ExternalPowerStateLabel; - _chargeBar = _window.ChargeBar; + _menu = new ApcMenu(this); + _menu.OnClose += Close; + _menu.OpenCentered(); } public ApcBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) @@ -44,84 +30,12 @@ namespace Content.Client.Power.APC base.UpdateState(state); var castState = (ApcBoundInterfaceState) state; - - if (_breakerButton != null) - { - _breakerButton.Pressed = castState.MainBreaker; - } - - if (_externalPowerStateLabel != null) - { - switch (castState.ApcExternalPower) - { - case ApcExternalPowerState.None: - _externalPowerStateLabel.Text = "None"; - _externalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateNone); - break; - case ApcExternalPowerState.Low: - _externalPowerStateLabel.Text = "Low"; - _externalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateLow); - break; - case ApcExternalPowerState.Good: - _externalPowerStateLabel.Text = "Good"; - _externalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - - if (_chargeBar != null) - { - _chargeBar.Value = castState.Charge; - UpdateChargeBarColor(castState.Charge); - - if (_window != null) - { - var chargePercentage = (castState.Charge / _chargeBar.MaxValue) * 100.0f; - _window.ChargePercentage.Text = " " + chargePercentage.ToString("0.00") + "%"; - } - } + _menu?.UpdateState(castState); } - private void UpdateChargeBarColor(float charge) + public void BreakerPressed() { - if (_chargeBar == null) - { - return; - } - - var normalizedCharge = charge / _chargeBar.MaxValue; - - const float leftHue = 0.0f; // Red - const float middleHue = 0.066f; // Orange - const float rightHue = 0.33f; // Green - const float saturation = 1.0f; // Uniform saturation - const float value = 0.8f; // Uniform value / brightness - const float alpha = 1.0f; // Uniform alpha - - // These should add up to 1.0 or your transition won't be smooth - const float leftSideSize = 0.5f; // Fraction of _chargeBar lerped from leftHue to middleHue - const float rightSideSize = 0.5f; // Fraction of _chargeBar lerped from middleHue to rightHue - - float finalHue; - if (normalizedCharge <= leftSideSize) - { - normalizedCharge /= leftSideSize; // Adjust range to 0.0 to 1.0 - finalHue = MathHelper.Lerp(leftHue, middleHue, normalizedCharge); - } - else - { - normalizedCharge = (normalizedCharge - leftSideSize) / rightSideSize; // Adjust range to 0.0 to 1.0. - finalHue = MathHelper.Lerp(middleHue, rightHue, normalizedCharge); - } - - // Check if null first to avoid repeatedly creating this. - _chargeBar.ForegroundStyleBoxOverride ??= new StyleBoxFlat(); - - var foregroundStyleBoxOverride = (StyleBoxFlat) _chargeBar.ForegroundStyleBoxOverride; - foregroundStyleBoxOverride.BackgroundColor = - Color.FromHsv(new Vector4(finalHue, saturation, value, alpha)); + SendMessage(new ApcToggleMainBreakerMessage()); } protected override void Dispose(bool disposing) @@ -130,69 +44,7 @@ namespace Content.Client.Power.APC if (disposing) { - _window?.Dispose(); - } - } - - private class ApcWindow : SS14Window - { - public Button BreakerButton { get; set; } - public Label ExternalPowerStateLabel { get; set; } - public ProgressBar ChargeBar { get; set; } - public Label ChargePercentage { get; set; } - - public ApcWindow() - { - Title = "APC"; - var rows = new BoxContainer - { - Orientation = LayoutOrientation.Vertical - }; - - var statusHeader = new Label {Text = "Power Status: "}; - rows.AddChild(statusHeader); - - var breaker = new BoxContainer - { - Orientation = LayoutOrientation.Horizontal - }; - var breakerLabel = new Label {Text = "Main Breaker: "}; - BreakerButton = new CheckButton {Text = "Toggle"}; - breaker.AddChild(breakerLabel); - breaker.AddChild(BreakerButton); - rows.AddChild(breaker); - - var externalStatus = new BoxContainer - { - Orientation = LayoutOrientation.Horizontal - }; - var externalStatusLabel = new Label {Text = "External Power: "}; - ExternalPowerStateLabel = new Label {Text = "Good"}; - ExternalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood); - externalStatus.AddChild(externalStatusLabel); - externalStatus.AddChild(ExternalPowerStateLabel); - rows.AddChild(externalStatus); - - var charge = new BoxContainer - { - Orientation = LayoutOrientation.Horizontal - }; - var chargeLabel = new Label {Text = "Charge:"}; - ChargeBar = new ProgressBar - { - HorizontalExpand = true, - MinValue = 0.0f, - MaxValue = 1.0f, - Page = 0.0f, - Value = 0.5f - }; - ChargePercentage = new Label(); - charge.AddChild(chargeLabel); - charge.AddChild(ChargeBar); - charge.AddChild(ChargePercentage); - rows.AddChild(charge); - - Contents.AddChild(rows); + _menu?.Dispose(); } } } diff --git a/Content.Client/Power/APC/UI/ApcMenu.xaml b/Content.Client/Power/APC/UI/ApcMenu.xaml new file mode 100644 index 0000000000..fbd0036df3 --- /dev/null +++ b/Content.Client/Power/APC/UI/ApcMenu.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/Content.Client/Power/APC/UI/ApcMenu.xaml.cs b/Content.Client/Power/APC/UI/ApcMenu.xaml.cs new file mode 100644 index 0000000000..60b0cb1d22 --- /dev/null +++ b/Content.Client/Power/APC/UI/ApcMenu.xaml.cs @@ -0,0 +1,109 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.IoC; +using System; +using Content.Client.Stylesheets; +using Content.Shared.APC; +using Robust.Client.Graphics; +using Robust.Shared.GameObjects; +using Robust.Shared.Localization; +using Robust.Shared.Maths; + +namespace Content.Client.Power.APC.UI +{ + [GenerateTypedNameReferences] + public partial class ApcMenu : SS14Window + { + public ApcMenu(ApcBoundUserInterface owner) + { + IoCManager.InjectDependencies(this); + RobustXamlLoader.Load(this); + + BreakerButton.OnPressed += _ => owner.BreakerPressed(); + } + + public void UpdateState(BoundUserInterfaceState state) + { + var castState = (ApcBoundInterfaceState) state; + + if (BreakerButton != null) + { + BreakerButton.Pressed = castState.MainBreaker; + } + + if (ExternalPowerStateLabel != null) + { + switch (castState.ApcExternalPower) + { + case ApcExternalPowerState.None: + ExternalPowerStateLabel.Text = Loc.GetString("apc-menu-power-state-none"); + ExternalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateNone); + break; + case ApcExternalPowerState.Low: + ExternalPowerStateLabel.Text = Loc.GetString("apc-menu-power-state-low"); + ExternalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateLow); + break; + case ApcExternalPowerState.Good: + ExternalPowerStateLabel.Text = Loc.GetString("apc-menu-power-state-good"); + ExternalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + if (ChargeBar != null) + { + ChargeBar.Value = castState.Charge; + UpdateChargeBarColor(castState.Charge); + + if (APCMenu != null) + { + var chargePercentage = (castState.Charge / ChargeBar.MaxValue) * 100.0f; + ChargePercentage.Text = " " + chargePercentage.ToString("0.00") + "%"; + } + } + } + + private void UpdateChargeBarColor(float charge) + { + if (ChargeBar == null) + { + return; + } + + var normalizedCharge = charge / ChargeBar.MaxValue; + + const float leftHue = 0.0f; // Red + const float middleHue = 0.066f; // Orange + const float rightHue = 0.33f; // Green + const float saturation = 1.0f; // Uniform saturation + const float value = 0.8f; // Uniform value / brightness + const float alpha = 1.0f; // Uniform alpha + + // These should add up to 1.0 or your transition won't be smooth + const float leftSideSize = 0.5f; // Fraction of ChargeBar lerped from leftHue to middleHue + const float rightSideSize = 0.5f; // Fraction of ChargeBar lerped from middleHue to rightHue + + float finalHue; + if (normalizedCharge <= leftSideSize) + { + normalizedCharge /= leftSideSize; // Adjust range to 0.0 to 1.0 + finalHue = MathHelper.Lerp(leftHue, middleHue, normalizedCharge); + } + else + { + normalizedCharge = (normalizedCharge - leftSideSize) / rightSideSize; // Adjust range to 0.0 to 1.0. + finalHue = MathHelper.Lerp(middleHue, rightHue, normalizedCharge); + } + + // Check if null first to avoid repeatedly creating this. + ChargeBar.ForegroundStyleBoxOverride ??= new StyleBoxFlat(); + + var foregroundStyleBoxOverride = (StyleBoxFlat) ChargeBar.ForegroundStyleBoxOverride; + foregroundStyleBoxOverride.BackgroundColor = + Color.FromHsv(new Vector4(finalHue, saturation, value, alpha)); + } + } +} diff --git a/Resources/Locale/en-US/ui/power-apc.ftl b/Resources/Locale/en-US/ui/power-apc.ftl new file mode 100644 index 0000000000..c283eb56af --- /dev/null +++ b/Resources/Locale/en-US/ui/power-apc.ftl @@ -0,0 +1,11 @@ +apc-menu-title = APC +apc-menu-breaker-label = Main Breaker:{" "} +apc-menu-breaker-button = Toggle +apc-menu-external-label = External Power:{" "} +apc-menu-charge-label = Charge:{" "} + +# For the power state label + +apc-menu-power-state-good = Good +apc-menu-power-state-low = Low +apc-menu-power-state-none = None