Commit Description:
Add text to graph.
Commit Description:
Add text to graph.
Show/Diff file:
Action:
isometric-park-fna/UI/Graph.cs
254 lines | 9.0 KiB | text/x-csharp | CSharpLexer
using System;
using Num = System.Numerics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using ImGuiNET;
using ImPlotNET;
using JM.LinqFaster;
using isometricparkfna.Messages;
using isometricparkfna.Components;
using isometricparkfna.Engines;
namespace isometricparkfna.UI
{
public static class GraphWindow
{
public static bool hadFocus = false;
public static int year = 1;
public static bool show_totals = false;
public static bool show_subsidies = false;
public static bool show_upkeep = false;
private static string[] money_series = { "Total Funds",
"Subsidies", "Upkeep", "Contracts", "Cashflow", "Misc"
};
private static string[] tree_series = { "Total trees", "Dead trees", "Crowded trees"};
public static Dictionary<string, IEnumerable<double>> data_sets = new Dictionary<string, IEnumerable<double>>();
public static Dictionary<string, bool> data_sets_show = new List<string>()
.Concat(money_series)
.Concat(tree_series)
.Select(e => (e, false))
.ToDictionary(t => t.Item1, t=> t.Item2);
public static uint[] colors = {0xFF000000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
0xFF999999, 0xFFAA0000, 0xFF00AA00, 0xFF0000AA, 0xFF000000
};
public static Dictionary<string, uint> data_sets_color = new List<string>()
.Concat(money_series)
.Concat(tree_series)
.Zip(colors, (first, second) => (first, second))
.ToDictionary(t => t.Item1, t => t.Item2);
public static void DrawLine(ImDrawListPtr draw_list, Num.Vector2[] points, uint col) {
var p = Num.Vector2.Zero;// ImGui.GetCursorScreenPos();
// var points = new Num.Vector2[] { new Num.Vector2(0, 0), new Num.Vector2(25, 25), new Num.Vector2(50, 500) };
for (int i = 0; i < points.Length; i++)
{
var c = ImGui.GetCursorScreenPos();
points[i] = Num.Vector2.Add(points[i], c);
}
// uint col = 0b_1111_1111_1111_0000;
// uint col = 0xFF000000;
draw_list.AddPolyline(ref points[0], points.Length, col, ImDrawFlags.RoundCornersDefault, 1.0f);
}
public static int Scale(Num.Vector2 domain, Num.Vector2 range, int num) {
//https://stats.stackexchange.com/a/281164
var domain_span = Math.Max(1, (domain.Y - domain.X));
var range_span = range.Y - range.X;
var start = range.X - domain.X;
return (int) (((num - domain.X) / domain_span) * range_span + range.X);
}
public static async void Render(ImFontPtr font, Simulation sim, ImGuiWindowBridgeEngine engine)
{
bool newShow = true;
ImGui.PushFont(font);
ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.None;
StyleSets.defaultSet.push();
if(GraphWindow.hadFocus)
{
ImGui.PushStyleColor(ImGuiCol.Text, StyleSets.white);
}
ImGui.SetNextWindowSize(new Num.Vector2(400, 400));
ImGui.Begin("Graph", ref newShow, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings);
if (GraphWindow.hadFocus)
{
ImGui.PopStyleColor();
}
GraphWindow.hadFocus = ImGui.IsWindowFocused();
data_sets["Total Funds"] = sim.allBudgets().Select(b => (double)b.money);
data_sets["Subsidies"] = sim.allBudgets().Select(b => (double)b.subsidy);
data_sets["Upkeep"] = sim.allBudgets().Select(b => (double)b.upkeep);
data_sets["Contracts"] = sim.allBudgets().Select(b => (double)b.contracts);
data_sets["Misc"] = sim.allBudgets().Select(b => (double)b.misc);
data_sets["Cashflow"] = sim.allBudgets().Select(b => (double)b.cashflow);
data_sets["Total trees"] = sim.allBudgets().Select(b => (double)b.trees);
data_sets["Dead trees"] = sim.allBudgets().Select(b => (double)b.dead_trees);
data_sets["Crowded trees"] = sim.allBudgets().Select(b => (double)b.crowded_trees);
var periods = 12.0d * GraphWindow.year;
var keys = data_sets_show.Keys.ToList();
var totals = data_sets["Total Funds"];
var max = 0.0d;
var min = 0.0d;
foreach( var key in keys) {
if (data_sets_show[key] && totals.Count() > 0) {
var series_max = data_sets[key].Max() * 1.10f;
max = Math.Max(series_max, max);
}
}
foreach( var key in keys) {
if (data_sets_show[key] && totals.Count() > 0) {
var series_min = data_sets[key].Min();
series_min = series_min >= 0? series_min * 0.90f : series_min *1.10f;
min = Math.Min(series_min, min);
}
}
ImPlot.PushStyleVar(ImPlotStyleVar.LineWeight, 2.0f);
ImPlot.PushStyleVar(ImPlotStyleVar.MinorAlpha, 0.0f);
ImPlot.SetNextPlotLimits(totals.Count()-periods, totals.Count(), min, max, ImGuiCond.Always);
if( ImPlot.BeginPlot("My Plot", null, null, new Num.Vector2(-1,0), ImPlotFlags.NoLegend | ImPlotFlags.NoMousePos )) {
// Span<double> totals = new Span<double>(new double[]{0.0, 1.0, 2.0, 9.0});
foreach (var key in keys) {
var show = data_sets_show[key];
var data = data_sets[key];
var data_array = data_sets[key].ToArray();
if (data_array.Length > 0 && show)
{
ImPlot.PlotLine(key, ref data_array[0], data_array.Length);
ImPlot.AnnotateClamped(data_array.Length-1, data_array[data_array.Length-1],
new Num.Vector2(5, -10), StyleSets.grey, key);
}
}
ImPlot.EndPlot();
}
ImPlot.PopStyleVar(2);
ImGui.RadioButton("1 year", ref GraphWindow.year, 1);
ImGui.SameLine();
ImGui.RadioButton("5 years", ref GraphWindow.year, 5);
ImGui.SameLine();
ImGui.RadioButton("25 years", ref GraphWindow.year, 25);
ImGui.SameLine();
ImGui.RadioButton("100 years", ref GraphWindow.year, 100);
ImGui.Text("Trees:");
for (int i = 0; i < tree_series.Length; i++)
{
var key = tree_series[i];
if (Menu.activeButton(key, data_sets_show[key], StyleSets.selected, StyleSets.white))
{
data_sets_show[key] = !data_sets_show[key];
}
if (i != tree_series.Length-1)
{
ImGui.SameLine();
}
}
ImGui.Text("Money:");
for (int i = 0; i < money_series.Length; i++)
{
var key = money_series[i];
if (Menu.activeButton(key, data_sets_show[key], StyleSets.selected, StyleSets.white))
{
data_sets_show[key] = !data_sets_show[key];
}
if ((i % 4 != 3) && (i != money_series.Length-1)) {
ImGui.SameLine();
}
}
var draw_list = ImGui.GetWindowDrawList();
var domain_min = int.MaxValue;
var domain_max = int.MinValue;
foreach (var key in keys)
{
if (data_sets_show[key] && data_sets[key].Count() > 0)
{
domain_min = Math.Min(domain_min, (int)data_sets[key].Min());
domain_max = Math.Max(domain_max, (int)data_sets[key].Max());
}
}
var padding = 10;
var range = new Num.Vector2(200 - padding, 0 + padding);
var domain = new Num.Vector2(domain_min, domain_max);
foreach (var key in keys)
{
var show = data_sets_show[key];
var data = data_sets[key];
var color = data_sets_color[key];
if (data.Count() > 0 && show)
{
IEnumerable<int> data_array = data_sets[key].Select((p) => Scale(domain, range, (int)p));
var data_array2 = data_array.Select((p, i) => new Num.Vector2(i * 10 + padding, p)).ToArray();
DrawLine(draw_list, data_array2, color);
draw_list.AddText(data_array2.Last(), color, key);
}
}
ImGui.Dummy(new Num.Vector2(200, 200));
ImGui.End();
ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.Left;
StyleSets.defaultSet.pop();
ImGui.PopFont();
}
}
}