From 244288fbcbf709875b0d5c0f34f153091b037665 Mon Sep 17 00:00:00 2001 From: Mohammad Odeh Date: Thu, 20 Feb 2025 16:13:33 -0500 Subject: [PATCH 01/23] Add custom right-click context menu Pass ImPlotFlags_NoCentralMenu to BeginPlot() Usage BeginCustomContext(){ ...; EndCustomContext() } within BeginPlot() --- implot.cpp | 34 +++++++++++++++++++++++++++++++++- implot.h | 11 +++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/implot.cpp b/implot.cpp index fd3690db..5594eac0 100644 --- a/implot.cpp +++ b/implot.cpp @@ -3191,7 +3191,8 @@ void EndPlot() { // main ctx menu - if (can_ctx && plot.Hovered) + // if (can_ctx && plot.Hovered) <-- old line // OdehM 2025-02-20 + if (can_ctx && !ImHasFlag(plot.Flags, ImPlotFlags_NoCentralMenu) && plot.Hovered) // <-- new line // OdehM 2025-02-20 ImGui::OpenPopup("##PlotContext"); if (ImGui::BeginPopup("##PlotContext")) { ShowPlotContextMenu(plot); @@ -5860,6 +5861,37 @@ void StyleColorsLight(ImPlotStyle* dst) { colors[ImPlotCol_Crosshairs] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f); } +//----------------------------------------------------------------------------- +// [SECTION] Context Menu // OdehM 2025-02-20 +//----------------------------------------------------------------------------- + +bool BeginCustomContext() +{ + ImPlotContext& gp = *GImPlot; + + if (gp.CurrentPlot == nullptr) return false; + + ImPlotPlot &plot = *gp.CurrentPlot; + + const bool can_ctx = plot.Hovered && + !plot.Items.Legend.Hovered && + !plot.ContextLocked && // <-- added + ImGui::IsMouseReleased(ImGuiMouseButton_Right); + + // main ctx menu + if (can_ctx) + ImGui::OpenPopup("##CustomPlotContext"); + + return ImGui::BeginPopup("##CustomPlotContext"); +} + +void EndCustomContext(bool include_default) +{ + if (include_default) + ShowPlotContextMenu(*(GImPlot->CurrentPlot)); + ImGui::EndPopup(); +} + //----------------------------------------------------------------------------- // [SECTION] Obsolete Functions/Types //----------------------------------------------------------------------------- diff --git a/implot.h b/implot.h index a7961c4f..f54f3815 100644 --- a/implot.h +++ b/implot.h @@ -42,6 +42,7 @@ // [SECTION] Input Mapping // [SECTION] Miscellaneous // [SECTION] Demo +// [SECTION] Context Menu // OdehM 2025-02-20 // [SECTION] Obsolete API #pragma once @@ -139,6 +140,7 @@ enum ImPlotFlags_ { ImPlotFlags_NoFrame = 1 << 6, // the ImGui frame will not be rendered ImPlotFlags_Equal = 1 << 7, // x and y axes pairs will be constrained to have the same units/pixel ImPlotFlags_Crosshairs = 1 << 8, // the default mouse cursor will be replaced with a crosshair when hovered + ImPlotFlags_NoCentralMenu = 1 << 9, // disable the central menu, but allow other menus (such as legends and axis) // OdehM 2025_02_20 ImPlotFlags_CanvasOnly = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText }; @@ -1247,6 +1249,15 @@ IMPLOT_API void ShowMetricsWindow(bool* p_popen = nullptr); // Shows the ImPlot demo window (add implot_demo.cpp to your sources!) IMPLOT_API void ShowDemoWindow(bool* p_open = nullptr); +//----------------------------------------------------------------------------- +// [SECTION] Context Menu // OdehM 2025-02-20 +//----------------------------------------------------------------------------- + +// Begin a custom central plot context menu +IMPLOT_API bool BeginCustomContext(); +// End a custom central plot context menu +IMPLOT_API void EndCustomContext(bool include_default = false); // if include_default is true, the normal context menu will be appended + } // namespace ImPlot //----------------------------------------------------------------------------- From fe62178c0fd96003ad12284daae1e883af5bf4c2 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 5 Mar 2025 19:01:56 +0100 Subject: [PATCH 02/23] Fixes for internal API changes in 1.92.x: ImFontBaked, ImGuiWindow::CalcFontSize(). (#614) --- implot.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/implot.cpp b/implot.cpp index 5594eac0..5c400c00 100644 --- a/implot.cpp +++ b/implot.cpp @@ -342,11 +342,16 @@ void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char *te if (!text_end) text_end = text_begin + strlen(text_begin); ImGuiContext& g = *GImGui; +#ifdef IMGUI_HAS_TEXTURES + ImFontBaked* font = g.Font->GetFontBaked(g.FontSize); + const float scale = g.FontSize / font->Size; +#else ImFont* font = g.Font; + const float scale = g.FontSize / font->FontSize; +#endif // Align to be pixel perfect pos.x = ImFloor(pos.x); pos.y = ImFloor(pos.y); - const float scale = g.FontSize / font->FontSize; const char* s = text_begin; int chars_exp = (int)(text_end - s); int chars_rnd = 0; @@ -3059,7 +3064,11 @@ void EndPlot() { ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.Items.ID); if (IO.MouseWheel != 0.0f) { ImVec2 max_step = legend.Rect.GetSize() * 0.67f; +#if IMGUI_VERSION_NUM < 19172 float font_size = ImGui::GetCurrentWindow()->CalcFontSize(); +#else + float font_size = ImGui::GetCurrentWindow()->FontRefSize; +#endif float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x)); legend.Scroll.x += scroll_step * IO.MouseWheel; legend.Scroll.y += scroll_step * IO.MouseWheel; @@ -3579,7 +3588,11 @@ void EndSubplots() { ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, subplot.Items.ID); if (IO.MouseWheel != 0.0f) { ImVec2 max_step = legend.Rect.GetSize() * 0.67f; +#if IMGUI_VERSION_NUM < 19172 float font_size = ImGui::GetCurrentWindow()->CalcFontSize(); +#else + float font_size = ImGui::GetCurrentWindow()->FontRefSize; +#endif float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x)); legend.Scroll.x += scroll_step * IO.MouseWheel; legend.Scroll.y += scroll_step * IO.MouseWheel; From 494a4d90e9047df532bd4f0f990ce9551423c4c1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 19 Mar 2025 18:55:40 +0100 Subject: [PATCH 03/23] Fixes for internal API changes in 1.92.x: PlotImage() uses ImTextureRef instead of ImTextureID. (#616) --- implot.h | 6 +++++- implot_demo.cpp | 9 ++++++++- implot_items.cpp | 8 ++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/implot.h b/implot.h index f54f3815..8e388cda 100644 --- a/implot.h +++ b/implot.h @@ -916,7 +916,11 @@ IMPLOT_TMP void PlotDigital(const char* label_id, const T* xs, const T* ys, int IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0); // Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down). -IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0); +#ifdef IMGUI_HAS_TEXTURES +IMPLOT_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), ImPlotImageFlags flags = 0); +#else +IMPLOT_API void PlotImage(const char* label_id, ImTextureID tex_ref, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0); +#endif // Plots a centered text label at point x,y with an optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...). IMPLOT_API void PlotText(const char* text, double x, double y, const ImVec2& pix_offset=ImVec2(0,0), ImPlotTextFlags flags=0); diff --git a/implot_demo.cpp b/implot_demo.cpp index d4536a4a..47298d64 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -871,7 +871,14 @@ void Demo_Images() { ImGui::SliderFloat2("UV1", &uv1.x, -2, 2, "%.1f"); ImGui::ColorEdit4("Tint",&tint.x); if (ImPlot::BeginPlot("##image")) { - ImPlot::PlotImage("my image",ImGui::GetIO().Fonts->TexID, bmin, bmax, uv0, uv1, tint); +#ifdef IMGUI_HAS_TEXTURES + // We use the font atlas ImTextureRef for this demo, but in your real code when you submit + // an image that you have loaded yourself, you would normally have a ImTextureID which works + // just as well (as ImTextureRef can be constructed from ImTextureID). + ImPlot::PlotImage("my image", ImGui::GetIO().Fonts->TexRef, bmin, bmax, uv0, uv1, tint); +#else + ImPlot::PlotImage("my image", ImGui::GetIO().Fonts->TexID, bmin, bmax, uv0, uv1, tint); +#endif ImPlot::EndPlot(); } } diff --git a/implot_items.cpp b/implot_items.cpp index 741eaaf2..f7de3465 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -2788,7 +2788,11 @@ void PlotDigitalG(const char* label_id, ImPlotGetter getter_func, void* data, in // [SECTION] PlotImage //----------------------------------------------------------------------------- -void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) { +#ifdef IMGUI_HAS_TEXTURES +void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) { +#else +void PlotImage(const char* label_id, ImTextureID tex_ref, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) { +#endif if (BeginItemEx(label_id, FitterRect(bmin,bmax))) { ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col); GetCurrentItem()->Color = tint_col32; @@ -2796,7 +2800,7 @@ void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPo ImVec2 p1 = PlotToPixels(bmin.x, bmax.y,IMPLOT_AUTO,IMPLOT_AUTO); ImVec2 p2 = PlotToPixels(bmax.x, bmin.y,IMPLOT_AUTO,IMPLOT_AUTO); PushPlotClipRect(); - draw_list.AddImage(user_texture_id, p1, p2, uv0, uv1, tint_col32); + draw_list.AddImage(tex_ref, p1, p2, uv0, uv1, tint_col32); PopPlotClipRect(); EndItem(); } From 9b6c70e25e9a78fc2a4e38a9f0130e303afd6aaf Mon Sep 17 00:00:00 2001 From: Brenton Bostick Date: Thu, 6 Nov 2025 15:33:48 -0500 Subject: [PATCH 04/23] various typo fixes (#642) --- implot.cpp | 8 ++++---- implot.h | 32 ++++++++++++++++---------------- implot_demo.cpp | 6 +++--- implot_internal.h | 4 ++-- implot_items.cpp | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/implot.cpp b/implot.cpp index 5c400c00..5164e6d8 100644 --- a/implot.cpp +++ b/implot.cpp @@ -96,7 +96,7 @@ You can read releases logs https://github.com/epezent/implot/releases for more d - 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. +- 2020/08/28 (0.5) - ImPlotMarker_ can no longer be combined with bitwise OR, |. This features caused unnecessary slow-down, and almost no one used it. - 2020/08/25 (0.5) - ImPlotAxisFlags_Scientific was removed. Logarithmic axes automatically uses scientific notation. - 2020/08/17 (0.5) - PlotText was changed so that text is centered horizontally and vertically about the desired point. - 2020/08/16 (0.5) - An ImPlotContext must be explicitly created and destroyed now with `CreateContext` and `DestroyContext`. Previously, the context was statically initialized in this source file. @@ -315,7 +315,7 @@ static const ImPlotStyleVarInfo GPlotStyleVarInfo[] = { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine + { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPadding { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding { ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing @@ -3633,7 +3633,7 @@ void EndSubplots() { // remove items if (gp.CurrentItems == &subplot.Items) gp.CurrentItems = nullptr; - // reset the plot items for the next frame (TODO: put this elswhere) + // reset the plot items for the next frame (TODO: put this elsewhere) for (int i = 0; i < subplot.Items.GetItemCount(); ++i) { subplot.Items.GetItemByIndex(i)->SeenThisFrame = false; } @@ -5218,7 +5218,7 @@ void ShowAxisMetrics(const ImPlotPlot& plot, const ImPlotAxis& axis) { ImGui::BulletText("Range: [%f,%f]",axis.Range.Min, axis.Range.Max); ImGui::BulletText("Pixels: %f", axis.PixelSize()); ImGui::BulletText("Aspect: %f", axis.GetAspect()); - ImGui::BulletText(axis.OrthoAxis == nullptr ? "OrtherAxis: NULL" : "OrthoAxis: 0x%08X", axis.OrthoAxis->ID); + ImGui::BulletText(axis.OrthoAxis == nullptr ? "OrthoAxis: NULL" : "OrthoAxis: 0x%08X", axis.OrthoAxis->ID); ImGui::BulletText("LinkedMin: %p", (void*)axis.LinkedMin); ImGui::BulletText("LinkedMax: %p", (void*)axis.LinkedMax); ImGui::BulletText("HasRange: %s", axis.HasRange ? "true" : "false"); diff --git a/implot.h b/implot.h index 8e388cda..0d002180 100644 --- a/implot.h +++ b/implot.h @@ -56,7 +56,7 @@ // Define attributes of all API symbols declarations (e.g. for DLL under Windows) // Using ImPlot via a shared library is not recommended, because we don't guarantee // backward nor forward ABI compatibility and also function call overhead. If you -// do use ImPlot as a DLL, be sure to call SetImGuiContext (see Miscellanous section). +// do use ImPlot as a DLL, be sure to call SetImGuiContext (see Miscellaneous section). #ifndef IMPLOT_API #define IMPLOT_API #endif @@ -124,14 +124,14 @@ enum ImAxis_ { ImAxis_Y1, // enabled by default ImAxis_Y2, // disabled by default ImAxis_Y3, // disabled by default - // bookeeping + // bookkeeping ImAxis_COUNT }; // Options for plots (see BeginPlot). enum ImPlotFlags_ { ImPlotFlags_None = 0, // default - ImPlotFlags_NoTitle = 1 << 0, // the plot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. "##MyPlot") + ImPlotFlags_NoTitle = 1 << 0, // the plot title will not be displayed (titles are also hidden if preceded by double hashes, e.g. "##MyPlot") ImPlotFlags_NoLegend = 1 << 1, // the legend will not be displayed ImPlotFlags_NoMouseText = 1 << 2, // the mouse position, in plot coordinates, will not be displayed inside of the plot ImPlotFlags_NoInputs = 1 << 3, // the user will not be able to interact with the plot @@ -171,7 +171,7 @@ enum ImPlotAxisFlags_ { // Options for subplots (see BeginSubplot) enum ImPlotSubplotFlags_ { ImPlotSubplotFlags_None = 0, // default - ImPlotSubplotFlags_NoTitle = 1 << 0, // the subplot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. "##MySubplot") + ImPlotSubplotFlags_NoTitle = 1 << 0, // the subplot title will not be displayed (titles are also hidden if preceded by double hashes, e.g. "##MySubplot") ImPlotSubplotFlags_NoLegend = 1 << 1, // the legend will not be displayed (only applicable if ImPlotSubplotFlags_ShareItems is enabled) ImPlotSubplotFlags_NoMenus = 1 << 2, // the user will not be able to open context menus with right-click ImPlotSubplotFlags_NoResize = 1 << 3, // resize splitters between subplot cells will be not be provided @@ -307,7 +307,7 @@ enum ImPlotHistogramFlags_ { ImPlotHistogramFlags_Horizontal = 1 << 10, // histogram bars will be rendered horizontally (not supported by PlotHistogram2D) ImPlotHistogramFlags_Cumulative = 1 << 11, // each bin will contain its count plus the counts of all previous bins (not supported by PlotHistogram2D) ImPlotHistogramFlags_Density = 1 << 12, // counts will be normalized, i.e. the PDF will be visualized, or the CDF will be visualized if Cumulative is also set - ImPlotHistogramFlags_NoOutliers = 1 << 13, // exclude values outside the specifed histogram range from the count toward normalizing and cumulative counts + ImPlotHistogramFlags_NoOutliers = 1 << 13, // exclude values outside the specified histogram range from the count toward normalizing and cumulative counts ImPlotHistogramFlags_ColMajor = 1 << 14 // data will be read in column major order (not supported by PlotHistogram) }; @@ -357,7 +357,7 @@ enum ImPlotCol_ { ImPlotCol_LegendText, // legend text color (defaults to ImPlotCol_InlayText) ImPlotCol_TitleText, // plot title text color (defaults to ImGuiCol_Text) ImPlotCol_InlayText, // color of text appearing inside of plots (defaults to ImGuiCol_Text) - ImPlotCol_AxisText, // axis label and tick lables color (defaults to ImGuiCol_Text) + ImPlotCol_AxisText, // axis label and tick labels color (defaults to ImGuiCol_Text) ImPlotCol_AxisGrid, // axis grid color (defaults to 25% ImPlotCol_AxisText) ImPlotCol_AxisTick, // axis tick color (defaults to AxisGrid) ImPlotCol_AxisBg, // background color of axis hover region (defaults to transparent) @@ -406,7 +406,7 @@ enum ImPlotStyleVar_ { enum ImPlotScale_ { ImPlotScale_Linear = 0, // default linear scale ImPlotScale_Time, // date/time scale - ImPlotScale_Log10, // base 10 logartithmic scale + ImPlotScale_Log10, // base 10 logarithmic scale ImPlotScale_SymLog, // symmetric log scale }; @@ -647,7 +647,7 @@ IMPLOT_API void EndPlot(); // Starts a subdivided plotting context. If the function returns true, // EndSubplots() MUST be called! Call BeginPlot/EndPlot AT MOST [rows*cols] -// times in between the begining and end of the subplot context. Plots are +// times in between the beginning and end of the subplot context. Plots are // added in row major order. // // Example: @@ -748,7 +748,7 @@ IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, c IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false); // Sets an axis' scale using built-in options. IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale); -// Sets an axis' scale using user supplied forward and inverse transfroms. +// Sets an axis' scale using user supplied forward and inverse transforms. IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=nullptr); // Sets an axis' limits constraints. IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max); @@ -778,7 +778,7 @@ IMPLOT_API void SetupFinish(); // using a preceding button or slider widget to change the plot limits). In // this case, you can use the `SetNext` API below. While this is not as feature // rich as the Setup API, most common needs are provided. These functions can be -// called anwhere except for inside of `Begin/EndPlot`. For example: +// called anywhere except for inside of `Begin/EndPlot`. For example: // if (ImGui::Button("Center Plot")) // ImPlot::SetNextPlotLimits(-1,1,-1,1); @@ -808,7 +808,7 @@ IMPLOT_API void SetNextAxesToFit(); // [SECTION] Plot Items //----------------------------------------------------------------------------- -// The main plotting API is provied below. Call these functions between +// The main plotting API is provided below. Call these functions between // Begin/EndPlot and after any Setup API calls. Each plots data on the current // x and y axes, which can be changed with `SetAxis/Axes`. // @@ -980,7 +980,7 @@ IMPLOT_API ImVec2 PlotToPixels(double x, double y, ImAxis x_axis = IMPLOT_AUTO, // Get the current Plot position (top-left) in pixels. IMPLOT_API ImVec2 GetPlotPos(); -// Get the curent Plot size in pixels. +// Get the current Plot size in pixels. IMPLOT_API ImVec2 GetPlotSize(); // Returns the mouse position in x,y coordinates of the current plot. Passing IMPLOT_AUTO uses the current axes. @@ -1086,7 +1086,7 @@ IMPLOT_API void EndDragDropSource(); // manually set these colors to whatever you like, and further can Push/Pop // them around individual plots for plot-specific styling (e.g. coloring axes). -// Provides access to plot style structure for permanant modifications to colors, sizes, etc. +// Provides access to plot style structure for permanent modifications to colors, sizes, etc. IMPLOT_API ImPlotStyle& GetStyle(); // Style plot colors for current ImGui style (default). @@ -1193,11 +1193,11 @@ IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO); // Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1]. IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = nullptr, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO); -// Shows a button with a colormap gradient brackground. +// Shows a button with a colormap gradient background. IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO); // When items in a plot sample their color from a colormap, the color is cached and does not change -// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted, +// unless explicitly overridden. Therefore, if you change the colormap after the item has already been plotted, // item colors will NOT update. If you need item colors to resample the new colormap, then use this // function to bust the cached colors. If #plot_title_id is nullptr, then every item in EVERY existing plot // will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the @@ -1209,7 +1209,7 @@ IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr); // [SECTION] Input Mapping //----------------------------------------------------------------------------- -// Provides access to input mapping structure for permanant modifications to controls for pan, select, etc. +// Provides access to input mapping structure for permanent modifications to controls for pan, select, etc. IMPLOT_API ImPlotInputMap& GetInputMap(); // Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. diff --git a/implot_demo.cpp b/implot_demo.cpp index 47298d64..ea46187b 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -1959,7 +1959,7 @@ void Demo_CustomDataAndGetters() { ImPlot::PopStyleVar(); // you can also pass C++ lambdas: - // auto lamda = [](void* data, int idx) { ... return ImPlotPoint(x,y); }; + // auto lambda = [](void* data, int idx) { ... return ImPlotPoint(x,y); }; // ImPlot::PlotLine("My Lambda", lambda, data, 1000); ImPlot::EndPlot(); @@ -2399,11 +2399,11 @@ void StyleSeaborn() { style.PlotMinSize = ImVec2(300,225); } -} // namespaece MyImPlot +} // namespace MyImPlot // WARNING: // -// You can use "implot_internal.h" to build custom plotting fuctions or extend ImPlot. +// You can use "implot_internal.h" to build custom plotting functions or extend ImPlot. // However, note that forward compatibility of this file is not guaranteed and the // internal API is subject to change. At some point we hope to bring more of this // into the public API and expose the necessary building blocks to fully support diff --git a/implot_internal.h b/implot_internal.h index bdebbd87..a2bb220c 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -51,7 +51,7 @@ // Constants can be changed unless stated otherwise. We may move some of these // to ImPlotStyleVar_ over time. -// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS) +// Minimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS) #define IMPLOT_MIN_TIME 0 // Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS) #define IMPLOT_MAX_TIME 32503680000 @@ -198,7 +198,7 @@ static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) { #endif } -// Lerp across an array of 32-bit collors given t in [0.0 1.0] +// Lerp across an array of 32-bit colors given t in [0.0 1.0] static inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) { int i1 = (int)((size - 1 ) * t); int i2 = i1 + 1; diff --git a/implot_items.cpp b/implot_items.cpp index f7de3465..492e99b1 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -97,7 +97,7 @@ static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); } #define IMPLOT_NUMERIC_TYPES (ImS8)(ImU8)(ImS16)(ImU16)(ImS32)(ImU32)(ImS64)(ImU64)(float)(double) #endif -// CALL_INSTANTIATE_FOR_NUMERIC_TYPES will duplicate the template instantion code `INSTANTIATE_MACRO(T)` on supported types. +// CALL_INSTANTIATE_FOR_NUMERIC_TYPES will duplicate the template instantiation code `INSTANTIATE_MACRO(T)` on supported types. #define _CAT(x, y) _CAT_(x, y) #define _CAT_(x,y) x ## y #define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END) From 16e5ff753866928b02cfaa5e2096fc4c44de618a Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Fri, 7 Nov 2025 04:40:37 +0100 Subject: [PATCH 05/23] chore: bump minimum required cmake version for CI The MacOS build was failing because CMAKE < 3.5 is no longer supported --- .github/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CMakeLists.txt b/.github/CMakeLists.txt index 118a26bc..67bf4b5b 100644 --- a/.github/CMakeLists.txt +++ b/.github/CMakeLists.txt @@ -1,5 +1,5 @@ # This build script is not meant for general use, it is for CI use only! -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.14) project(implot) # From 35407e303234bd74260952895be19824119f5add Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 8 Nov 2025 08:54:36 +0100 Subject: [PATCH 06/23] feat: implot example --- .gitignore | 27 ++++++++++ example/CMakeLists.txt | 66 +++++++++++++++++++++++ example/README.md | 6 +++ example/main.cpp | 116 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 .gitignore create mode 100644 example/CMakeLists.txt create mode 100644 example/README.md create mode 100644 example/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f49d26dc --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +## Dear ImGui artifacts +imgui.ini +imgui*.ini + +## Visual Studio artifacts +.vs +ipch +*.opensdf +*.log +*.pdb +*.ilk +*.user +*.sdf +*.suo +*.VC.db +*.VC.VC.opendb + +## Commonly used CMake directories & CMake CPM cache +build*/ +.cache + +## JetBrains IDE artifacts +.idea +cmake-build-* + +## VS code artifacts +.vscode diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000..d568bf56 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,66 @@ +cmake_minimum_required(VERSION 3.14) +project(ImPlotExample LANGUAGES CXX C) + +# Set the C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +include(FetchContent) + +# Setup OpenGL +cmake_policy(SET CMP0072 NEW) # Pefer GLVND over legacy GL libraries +find_package(OpenGL REQUIRED) + +# Setup GLFW +FetchContent_Declare( + glfw + GIT_REPOSITORY "https://github.com/glfw/glfw" + GIT_TAG "3.3.8" + GIT_PROGRESS TRUE + GIT_SHALLOW TRUE +) +FetchContent_MakeAvailable(glfw) + +# Setup ImGui +FetchContent_Declare( + imgui + GIT_REPOSITORY "https://github.com/ocornut/imgui" + GIT_TAG "v1.92.4" + GIT_PROGRESS TRUE + GIT_SHALLOW TRUE +) +FetchContent_MakeAvailable(imgui) +set(IMGUI_SOURCE + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp +) +add_library(imgui STATIC ${IMGUI_SOURCE}) +target_include_directories(imgui PUBLIC "${imgui_SOURCE_DIR};${imgui_SOURCE_DIR}/backends/") +target_link_libraries(imgui PUBLIC glfw OpenGL::GL) + +# Setup ImPlot +set(IMPLOT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..) +set(IMPLOT_SOURCE + ${IMPLOT_SOURCE_DIR}/implot.cpp + ${IMPLOT_SOURCE_DIR}/implot_demo.cpp + ${IMPLOT_SOURCE_DIR}/implot_items.cpp +) +add_library(implot STATIC ${IMPLOT_SOURCE}) +target_include_directories(implot PUBLIC ${IMPLOT_SOURCE_DIR}) +target_link_libraries(implot PUBLIC imgui) + +# Add the executable +set(EXAMPLE_SOURCE + main.cpp +) +add_executable(example ${EXAMPLE_SOURCE}) +target_link_libraries(example PRIVATE implot) + +# Silence OpenGL deprecation warnings on macOS +if(APPLE) + target_compile_definitions(example PRIVATE GL_SILENCE_DEPRECATION) +endif() diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..3854bde0 --- /dev/null +++ b/example/README.md @@ -0,0 +1,6 @@ +# ImPlot Example + +This is a simple example demonstrating how to build ImPlot with CMake. You can build and run the example using the following commands: +``` +cmake -B build && cmake --build build && build/example +``` diff --git a/example/main.cpp b/example/main.cpp new file mode 100644 index 00000000..8aff4d30 --- /dev/null +++ b/example/main.cpp @@ -0,0 +1,116 @@ +// MIT License + +// Copyright (c) 2020-2024 Evan Pezent +// Copyright (c) 2025 Breno Cunha Queiroz + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_opengl3.h" +#include "implot.h" +#include +#include + +// Callback to handle GLFW errors +void glfw_error_callback(int error, const char* description) { std::cerr << "GLFW Error " << error << ": " << description << std::endl; } + +int main() { + // Setup error callback + glfwSetErrorCallback(glfw_error_callback); + + // Initialize GLFW + if (!glfwInit()) { + std::cerr << "Failed to initialize GLFW" << std::endl; + return -1; + } + + // Setup OpenGL version +#if defined(__APPLE__) + // GL 3.2 + GLSL 150 (MacOS) + const char* glsl_version = "#version 150"; + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on MacOS +#else + // GL 3.0 + GLSL 130 (Windows and Linux) + const char* glsl_version = "#version 130"; + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); +#endif + + // Create window + GLFWwindow* window = glfwCreateWindow(1200, 800, "ImPlot Example", nullptr, nullptr); + if (!window) { + std::cerr << "Failed to create GLFW window" << std::endl; + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent(window); + glfwSwapInterval(0); // Disable vsync + + // Setup context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImPlot::CreateContext(); + + // Setup style + ImGui::StyleColorsDark(); + + // Setup backend + ImGui_ImplGlfw_InitForOpenGL(window, true); + ImGui_ImplOpenGL3_Init(glsl_version); + + // Main loop + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + // Start frame + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + // Demo windows + ImGui::ShowDemoWindow(); + ImPlot::ShowDemoWindow(); + + // Render + ImGui::Render(); + int display_w, display_h; + glfwGetFramebufferSize(window, &display_w, &display_h); + glViewport(0, 0, display_w, display_h); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + + // Swap buffers + glfwSwapBuffers(window); + } + + // Cleanup + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImPlot::DestroyContext(); + ImGui::DestroyContext(); + glfwDestroyWindow(window); + glfwTerminate(); + + return 0; +} From 61ac306712dd9723d157bbec9d2b51a60a1e9d67 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 8 Nov 2025 09:00:54 +0100 Subject: [PATCH 07/23] chore: update copyright notice --- implot.cpp | 3 ++- implot.h | 3 ++- implot_demo.cpp | 3 ++- implot_internal.h | 3 ++- implot_items.cpp | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/implot.cpp b/implot.cpp index 5164e6d8..5cb0f0ee 100644 --- a/implot.cpp +++ b/implot.cpp @@ -1,6 +1,7 @@ // MIT License -// Copyright (c) 2023 Evan Pezent +// Copyright (c) 2020-2024 Evan Pezent +// Copyright (c) 2025 Breno Cunha Queiroz // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/implot.h b/implot.h index 0d002180..5cfe0776 100644 --- a/implot.h +++ b/implot.h @@ -1,6 +1,7 @@ // MIT License -// Copyright (c) 2023 Evan Pezent +// Copyright (c) 2020-2024 Evan Pezent +// Copyright (c) 2025 Breno Cunha Queiroz // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/implot_demo.cpp b/implot_demo.cpp index ea46187b..f4e0f8d6 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -1,6 +1,7 @@ // MIT License -// Copyright (c) 2023 Evan Pezent +// Copyright (c) 2020-2024 Evan Pezent +// Copyright (c) 2025 Breno Cunha Queiroz // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/implot_internal.h b/implot_internal.h index a2bb220c..77a07539 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -1,6 +1,7 @@ // MIT License -// Copyright (c) 2023 Evan Pezent +// Copyright (c) 2020-2024 Evan Pezent +// Copyright (c) 2025 Breno Cunha Queiroz // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/implot_items.cpp b/implot_items.cpp index 492e99b1..4d395e0a 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -1,6 +1,7 @@ // MIT License -// Copyright (c) 2023 Evan Pezent +// Copyright (c) 2020-2024 Evan Pezent +// Copyright (c) 2025 Breno Cunha Queiroz // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal From 12955f08b880e93af31db38feb86baeb1c9a3bc6 Mon Sep 17 00:00:00 2001 From: Mihaly Sisak Date: Sat, 8 Nov 2025 10:40:48 +0100 Subject: [PATCH 08/23] style: rename drag functions argument held to out_held in header (#641) Modifies implot.h DragPoint, DragLineX, DragLineY, DragRect functions held argument to out_held. The last parameter is called out_held in the implementation cpp file. This change brings that to the header, provides clearer understanding for the user. Co-authored-by: Breno Cunha Queiroz --- implot.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/implot.h b/implot.h index 5cfe0776..446eaf2a 100644 --- a/implot.h +++ b/implot.h @@ -940,13 +940,13 @@ IMPLOT_API void PlotDummy(const char* label_id, ImPlotDummyFlags flags=0); // user interactions can be retrieved through the optional output parameters. // Shows a draggable point at x,y. #col defaults to ImGuiCol_Text. -IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); +IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* out_held = nullptr); // Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text. -IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); +IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* out_held = nullptr); // Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text. -IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); +IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* out_held = nullptr); // Shows a draggable and resizeable rectangle. -IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); +IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* out_held = nullptr); // Shows an annotation callout at a chosen point. Clamping keeps annotations in the plot area. Annotations are always rendered on top. IMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, bool round = false); From 2992339de565746ee4a8df1f0ae4306687869fe1 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 8 Nov 2025 11:00:20 +0100 Subject: [PATCH 09/23] feat: add IMPLOT_VERSION_NUM --- implot.h | 4 +++- implot_demo.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/implot.h b/implot.h index 446eaf2a..a12e0657 100644 --- a/implot.h +++ b/implot.h @@ -63,7 +63,9 @@ #endif // ImPlot version string. -#define IMPLOT_VERSION "0.17" +#define IMPLOT_VERSION "0.17 WIP" +// ImPlot version integer encoded as XYYZZ (X=major, YY=minor, ZZ=patch). +#define IMPLOT_VERSION_NUM 1700 // Indicates variable should deduced automatically. #define IMPLOT_AUTO -1 // Special color used to indicate that a color should be deduced automatically. diff --git a/implot_demo.cpp b/implot_demo.cpp index f4e0f8d6..718fbc01 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -2222,7 +2222,7 @@ void ShowDemoWindow(bool* p_open) { ImGui::EndMenuBar(); } //------------------------------------------------------------------------- - ImGui::Text("ImPlot says hello. (%s)", IMPLOT_VERSION); + ImGui::Text("ImPlot says hello! (%s) (%d)", IMPLOT_VERSION, IMPLOT_VERSION_NUM); // display warning about 16-bit indices static bool showWarning = sizeof(ImDrawIdx)*8 == 16 && (ImGui::GetIO().BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) == false; if (showWarning) { From 6ad10b0ebe0a2cb4eaa09a889f431e85931ed7b5 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 8 Nov 2025 11:37:03 +0100 Subject: [PATCH 10/23] fix: add missing default constructors (#645) The default constructors for ImPlotPointError, ImPlotTag, and ImPlotTick were missing. --- implot_internal.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/implot_internal.h b/implot_internal.h index 77a07539..f05c47f7 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -421,6 +421,7 @@ struct ImPlotColormapData { // ImPlotPoint with positive/negative error values struct ImPlotPointError { double X, Y, Neg, Pos; + ImPlotPointError() { X = 0; Y = 0; Neg = 0; Pos = 0; } ImPlotPointError(double x, double y, double neg, double pos) { X = x; Y = y; Neg = neg; Pos = pos; } @@ -487,6 +488,14 @@ struct ImPlotTag { ImU32 ColorBg; ImU32 ColorFg; int TextOffset; + + ImPlotTag() { + Axis = 0; + Value = 0; + ColorBg = 0; + ColorFg = 0; + TextOffset = 0; + } }; struct ImPlotTagCollection { @@ -541,6 +550,17 @@ struct ImPlotTick int Level; int Idx; + ImPlotTick() { + PlotPos = 0; + PixelPos = 0; + LabelSize = ImVec2(0,0); + TextOffset = -1; + Major = false; + ShowLabel = false; + Level = 0; + Idx = -1; + } + ImPlotTick(double value, bool major, int level, bool show_label) { PixelPos = 0; PlotPos = value; From 648487283023413310bed75171488399bbe6d29b Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 8 Nov 2025 11:43:20 +0100 Subject: [PATCH 11/23] fix: remove extra ; and trailing whitespaces Fixes #635 --- implot_items.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/implot_items.cpp b/implot_items.cpp index 4d395e0a..734503af 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -2204,7 +2204,7 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col, bool detached = false) { const float resolution = 50 / (2 * IM_PI); ImVec2 buffer[52]; - + int n = ImMax(3, (int)((a1 - a0) * resolution)); double da = (a1 - a0) / (n - 1); int i = 0; @@ -2212,14 +2212,14 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent if (detached) { const double offset = 0.08; // Offset of the detached slice const double width_scale = 0.95; // Scale factor for the width of the detached slice - + double a_mid = (a0 + a1) / 2; double new_a0 = a_mid - (a1 - a0) * width_scale / 2; double new_a1 = a_mid + (a1 - a0) * width_scale / 2; double new_da = (new_a1 - new_a0) / (n - 1); - + ImPlotPoint offsetCenter(center.x + offset * cos(a_mid), center.y + offset * sin(a_mid)); - + // Start point (center of the offset) buffer[0] = PlotToPixels(offsetCenter, IMPLOT_AUTO, IMPLOT_AUTO); @@ -2237,17 +2237,17 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent for (; i < n; ++i) { double a = a0 + i * da; buffer[i + 1] = PlotToPixels( - center.x + radius * cos(a), - center.y + radius * sin(a), + center.x + radius * cos(a), + center.y + radius * sin(a), IMPLOT_AUTO, IMPLOT_AUTO); } } // Close the shape buffer[i + 1] = buffer[0]; - + // fill draw_list.AddConvexPolyFilled(buffer, n + 2, col); - + // border (for AA) draw_list.AddPolyline(buffer, n + 2, col, 0, 2.0f); } @@ -2318,7 +2318,7 @@ void PlotPieChartEx(const char* const label_ids[], const T* values, int count, I int PieChartFormatter(double value, char* buff, int size, void* data) { const char* fmt = (const char*)data; return snprintf(buff, size, fmt, value); -}; +} template void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) { @@ -2358,7 +2358,7 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou ImVec2 size = ImGui::CalcTextSize(buffer); double angle = a0 + (a1 - a0) * 0.5; const bool hovered = ImPlot::IsLegendEntryHovered(label_ids[i]) && ImHasFlag(flags, ImPlotPieChartFlags_Exploding); - const double offset = (hovered ? 0.6 : 0.5) * radius; + const double offset = (hovered ? 0.6 : 0.5) * radius; ImVec2 pos = PlotToPixels(center.x + offset * cos(angle), center.y + offset * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO); ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color)); draw_list.AddText(pos - size * 0.5f, col, buffer); From c8a982cce7dbfb20b9e53996868f1d95040b71e0 Mon Sep 17 00:00:00 2001 From: Alex Swaim Date: Sat, 8 Nov 2025 15:49:38 -0600 Subject: [PATCH 12/23] fix: missing IMPLOT_API in some functions (#549) * Add IMPLOT_API to constructors and functions of ImPlotPoint, ImPlotRange, and ImPlotRect * fix: missing IMPLOT_API in locator functions --------- Co-authored-by: Alex Swaim Co-authored-by: Breno Cunha Queiroz --- implot.h | 38 +++++++++++++++++++------------------- implot_internal.h | 8 ++++---- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/implot.h b/implot.h index a12e0657..eb9bc1de 100644 --- a/implot.h +++ b/implot.h @@ -474,11 +474,11 @@ enum ImPlotBin_ { IM_MSVC_RUNTIME_CHECKS_OFF struct ImPlotPoint { double x, y; - constexpr ImPlotPoint() : x(0.0), y(0.0) { } - constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y) { } - constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y) { } - double& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((double*)(void*)(char*)this)[idx]; } - double operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const double*)(const void*)(const char*)this)[idx]; } + IMPLOT_API constexpr ImPlotPoint() : x(0.0), y(0.0) { } + IMPLOT_API constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y) { } + IMPLOT_API constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y) { } + IMPLOT_API double& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((double*)(void*)(char*)this)[idx]; } + IMPLOT_API double operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const double*)(const void*)(const char*)this)[idx]; } #ifdef IMPLOT_POINT_CLASS_EXTRA IMPLOT_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h // to convert back and forth between your math types and ImPlotPoint. @@ -489,25 +489,25 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // Range defined by a min/max value. struct ImPlotRange { double Min, Max; - constexpr ImPlotRange() : Min(0.0), Max(0.0) { } - constexpr ImPlotRange(double _min, double _max) : Min(_min), Max(_max) { } - bool Contains(double value) const { return value >= Min && value <= Max; } - double Size() const { return Max - Min; } - double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; } + IMPLOT_API constexpr ImPlotRange() : Min(0.0), Max(0.0) { } + IMPLOT_API constexpr ImPlotRange(double _min, double _max) : Min(_min), Max(_max) { } + IMPLOT_API bool Contains(double value) const { return value >= Min && value <= Max; } + IMPLOT_API double Size() const { return Max - Min; } + IMPLOT_API double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; } }; // Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max(). struct ImPlotRect { ImPlotRange X, Y; - constexpr ImPlotRect() : X(0.0,0.0), Y(0.0,0.0) { } - constexpr ImPlotRect(double x_min, double x_max, double y_min, double y_max) : X(x_min, x_max), Y(y_min, y_max) { } - bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); } - bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); } - ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); } - ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); } - ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); } - ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); } - ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); } + IMPLOT_API constexpr ImPlotRect() : X(0.0,0.0), Y(0.0,0.0) { } + IMPLOT_API constexpr ImPlotRect(double x_min, double x_max, double y_min, double y_max) : X(x_min, x_max), Y(y_min, y_max) { } + IMPLOT_API bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); } + IMPLOT_API bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); } + IMPLOT_API ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); } + IMPLOT_API ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); } + IMPLOT_API ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); } + IMPLOT_API ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); } + IMPLOT_API ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); } }; // Plot style structure diff --git a/implot_internal.h b/implot_internal.h index f05c47f7..46dfaa5e 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -1700,10 +1700,10 @@ static inline int Formatter_Time(double, char* buff, int size, void* data) { // [SECTION] Locator //------------------------------------------------------------------------------ -void Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); -void Locator_Time(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); -void Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); -void Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); +IMPLOT_API void Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); +IMPLOT_API void Locator_Time(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); +IMPLOT_API void Locator_Log10(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); +IMPLOT_API void Locator_SymLog(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data); } // namespace ImPlot From ef6322283d0c929ef467693f48ab4d6f54ac2612 Mon Sep 17 00:00:00 2001 From: howprice Date: Sun, 9 Nov 2025 05:49:18 +0000 Subject: [PATCH 13/23] feat: add ImPlotLegendFlags_Reverse (#640) * Add ImPlotLegendFlags_Reverse This is handy for making the order of legend items match the order of the data in stacked plots. See https://github.com/epezent/implot/issues/292 --------- Co-authored-by: Breno Cunha Queiroz --- implot.cpp | 2 +- implot.h | 1 + implot_demo.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/implot.cpp b/implot.cpp index 5cb0f0ee..23003169 100644 --- a/implot.cpp +++ b/implot.cpp @@ -652,7 +652,7 @@ bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool hov } // render for (int i = 0; i < num_items; ++i) { - const int idx = indices[i]; + const int idx = ImHasFlag(items.Legend.Flags, ImPlotLegendFlags_Reverse) ? indices[num_items - 1 - i] : indices[i]; ImPlotItem* item = items.GetLegendItem(idx); const char* label = items.GetLegendLabel(idx); const float label_width = ImGui::CalcTextSize(label, nullptr, true).x; diff --git a/implot.h b/implot.h index eb9bc1de..c8ce05b4 100644 --- a/implot.h +++ b/implot.h @@ -197,6 +197,7 @@ enum ImPlotLegendFlags_ { ImPlotLegendFlags_Outside = 1 << 4, // legend will be rendered outside of the plot area ImPlotLegendFlags_Horizontal = 1 << 5, // legend entries will be displayed horizontally ImPlotLegendFlags_Sort = 1 << 6, // legend entries will be displayed in alphabetical order + ImPlotLegendFlags_Reverse = 1 << 7, // legend entries will be displayed in reverse order }; // Options for mouse hover text (see SetupMouseText) diff --git a/implot_demo.cpp b/implot_demo.cpp index 718fbc01..9e0b5c4a 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -379,6 +379,7 @@ void Demo_ShadedPlots() { ImGui::DragFloat("Alpha",&alpha,0.01f,0,1); if (ImPlot::BeginPlot("Shaded Plots")) { + ImPlot::SetupLegend(ImPlotLocation_NorthWest, ImPlotLegendFlags_Reverse); // reverse legend to match vertical order on plot ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha); ImPlot::PlotShaded("Uncertain Data",xs,ys1,ys2,1001); ImPlot::PlotLine("Uncertain Data", xs, ys, 1001); From e60fee3b78924e66b106c14ae6dc2f165a4b3e01 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Tue, 11 Nov 2025 05:22:38 +0100 Subject: [PATCH 14/23] chore: ignore llm instruction files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index f49d26dc..852a8186 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,7 @@ cmake-build-* ## VS code artifacts .vscode + +## LLM instruction files +CLAUDE.md +GEMINI.md From 049b09020ec440a28c1aea4d604f591e914034bd Mon Sep 17 00:00:00 2001 From: ozlb Date: Tue, 11 Nov 2025 06:24:50 +0100 Subject: [PATCH 15/23] fix: digital plots do not respect axis inversion (#522) * PlotDigital : Fix Digital plots do not respect axis inversion https://github.com/epezent/implot/issues/520 * fix: digital plot demo not spanning whole x-axis * fix: digital plots disappearing on y-axis inversion --------- Co-authored-by: Breno Cunha Queiroz --- implot_demo.cpp | 25 ++++++++++++++----------- implot_items.cpp | 23 +++++++++++------------ 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index 9e0b5c4a..06a3add1 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -822,19 +822,22 @@ void Demo_DigitalPlots() { ImGui::Checkbox("analog_0", &showAnalog[0]); ImGui::SameLine(); ImGui::Checkbox("analog_1", &showAnalog[1]); - static float t = 0; + static float t = 0, last_t = 0; if (!paused) { t += ImGui::GetIO().DeltaTime; - //digital signal values - if (showDigital[0]) - dataDigital[0].AddPoint(t, sinf(2*t) > 0.45); - if (showDigital[1]) - dataDigital[1].AddPoint(t, sinf(2*t) < 0.45); - //Analog signal values - if (showAnalog[0]) - dataAnalog[0].AddPoint(t, sinf(2*t)); - if (showAnalog[1]) - dataAnalog[1].AddPoint(t, cosf(2*t)); + if (t - last_t >= 0.01f) { + last_t = t; + // Digital signal values + if (showDigital[0]) + dataDigital[0].AddPoint(t, sinf(2*t) > 0.45); + if (showDigital[1]) + dataDigital[1].AddPoint(t, sinf(2*t) < 0.45); + // Analog signal values + if (showAnalog[0]) + dataAnalog[0].AddPoint(t, sinf(2*t)); + if (showAnalog[1]) + dataAnalog[1].AddPoint(t, cosf(2*t)); + } } if (ImPlot::BeginPlot("##Digital")) { ImPlot::SetupAxisLimits(ImAxis_X1, t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always); diff --git a/implot_items.cpp b/implot_items.cpp index 734503af..af03bf16 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -2732,15 +2732,15 @@ void PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags if (ImNanOrInf(itemData2.y)) itemData2.y = ImConstrainNan(ImConstrainInf(itemData2.y)); int pixY_0 = (int)(s.LineWeight); itemData1.y = ImMax(0.0, itemData1.y); - float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y; - int pixY_1 = (int)(pixY_1_float); //allow only positive values - int pixY_chPosOffset = (int)(ImMax(s.DigitalBitHeight, pixY_1_float) + s.DigitalBitGap); + const float pixY_1 = s.DigitalBitHeight * (float)itemData1.y; + const int pixY_chPosOffset = (int)(ImMax(s.DigitalBitHeight, pixY_1) + s.DigitalBitGap); pixYMax = ImMax(pixYMax, pixY_chPosOffset); ImVec2 pMin = PlotToPixels(itemData1,IMPLOT_AUTO,IMPLOT_AUTO); ImVec2 pMax = PlotToPixels(itemData2,IMPLOT_AUTO,IMPLOT_AUTO); - int pixY_Offset = 0; //20 pixel from bottom due to mouse cursor label - pMin.y = (y_axis.PixelMin) + ((-gp.DigitalPlotOffset) - pixY_Offset); - pMax.y = (y_axis.PixelMin) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset); + const int pixY_Offset = 0; //20 pixel from bottom due to mouse cursor label + const float y_ref = y_axis.IsInverted() ? y_axis.PixelMax : y_axis.PixelMin; + pMin.y = y_ref - (gp.DigitalPlotOffset + pixY_Offset); + pMax.y = y_ref - (gp.DigitalPlotOffset + pixY_0 + (int)pixY_1 + pixY_Offset); //plot only one rectangle for same digital state while (((i+2) < getter.Count) && (itemData1.y == itemData2.y)) { const int in = (i + 1); @@ -2749,13 +2749,12 @@ void PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags pMax.x = PlotToPixels(itemData2,IMPLOT_AUTO,IMPLOT_AUTO).x; i++; } - //do not extend plot outside plot range - if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin; - if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin; - if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976 - if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976 + // do not extend plot outside plot range + pMin.x = ImClamp(pMin.x, !x_axis.IsInverted() ? x_axis.PixelMin : x_axis.PixelMax, !x_axis.IsInverted() ? x_axis.PixelMax - 1 : x_axis.PixelMin - 1); + pMax.x = ImClamp(pMax.x, !x_axis.IsInverted() ? x_axis.PixelMin : x_axis.PixelMax, !x_axis.IsInverted() ? x_axis.PixelMax - 1 : x_axis.PixelMin - 1); + //plot a rectangle that extends up to x2 with y1 height - if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) { + if ((gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) { // ImVec4 colAlpha = item->Color; // colAlpha.w = item->Highlight ? 1.0f : 0.9f; draw_list.AddRectFilled(pMin, pMax, ImGui::GetColorU32(s.Colors[ImPlotCol_Fill])); From c5d42bac81cab54d3b1f55d0dd9fe9185ff6746c Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Tue, 11 Nov 2025 07:14:24 +0100 Subject: [PATCH 16/23] feat: remove 60 FPS assumption from realtime plots --- implot_demo.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index 06a3add1..caf99ef2 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -892,16 +892,20 @@ void Demo_Images() { void Demo_RealtimePlots() { ImGui::BulletText("Move your mouse to change the data!"); - ImGui::BulletText("This example assumes 60 FPS. Higher FPS requires larger buffer size."); static ScrollingBuffer sdata1, sdata2; static RollingBuffer rdata1, rdata2; ImVec2 mouse = ImGui::GetMousePos(); - static float t = 0; + + // Add points to the buffers every 0.02 seconds + static float t = 0, last_t = 0.0f; + if (t == 0 || t - last_t >= 0.02f) { + sdata1.AddPoint(t, mouse.x * 0.0005f); + rdata1.AddPoint(t, mouse.x * 0.0005f); + sdata2.AddPoint(t, mouse.y * 0.0005f); + rdata2.AddPoint(t, mouse.y * 0.0005f); + last_t = t; + } t += ImGui::GetIO().DeltaTime; - sdata1.AddPoint(t, mouse.x * 0.0005f); - rdata1.AddPoint(t, mouse.x * 0.0005f); - sdata2.AddPoint(t, mouse.y * 0.0005f); - rdata2.AddPoint(t, mouse.y * 0.0005f); static float history = 10.0f; ImGui::SliderFloat("History",&history,1,30,"%.1f s"); From d90583b2e9595cd59f93e8bd32a673304a23453d Mon Sep 17 00:00:00 2001 From: Piotr Rybicki Date: Tue, 11 Nov 2025 07:19:33 +0100 Subject: [PATCH 17/23] fix: dpi scaling for hardcoded plot sizes in demo (#636) The demo used hardcoded pixel values for several plots which didn't scale with DPI, causing them to appear too small on high-DPI displays. Following ImGui's convention, this commit replaces hardcoded pixel values with ImGui::GetTextLineHeight() multiplied by appropriate factors. This ensures plots scale correctly with font size and DPI settings. Affected plots: - PolitiFact: Who Lies More? (400px -> 25*TextLineHeight) - Pie charts (250x250px -> 16*TextLineHeight square) - Heatmaps (225x225px -> 14*TextLineHeight square) - Scrolling/Rolling plots (150px -> 10*TextLineHeight) - DragRects/DragPoints plots (150px -> 10*TextLineHeight) - Drag and Drop plots (195px -> 13*TextLineHeight) This follows the same pattern used throughout ImGui's demo code for ensuring DPI-aware sizing. Co-authored-by: Breno Cunha Queiroz --- implot_demo.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index caf99ef2..7c577d93 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -533,7 +533,7 @@ void Demo_BarStacks() { static const char* labels_div[] = {"Pants on Fire","False","Mostly False","Mostly False","False","Pants on Fire","Half True","Mostly True","True"}; ImPlot::PushColormap(Liars); - if (ImPlot::BeginPlot("PolitiFact: Who Lies More?",ImVec2(-1,400),ImPlotFlags_NoMouseText)) { + if (ImPlot::BeginPlot("PolitiFact: Who Lies More?",ImVec2(-1,ImGui::GetTextLineHeight()*25),ImPlotFlags_NoMouseText)) { ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Outside|ImPlotLegendFlags_Horizontal); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Invert); ImPlot::SetupAxisTicks(ImAxis_Y1,0,19,20,politicians,false); @@ -619,7 +619,7 @@ void Demo_PieCharts() { CHECKBOX_FLAG(flags, ImPlotPieChartFlags_IgnoreHidden); CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Exploding); - if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { + if (ImPlot::BeginPlot("##Pie1", ImVec2(ImGui::GetTextLineHeight()*16,ImGui::GetTextLineHeight()*16), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxesLimits(0, 1, 0, 1); ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, "%.2f", 90, flags); @@ -632,7 +632,7 @@ void Demo_PieCharts() { static int data2[] = {1,1,2,3,5}; ImPlot::PushColormap(ImPlotColormap_Pastel); - if (ImPlot::BeginPlot("##Pie2", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { + if (ImPlot::BeginPlot("##Pie2", ImVec2(ImGui::GetTextLineHeight()*16,ImGui::GetTextLineHeight()*16), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxesLimits(0, 1, 0, 1); ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, "%.0f", 180, flags); @@ -679,7 +679,7 @@ void Demo_Heatmaps() { ImPlot::PushColormap(map); - if (ImPlot::BeginPlot("##Heatmap1",ImVec2(225,225),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) { + if (ImPlot::BeginPlot("##Heatmap1",ImVec2(ImGui::GetTextLineHeight()*14,ImGui::GetTextLineHeight()*14),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) { ImPlot::SetupAxes(nullptr, nullptr, axes_flags, axes_flags); ImPlot::SetupAxisTicks(ImAxis_X1,0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels); ImPlot::SetupAxisTicks(ImAxis_Y1,1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels); @@ -697,7 +697,7 @@ void Demo_Heatmaps() { for (int i = 0; i < size*size; ++i) values2[i] = RandomRange(0.0,1.0); - if (ImPlot::BeginPlot("##Heatmap2",ImVec2(225,225))) { + if (ImPlot::BeginPlot("##Heatmap2",ImVec2(ImGui::GetTextLineHeight()*14,ImGui::GetTextLineHeight()*14))) { ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxesLimits(-1,1,-1,1); ImPlot::PlotHeatmap("heat1",values2,size,size,0,1,nullptr); @@ -914,7 +914,7 @@ void Demo_RealtimePlots() { static ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels; - if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1,150))) { + if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1,ImGui::GetTextLineHeight()*10))) { ImPlot::SetupAxes(nullptr, nullptr, flags, flags); ImPlot::SetupAxisLimits(ImAxis_X1,t - history, t, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_Y1,0,1); @@ -923,7 +923,7 @@ void Demo_RealtimePlots() { ImPlot::PlotLine("Mouse Y", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), 0, sdata2.Offset, 2*sizeof(float)); ImPlot::EndPlot(); } - if (ImPlot::BeginPlot("##Rolling", ImVec2(-1,150))) { + if (ImPlot::BeginPlot("##Rolling", ImVec2(-1,ImGui::GetTextLineHeight()*10))) { ImPlot::SetupAxes(nullptr, nullptr, flags, flags); ImPlot::SetupAxisLimits(ImAxis_X1,0,history, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_Y1,0,1); @@ -1536,7 +1536,7 @@ void Demo_DragRects() { ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine(); ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs); - if (ImPlot::BeginPlot("##Main",ImVec2(-1,150))) { + if (ImPlot::BeginPlot("##Main",ImVec2(-1,ImGui::GetTextLineHeight()*10))) { ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoTickLabels,ImPlotAxisFlags_NoTickLabels); ImPlot::SetupAxesLimits(0,0.01,-1,1); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); @@ -1547,7 +1547,7 @@ void Demo_DragRects() { } ImVec4 bg_col = held ? ImVec4(0.5f,0,0.5f,1) : (hovered ? ImVec4(0.25f,0,0.25f,1) : ImPlot::GetStyle().Colors[ImPlotCol_PlotBg]); ImPlot::PushStyleColor(ImPlotCol_PlotBg, bg_col); - if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) { + if (ImPlot::BeginPlot("##rect",ImVec2(-1,ImGui::GetTextLineHeight()*10), ImPlotFlags_CanvasOnly)) { ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); @@ -1761,7 +1761,7 @@ void Demo_DragAndDrop() { ImGui::BeginChild("DND_RIGHT",ImVec2(-1,400)); // plot 1 (time series) ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight; - if (ImPlot::BeginPlot("##DND1", ImVec2(-1,195))) { + if (ImPlot::BeginPlot("##DND1", ImVec2(-1,ImGui::GetTextLineHeight()*13))) { ImPlot::SetupAxis(ImAxis_X1, nullptr, flags|ImPlotAxisFlags_Lock); ImPlot::SetupAxis(ImAxis_Y1, "[drop here]", flags); ImPlot::SetupAxis(ImAxis_Y2, "[drop here]", flags|ImPlotAxisFlags_Opposite); @@ -1807,7 +1807,7 @@ void Demo_DragAndDrop() { ImPlot::EndPlot(); } // plot 2 (Lissajous) - if (ImPlot::BeginPlot("##DND2", ImVec2(-1,195))) { + if (ImPlot::BeginPlot("##DND2", ImVec2(-1,ImGui::GetTextLineHeight()*13))) { ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndx != nullptr ? dndx->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]); ImPlot::SetupAxis(ImAxis_X1, dndx == nullptr ? "[drop here]" : dndx->Label, flags); ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndy != nullptr ? dndy->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]); From bcf5acee67c24a3454e6a93252d452ddc6b53df5 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Fri, 14 Nov 2025 07:04:37 +0100 Subject: [PATCH 18/23] docs: add issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 19 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 11 +++++++++++ 3 files changed, 38 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..ca68b2b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,19 @@ +--- +name: 🐛 Bug report +about: Create a bug report to help us improve ImPlot +title: '[Bug] A brief, descriptive title' +labels: type:fix, status:todo, prio:high +assignees: brenocq +--- +**Bug description** +A clear and concise description of what the bug is. + +**Bug video/screenshot** +Attach png/jpg/mp4/gif files if applicable to help explain your problem. + +**Code to reproduce the bug** +```cpp +void MyBug() { + // Minimal code snippet that reproduces the bug +} +``` diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..07d58e9f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: ❓ Q&A + url: https://github.com/epezent/implot/discussions/categories/q-a + about: Have any questions or need help? Ask here! + - name: 📸 Gallery + url: https://github.com/epezent/implot/discussions/180 + about: Share screenshots/videos of your projects using ImPlot! diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..454013d0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,11 @@ +--- +name: 🚀 Feature request +about: Suggest an idea or enhancement for ImPlot +title: '[Feature] A brief, descriptive title' +labels: type:feat, status:idea, prio:medium +--- +**Feature description** +A clear and concise description of the new feature. + +**Feature videos/screenshots** +Attach png/jpg/mp4/gif files if applicable to help explain your idea. From 12abeee48cbefb788747d5cea42d06f7ba94f4a5 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 15 Nov 2025 18:05:00 +0100 Subject: [PATCH 19/23] feat: add reverse flag to legend options demo --- implot_demo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/implot_demo.cpp b/implot_demo.cpp index 7c577d93..990b1a26 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -1399,6 +1399,7 @@ void Demo_LegendOptions() { CHECKBOX_FLAG(flags, ImPlotLegendFlags_Horizontal); CHECKBOX_FLAG(flags, ImPlotLegendFlags_Outside); CHECKBOX_FLAG(flags, ImPlotLegendFlags_Sort); + CHECKBOX_FLAG(flags, ImPlotLegendFlags_Reverse); ImGui::SliderFloat2("LegendPadding", (float*)&GetStyle().LegendPadding, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("LegendInnerPadding", (float*)&GetStyle().LegendInnerPadding, 0.0f, 10.0f, "%.0f"); From baa0370c6a4fdf1a009c8383507a86df38881a5a Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Fri, 28 Nov 2025 18:10:22 +0100 Subject: [PATCH 20/23] chore: decrease example c++ standard version to 11 --- example/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index d568bf56..8246a592 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14) project(ImPlotExample LANGUAGES CXX C) # Set the C++ standard -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) From f2a2b2cb164ce8082791ad89cac184d4f0826ecf Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sun, 30 Nov 2025 23:07:01 +0100 Subject: [PATCH 21/23] chore: update version to v0.17 --- implot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implot.h b/implot.h index c8ce05b4..deae19c9 100644 --- a/implot.h +++ b/implot.h @@ -63,7 +63,7 @@ #endif // ImPlot version string. -#define IMPLOT_VERSION "0.17 WIP" +#define IMPLOT_VERSION "0.17" // ImPlot version integer encoded as XYYZZ (X=major, YY=minor, ZZ=patch). #define IMPLOT_VERSION_NUM 1700 // Indicates variable should deduced automatically. From 56e6898b0b9ba5e39db588f2e09545360b5d2c43 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Wed, 3 Dec 2025 06:52:18 +0100 Subject: [PATCH 22/23] chore: bump version to v0.18 WIP --- implot.cpp | 2 +- implot.h | 6 +++--- implot_demo.cpp | 2 +- implot_internal.h | 2 +- implot_items.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/implot.cpp b/implot.cpp index 23003169..8aff281a 100644 --- a/implot.cpp +++ b/implot.cpp @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.17 +// ImPlot v0.18 WIP /* diff --git a/implot.h b/implot.h index deae19c9..b2e60a09 100644 --- a/implot.h +++ b/implot.h @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.17 +// ImPlot v0.18 WIP // Table of Contents: // @@ -63,9 +63,9 @@ #endif // ImPlot version string. -#define IMPLOT_VERSION "0.17" +#define IMPLOT_VERSION "0.18 WIP" // ImPlot version integer encoded as XYYZZ (X=major, YY=minor, ZZ=patch). -#define IMPLOT_VERSION_NUM 1700 +#define IMPLOT_VERSION_NUM 1800 // Indicates variable should deduced automatically. #define IMPLOT_AUTO -1 // Special color used to indicate that a color should be deduced automatically. diff --git a/implot_demo.cpp b/implot_demo.cpp index 990b1a26..2c079ad3 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.17 +// ImPlot v0.18 WIP // We define this so that the demo does not accidentally use deprecated API #ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS diff --git a/implot_internal.h b/implot_internal.h index 46dfaa5e..b9d453ab 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.17 +// ImPlot v0.18 WIP // You may use this file to debug, understand or extend ImPlot features but we // don't provide any guarantee of forward compatibility! diff --git a/implot_items.cpp b/implot_items.cpp index af03bf16..3b00ae4c 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.17 +// ImPlot v0.18 WIP #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS From dc0b1f3eec6ccf925d170dc10ad4e4a91a0ff6d7 Mon Sep 17 00:00:00 2001 From: Junkyo Lee <59576365+JunkyoLee@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:47:08 -0800 Subject: [PATCH 23/23] fix: `DragRect` resizing when its size is zero (#661) --- implot.cpp | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/implot.cpp b/implot.cpp index 8aff281a..a7d43eed 100644 --- a/implot.cpp +++ b/implot.cpp @@ -4103,31 +4103,34 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m bool modified = false; bool clicked = false, hovered = false, held = false; - ImRect b_rect(pc.x-DRAG_GRAB_HALF_SIZE,pc.y-DRAG_GRAB_HALF_SIZE,pc.x+DRAG_GRAB_HALF_SIZE,pc.y+DRAG_GRAB_HALF_SIZE); - ImGui::KeepAliveID(id); - if (input) { - // middle point - clicked = ImGui::ButtonBehavior(b_rect,id,&hovered,&held); - if (out_clicked) *out_clicked = clicked; - if (out_hovered) *out_hovered = hovered; - if (out_held) *out_held = held; - } + const bool is_movable = *x_min != *x_max || *y_min != *y_max; + if (is_movable) { + ImGui::KeepAliveID(id); + if (input) { + // middle point + ImRect b_rect(pc.x-DRAG_GRAB_HALF_SIZE,pc.y-DRAG_GRAB_HALF_SIZE,pc.x+DRAG_GRAB_HALF_SIZE,pc.y+DRAG_GRAB_HALF_SIZE); + clicked = ImGui::ButtonBehavior(b_rect,id,&hovered,&held); + if (out_clicked) *out_clicked = clicked; + if (out_hovered) *out_hovered = hovered; + if (out_held) *out_held = held; + } - if ((hovered || held) && show_curs) - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); - if (held && ImGui::IsMouseDragging(0)) { - for (int i = 0; i < 4; ++i) { - ImPlotPoint pp = PixelsToPlot(p[i] + ImGui::GetIO().MouseDelta,IMPLOT_AUTO,IMPLOT_AUTO); - *y[i] = pp.y; - *x[i] = pp.x; + if ((hovered || held) && show_curs) + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); + if (held && ImGui::IsMouseDragging(0)) { + for (int i = 0; i < 4; ++i) { + ImPlotPoint pp = PixelsToPlot(p[i] + ImGui::GetIO().MouseDelta,IMPLOT_AUTO,IMPLOT_AUTO); + *y[i] = pp.y; + *x[i] = pp.x; + } + modified = true; } - modified = true; } for (int i = 0; i < 4; ++i) { // points - b_rect = ImRect(p[i].x-DRAG_GRAB_HALF_SIZE,p[i].y-DRAG_GRAB_HALF_SIZE,p[i].x+DRAG_GRAB_HALF_SIZE,p[i].y+DRAG_GRAB_HALF_SIZE); + ImRect b_rect(p[i].x - DRAG_GRAB_HALF_SIZE, p[i].y - DRAG_GRAB_HALF_SIZE, p[i].x + DRAG_GRAB_HALF_SIZE, p[i].y + DRAG_GRAB_HALF_SIZE); ImGuiID p_id = id + i + 1; ImGui::KeepAliveID(p_id); if (input) {