using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
+using Vector4 = Robust.Shared.Maths.Vector4;
namespace Content.Client.Power;
// Update power value
// Don't use SI prefixes, just give the number in W, so that it is readily apparent which consumer is using a lot of power.
button.PowerValue.Text = Loc.GetString("power-monitoring-window-button-value", ("value", Math.Round(entry.PowerValue).ToString("N0")));
+
+ // Update battery level if applicable
+ if (entry.BatteryLevel != null)
+ {
+ button.BatteryLevel.Value = entry.BatteryLevel.Value;
+ button.BatteryLevel.Visible = true;
+
+ button.BatteryPercentage.Text = entry.BatteryLevel.Value.ToString("P0");
+ button.BatteryPercentage.Visible = true;
+
+ // Set progress bar color based on percentage
+ var color = Color.FromHsv(new Vector4(entry.BatteryLevel.Value * 0.33f, 1, 1, 1));
+
+ button.BatteryLevel.ForegroundStyleBoxOverride = new StyleBoxFlat { BackgroundColor = color };
+ }
+ else
+ {
+ button.BatteryLevel.Visible = false;
+ button.BatteryPercentage.Visible = false;
+ }
}
private void UpdateEntrySourcesOrLoads(BoxContainer masterContainer, BoxContainer currentContainer, PowerMonitoringConsoleEntry[]? entries, SpriteSpecifier.Texture icon)
public BoxContainer MainContainer;
public TextureRect TextureRect;
public Label NameLocalized;
+
+ public ProgressBar BatteryLevel;
+ public PanelContainer BackgroundPanel;
+ public Label BatteryPercentage;
+
public Label PowerValue;
public PowerMonitoringButton()
MainContainer.AddChild(NameLocalized);
+ BatteryLevel = new ProgressBar()
+ {
+ SetWidth = 47f,
+ SetHeight = 20f,
+ Margin = new Thickness(15, 0, 0, 0),
+ MaxValue = 1,
+ Visible = false,
+ BackgroundStyleBoxOverride = new StyleBoxFlat { BackgroundColor = Color.Black },
+ };
+
+ MainContainer.AddChild(BatteryLevel);
+
+ BackgroundPanel = new PanelContainer
+ {
+ // Draw a half-transparent box over the battery level to make the text more readable.
+ PanelOverride = new StyleBoxFlat
+ {
+ BackgroundColor = new Color(0, 0, 0, 0.9f)
+ },
+ HorizontalAlignment = HAlignment.Center,
+ VerticalAlignment = VAlignment.Center,
+ HorizontalExpand = true,
+ VerticalExpand = true,
+ // Box is undersized perfectly compared to the progress bar, so a little bit of the unaffected progress bar is visible.
+ SetSize = new Vector2(43f, 16f)
+ };
+
+ BatteryLevel.AddChild(BackgroundPanel);
+
+ BatteryPercentage = new Label()
+ {
+ VerticalAlignment = VAlignment.Center,
+ HorizontalAlignment = HAlignment.Center,
+ Align = Label.AlignMode.Center,
+ SetWidth = 45f,
+ MinWidth = 20f,
+ Margin = new Thickness(10, -4, 10, 0),
+ ClipText = true,
+ Visible = false,
+ };
+
+ BackgroundPanel.AddChild(BatteryPercentage);
+
PowerValue = new Label()
{
HorizontalAlignment = HAlignment.Right,
continue;
// Get the device power stats
- var powerValue = GetPrimaryPowerValues(ent, device, out var powerSupplied, out var powerUsage, out var batteryUsage);
+ var powerStats = GetPowerStats(ent, device);
+ //, out var powerSupplied, out var powerUsage, out var batteryUsage);
// Update all running totals
- totalSources += powerSupplied;
- totalLoads += powerUsage;
- totalBatteryUsage += batteryUsage;
+ totalSources += powerStats.PowerSupplied;
+ totalLoads += powerStats.PowerUsage;
+ totalBatteryUsage += powerStats.BatteryUsage;
// Continue on if the device is not in the current focus group
if (device.Group != component.FocusGroup)
continue;
// Generate a new console entry with which to populate the UI
- var entry = new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), device.Group, powerValue);
+ var entry = new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), device.Group, powerStats.PowerValue, powerStats.BatteryLevel);
allEntries.Add(entry);
}
loadsForFocus.ToArray()));
}
- private double GetPrimaryPowerValues(EntityUid uid, PowerMonitoringDeviceComponent device, out double powerSupplied, out double powerUsage, out double batteryUsage)
+ private PowerStats GetPowerStats(EntityUid uid, PowerMonitoringDeviceComponent device)
{
- var powerValue = 0d;
- powerSupplied = 0d;
- powerUsage = 0d;
- batteryUsage = 0d;
+ var stats = new PowerStats();
if (device.Group == PowerMonitoringConsoleGroup.Generator)
{
// This covers most power sources
if (TryComp<PowerSupplierComponent>(uid, out var supplier))
{
- powerValue = supplier.CurrentSupply;
- powerSupplied += powerValue;
+ stats.PowerValue = supplier.CurrentSupply;
+ stats.PowerSupplied += stats.PowerValue;
}
// Edge case: radiation collectors
else if (TryComp<BatteryDischargerComponent>(uid, out var _) &&
TryComp<PowerNetworkBatteryComponent>(uid, out var battery))
{
- powerValue = battery.NetworkBattery.CurrentSupply;
- powerSupplied += powerValue;
+ stats.PowerValue = battery.NetworkBattery.CurrentSupply;
+ stats.PowerSupplied += stats.PowerValue;
+
+
+ stats.BatteryLevel = GetBatteryLevel(uid);
}
}
if (TryComp<PowerNetworkBatteryComponent>(uid, out var battery))
{
- powerValue = battery.CurrentSupply;
+ stats.BatteryLevel = GetBatteryLevel(uid);
+
+ stats.PowerValue = battery.CurrentSupply;
// Load due to network battery recharging
- powerUsage += Math.Max(battery.CurrentReceiving - battery.CurrentSupply, 0d);
+ stats.PowerUsage += Math.Max(battery.CurrentReceiving - battery.CurrentSupply, 0d);
// Track battery usage
- batteryUsage += Math.Max(battery.CurrentSupply - battery.CurrentReceiving, 0d);
+ stats.BatteryUsage += Math.Max(battery.CurrentSupply - battery.CurrentReceiving, 0d);
// Records loads attached to APCs
if (device.Group == PowerMonitoringConsoleGroup.APC && battery.Enabled)
{
- powerUsage += battery.NetworkBattery.LoadingNetworkDemand;
+ stats.PowerUsage += battery.NetworkBattery.LoadingNetworkDemand;
}
}
}
if (childDevice.IsCollectionMaster && childDevice.ChildDevices.ContainsKey(uid))
continue;
- var childPowerValue = GetPrimaryPowerValues(child, childDevice, out var childPowerSupplied, out var childPowerUsage, out var childBatteryUsage);
+ var childResult = GetPowerStats(child, childDevice);
- powerValue += childPowerValue;
- powerSupplied += childPowerSupplied;
- powerUsage += childPowerUsage;
- batteryUsage += childBatteryUsage;
+ stats.PowerValue += childResult.PowerValue;
+ stats.PowerSupplied += childResult.PowerSupplied;
+ stats.PowerUsage += childResult.PowerUsage;
+ stats.BatteryUsage += childResult.BatteryUsage;
}
}
- return powerValue;
+ return stats;
+ }
+
+ private float? GetBatteryLevel(EntityUid uid)
+ {
+ if (!TryComp<BatteryComponent>(uid, out var battery))
+ return null;
+
+ var effectiveMax = battery.MaxCharge;
+ if (effectiveMax == 0)
+ effectiveMax = 1;
+
+ return battery.CurrentCharge / effectiveMax;
}
private void GetSourcesForNode(EntityUid uid, Node node, out List<PowerMonitoringConsoleEntry> sources)
continue;
}
- indexedSources.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, powerSupplier.CurrentSupply));
+ indexedSources.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, powerSupplier.CurrentSupply, GetBatteryLevel(ent)));
}
}
continue;
}
- indexedSources.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, entBattery.CurrentSupply));
+ indexedSources.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, entBattery.CurrentSupply, GetBatteryLevel(ent)));
}
}
for (int i = 0; i < sources.Count; i++)
{
var entry = sources[i];
- sources[i] = new PowerMonitoringConsoleEntry(entry.NetEntity, entry.Group, entry.PowerValue * powerFraction);
+ sources[i] = new PowerMonitoringConsoleEntry(entry.NetEntity, entry.Group, entry.PowerValue * powerFraction, entry.BatteryLevel);
}
}
continue;
}
- indexedLoads.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, powerConsumer.ReceivedPower));
+ indexedLoads.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, powerConsumer.ReceivedPower, GetBatteryLevel(ent)));
}
}
continue;
}
- indexedLoads.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, battery.CurrentReceiving));
+ indexedLoads.Add(ent, new PowerMonitoringConsoleEntry(EntityManager.GetNetEntity(ent), entDevice.Group, battery.CurrentReceiving, GetBatteryLevel(ent)));
}
}
for (int i = 0; i < indexedLoads.Values.Count; i++)
{
var entry = loads[i];
- loads[i] = new PowerMonitoringConsoleEntry(entry.NetEntity, entry.Group, entry.PowerValue * powerFraction);
+ loads[i] = new PowerMonitoringConsoleEntry(entry.NetEntity, entry.Group, entry.PowerValue * powerFraction, entry.BatteryLevel);
}
}
Dirty(uid, component);
}
+
+ private struct PowerStats
+ {
+ public double PowerValue { get; set; }
+ public double PowerSupplied { get; set; }
+ public double PowerUsage { get; set; }
+ public double BatteryUsage { get; set; }
+ public float? BatteryLevel { get; set; }
+ }
}