From 51930a5ae64587379c34fa54037e8ef6cbc7190f Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Fri, 9 Jul 2021 17:39:12 -0700 Subject: [PATCH 1/6] fix imgui backward compat, YAxis[3], and add new demo benchmark option for LineG --- implot.cpp | 7 +------ implot_demo.cpp | 22 ++++++++++++++++++---- implot_internal.h | 9 +++++++-- implot_items.cpp | 6 ------ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/implot.cpp b/implot.cpp index 7b7924c..d6d3fbf 100644 --- a/implot.cpp +++ b/implot.cpp @@ -83,11 +83,6 @@ You can read releases logs https://github.com/epezent/implot/releases for more d #define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All #endif -// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize() -#if (IMGUI_VERSION_NUM < 18303) -#define GetBufSize GetSize // A little bit ugly since 'GetBufSize' could technically be used elsewhere (but currently isn't). Could use a proxy define if needed. -#endif - // Global plot context ImPlotContext* GImPlot = NULL; @@ -4483,7 +4478,7 @@ void ShowMetricsWindow(bool* p_popen) { if (ImHasFlag(plot->Flags, ImPlotFlags_YAxis2)) fg.AddRect(plot->YAxis[1].HoverRect.Min, plot->YAxis[1].HoverRect.Max, IM_COL32(0,255,0,255)); if (ImHasFlag(plot->Flags, ImPlotFlags_YAxis3)) - fg.AddRect(plot->YAxis[3].HoverRect.Min, plot->YAxis[2].HoverRect.Max, IM_COL32(0,255,0,255)); + fg.AddRect(plot->YAxis[2].HoverRect.Min, plot->YAxis[2].HoverRect.Max, IM_COL32(0,255,0,255)); } } for (int p = 0; p < n_subplots; ++p) { diff --git a/implot_demo.cpp b/implot_demo.cpp index 46e7269..a1ef3e2 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -2063,9 +2063,10 @@ struct BenchData { enum BenchMode { Line = 0, - Shaded = 1, - Scatter = 2, - Bars = 3 + LineG = 1, + Shaded = 2, + Scatter = 3, + Bars = 4 }; struct BenchRecord { @@ -2074,6 +2075,11 @@ struct BenchRecord { ImVector Data; }; +ImPlotPoint BenchmarkGetter(void* data, int idx) { + float* values = (float*)data; + return ImPlotPoint(idx, values[idx]); +} + void ShowBenchmarkTool() { static const int max_items = 500; static BenchData items[max_items]; @@ -2083,7 +2089,7 @@ void ShowBenchmarkTool() { static int F = 0; static double t1, t2; static int mode = BenchMode::Line; - const char* names[] = {"Line","Shaded","Scatter","Bars"}; + const char* names[] = {"Line","LineG","Shaded","Scatter","Bars"}; static ImVector records; @@ -2143,6 +2149,14 @@ void ShowBenchmarkTool() { ImGui::PopID(); } } + else if (mode == BenchMode::LineG) { + for (int i = 0; i < L; ++i) { + ImGui::PushID(i); + ImPlot::SetNextLineStyle(items[i].Col); + ImPlot::PlotLineG("##item",BenchmarkGetter,items[i].Data,1000); + ImGui::PopID(); + } + } else if (mode == BenchMode::Shaded) { for (int i = 0; i < L; ++i) { ImGui::PushID(i); diff --git a/implot_internal.h b/implot_internal.h index 2ea2e52..c7f40ea 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -42,6 +42,11 @@ #error Must include implot.h before implot_internal.h #endif +// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize() +#if (IMGUI_VERSION_NUM < 18303) +#define GetBufSize GetSize +#endif + //----------------------------------------------------------------------------- // [SECTION] Constants //----------------------------------------------------------------------------- @@ -1264,8 +1269,8 @@ void FillRange(ImVector& buffer, int n, T vmin, T vmax) { // Offsets and strides a data buffer template -static inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) { - idx = ImPosMod(offset + idx, count); +static inline T OffsetAndStride(const T* data, int idx, int , int , int stride) { + // idx = ImPosMod(offset + idx, count); return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride); } diff --git a/implot_items.cpp b/implot_items.cpp index dc9d6bd..4abbb64 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -47,12 +47,6 @@ #define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All #endif -// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize() -#if (IMGUI_VERSION_NUM < 18303) -#define GetBufSize GetSize // A little bit ugly since 'GetBufSize' could technically be used elsewhere (but currently isn't). Could use a proxy define if needed. -#endif - - namespace ImPlot { //----------------------------------------------------------------------------- From bffd448207be312f46cd0a874c2f7325884fe041 Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Fri, 9 Jul 2021 20:22:21 -0700 Subject: [PATCH 2/6] revert OffsetAndStride --- implot.h | 2 ++ implot_internal.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/implot.h b/implot.h index 316915b..d045cbf 100644 --- a/implot.h +++ b/implot.h @@ -537,6 +537,8 @@ template IMPLOT_API void PlotBarsH(const char* label_id, const T* v template IMPLOT_API void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset=0, int stride=sizeof(T)); IMPLOT_API void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset=0); + + // Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot. template IMPLOT_API 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 IMPLOT_API 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)); diff --git a/implot_internal.h b/implot_internal.h index c7f40ea..5da0689 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -1270,7 +1270,7 @@ void FillRange(ImVector& buffer, int n, T vmin, T vmax) { // Offsets and strides a data buffer template static inline T OffsetAndStride(const T* data, int idx, int , int , int stride) { - // idx = ImPosMod(offset + idx, count); + idx = ImPosMod(offset + idx, count); return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride); } From cd4704fd52dfe163ebeab5cc86dc2e8aafb7f6df Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Fri, 9 Jul 2021 20:23:12 -0700 Subject: [PATCH 3/6] revert OffsetAndStride --- implot.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/implot.h b/implot.h index d045cbf..316915b 100644 --- a/implot.h +++ b/implot.h @@ -537,8 +537,6 @@ template IMPLOT_API void PlotBarsH(const char* label_id, const T* v template IMPLOT_API void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset=0, int stride=sizeof(T)); IMPLOT_API void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset=0); - - // Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot. template IMPLOT_API 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 IMPLOT_API 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)); From 83cb14b54a4f376965d30e2972c7464673b9f068 Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Fri, 9 Jul 2021 20:29:04 -0700 Subject: [PATCH 4/6] fix offsetandstride args...oops --- implot_internal.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/implot_internal.h b/implot_internal.h index 5da0689..065c2d0 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -1269,11 +1269,10 @@ void FillRange(ImVector& buffer, int n, T vmin, T vmax) { // Offsets and strides a data buffer template -static inline T OffsetAndStride(const T* data, int idx, int , int , int stride) { +static inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) { idx = ImPosMod(offset + idx, count); return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride); } - // Calculate histogram bin counts and widths template static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) { From 2dc2a4cfd5e3f0419b1f864cdaedba94ec8ef3a5 Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Thu, 15 Jul 2021 20:40:51 -0700 Subject: [PATCH 5/6] improve tick label culling --- implot.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/implot.cpp b/implot.cpp index d6d3fbf..12ce6eb 100644 --- a/implot.cpp +++ b/implot.cpp @@ -690,6 +690,9 @@ bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool hov // Tick Utils //----------------------------------------------------------------------------- +static const float TICK_FILL_X = 0.8f; +static const float TICK_FILL_Y = 1.0f; + void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt) { const int idx0 = ticks.Size; const int nMinor = 10; @@ -700,12 +703,7 @@ void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, const double graphmax = ceil(range.Max / interval) * interval; bool first_major_set = false; int first_major_idx = 0; - - char dummy[32]; - sprintf(dummy,fmt,-ImAbs(interval / nMinor)); - ImVec2 dummy_size = ImGui::CalcTextSize(dummy); ImVec2 total_size(0,0); - for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) { // is this zero? combat zero formatting issues if (major-interval < 0 && major+interval > 0) @@ -715,19 +713,17 @@ void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, first_major_idx = ticks.Size; first_major_set = true; } - ticks.Append(major, true, true, fmt); - total_size += dummy_size; + total_size += ticks.Append(major, true, true, fmt).LabelSize; } for (int i = 1; i < nMinor; ++i) { double minor = major + i * interval / nMinor; if (range.Contains(minor)) { - ticks.Append(minor, false, true, fmt); - total_size += dummy_size; + total_size += ticks.Append(minor, false, true, fmt).LabelSize; } } } // prune if necessary - if ((orn == ImPlotOrientation_Horizontal && total_size.x > pix) || (orn == ImPlotOrientation_Vertical && total_size.y > pix)) { + if ((orn == ImPlotOrientation_Horizontal && total_size.x > pix*TICK_FILL_X) || (orn == ImPlotOrientation_Vertical && total_size.y > pix*TICK_FILL_Y)) { for (int i = first_major_idx-1; i >= idx0; i -= 2) ticks.Ticks[i].ShowLabel = false; for (int i = first_major_idx+1; i < ticks.Size; i += 2) From 507459fd5f7d6b210ad2a8663d0ae765251fcedf Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Fri, 23 Jul 2021 16:32:57 -0700 Subject: [PATCH 6/6] move axis equal constraint after pixel determination --- implot.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/implot.cpp b/implot.cpp index 12ce6eb..2e0ddad 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2054,22 +2054,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con for (int i = 0; i < IMPLOT_Y_AXES; ++i) plot.YAxis[i].Constrain(); - // constrain equal axes for primary x and y if not approximately equal - // constrains x to y since x pixel size depends on y labels width, and causes feedback loops in opposite case - if (ImHasFlag(plot.Flags, ImPlotFlags_Equal)) { - double xar = plot.XAxis.GetAspect(); - double yar = plot.YAxis[0].GetAspect(); - // edge case: user has set x range this frame, so fit y to x so that we honor their request for x range - // NB: because of feedback across several frames, the user's x request may not be perfectly honored - if (gp.NextPlotData.HasXRange) { - plot.YAxis[0].SetAspect(xar); - } - else { - if (!ImAlmostEqual(xar,yar) && !plot.YAxis[0].IsInputLocked()) - plot.XAxis.SetAspect(yar); - } - } - // AXIS COLORS ----------------------------------------------------------------- UpdateAxisColors(ImPlotCol_XAxis, &plot.XAxis); @@ -2236,6 +2220,23 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con for (int i = 0; i < IMPLOT_Y_AXES; ++i) plot.YAxis[i].Pixels = plot.PlotRect.GetHeight(); + // Equal axis constraint. Must happen after we set Pixels + // constrain equal axes for primary x and y if not approximately equal + // constrains x to y since x pixel size depends on y labels width, and causes feedback loops in opposite case + if (ImHasFlag(plot.Flags, ImPlotFlags_Equal)) { + double xar = plot.XAxis.GetAspect(); + double yar = plot.YAxis[0].GetAspect(); + // edge case: user has set x range this frame, so fit y to x so that we honor their request for x range + // NB: because of feedback across several frames, the user's x request may not be perfectly honored + if (gp.NextPlotData.HasXRange) { + plot.YAxis[0].SetAspect(xar); + } + else { + if (!ImAlmostEqual(xar,yar) && !plot.YAxis[0].IsInputLocked()) + plot.XAxis.SetAspect(yar); + } + } + // INPUT ------------------------------------------------------------------ HandlePlotInput(plot);