committed by
GitHub
parent
ea60a81fdf
commit
103bc19508
459
Pow3r/Program.UI.cs
Normal file
459
Pow3r/Program.UI.cs
Normal file
@@ -0,0 +1,459 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ImGuiNET;
|
||||
using Robust.Shared.Maths;
|
||||
using static ImGuiNET.ImGui;
|
||||
using Color = System.Drawing.Color;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
using RobustVec2 = Robust.Shared.Maths.Vector2;
|
||||
using static Content.Server.Power.Pow3r.PowerState;
|
||||
|
||||
namespace Pow3r
|
||||
{
|
||||
internal sealed partial class Program
|
||||
{
|
||||
private bool _showDemo;
|
||||
|
||||
private Dictionary<NodeId, DisplayLoad> _displayLoads = new();
|
||||
private Dictionary<NodeId, DisplayBattery> _displayBatteries = new();
|
||||
private Dictionary<NodeId, DisplayNetwork> _displayNetworks = new();
|
||||
private Dictionary<NodeId, DisplaySupply> _displaySupplies = new();
|
||||
|
||||
private void DoUI(float frameTime)
|
||||
{
|
||||
if (BeginMainMenuBar())
|
||||
{
|
||||
_showDemo ^= MenuItem("Demo");
|
||||
EndMainMenuBar();
|
||||
}
|
||||
|
||||
SetNextWindowSize(new Vector2(150, 200));
|
||||
|
||||
Begin("CreateButtons",
|
||||
ImGuiWindowFlags.NoTitleBar |
|
||||
ImGuiWindowFlags.NoCollapse |
|
||||
ImGuiWindowFlags.NoResize);
|
||||
|
||||
if (Button("Generator"))
|
||||
{
|
||||
var id = AllocId();
|
||||
_state.Supplies.Add(id, new Supply { Id = id });
|
||||
_displaySupplies.Add(id, new DisplaySupply());
|
||||
}
|
||||
|
||||
if (Button("Load"))
|
||||
{
|
||||
var id = AllocId();
|
||||
_state.Loads.Add(id, new Load { Id = id });
|
||||
_displayLoads.Add(id, new DisplayLoad());
|
||||
}
|
||||
|
||||
if (Button("Network"))
|
||||
{
|
||||
var id = AllocId();
|
||||
_state.Networks.Add(id, new Network { Id = id });
|
||||
_displayNetworks.Add(id, new DisplayNetwork());
|
||||
}
|
||||
|
||||
if (Button("Battery"))
|
||||
{
|
||||
var id = AllocId();
|
||||
_state.Batteries.Add(id, new Battery { Id = id });
|
||||
_displayBatteries.Add(id, new DisplayBattery());
|
||||
}
|
||||
|
||||
Checkbox("Paused", ref _paused);
|
||||
SliderInt("TPS", ref _tps, 1, 120);
|
||||
SetNextItemWidth(-1);
|
||||
Combo("", ref _currentSolver, _solverNames, _solverNames.Length);
|
||||
|
||||
if (Button("Single step"))
|
||||
RunSingleStep();
|
||||
|
||||
End();
|
||||
|
||||
Begin("Simulating timing");
|
||||
|
||||
PlotLines("Tick time (ms)", ref _simTickTimes[0], MaxTickData, _tickDataIdx + 1,
|
||||
$"{_simTickTimes[_tickDataIdx]:N2}",
|
||||
0,
|
||||
0.1f, new Vector2(250, 150));
|
||||
|
||||
End();
|
||||
|
||||
Begin("Frame timings");
|
||||
|
||||
PlotLines("Frame (ms)", ref _frameTimings[0], _frameTimings.Length, _frameTimeIdx + 1,
|
||||
$"{_frameTimings[_frameTimeIdx]:N2}",
|
||||
0,
|
||||
33.333f, new Vector2(250, 150));
|
||||
|
||||
End();
|
||||
|
||||
{
|
||||
Begin("Memory");
|
||||
|
||||
var heap = GC.GetTotalMemory(false);
|
||||
Text($"Managed heap: {heap>>20} MiB");
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
foreach (var network in _state.Networks.Values)
|
||||
{
|
||||
var displayNetwork = _displayNetworks[network.Id];
|
||||
Begin($"Network {network.Id}##Gen{network.Id}");
|
||||
|
||||
Text($"Height: {network.Height}");
|
||||
|
||||
displayNetwork.CurrentWindowPos = CalcWindowCenter();
|
||||
|
||||
if (Button("Delete"))
|
||||
{
|
||||
_remQueue.Enqueue(network);
|
||||
|
||||
if (_linking == network)
|
||||
{
|
||||
_linking = null;
|
||||
}
|
||||
}
|
||||
|
||||
SameLine();
|
||||
|
||||
if (_linking != null)
|
||||
{
|
||||
if (_linking == network && Button("Cancel"))
|
||||
{
|
||||
_linking = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Button("Link..."))
|
||||
{
|
||||
_linking = network;
|
||||
}
|
||||
}
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
foreach (var load in _state.Loads.Values)
|
||||
{
|
||||
var displayLoad = _displayLoads[load.Id];
|
||||
|
||||
Begin($"Load {load.Id}##Load{load.Id}");
|
||||
|
||||
Checkbox("Enabled", ref load.Enabled);
|
||||
SliderFloat("Desired", ref load.DesiredPower, 0, 1000, "%.0f W");
|
||||
|
||||
displayLoad.CurrentWindowPos = CalcWindowCenter();
|
||||
|
||||
PlotLines("", ref displayLoad.ReceivedPowerData[0], MaxTickData, _tickDataIdx + 1,
|
||||
$"Receiving: {load.ReceivingPower:N1} W",
|
||||
0,
|
||||
load.DesiredPower, new Vector2(250, 150));
|
||||
|
||||
if (Button("Delete"))
|
||||
{
|
||||
_remQueue.Enqueue(load);
|
||||
}
|
||||
|
||||
SameLine();
|
||||
if (_linking != null)
|
||||
{
|
||||
if (Button("Link"))
|
||||
{
|
||||
_linking.Loads.Add(load.Id);
|
||||
_linking = null;
|
||||
RefreshLinks();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (load.LinkedNetwork != default && Button("Unlink"))
|
||||
{
|
||||
var net = _state.Networks[load.LinkedNetwork];
|
||||
net.Loads.Remove(load.Id);
|
||||
load.LinkedNetwork = default;
|
||||
}
|
||||
}
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
foreach (var supply in _state.Supplies.Values)
|
||||
{
|
||||
var displaySupply = _displaySupplies[supply.Id];
|
||||
Begin($"Generator {supply.Id}##Gen{supply.Id}");
|
||||
|
||||
Checkbox("Enabled", ref supply.Enabled);
|
||||
SliderFloat("Available", ref supply.MaxSupply, 0, 1000, "%.0f W");
|
||||
SliderFloat("Ramp", ref supply.SupplyRampRate, 0, 100, "%.0f W/s");
|
||||
SliderFloat("Tolerance", ref supply.SupplyRampTolerance, 0, 100, "%.0f W");
|
||||
|
||||
displaySupply.CurrentWindowPos = CalcWindowCenter();
|
||||
|
||||
Text($"Ramp Position: {supply.SupplyRampPosition:N1}");
|
||||
|
||||
PlotLines("", ref displaySupply.SuppliedPowerData[0], MaxTickData, _tickDataIdx + 1,
|
||||
$"Supply: {supply.CurrentSupply:N1} W",
|
||||
0, supply.MaxSupply, new Vector2(250, 150));
|
||||
|
||||
if (Button("Delete"))
|
||||
{
|
||||
_remQueue.Enqueue(supply);
|
||||
}
|
||||
|
||||
SameLine();
|
||||
if (_linking != null)
|
||||
{
|
||||
if (Button("Link"))
|
||||
{
|
||||
_linking.Supplies.Add(supply.Id);
|
||||
_linking = null;
|
||||
RefreshLinks();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (supply.LinkedNetwork != default && Button("Unlink"))
|
||||
{
|
||||
var net = _state.Networks[supply.LinkedNetwork];
|
||||
net.Supplies.Remove(supply.Id);
|
||||
supply.LinkedNetwork = default;
|
||||
}
|
||||
}
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
foreach (var battery in _state.Batteries.Values)
|
||||
{
|
||||
var displayBattery = _displayBatteries[battery.Id];
|
||||
|
||||
Begin($"Battery {battery.Id}##Bat{battery.Id}");
|
||||
|
||||
Checkbox("Enabled", ref battery.Enabled);
|
||||
SliderFloat("Capacity", ref battery.Capacity, 0, 100000, "%.0f J");
|
||||
SliderFloat("Max charge rate", ref battery.MaxChargeRate, 0, 1000, "%.0f W");
|
||||
SliderFloat("Max supply", ref battery.MaxSupply, 0, 1000, "%.0f W");
|
||||
SliderFloat("Ramp", ref battery.SupplyRampRate, 0, 100, "%.0f W/s");
|
||||
SliderFloat("Tolerance", ref battery.SupplyRampTolerance, 0, 100, "%.0f W");
|
||||
var percent = 100 * battery.Efficiency;
|
||||
SliderFloat("Efficiency", ref percent, 0, 100, "%.0f %%");
|
||||
battery.Efficiency = percent / 100;
|
||||
|
||||
displayBattery.CurrentWindowPos = CalcWindowCenter();
|
||||
|
||||
SliderFloat("Ramp position", ref battery.SupplyRampPosition, 0, battery.MaxSupply, "%.0f W");
|
||||
|
||||
PlotLines("", ref displayBattery.SuppliedPowerData[0], MaxTickData, _tickDataIdx + 1,
|
||||
$"OUT: {battery.CurrentSupply:N1} W",
|
||||
0, battery.MaxSupply + 1000, new Vector2(250, 75));
|
||||
|
||||
PlotLines("", ref displayBattery.ReceivingPowerData[0], MaxTickData, _tickDataIdx + 1,
|
||||
$"IN: {battery.CurrentReceiving:N1} W",
|
||||
0, battery.MaxChargeRate + 1000, new Vector2(250, 75));
|
||||
|
||||
PlotLines("", ref displayBattery.StoredPowerData[0], MaxTickData, _tickDataIdx + 1,
|
||||
$"Charge: {battery.CurrentStorage:N1} J",
|
||||
0, battery.Capacity, new Vector2(250, 75));
|
||||
|
||||
if (Button("Delete"))
|
||||
{
|
||||
_remQueue.Enqueue(battery);
|
||||
}
|
||||
|
||||
SameLine();
|
||||
if (_linking != null)
|
||||
{
|
||||
if (battery.LinkedNetworkCharging == default && Button("Link as load"))
|
||||
{
|
||||
_linking.BatteriesCharging.Add(battery.Id);
|
||||
_linking = null;
|
||||
RefreshLinks();
|
||||
}
|
||||
else
|
||||
{
|
||||
SameLine();
|
||||
if (battery.LinkedNetworkDischarging == default && Button("Link as supply"))
|
||||
{
|
||||
_linking.BatteriesDischarging.Add(battery.Id);
|
||||
_linking = null;
|
||||
RefreshLinks();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battery.LinkedNetworkCharging != default && Button("Unlink loading"))
|
||||
{
|
||||
var net = _state.Networks[battery.LinkedNetworkCharging];
|
||||
net.BatteriesCharging.Remove(battery.Id);
|
||||
battery.LinkedNetworkCharging = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
SameLine();
|
||||
if (battery.LinkedNetworkDischarging != default && Button("Unlink supplying"))
|
||||
{
|
||||
var net = _state.Networks[battery.LinkedNetworkDischarging];
|
||||
net.BatteriesDischarging.Remove(battery.Id);
|
||||
battery.LinkedNetworkDischarging = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Button("Empty"))
|
||||
battery.CurrentStorage = 0;
|
||||
SameLine();
|
||||
if (Button("Fill"))
|
||||
battery.CurrentStorage = battery.Capacity;
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
var bgDrawList = GetBackgroundDrawList();
|
||||
|
||||
foreach (var network in _state.Networks.Values)
|
||||
{
|
||||
var displayNet = _displayNetworks[network.Id];
|
||||
foreach (var supplyId in network.Supplies)
|
||||
{
|
||||
var supply = _displaySupplies[supplyId];
|
||||
DrawArrowLine(bgDrawList, displayNet.CurrentWindowPos, supply.CurrentWindowPos, Color.LawnGreen);
|
||||
}
|
||||
|
||||
foreach (var loadId in network.Loads)
|
||||
{
|
||||
var load = _displayLoads[loadId];
|
||||
DrawArrowLine(bgDrawList, load.CurrentWindowPos, displayNet.CurrentWindowPos, Color.Red);
|
||||
}
|
||||
|
||||
foreach (var batteryId in network.BatteriesCharging)
|
||||
{
|
||||
var battery = _displayBatteries[batteryId];
|
||||
DrawArrowLine(bgDrawList, battery.CurrentWindowPos, displayNet.CurrentWindowPos, Color.Purple);
|
||||
}
|
||||
|
||||
foreach (var batteryId in network.BatteriesDischarging)
|
||||
{
|
||||
var battery = _displayBatteries[batteryId];
|
||||
DrawArrowLine(bgDrawList, displayNet.CurrentWindowPos, battery.CurrentWindowPos, Color.Cyan);
|
||||
}
|
||||
}
|
||||
|
||||
if (_showDemo)
|
||||
{
|
||||
ShowDemoWindow();
|
||||
}
|
||||
|
||||
var reLink = false;
|
||||
while (_remQueue.TryDequeue(out var item))
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case Network n:
|
||||
_state.Networks.Remove(n.Id);
|
||||
_displayNetworks.Remove(n.Id);
|
||||
reLink = true;
|
||||
break;
|
||||
|
||||
case Supply s:
|
||||
_state.Supplies.Remove(s.Id);
|
||||
_state.Networks.Values.ForEach(n => n.Supplies.Remove(s.Id));
|
||||
_displaySupplies.Remove(s.Id);
|
||||
break;
|
||||
|
||||
case Load l:
|
||||
_state.Loads.Remove(l.Id);
|
||||
_state.Networks.Values.ForEach(n => n.Loads.Remove(l.Id));
|
||||
_displayLoads.Remove(l.Id);
|
||||
break;
|
||||
|
||||
case Battery b:
|
||||
_state.Batteries.Remove(b.Id);
|
||||
_state.Networks.Values.ForEach(n => n.BatteriesCharging.Remove(b.Id));
|
||||
_state.Networks.Values.ForEach(n => n.BatteriesDischarging.Remove(b.Id));
|
||||
_displayBatteries.Remove(b.Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reLink)
|
||||
RefreshLinks();
|
||||
}
|
||||
|
||||
|
||||
private void DrawArrowLine(ImDrawListPtr ptr, Vector2 a, Vector2 b, Color color)
|
||||
{
|
||||
// A: to
|
||||
// B: from
|
||||
|
||||
const float wingLength = 15;
|
||||
const float thickness = 3;
|
||||
|
||||
var cvtColor = CvtColor(color);
|
||||
|
||||
ptr.AddLine(a, b, cvtColor, thickness);
|
||||
|
||||
var angleA = Angle.FromDegrees(45);
|
||||
var angleB = Angle.FromDegrees(-45);
|
||||
|
||||
var mid = (a + b) / 2;
|
||||
var dir = -Vector2.Normalize(a - b);
|
||||
|
||||
var rVec = new RobustVec2(dir.X, dir.Y);
|
||||
|
||||
var wingADir = CvtVec(angleA.RotateVec(rVec));
|
||||
var wingBDir = CvtVec(angleB.RotateVec(rVec));
|
||||
|
||||
var wingA = wingADir * wingLength + mid;
|
||||
var wingB = wingBDir * wingLength + mid;
|
||||
|
||||
ptr.AddLine(mid, wingA, cvtColor, thickness);
|
||||
ptr.AddLine(mid, wingB, cvtColor, thickness);
|
||||
}
|
||||
|
||||
private static uint CvtColor(Color color)
|
||||
{
|
||||
return color.R | ((uint) color.G << 8) | ((uint) color.B << 16) | ((uint) color.A << 24);
|
||||
}
|
||||
|
||||
private static Vector2 CalcWindowCenter()
|
||||
{
|
||||
return GetWindowPos() + GetWindowSize() / 2;
|
||||
}
|
||||
|
||||
private static Vector2 CvtVec(RobustVec2 vec)
|
||||
{
|
||||
return new Vector2(vec.X, vec.Y);
|
||||
}
|
||||
|
||||
private sealed class DisplayNetwork
|
||||
{
|
||||
public Vector2 CurrentWindowPos;
|
||||
}
|
||||
|
||||
private sealed class DisplayBattery
|
||||
{
|
||||
public Vector2 CurrentWindowPos;
|
||||
public readonly float[] ReceivingPowerData = new float[MaxTickData];
|
||||
public readonly float[] SuppliedPowerData = new float[MaxTickData];
|
||||
public readonly float[] StoredPowerData = new float[MaxTickData];
|
||||
}
|
||||
|
||||
private sealed class DisplayLoad
|
||||
{
|
||||
public Vector2 CurrentWindowPos;
|
||||
public readonly float[] ReceivedPowerData = new float[MaxTickData];
|
||||
}
|
||||
|
||||
private sealed class DisplaySupply
|
||||
{
|
||||
public Vector2 CurrentWindowPos;
|
||||
public readonly float[] SuppliedPowerData = new float[MaxTickData];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user