From 75e779c9313bd65a50f1922741111984569cdec5 Mon Sep 17 00:00:00 2001 From: epezent Date: Mon, 7 Sep 2020 16:08:59 -0500 Subject: [PATCH] finish templetizing API, several optimizations to plotting pipeline, remmove t_float etc from demo --- implot.cpp | 1 + implot.h | 66 ++++--- implot_demo.cpp | 292 +++++++++++++-------------- implot_items.cpp | 499 +++++++++++++++++++++++++---------------------- 4 files changed, 458 insertions(+), 400 deletions(-) diff --git a/implot.cpp b/implot.cpp index d2ab549..9191684 100644 --- a/implot.cpp +++ b/implot.cpp @@ -31,6 +31,7 @@ Below is a change-log of API breaking changes only. If you are using one of the When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files. You can read releases logs https://github.com/epezent/implot/releases for more details. +- 2020/09/07 (0.8) - Plotting functions which accept a custom getter function pointer have been post-fixed with a G (e.g. PlotLineG) - 2020/09/06 (0.7) - Several flags under ImPlotFlags and ImPlotAxisFlags were inverted (e.g. ImPlotFlags_Legend -> ImPlotFlags_NoLegend) so that the default flagset is simply 0. This more closely matches ImGui's style and makes it easier to enable non-default but commonly used flags (e.g. ImPlotAxisFlags_Time). - 2020/08/28 (0.5) - ImPlotMarker_ can no longer be combined with bitwise OR, |. This features caused unecessary slow-down, and almost no one used it. diff --git a/implot.h b/implot.h index e92cf52..5df3c07 100644 --- a/implot.h +++ b/implot.h @@ -301,8 +301,40 @@ void EndPlot(); // Plot Items //----------------------------------------------------------------------------- -// Supported Types for T* +// The template functions below are explicitly instantiated in implot_items.cpp. +// They are not intended to be used generically with custom types. You will get +// a linker error if you try! All functions support the following scalar types: +// // float, double, ImS8, ImU8, ImS16, ImU16, ImS32, ImU32, ImS64, ImU64 +// +// +// If you need to plot custom or non-homogenous data you have a few options: +// +// 1. If your data is a simple struct/class (e.g. Vector2f), you can use striding. +// This is the most performant option if applicable. +// +// struct Vector2f { float X, Y; }; +// ... +// Vector2f data[42]; +// ImPlot::PlotLine("line", &data[0].x, &data[0].y, 42, 0, sizeof(Vector2f)); // or sizeof(float)*2 +// +// 2. Write a custom getter function or C++ lambda and pass it and your data to +// an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a +// slight performance cost, but probably not enough to worry about. +// +// ImPlotPoint MyDataGetter(void* data, int idx) { +// MyData* my_data = (MyData*)data; +// ImPlotPoint p; +// p.X = my_data->GetTime(idx); +// p.Y = my_data->GetValue(idx); +// return p +// } +// ... +// MyData my_data; +// ImPlot::PlotScatterG("scatter", MyDataGetter, &my_data, my_data.Size()); +// +// NB: All types are converted to double before plotting. You may loose information +// if you try plotting extremely large 64-bit integral types. Proceed with caution! // Plots a standard 2D line plot. template void PlotLine(const char* label_id, const T* values, int count, int offset = 0, int stride = sizeof(T)); @@ -330,41 +362,29 @@ template void PlotBarsH(const char* label_id, const T* values, int template void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset = 0, int stride = sizeof(T)); void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset = 0); -// TODO ... - // Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot. -void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset = 0, int stride = sizeof(float)); -void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset = 0, int stride = sizeof(double)); -void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset = 0, int stride = sizeof(float)); -void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double)); +template void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset = 0, int stride = sizeof(T)); +template void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset = 0, int stride = sizeof(T)); // Plots horizontal error bars. The label_id should be the same as the label_id of the associated line or bar plot. -void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset = 0, int stride = sizeof(float)); -void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset = 0, int stride = sizeof(double)); -void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset = 0, int stride = sizeof(float)); -void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double)); +template void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset = 0, int stride = sizeof(T)); +template void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset = 0, int stride = sizeof(T)); /// Plots vertical stems. -void PlotStems(const char* label_id, const float* values, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float)); -void PlotStems(const char* label_id, const double* values, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double)); -void PlotStems(const char* label_id, const float* xs, const float* ys, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float)); -void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double)); +template void PlotStems(const char* label_id, const T* values, int count, double y_ref = 0, int offset = 0, int stride = sizeof(T)); +template void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref = 0, int offset = 0, int stride = sizeof(T)); // Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels. -void PlotPieChart(const char* const label_ids[], const float* values, int count, float x, float y, float radius, bool normalize = false, const char* label_fmt = "%.1f", float angle0 = 90); -void PlotPieChart(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize = false, const char* label_fmt = "%.1f", double angle0 = 90); +template void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize = false, const char* label_fmt = "%.1f", double angle0 = 90); // Plots a 2D heatmap chart. Values are expected to be in row-major order. #label_fmt can be set to NULL for no labels. -void PlotHeatmap(const char* label_id, const float* values, int rows, int cols, float scale_min, float scale_max, const char* label_fmt = "%.1f", const ImPlotPoint& bounds_min = ImPlotPoint(0,0), const ImPlotPoint& bounds_max = ImPlotPoint(1,1)); -void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* label_fmt = "%.1f", const ImPlotPoint& bounds_min = ImPlotPoint(0,0), const ImPlotPoint& bounds_max = ImPlotPoint(1,1)); +template void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* label_fmt = "%.1f", const ImPlotPoint& bounds_min = ImPlotPoint(0,0), const ImPlotPoint& bounds_max = ImPlotPoint(1,1)); // Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot. -void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); -void PlotDigital(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double)); -void PlotDigital(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0); +template void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset = 0, int stride = sizeof(T)); + void PlotDigitalG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0); // Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...). -void PlotText(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); void PlotText(const char* text, double x, double y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); //----------------------------------------------------------------------------- diff --git a/implot_demo.cpp b/implot_demo.cpp index 4b8d8f6..229c4ec 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -32,9 +32,16 @@ #define sprintf sprintf_s #endif +// Encapsulates examples for customizing ImPlot. namespace MyImPlot { -// Examples for passing custom function pointers to ImPlot in Custom Getters section. +// Example for Custom Data and Getters section. +struct Vector2f { + Vector2f(float _x, float _y) { x = _x; y = _y; } + float x, y; +}; + +// Example for Custom Data and Getters section. struct WaveData { double X, Amp, Freq, Offset; WaveData(double x, double amp, double freq, double offset) { X = x; Amp = amp; Freq = freq; Offset = offset; } @@ -42,44 +49,25 @@ struct WaveData { ImPlotPoint SineWave(void* wave_data, int idx); ImPlotPoint SawWave(void* wave_data, int idx); ImPlotPoint Spiral(void*, int idx); -// Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom. + +// Example for Tables section. void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size); -// Example for Custom Plotters and Tooltips section. Plots a candlestick chart for financial data. See implementation at bottom. + +// Example for Custom Plotters and Tooltips section. void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip = true, float width_percent = 0.25f, ImVec4 bullCol = ImVec4(0,1,0,1), ImVec4 bearCol = ImVec4(1,0,0,1)); -// Sets style to mimic Seaborn + +// Example for Custom Styles section. void StyleSeaborn(); } // namespace MyImPlot namespace ImPlot { -/// Choose whether the demo uses double or float versions of the ImPlot API. -/// NB: You don't ever need to typdef of define values for ImPlot. This -/// is only being done here for the sake of demoing both precision types. - -// #define IMPLOT_DEMO_USE_DOUBLE -#ifdef IMPLOT_DEMO_USE_DOUBLE -typedef double t_float; -typedef ImPlotPoint t_float2; -#define Sin sin -#define Cos cos -#define Pow pow -#define Log log -#define Fmod fmod -#else -typedef float t_float; -typedef ImVec2 t_float2; -#define Sin sinf -#define Cos cosf -#define Pow powf -#define Log logf -#define Fmod fmodf -#endif - void ShowBenchmarkTool(); -inline t_float RandomRange(t_float min, t_float max) { - t_float scale = rand() / (t_float) RAND_MAX; +template +inline T RandomRange(T min, T max) { + T scale = rand() / (T) RAND_MAX; return min + scale * ( max - min ); } @@ -87,17 +75,17 @@ inline t_float RandomRange(t_float min, t_float max) { struct ScrollingBuffer { int MaxSize; int Offset; - ImVector Data; + ImVector Data; ScrollingBuffer() { MaxSize = 2000; Offset = 0; Data.reserve(MaxSize); } - void AddPoint(t_float x, t_float y) { + void AddPoint(float x, float y) { if (Data.size() < MaxSize) - Data.push_back(t_float2(x,y)); + Data.push_back(ImVec2(x,y)); else { - Data[Offset] = t_float2(x,y); + Data[Offset] = ImVec2(x,y); Offset = (Offset + 1) % MaxSize; } } @@ -111,17 +99,17 @@ struct ScrollingBuffer { // utility structure for realtime plot struct RollingBuffer { - t_float Span; - ImVector Data; + float Span; + ImVector Data; RollingBuffer() { Span = 10.0f; Data.reserve(2000); } - void AddPoint(t_float x, t_float y) { - t_float xmod = Fmod(x, Span); + void AddPoint(float x, float y) { + float xmod = fmodf(x, Span); if (!Data.empty() && xmod < Data.back().x) Data.shrink(0); - Data.push_back(t_float2(xmod, y)); + Data.push_back(ImVec2(xmod, y)); } }; @@ -145,7 +133,7 @@ struct HugeTimeData { }; void ShowDemoWindow(bool* p_open) { - t_float DEMO_TIME = (t_float)ImGui::GetTime(); + double DEMO_TIME = ImGui::GetTime(); static bool show_imgui_metrics = false; static bool show_imgui_style_editor = false; static bool show_implot_style_editor = false; @@ -249,7 +237,7 @@ void ShowDemoWindow(bool* p_open) { static float xs1[1001], ys1[1001]; for (int i = 0; i < 1001; ++i) { xs1[i] = i * 0.001f; - ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + DEMO_TIME / 10)); + ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + (float)DEMO_TIME / 10)); } static double xs2[11], ys2[11]; for (int i = 0; i < 11; ++i) { @@ -266,13 +254,13 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Filled Line Plots")) { - static t_float xs1[101], ys1[101], ys2[101], ys3[101]; + static double xs1[101], ys1[101], ys2[101], ys3[101]; srand(0); for (int i = 0; i < 101; ++i) { xs1[i] = (float)i; - ys1[i] = RandomRange(400,450); - ys2[i] = RandomRange(275,350); - ys3[i] = RandomRange(150,225); + ys1[i] = RandomRange(400.0,450.0); + ys2[i] = RandomRange(275.0,350.0); + ys3[i] = RandomRange(150.0,225.0); } static bool show_lines = true; static bool show_fills = true; @@ -300,15 +288,15 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Shaded Plots")) { - static t_float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001]; + static float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001]; srand(0); for (int i = 0; i < 1001; ++i) { xs[i] = i * 0.001f; - ys[i] = 0.25f + 0.25f * Sin(25 * xs[i]) * Sin(5 * xs[i]) + RandomRange(-0.01f, 0.01f); + ys[i] = 0.25f + 0.25f * sinf(25 * xs[i]) * sinf(5 * xs[i]) + RandomRange(-0.01f, 0.01f); ys1[i] = ys[i] + RandomRange(0.1f, 0.12f); ys2[i] = ys[i] - RandomRange(0.1f, 0.12f); - ys3[i] = 0.75f + 0.2f * Sin(25 * xs[i]); - ys4[i] = 0.75f + 0.1f * Cos(25 * xs[i]); + ys3[i] = 0.75f + 0.2f * sinf(25 * xs[i]); + ys4[i] = 0.75f + 0.1f * cosf(25 * xs[i]); } static float alpha = 0.25f; ImGui::DragFloat("Alpha",&alpha,0.01f,0,1); @@ -327,15 +315,15 @@ void ShowDemoWindow(bool* p_open) { //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Scatter Plots")) { srand(0); - static t_float xs1[100], ys1[100]; + static float xs1[100], ys1[100]; for (int i = 0; i < 100; ++i) { xs1[i] = i * 0.01f; - ys1[i] = xs1[i] + 0.1f * ((t_float)rand() / (t_float)RAND_MAX); + ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); } - static t_float xs2[50], ys2[50]; + static float xs2[50], ys2[50]; for (int i = 0; i < 50; i++) { - xs2[i] = 0.25f + 0.2f * ((t_float)rand() / (t_float)RAND_MAX); - ys2[i] = 0.75f + 0.2f * ((t_float)rand() / (t_float)RAND_MAX); + xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); + ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); } if (ImPlot::BeginPlot("Scatter Plot", NULL, NULL)) { @@ -386,14 +374,14 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Error Bars")) { - static t_float xs[5] = {1,2,3,4,5}; - static t_float bar[5] = {1,2,5,3,4}; - static t_float lin1[5] = {8,8,9,7,8}; - static t_float lin2[5] = {6,7,6,9,6}; - static t_float err1[5] = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f}; - static t_float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f}; - static t_float err3[5] = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f}; - static t_float err4[5] = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f}; + static float xs[5] = {1,2,3,4,5}; + static float bar[5] = {1,2,5,3,4}; + static float lin1[5] = {8,8,9,7,8}; + static float lin2[5] = {6,7,6,9,6}; + static float err1[5] = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f}; + static float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f}; + static float err3[5] = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f}; + static float err4[5] = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f}; ImPlot::SetNextPlotLimits(0, 6, 0, 10); @@ -417,11 +405,11 @@ void ShowDemoWindow(bool* p_open) { } } if (ImGui::CollapsingHeader("Stem Plots")) { - static t_float xs[51], ys1[51], ys2[51]; + static double xs[51], ys1[51], ys2[51]; for (int i = 0; i < 51; ++i) { - xs[i] = i * 0.02f; - ys1[i] = 1.0f + 0.5f * Sin(25*xs[i])*Cos(2*xs[i]); - ys2[i] = 0.5f + 0.25f * Sin(10*xs[i]) * Sin(xs[i]); + xs[i] = i * 0.02; + ys1[i] = 1.0 + 0.5 * sin(25*xs[i])*cos(2*xs[i]); + ys2[i] = 0.5 + 0.25 * sin(10*xs[i]) * sin(xs[i]); } ImPlot::SetNextPlotLimits(0,1,0,1.6); if (ImPlot::BeginPlot("Stem Plots")) { @@ -449,38 +437,34 @@ void ShowDemoWindow(bool* p_open) { ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always); if (ImPlot::BeginPlot("##Pie1", NULL, NULL, ImVec2(250,250), ImPlotFlags_NoMousePos, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { - ImPlot::PlotPieChart(labels1, data1, 4, 0.5f, 0.5f, 0.4f, normalize, "%.2f"); + ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, normalize, "%.2f"); ImPlot::EndPlot(); } ImGui::SameLine(); static const char* labels2[] = {"A","B","C","D","E"}; - static t_float data2[] = {1,1,2,3,5}; + static int data2[] = {1,1,2,3,5}; ImPlot::PushColormap(ImPlotColormap_Pastel); ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always); if (ImPlot::BeginPlot("##Pie2", NULL, NULL, ImVec2(250,250), ImPlotFlags_NoMousePos, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { - ImPlot::PlotPieChart(labels2, data2, 5, 0.5f, 0.5f, 0.4f, true, "%.0f", 180); + ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, true, "%.0f", 180); ImPlot::EndPlot(); } ImPlot::PopColormap(); } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Heatmaps")) { - static t_float values1[7][7] = {{0.8f, 2.4f, 2.5f, 3.9f, 0.0f, 4.0f, 0.0f}, - {2.4f, 0.0f, 4.0f, 1.0f, 2.7f, 0.0f, 0.0f}, - {1.1f, 2.4f, 0.8f, 4.3f, 1.9f, 4.4f, 0.0f}, - {0.6f, 0.0f, 0.3f, 0.0f, 3.1f, 0.0f, 0.0f}, - {0.7f, 1.7f, 0.6f, 2.6f, 2.2f, 6.2f, 0.0f}, - {1.3f, 1.2f, 0.0f, 0.0f, 0.0f, 3.2f, 5.1f}, - {0.1f, 2.0f, 0.0f, 1.4f, 0.0f, 1.9f, 6.3f}}; - static float scale_min = 0; - static float scale_max = 6.3f; - static t_float values2[100*100]; - srand((unsigned int)(DEMO_TIME*1000000)); - for (int i = 0; i < 100*100; ++i) - values2[i] = RandomRange(0,1); + static float values1[7][7] = {{0.8f, 2.4f, 2.5f, 3.9f, 0.0f, 4.0f, 0.0f}, + {2.4f, 0.0f, 4.0f, 1.0f, 2.7f, 0.0f, 0.0f}, + {1.1f, 2.4f, 0.8f, 4.3f, 1.9f, 4.4f, 0.0f}, + {0.6f, 0.0f, 0.3f, 0.0f, 3.1f, 0.0f, 0.0f}, + {0.7f, 1.7f, 0.6f, 2.6f, 2.2f, 6.2f, 0.0f}, + {1.3f, 1.2f, 0.0f, 0.0f, 0.0f, 3.2f, 5.1f}, + {0.1f, 2.0f, 0.0f, 1.4f, 0.0f, 1.9f, 6.3f}}; + static float scale_min = 0; + static float scale_max = 6.3f; static const char* xlabels[] = {"C1","C2","C3","C4","C5","C6","C7"}; static const char* ylabels[] = {"R1","R2","R3","R4","R5","R6","R7"}; @@ -507,6 +491,11 @@ void ShowDemoWindow(bool* p_open) { ImGui::SameLine(); + static double values2[100*100]; + srand((unsigned int)(DEMO_TIME*1000000)); + for (int i = 0; i < 100*100; ++i) + values2[i] = RandomRange(0.0,1.0); + static ImVec4 gray[2] = {ImVec4(0,0,0,1), ImVec4(1,1,1,1)}; ImPlot::PushColormap(gray, 2); ImPlot::SetNextPlotLimits(-1,1,-1,1); @@ -524,7 +513,7 @@ void ShowDemoWindow(bool* p_open) { static ScrollingBuffer sdata1, sdata2; static RollingBuffer rdata1, rdata2; ImVec2 mouse = ImGui::GetMousePos(); - static t_float t = 0; + static float t = 0; t += ImGui::GetIO().DeltaTime; sdata1.AddPoint(t, mouse.x * 0.0005f); rdata1.AddPoint(t, mouse.x * 0.0005f); @@ -539,7 +528,7 @@ void ShowDemoWindow(bool* p_open) { static ImPlotAxisFlags rt_axis = ImPlotAxisFlags_NoTickLabels; ImPlot::SetNextPlotLimitsX(t - history, t, ImGuiCond_Always); if (ImPlot::BeginPlot("##Scrolling", NULL, NULL, ImVec2(-1,150), 0, rt_axis, rt_axis | ImPlotAxisFlags_LockMin)) { - ImPlot::PlotShaded("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), 0, sdata1.Offset, 2 * sizeof(t_float)); + ImPlot::PlotShaded("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), 0, sdata1.Offset, 2 * sizeof(float)); ImPlot::PlotLine("Data 2", &sdata2.Data[0], sdata2.Data.size(), sdata2.Offset); ImPlot::EndPlot(); } @@ -549,7 +538,7 @@ void ShowDemoWindow(bool* p_open) { // as ImVec2* (or ImPlot*): ImPlot::PlotLine("Data 1", &rdata1.Data[0], rdata1.Data.size()); // as float*, float* (or double*, double*) with stride of 2 * sizeof - ImPlot::PlotLine("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(t_float)); + ImPlot::PlotLine("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float)); ImPlot::EndPlot(); } } @@ -562,8 +551,8 @@ void ShowDemoWindow(bool* p_open) { ImPlot::SetNextPlotLimits(0, 10, 0, 12); if (ImPlot::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,0), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { - t_float xs[2] = {1,4}; - t_float ys[2] = {10,11}; + ImS8 xs[2] = {1,4}; + ImS8 ys[2] = {10,11}; // filled markers for (int m = 1; m < ImPlotMarker_COUNT; ++m) { @@ -595,12 +584,12 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Log Scale")) { - static t_float xs[1001], ys1[1001], ys2[1001], ys3[1001]; + static double xs[1001], ys1[1001], ys2[1001], ys3[1001]; for (int i = 0; i < 1001; ++i) { xs[i] = i*0.1f; - ys1[i] = Sin(xs[i]) + 1; - ys2[i] = Log(xs[i]); - ys3[i] = Pow(10.0f, xs[i]); + ys1[i] = sin(xs[i]) + 1; + ys2[i] = log(xs[i]); + ys3[i] = pow(10.0, xs[i]); } ImGui::BulletText("Open the plot context menu (double right click) to change scales."); @@ -655,12 +644,12 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Multiple Y-Axes")) { - static t_float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001]; + static float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001]; for (int i = 0; i < 1001; ++i) { xs[i] = (i*0.1f); - ys1[i] = Sin(xs[i]) * 3 + 1; - ys2[i] = Cos(xs[i]) * 0.2f + 0.5f; - ys3[i] = Sin(xs[i]+0.5f) * 100 + 200; + ys1[i] = sinf(xs[i]) * 3 + 1; + ys2[i] = cosf(xs[i]) * 0.2f + 0.5f; + ys3[i] = sinf(xs[i]+0.5f) * 100 + 200; xs2[i] = xs[i] + 10.0f; } static bool y2_axis = true; @@ -699,7 +688,7 @@ void ShowDemoWindow(bool* p_open) { if (ImGui::CollapsingHeader("Linked Axes")) { static double xmin = 0, xmax = 1, ymin = 0, ymax = 1; static bool linkx = true, linky = true; - t_float data[2] = {0,1}; + int data[2] = {0,1}; ImGui::Checkbox("Link X", &linkx); ImGui::SameLine(); ImGui::Checkbox("Link Y", &linky); @@ -716,7 +705,7 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Querying")) { - static ImVector data; + static ImVector data; static ImPlotLimits range, query; ImGui::BulletText("Ctrl + click in the plot area to draw points."); @@ -730,14 +719,14 @@ void ShowDemoWindow(bool* p_open) { if (ImPlot::BeginPlot("##Drawing", NULL, NULL, ImVec2(-1,0), ImPlotFlags_Query, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { if (ImPlot::IsPlotHovered() && ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyCtrl) { ImPlotPoint pt = ImPlot::GetPlotMousePos(); - data.push_back(t_float2((t_float)pt.x, (t_float)pt.y)); + data.push_back(pt); } if (data.size() > 0) - ImPlot::PlotScatter("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(t_float)); + ImPlot::PlotScatter("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(double)); if (ImPlot::IsPlotQueried() && data.size() > 0) { ImPlotLimits range2 = ImPlot::GetPlotQuery(); int cnt = 0; - t_float2 avg; + ImPlotPoint avg; for (int i = 0; i < data.size(); ++i) { if (range2.Contains(data[i].x, data[i].y)) { avg.x += data[i].x; @@ -762,19 +751,19 @@ void ShowDemoWindow(bool* p_open) { //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Views")) { // mimic's soulthread's imgui_plot demo - static t_float x_data[512]; - static t_float y_data1[512]; - static t_float y_data2[512]; - static t_float y_data3[512]; - static t_float sampling_freq = 44100; - static t_float freq = 500; + static float x_data[512]; + static float y_data1[512]; + static float y_data2[512]; + static float y_data3[512]; + static float sampling_freq = 44100; + static float freq = 500; for (size_t i = 0; i < 512; ++i) { - const t_float t = i / sampling_freq; + const float t = i / sampling_freq; x_data[i] = t; - const t_float arg = 2 * 3.14f * freq * t; - y_data1[i] = Sin(arg); - y_data2[i] = y_data1[i] * -0.6f + Sin(2 * arg) * 0.4f; - y_data3[i] = y_data2[i] * -0.6f + Sin(3 * arg) * 0.4f; + const float arg = 2 * 3.14f * freq * t; + y_data1[i] = sinf(arg); + y_data2[i] = y_data1[i] * -0.6f + sinf(2 * arg) * 0.4f; + y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f; } ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls)."); ImPlot::SetNextPlotLimits(0,0.01,-1,1); @@ -836,7 +825,7 @@ void ShowDemoWindow(bool* p_open) { ImGui::EndGroup(); ImGui::SameLine(); srand((unsigned int)DEMO_TIME*10000000); - static t_float t = 0; + static float t = 0; if (!paused) { t += ImGui::GetIO().DeltaTime; for (int i = 0; i < K_CHANNELS; ++i) { @@ -851,7 +840,7 @@ void ShowDemoWindow(bool* p_open) { char label[K_CHANNELS]; sprintf(label, "data_%d", i); ImPlot::SetPlotYAxis(yAxis[i]); - ImPlot::PlotLine(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(t_float)); + ImPlot::PlotLine(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(float)); // allow legend labels to be dragged and dropped if (ImPlot::BeginLegendDragDropSource(label)) { ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); @@ -923,35 +912,35 @@ void ShowDemoWindow(bool* p_open) { } ImGui::EndGroup(); ImGui::SameLine(); - static t_float t = 0; + static float t = 0; if (!paused) { t += ImGui::GetIO().DeltaTime; //digital signal values int i = 0; if (showDigital[i]) - dataDigital[i].AddPoint(t, Sin(2*t) > 0.45); + dataDigital[i].AddPoint(t, sinf(2*t) > 0.45); i++; if (showDigital[i]) - dataDigital[i].AddPoint(t, Sin(2*t) < 0.45); + dataDigital[i].AddPoint(t, sinf(2*t) < 0.45); i++; if (showDigital[i]) - dataDigital[i].AddPoint(t, Fmod(t,5.0f)); + dataDigital[i].AddPoint(t, fmodf(t,5.0f)); i++; if (showDigital[i]) - dataDigital[i].AddPoint(t, Sin(2*t) < 0.17); + dataDigital[i].AddPoint(t, sinf(2*t) < 0.17); //Analog signal values i = 0; if (showAnalog[i]) - dataAnalog[i].AddPoint(t, Sin(2*t)); + dataAnalog[i].AddPoint(t, sinf(2*t)); i++; if (showAnalog[i]) - dataAnalog[i].AddPoint(t, Cos(2*t)); + dataAnalog[i].AddPoint(t, cosf(2*t)); i++; if (showAnalog[i]) - dataAnalog[i].AddPoint(t, Sin(2*t) * Cos(2*t)); + dataAnalog[i].AddPoint(t, sinf(2*t) * cosf(2*t)); i++; if (showAnalog[i]) - dataAnalog[i].AddPoint(t, Sin(2*t) - Cos(2*t)); + dataAnalog[i].AddPoint(t, sinf(2*t) - cosf(2*t)); } ImPlot::SetNextPlotLimitsY(-1, 1); ImPlot::SetNextPlotLimitsX(t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always); @@ -960,7 +949,7 @@ void ShowDemoWindow(bool* p_open) { if (showDigital[i] && dataDigital[i].Data.size() > 0) { char label[32]; sprintf(label, "digital_%d", i); - ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(t_float)); + ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float)); } } for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { @@ -968,7 +957,7 @@ void ShowDemoWindow(bool* p_open) { char label[32]; sprintf(label, "analog_%d", i); if (dataAnalog[i].Data.size() > 0) - ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(t_float)); + ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float)); } } ImPlot::EndPlot(); @@ -1010,7 +999,7 @@ void ShowDemoWindow(bool* p_open) { static float data[100]; srand(row); for (int i = 0; i < 100; ++i) - data[i] = (float)RandomRange(0,10); + data[i] = RandomRange(0.0f,10.0f); ImGui::TableSetColumnIndex(0); ImGui::Text("EMG %d", row); ImGui::TableSetColumnIndex(1); @@ -1032,12 +1021,12 @@ void ShowDemoWindow(bool* p_open) { static const int k_circles = 11; static const int k_points_per = 50; static const int k_size = 2 * k_points_per * k_circles; - static t_float interleaved_data[k_size]; + static double interleaved_data[k_size]; for (int p = 0; p < k_points_per; ++p) { for (int c = 0; c < k_circles; ++c) { - t_float r = (t_float)c / (k_circles - 1) * 0.2f + 0.2f; - interleaved_data[p*2*k_circles + 2*c + 0] = 0.5f + r * Cos((t_float)p/k_points_per * 6.28f); - interleaved_data[p*2*k_circles + 2*c + 1] = 0.5f + r * Sin((t_float)p/k_points_per * 6.28f); + double r = (double)c / (k_circles - 1) * 0.2 + 0.2; + interleaved_data[p*2*k_circles + 2*c + 0] = 0.5 + r * cos((double)p/k_points_per * 6.28); + interleaved_data[p*2*k_circles + 2*c + 1] = 0.5 + r * sin((double)p/k_points_per * 6.28); } } static int offset = 0; @@ -1053,7 +1042,7 @@ void ShowDemoWindow(bool* p_open) { char buff[16]; for (int c = 0; c < k_circles; ++c) { sprintf(buff, "Circle %d", c); - ImPlot::PlotLine(buff, &interleaved_data[c*2 + 0], &interleaved_data[c*2 + 1], k_points_per, offset, 2*k_circles*sizeof(t_float)); + ImPlot::PlotLine(buff, &interleaved_data[c*2 + 0], &interleaved_data[c*2 + 1], k_points_per, offset, 2*k_circles*sizeof(double)); } ImPlot::EndPlot(); ImPlot::PopColormap(); @@ -1061,12 +1050,25 @@ void ShowDemoWindow(bool* p_open) { // offset++; uncomment for animation! } //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Custom Getters")) { - ImGui::BulletText("Most plotters can be passed a function pointer for getting data."); - ImGui::BulletText("You can optionally pass user data to be given to your getter."); - ImGui::BulletText("C++ lambdas can be passed as function pointers as well."); - if (ImPlot::BeginPlot("##Custom Getters")) { + if (ImGui::CollapsingHeader("Custom Data and Getters")) { + ImGui::BulletText("You can plot custom structs using the stride feature."); + ImGui::BulletText("Most plotters can also be passed a function pointer for getting data."); + ImGui::Indent(); + ImGui::BulletText("You can optionally pass user data to be given to your getter function."); + ImGui::BulletText("C++ lambdas can be passed as function pointers as well!"); + ImGui::Unindent(); + + MyImPlot::Vector2f vec2_data[2] = { MyImPlot::Vector2f(0,0), MyImPlot::Vector2f(1,1) }; + + if (ImPlot::BeginPlot("##Custom Data")) { + + // custom structs using stride example: + ImPlot::PlotLine("Vector2f", &vec2_data[0].x, &vec2_data[0].y, 2, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */); + + // custom getter example 1: ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, NULL, 1000); + + // custom getter example 2: static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75); static MyImPlot::WaveData data2(0.001, 0.2, 4, 0.25); ImPlot::PlotLineG("Waves", MyImPlot::SineWave, &data1, 1000); @@ -1074,9 +1076,11 @@ void ShowDemoWindow(bool* p_open) { ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f); ImPlot::PlotShadedG("Waves", MyImPlot::SineWave, &data1, MyImPlot::SawWave, &data2, 1000); ImPlot::PopStyleVar(); + // you can also pass C++ lambdas: // auto lamda = [](void* data, int idx) { ... return ImPlotPoint(x,y); }; // ImPlot::PlotLine("My Lambda", lambda, data, 1000); + ImPlot::EndPlot(); } } @@ -1115,9 +1119,9 @@ void ShowDemoWindow(bool* p_open) { MyImPlot::StyleSeaborn(); ImPlot::SetNextPlotLimits(-0.5f, 9.5f, 0, 10); if (ImPlot::BeginPlot("seaborn style", "x-axis", "y-axis")) { - t_float lin[10] = {8,8,9,7,8,8,8,9,7,8}; - t_float bar[10] = {1,2,5,3,4,1,2,5,3,4}; - t_float dot[10] = {7,6,6,7,8,5,6,5,8,7}; + unsigned int lin[10] = {8,8,9,7,8,8,8,9,7,8}; + unsigned int bar[10] = {1,2,5,3,4,1,2,5,3,4}; + unsigned int dot[10] = {7,6,6,7,8,5,6,5,8,7}; ImPlot::PlotBars("Bars", bar, 10, 0.5f); ImPlot::PlotLine("Line", lin, 10); ImPlot::NextColormapColor(); // skip green @@ -1154,9 +1158,9 @@ void ShowDemoWindow(bool* p_open) { static bool markers = false; static bool shaded = false; - static t_float vals[101]; + static float vals[101]; for (int i = 0; i < 101; ++i) - vals[i] = amplitude * Sin(frequency * i); + vals[i] = amplitude * sinf(frequency * i); ImPlot::SetNextPlotLimits(0,100,-1,1); if (ImPlot::BeginPlot("Right Click the Legend")) { @@ -1240,8 +1244,8 @@ ImPlotPoint Spiral(void*, int idx) { float n = (r - a) / b; // number of revolutions double th = 2 * n * 3.14; // angle float Th = float(th * idx / (1000 - 1)); - return ImPlotPoint(0.5f+(a + b*Th / (2.0f * (float) 3.14))*Cos(Th), - 0.5f + (a + b*Th / (2.0f * (float)3.14))*Sin(Th)); + return ImPlotPoint(0.5f+(a + b*Th / (2.0f * (float) 3.14))*cos(Th), + 0.5f + (a + b*Th / (2.0f * (float)3.14))*sin(Th)); } // Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom. @@ -1412,12 +1416,12 @@ namespace ImPlot { struct BenchData { BenchData() { - float y = (float)RandomRange(0,1); + float y = RandomRange(0.0f,1.0f); Data = new float[1000]; for (int i = 0; i < 1000; ++i) { - Data[i] = y + (float)RandomRange(-0.01f,0.01f); + Data[i] = y + RandomRange(-0.01f,0.01f); } - Col = ImVec4((float)RandomRange(0,1),(float)RandomRange(0,1),(float)RandomRange(0,1),1); + Col = ImVec4(RandomRange(0.0f,1.0f),RandomRange(0.0f,1.0f),RandomRange(0.0f,1.0f),0.5f); } ~BenchData() { delete[] Data; } float* Data; diff --git a/implot_items.cpp b/implot_items.cpp index d2f119d..a365e3d 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -95,6 +95,34 @@ ImPlotItem* GetCurrentItem() { return gp.CurrentItem; } +void SetNextLineStyle(const ImVec4& col, float weight) { + ImPlotContext& gp = *GImPlot; + gp.NextItemStyle.Colors[ImPlotCol_Line] = col; + gp.NextItemStyle.LineWeight = weight; +} + +void SetNextFillStyle(const ImVec4& col, float alpha) { + ImPlotContext& gp = *GImPlot; + gp.NextItemStyle.Colors[ImPlotCol_Fill] = col; + gp.NextItemStyle.FillAlpha = alpha; +} + +void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) { + ImPlotContext& gp = *GImPlot; + gp.NextItemStyle.Marker = marker; + gp.NextItemStyle.Colors[ImPlotCol_MarkerFill] = fill; + gp.NextItemStyle.MarkerSize = size; + gp.NextItemStyle.Colors[ImPlotCol_MarkerOutline] = outline; + gp.NextItemStyle.MarkerWeight = weight; +} + +void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) { + ImPlotContext& gp = *GImPlot; + gp.NextItemStyle.Colors[ImPlotCol_ErrorBar] = col; + gp.NextItemStyle.ErrorBarSize = size; + gp.NextItemStyle.ErrorBarWeight = weight; +} + void BustItemCache() { ImPlotContext& gp = *GImPlot; for (int p = 0; p < gp.Plots.GetSize(); ++p) { @@ -104,6 +132,10 @@ void BustItemCache() { } } +//----------------------------------------------------------------------------- +// Begin/EndItem +//----------------------------------------------------------------------------- + // Begins a new item. Returns false if the item should not be plotted. bool BeginItem(const char* label_id, ImPlotCol recolor_from) { ImPlotContext& gp = *GImPlot; @@ -172,35 +204,6 @@ void EndItem() { gp.CurrentItem = NULL; } -void SetNextLineStyle(const ImVec4& col, float weight) { - ImPlotContext& gp = *GImPlot; - gp.NextItemStyle.Colors[ImPlotCol_Line] = col; - gp.NextItemStyle.LineWeight = weight; -} - -void SetNextFillStyle(const ImVec4& col, float alpha) { - ImPlotContext& gp = *GImPlot; - gp.NextItemStyle.Colors[ImPlotCol_Fill] = col; - gp.NextItemStyle.FillAlpha = alpha; -} - -void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) { - ImPlotContext& gp = *GImPlot; - gp.NextItemStyle.Marker = marker; - gp.NextItemStyle.Colors[ImPlotCol_MarkerFill] = fill; - gp.NextItemStyle.MarkerSize = size; - gp.NextItemStyle.Colors[ImPlotCol_MarkerOutline] = outline; - gp.NextItemStyle.MarkerWeight = weight; -} - -void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) { - ImPlotContext& gp = *GImPlot; - gp.NextItemStyle.Colors[ImPlotCol_ErrorBar] = col; - gp.NextItemStyle.ErrorBarSize = size; - gp.NextItemStyle.ErrorBarWeight = weight; -} - - //----------------------------------------------------------------------------- // GETTERS //----------------------------------------------------------------------------- @@ -208,6 +211,8 @@ void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) { // Getters can be thought of as iterators that convert user data (e.g. raw arrays) // to ImPlotPoints +// TODO: Make members const + // Interprets an array of Y points as ImPlotPoints where the X value is the index template struct GetterYs { @@ -221,7 +226,7 @@ struct GetterYs { int Count; int Offset; int Stride; - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)idx, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); } }; @@ -240,7 +245,7 @@ struct GetterXsYs { int Count; int Offset; int Stride; - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); } }; @@ -249,7 +254,7 @@ struct GetterXsYs { template struct GetterYRef { GetterYRef(T y_ref, int count) { YRef = y_ref; Count = count; } - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)idx, (double)YRef); } T YRef; @@ -271,7 +276,7 @@ struct GetterXsYRef { int Count; int Offset; int Stride; - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)YRef); } }; @@ -283,7 +288,7 @@ struct GetterImVec2 { Count = count; Offset = count ? ImPosMod(offset, count) : 0; } - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { idx = ImPosMod(Offset + idx, Count); return ImPlotPoint((double)Data[idx].x, (double)Data[idx].y); } @@ -299,7 +304,7 @@ struct GetterImPlotPoint { Count = count; Offset = count ? ImPosMod(offset, count) : 0; } - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { idx = ImPosMod(Offset + idx, Count); return Data[idx]; } @@ -316,7 +321,7 @@ struct GetterFuncPtrImPlotPoint { Count = count; Offset = count ? ImPosMod(offset, count) : 0; } - inline ImPlotPoint operator()(int idx) { + inline ImPlotPoint operator()(int idx) const { idx = ImPosMod(Offset + idx, Count); return getter(Data, idx); } @@ -330,14 +335,14 @@ template struct GetterBarV { const T* Ys; double XShift; int Count; int Offset; int Stride; GetterBarV(const T* ys, double xshift, int count, int offset, int stride) { Ys = ys; XShift = xshift; Count = count; Offset = offset; Stride = stride; } - inline ImPlotPoint operator()(int idx) { return ImPlotPoint((double)idx + (double)XShift, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); } + inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)idx + (double)XShift, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); } }; template struct GetterBarH { const T* Xs; double YShift; int Count; int Offset; int Stride; GetterBarH(const T* xs, double yshift, int count, int offset, int stride) { Xs = xs; YShift = yshift; Count = count; Offset = offset; Stride = stride; } - inline ImPlotPoint operator()(int idx) { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); } + inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); } }; template @@ -346,7 +351,7 @@ struct GetterError { GetterError(const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) { Xs = xs; Ys = ys; Neg = neg; Pos = pos; Count = count; Offset = offset; Stride = stride; } - ImPlotPointError operator()(int idx) { + ImPlotPointError operator()(int idx) const { return ImPlotPointError((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride), (double)OffsetAndStride(Neg, idx, Count, Offset, Stride), @@ -363,62 +368,54 @@ struct GetterError { // Transforms points for linear x and linear y space struct TransformerLinLin { TransformerLinLin() : YAxis(GetCurrentYAxis()) {} - - inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } - inline ImVec2 operator()(double x, double y) { + // inline ImVec2 operator()(const ImPlotPoint& plt) const { return (*this)(plt.x, plt.y); } + inline ImVec2 operator()(const ImPlotPoint& plt) const { ImPlotContext& gp = *GImPlot; - return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), - (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); + return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)), + (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); } - int YAxis; + const int YAxis; }; // Transforms points for log x and linear y space struct TransformerLogLin { TransformerLogLin() : YAxis(GetCurrentYAxis()) {} - - inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } - inline ImVec2 operator()(double x, double y) { + inline ImVec2 operator()(const ImPlotPoint& plt) const { ImPlotContext& gp = *GImPlot; - double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX; - x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t); + double t = ImLog10(plt.x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX; + double x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t); return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), - (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); + (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); } - - int YAxis; + const int YAxis; }; // Transforms points for linear x and log y space struct TransformerLinLog { TransformerLinLog() : YAxis(GetCurrentYAxis()) {} - - inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } - inline ImVec2 operator()(double x, double y) { + inline ImVec2 operator()(const ImPlotPoint& plt) const { ImPlotContext& gp = *GImPlot; - double t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis]; - y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t); - return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), + double t = ImLog10(plt.y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis]; + double y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t); + return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)), (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); } - int YAxis; + const int YAxis; }; // Transforms points for log x and log y space struct TransformerLogLog { TransformerLogLog() : YAxis(GetCurrentYAxis()) {} - - inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } - inline ImVec2 operator()(double x, double y) { + inline ImVec2 operator()(const ImPlotPoint& plt) const { ImPlotContext& gp = *GImPlot; - double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX; - x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t); - t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis]; - y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t); + double t = ImLog10(plt.x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX; + double x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t); + t = ImLog10(plt.y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis]; + double y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t); return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); } - int YAxis; + const int YAxis; }; //----------------------------------------------------------------------------- @@ -460,16 +457,16 @@ inline void AddLine(const ImVec2& P1, const ImVec2& P2, float weight, ImU32 col, template struct LineStripRenderer { - inline LineStripRenderer(TGetter getter, TTransformer transformer, ImU32 col, float weight) : + inline LineStripRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) : Getter(getter), - Transformer(transformer) - { - Prims = Getter.Count - 1; - Col = col; - Weight = weight; + Transformer(transformer), + Prims(Getter.Count - 1), + Col(col), + Weight(weight) + { P1 = Transformer(Getter(0)); } - inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) { + inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const { ImVec2 P2 = Transformer(Getter(prim + 1)); if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { P1 = P2; @@ -479,29 +476,27 @@ struct LineStripRenderer { P1 = P2; return true; } - TGetter Getter; - TTransformer Transformer; - int Prims; - ImU32 Col; - float Weight; - ImVec2 P1; + const TGetter& Getter; + const TTransformer& Transformer; + const int Prims; + const ImU32 Col; + const float Weight; + mutable ImVec2 P1; static const int IdxConsumed = 6; static const int VtxConsumed = 4; }; template struct LineSegmentsRenderer { - inline LineSegmentsRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col, float weight) : + inline LineSegmentsRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col, float weight) : Getter1(getter1), Getter2(getter2), - Transformer(transformer) - { - - Prims = ImMin(Getter1.Count, Getter2.Count); - Col = col; - Weight = weight; - } - inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) { + Transformer(transformer), + Prims(ImMin(Getter1.Count, Getter2.Count)), + Col(col), + Weight(weight) + {} + inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const { ImVec2 P1 = Transformer(Getter1(prim)); ImVec2 P2 = Transformer(Getter2(prim)); if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) @@ -509,30 +504,30 @@ struct LineSegmentsRenderer { AddLine(P1,P2,Weight,Col,DrawList,uv); return true; } - TGetter1 Getter1; - TGetter2 Getter2; - TTransformer Transformer; - int Prims; - ImU32 Col; - float Weight; + const TGetter1& Getter1; + const TGetter2& Getter2; + const TTransformer& Transformer; + const int Prims; + const ImU32 Col; + const float Weight; static const int IdxConsumed = 6; static const int VtxConsumed = 4; }; template struct ShadedRenderer { - ShadedRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col) : + ShadedRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col) : Getter1(getter1), Getter2(getter2), Transformer(transformer), + Prims(ImMin(Getter1.Count, Getter2.Count) - 1), Col(col) { - Prims = ImMin(Getter1.Count, Getter2.Count) - 1; P11 = Transformer(Getter1(0)); P12 = Transformer(Getter2(0)); } - inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) { + inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) const { // TODO: Culling ImVec2 P21 = Transformer(Getter1(prim+1)); ImVec2 P22 = Transformer(Getter2(prim+1)); @@ -566,26 +561,26 @@ struct ShadedRenderer { P12 = P22; return true; } - TGetter1 Getter1; - TGetter2 Getter2; - TTransformer Transformer; - int Prims; - ImU32 Col; - ImVec2 P11, P12; + const TGetter1& Getter1; + const TGetter2& Getter2; + const TTransformer& Transformer; + const int Prims; + const ImU32 Col; + mutable ImVec2 P11; + mutable ImVec2 P12; static const int IdxConsumed = 6; static const int VtxConsumed = 5; }; template struct RectRenderer { - inline RectRenderer(TGetter getter, TTransformer transformer, ImU32 col) : + inline RectRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col) : Getter(getter), - Transformer(transformer) - { - Prims = Getter.Count / 2; - Col = col; - } - inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) { + Transformer(transformer), + Prims(Getter.Count / 2), + Col(col) + {} + inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) const { // TODO: Culling ImVec2 P1 = Transformer(Getter(2*prim)); ImVec2 P2 = Transformer(Getter(2*prim+1)); @@ -614,10 +609,10 @@ struct RectRenderer { DrawList._VtxCurrentIdx += 4; return true; } - TGetter Getter; - TTransformer Transformer; - int Prims; - ImU32 Col; + const TGetter& Getter; + const TTransformer& Transformer; + const int Prims; + const ImU32 Col; static const int IdxConsumed = 6; static const int VtxConsumed = 4; }; @@ -630,7 +625,7 @@ template <> const unsigned int MaxIdx::Value = 4294967295; /// Renders primitive shapes in bulk as efficiently as possible. template -inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList, const ImRect& cull_rect) { +inline void RenderPrimitives(const Renderer& renderer, ImDrawList& DrawList, const ImRect& cull_rect) { unsigned int prims = renderer.Prims; unsigned int prims_culled = 0; unsigned int idx = 0; @@ -667,7 +662,7 @@ inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList, const ImRe } template -inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { +inline void RenderLineStrip(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { ImPlotContext& gp = *GImPlot; if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) { ImVec2 p1 = transformer(getter(0)); @@ -684,7 +679,7 @@ inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList& } template -inline void RenderLineSegments(Getter1 getter1, Getter2 getter2, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { +inline void RenderLineSegments(const Getter1& getter1, const Getter2& getter2, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { ImPlotContext& gp = *GImPlot; if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) { int I = ImMin(getter1.Count, getter2.Count); @@ -810,11 +805,11 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr } //----------------------------------------------------------------------------- -// PLOT LINES +// PLOT LINE //----------------------------------------------------------------------------- template -inline void PlotLineEx(const char* label_id, Getter getter) { +inline void PlotLineEx(const char* label_id, const Getter& getter) { if (BeginItem(label_id, ImPlotCol_Line)) { if (FitThisFrame()) { for (int i = 0; i < getter.Count; ++i) { @@ -906,7 +901,7 @@ void PlotLineG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int //----------------------------------------------------------------------------- template -inline void PlotScatterEx(const char* label_id, Getter getter) { +inline void PlotScatterEx(const char* label_id, const Getter& getter) { if (BeginItem(label_id, ImPlotCol_MarkerOutline)) { if (FitThisFrame()) { for (int i = 0; i < getter.Count; ++i) { @@ -990,7 +985,7 @@ void PlotScatterG(const char* label_id, ImPlotPoint (*getter_func)(void* data, i //----------------------------------------------------------------------------- template -inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) { +inline void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2) { if (BeginItem(label_id, ImPlotCol_Fill)) { if (FitThisFrame()) { for (int i = 0; i < ImMin(getter1.Count, getter2.Count); ++i) { @@ -1082,10 +1077,10 @@ void PlotShadedG(const char* label_id, ImPlotPoint (*g1)(void* data, int idx), v // TODO: Migrate to RenderPrimitives -template -void PlotBarsEx(const char* label_id, Getter getter, TWidth width) { +template +void PlotBarsEx(const char* label_id, const Getter& getter, double width) { if (BeginItem(label_id, ImPlotCol_Fill)) { - const TWidth half_width = width / 2; + const double half_width = width / 2; if (FitThisFrame()) { for (int i = 0; i < getter.Count; ++i) { ImPlotPoint p = getter(i); @@ -1162,7 +1157,7 @@ void PlotBarsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int // TODO: Migrate to RenderPrimitives template -void PlotBarsHEx(const char* label_id, Getter getter, THeight height) { +void PlotBarsHEx(const char* label_id, const Getter& getter, THeight height) { if (BeginItem(label_id, ImPlotCol_Fill)) { const THeight half_height = height / 2; if (FitThisFrame()) { @@ -1239,7 +1234,7 @@ void PlotBarsHG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int //----------------------------------------------------------------------------- template -void PlotErrorBarsEx(const char* label_id, Getter getter) { +void PlotErrorBarsEx(const char* label_id, const Getter& getter) { if (BeginItem(label_id)) { if (FitThisFrame()) { for (int i = 0; i < getter.Count; ++i) { @@ -1267,34 +1262,45 @@ void PlotErrorBarsEx(const char* label_id, Getter getter) { } } -// float -void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { - GetterError getter(xs, ys, err, err, count, offset, stride); +template +void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset, int stride) { + GetterError getter(xs, ys, err, err, count, offset, stride); PlotErrorBarsEx(label_id, getter); } -void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride) { - GetterError getter(xs, ys, neg, pos, count, offset, stride); - PlotErrorBarsEx(label_id, getter); -} +template void PlotErrorBars(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride); -// double -void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { - GetterError getter(xs, ys, err, err, count, offset, stride); - PlotErrorBarsEx(label_id, getter); -} - -void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride) { - GetterError getter(xs, ys, neg, pos, count, offset, stride); +template +void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) { + GetterError getter(xs, ys, neg, pos, count, offset, stride); PlotErrorBarsEx(label_id, getter); } +template void PlotErrorBars(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* neg, const ImU16* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* neg, const ImS32* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* neg, const ImU32* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* neg, const ImS64* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* neg, const ImU64* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride); +template void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride); //----------------------------------------------------------------------------- // PLOT ERROR BARS H //----------------------------------------------------------------------------- template -void PlotErrorBarsHEx(const char* label_id, Getter getter) { +void PlotErrorBarsHEx(const char* label_id, const Getter& getter) { if (BeginItem(label_id)) { if (FitThisFrame()) { for (int i = 0; i < getter.Count; ++i) { @@ -1322,34 +1328,46 @@ void PlotErrorBarsHEx(const char* label_id, Getter getter) { } } -// float -void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { - GetterError getter(xs, ys, err, err, count, offset, stride); +template +void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset, int stride) { + GetterError getter(xs, ys, err, err, count, offset, stride); PlotErrorBarsHEx(label_id, getter); } -void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride) { - GetterError getter(xs, ys, neg, pos, count, offset, stride); +template void PlotErrorBarsH(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride); + +template +void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) { + GetterError getter(xs, ys, neg, pos, count, offset, stride); PlotErrorBarsHEx(label_id, getter); } -// double -void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { - GetterError getter(xs, ys, err, err, count, offset, stride); - PlotErrorBarsHEx(label_id, getter); -} - -void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride) { - GetterError getter(xs, ys, neg, pos, count, offset, stride); - PlotErrorBarsHEx(label_id, getter); -} +template void PlotErrorBarsH(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* neg, const ImU16* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* neg, const ImS32* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* neg, const ImU32* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* neg, const ImS64* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* neg, const ImU64* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride); +template void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride); //----------------------------------------------------------------------------- // PLOT STEMS //----------------------------------------------------------------------------- template -inline void PlotStemsEx(const char* label_id, GetterM get_mark, GetterB get_base) { +inline void PlotStemsEx(const char* label_id, const GetterM& get_mark, const GetterB& get_base) { if (BeginItem(label_id, ImPlotCol_Line)) { if (FitThisFrame()) { for (int i = 0; i < get_base.Count; ++i) { @@ -1385,29 +1403,41 @@ inline void PlotStemsEx(const char* label_id, GetterM get_mark, GetterB get_base } } -void PlotStems(const char* label_id, const float* values, int count, float y_ref, int offset, int stride) { - GetterYs get_mark(values,count,offset,stride); - GetterYRef get_base(y_ref,count); - PlotStemsEx(label_id, get_mark, get_base); -} - -void PlotStems(const char* label_id, const double* values, int count, double y_ref, int offset, int stride) { - GetterYs get_mark(values,count,offset,stride); +template +void PlotStems(const char* label_id, const T* values, int count, double y_ref, int offset, int stride) { + GetterYs get_mark(values,count,offset,stride); GetterYRef get_base(y_ref,count); PlotStemsEx(label_id, get_mark, get_base); } -void PlotStems(const char* label_id, const float* xs, const float* ys, int count, float y_ref, int offset, int stride) { - GetterXsYs get_mark(xs,ys,count,offset,stride); - GetterXsYRef get_base(xs,y_ref,count,offset,stride); +template void PlotStems(const char* label_id, const ImS8* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU8* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImS16* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU16* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImS32* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU32* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImS64* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU64* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const float* values, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const double* values, int count, double y_ref, int offset, int stride); + +template +void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref, int offset, int stride) { + GetterXsYs get_mark(xs,ys,count,offset,stride); + GetterXsYRef get_base(xs,y_ref,count,offset,stride); PlotStemsEx(label_id, get_mark, get_base); } -void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride) { - GetterXsYs get_mark(xs,ys,count,offset,stride); - GetterXsYRef get_base(xs,y_ref,count,offset,stride); - PlotStemsEx(label_id, get_mark, get_base); -} +template void PlotStems(const char* label_id, const ImS8* xs, const ImS8* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU8* xs, const ImU8* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImS16* xs, const ImS16* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU16* xs, const ImU16* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImS32* xs, const ImS32* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU32* xs, const ImU32* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImS64* xs, const ImS64* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const ImU64* xs, const ImU64* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const float* xs, const float* ys, int count, double y_ref, int offset, int stride); +template void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride); //----------------------------------------------------------------------------- // PLOT PIE CHART @@ -1427,19 +1457,19 @@ inline void RenderPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, doub } template -void PlotPieChartEx(const char* const label_ids[], const T* values, int count, T x, T y, T radius, bool normalize, const char* fmt, T angle0) { +void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0) { IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!"); ImDrawList & DrawList = *GetPlotDrawList(); - T sum = 0; + double sum = 0; for (int i = 0; i < count; ++i) - sum += values[i]; - normalize = normalize || sum > 1.0f; + sum += (double)values[i]; + normalize = normalize || sum > 1.0; ImPlotPoint center(x,y); PushPlotClipRect(); - T a0 = angle0 * 2 * IM_PI / 360.0f; - T a1 = angle0 * 2 * IM_PI / 360.0f; + double a0 = angle0 * 2 * IM_PI / 360.0; + double a1 = angle0 * 2 * IM_PI / 360.0; for (int i = 0; i < count; ++i) { - T percent = normalize ? values[i] / sum : values[i]; + double percent = normalize ? (double)values[i] / sum : (double)values[i]; a1 = a0 + 2 * IM_PI * percent; if (BeginItem(label_ids[i])) { ImU32 col = ImGui::GetColorU32(GetCurrentItem()->Color); @@ -1447,26 +1477,26 @@ void PlotPieChartEx(const char* const label_ids[], const T* values, int count, T RenderPieSlice(DrawList, center, radius, a0, a1, col); } else { - RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5f, col); - RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5f, a1, col); + RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5, col); + RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5, a1, col); } EndItem(); } a0 = a1; } if (fmt != NULL) { - a0 = angle0 * 2 * IM_PI / 360.0f; - a1 = angle0 * 2 * IM_PI / 360.0f; + a0 = angle0 * 2 * IM_PI / 360.0; + a1 = angle0 * 2 * IM_PI / 360.0; char buffer[32]; for (int i = 0; i < count; ++i) { ImPlotItem* item = GetItem(label_ids[i]); - T percent = normalize ? values[i] / sum : values[i]; + double percent = normalize ? (double)values[i] / sum : (double)values[i]; a1 = a0 + 2 * IM_PI * percent; if (item->Show) { - sprintf(buffer, fmt, values[i]); + sprintf(buffer, fmt, (double)values[i]); ImVec2 size = ImGui::CalcTextSize(buffer); - T angle = a0 + (a1 - a0) * 0.5f; - ImVec2 pos = PlotToPixels(center.x + 0.5f * radius * cos(angle), center.y + 0.5f * radius * sin(angle)); + double angle = a0 + (a1 - a0) * 0.5; + ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle)); ImU32 col = CalcTextColor(item->Color); DrawList.AddText(pos - size * 0.5f, col, buffer); } @@ -1476,22 +1506,23 @@ void PlotPieChartEx(const char* const label_ids[], const T* values, int count, T PopPlotClipRect(); } -// float -void PlotPieChart(const char* const label_ids[], const float* values, int count, float x, float y, float radius, bool normalize, const char* fmt, float angle0) { - return PlotPieChartEx(label_ids, values, count, x, y, radius, normalize, fmt, angle0); -} - -// double -void PlotPieChart(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0) { - return PlotPieChartEx(label_ids, values, count, x, y, radius, normalize, fmt, angle0); -} +template void PlotPieChart(const char* const label_ids[], const ImS8* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImU8* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImS16* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImU16* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImS32* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImU32* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImS64* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const ImU64* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const float* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); +template void PlotPieChart(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0); //----------------------------------------------------------------------------- // PLOT HEATMAP //----------------------------------------------------------------------------- template -void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, T scale_min, T scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { +void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { ImPlotContext& gp = *GImPlot; const double w = (bounds_max.x - bounds_min.x) / cols; const double h = (bounds_max.y - bounds_min.y) / rows; @@ -1502,10 +1533,10 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value ImPlotPoint p; p.x = bounds_min.x + 0.5*w + c*w; p.y = bounds_max.y - (0.5*h + r*h); - ImVec2 a = transformer(p.x - half_size.x, p.y - half_size.y); - ImVec2 b = transformer(p.x + half_size.x, p.y + half_size.y); - float t = (float)ImRemap(values[i], scale_min, scale_max, T(0), T(1)); - ImVec4 color = LerpColormap(t); + ImVec2 a = transformer(ImPlotPoint(p.x - half_size.x, p.y - half_size.y)); + ImVec2 b = transformer(ImPlotPoint(p.x + half_size.x, p.y + half_size.y)); + double t = ImRemap((double)values[i], scale_min, scale_max, 0.0, 1.0); + ImVec4 color = LerpColormap((float)t); color.w *= gp.Style.FillAlpha; ImU32 col = ImGui::GetColorU32(color); DrawList.AddRectFilled(a, b, col); @@ -1523,8 +1554,8 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value char buff[32]; sprintf(buff, fmt, values[i]); ImVec2 size = ImGui::CalcTextSize(buff); - float t = (float)ImRemap(values[i], scale_min, scale_max, T(0), T(1)); - ImVec4 color = LerpColormap(t); + double t = ImRemap((double)values[i], scale_min, scale_max, 0.0, 1.0); + ImVec4 color = LerpColormap((float)t); ImU32 col = CalcTextColor(color); DrawList.AddText(px - size * 0.5f, col, buff); i++; @@ -1534,7 +1565,7 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value } template -void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T scale_min, T scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { +void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!"); if (BeginItem(label_id)) { if (FitThisFrame()) { @@ -1552,21 +1583,22 @@ void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T } } -// float -void PlotHeatmap(const char* label_id, const float* values, int rows, int cols, float scale_min, float scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { - return PlotHeatmapEx(label_id, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); -} - -// double -void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { - return PlotHeatmapEx(label_id, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); -} +template void PlotHeatmap(const char* label_id, const ImS8* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImU8* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImS16* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImU16* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImS32* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImU32* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImS64* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const ImU64* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const float* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); +template void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); //----------------------------------------------------------------------------- // PLOT DIGITAL //----------------------------------------------------------------------------- -// TODO: Make this behave like all the other plot types +// TODO: Make this behave like all the other plot types (.e. not fixed in y axis) template inline void PlotDigitalEx(const char* label_id, Getter getter) { @@ -1624,20 +1656,26 @@ inline void PlotDigitalEx(const char* label_id, Getter getter) { } } -// float -void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { - GetterXsYs getter(xs,ys,count,offset,stride); + +template +void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset, int stride) { + GetterXsYs getter(xs,ys,count,offset,stride); return PlotDigitalEx(label_id, getter); } -// double -void PlotDigital(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) { - GetterXsYs getter(xs,ys,count,offset,stride); - return PlotDigitalEx(label_id, getter); -} +template void PlotDigital(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride); +template void PlotDigital(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride); // custom -void PlotDigital(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) { +void PlotDigitalG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) { GetterFuncPtrImPlotPoint getter(getter_func,data,count,offset); return PlotDigitalEx(label_id, getter); } @@ -1646,7 +1684,7 @@ void PlotDigital(const char* label_id, ImPlotPoint (*getter_func)(void* data, in // PLOT RECTS //----------------------------------------------------------------------------- template -void PlotRectsEx(const char* label_id, Getter getter) { +void PlotRectsEx(const char* label_id, const Getter& getter) { if (BeginItem(label_id, ImPlotCol_Fill)) { if (FitThisFrame()) { for (int i = 0; i < getter.Count; ++i) { @@ -1691,11 +1729,6 @@ void PlotRects(const char* label_id, ImPlotPoint (*getter_func)(void* data, int // PLOT TEXT //----------------------------------------------------------------------------- -// float -void PlotText(const char* text, float x, float y, bool vertical, const ImVec2& pixel_offset) { - return PlotText(text, (double)x, (double)y, vertical, pixel_offset); -} - // double void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) { IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");