From 244288fbcbf709875b0d5c0f34f153091b037665 Mon Sep 17 00:00:00 2001 From: Mohammad Odeh Date: Thu, 20 Feb 2025 16:13:33 -0500 Subject: [PATCH 01/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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) { From d6c3b4dfa2b39aa57a074a0144065f2ba755da30 Mon Sep 17 00:00:00 2001 From: Mohammad Odeh Date: Mon, 29 Jun 2026 10:46:55 -0400 Subject: [PATCH 24/24] Update to v1.0 --- README.md | 2 +- implot.cpp | 106 ++++--- implot.h | 95 +++--- implot_demo.cpp | 443 ++++++++++++++++++++++++++- implot_internal.h | 4 +- implot_items.cpp | 764 +++++++++++++++++++++++++++++++++++----------- 6 files changed, 1149 insertions(+), 265 deletions(-) diff --git a/README.md b/README.md index b40518cd..54249b45 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Of course, there's much more you can do with ImPlot... A comprehensive example of ImPlot's features can be found in `implot_demo.cpp`. Add this file to your sources and call `ImPlot::ShowDemoWindow()` somewhere in your update loop. You are encouraged to use this file as a reference when needing to implement various plot types. The demo is always updated to show new plot types and features as they are added, so check back with each release! -An online version of the demo is hosted [here](https://traineq.org/implot_demo/src/implot_demo.html). You can view the plots and the source code that generated them. Note that this demo may not always be up to date and is not as performant as a desktop implementation, but it should give you a general taste of what's possible with ImPlot. Special thanks to [pthom](https://github.com/pthom) for creating and hosting this! +An online version of the demo is hosted [here](https://pthom.github.io/imgui_explorer/?lib=implot). You can view the plots and the source code that generated them. Note that this demo may not always be up to date and is not as performant as a desktop implementation, but it should give you a general taste of what's possible with ImPlot. Special thanks to [pthom](https://github.com/pthom) for creating and hosting this! More sophisticated demos requiring lengthier code and/or third-party libraries can be found in a separate repository: [implot_demos](https://github.com/epezent/implot_demos). Here, you will find advanced signal processing and ImPlot usage in action. Please read the `Contributing` section of that repository if you have an idea for a new demo! diff --git a/implot.cpp b/implot.cpp index 6c474db8..c18db38d 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.18 WIP +// ImPlot v1.1 WIP /* @@ -32,7 +32,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. -- 2026/02/12 (0.18) - ImPlotSpec replaces the SetNextXXX style functions. The guide below shows show to migrate from SetNextXXX to ImPlotSpec. +- 2026/02/12 (1.0) - ImPlotSpec replaces the SetNextXXX style functions. The guide below shows show to migrate from SetNextXXX to ImPlotSpec. - `SetNextLineStyle` has been removed, styling should be set via ImPlotSpec. ``` // Before @@ -87,7 +87,7 @@ You can read releases logs https://github.com/epezent/implot/releases for more d ImPlot::PlotErrorBars("ErrorBar", xs, ys, err, count, spec); ``` - Flags, Offset and Stride should also be set via ImPlotSpec now. -- 2023/10/02 (0.18) - ImPlotSpec was made the default and _only_ way of styling plot items. Therefore the following features were removed: +- 2023/10/02 (1.0) - ImPlotSpec was made the default and _only_ way of styling plot items. Therefore the following features were removed: - ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar have been removed and thus are no longer supported by PushStyleColor. You can use a common ImPlotSpec instance across multiple PlotX calls to emulate PushStyleColor behavior. - ImPlotStyleVar_LineWeight, ImPlotStyleVar_Marker, ImPlotStyleVar_MarkerSize, ImPlotStyleVar_MarkerWeight, ImPlotStyleVar_FillAlpha, ImPlotStyleVar_ErrorBarSize, and ImPlotStyleVar_ErrorBarWeight @@ -215,8 +215,11 @@ You can read releases logs https://github.com/epezent/implot/releases for more d // Clang/GCC warnings with -Weverything #if defined(__clang__) #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal +#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated +#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked +#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #endif // Global plot context @@ -305,6 +308,8 @@ const char* GetMarkerName(ImPlotMarker marker) { case ImPlotMarker_Cross: return "Cross"; case ImPlotMarker_Plus: return "Plus"; case ImPlotMarker_Asterisk: return "Asterisk"; + case ImPlotMarker_Vertical: return "Vertical"; + case ImPlotMarker_Horizontal: return "Horizontal"; default: return ""; } } @@ -501,22 +506,22 @@ void Initialize(ImPlotContext* ctx) { ResetCtxForNextAlignedPlots(ctx); ResetCtxForNextSubplot(ctx); - const ImU32 Deep[] = {4289753676, 4283598045, 4285048917, 4283584196, 4289950337, 4284512403, 4291005402, 4287401100, 4285839820, 4291671396 }; - const ImU32 Dark[] = {4280031972, 4290281015, 4283084621, 4288892568, 4278222847, 4281597951, 4280833702, 4290740727, 4288256409 }; - const ImU32 Pastel[] = {4289639675, 4293119411, 4291161036, 4293184478, 4289124862, 4291624959, 4290631909, 4293712637, 4294111986 }; - const ImU32 Paired[] = {4293119554, 4290017311, 4287291314, 4281114675, 4288256763, 4280031971, 4285513725, 4278222847, 4292260554, 4288298346, 4288282623, 4280834481}; - const ImU32 Viridis[] = {4283695428, 4285867080, 4287054913, 4287455029, 4287526954, 4287402273, 4286883874, 4285579076, 4283552122, 4280737725, 4280674301 }; - const ImU32 Plasma[] = {4287039501, 4288480321, 4289200234, 4288941455, 4287638193, 4286072780, 4284638433, 4283139314, 4281771772, 4280667900, 4280416752 }; - const ImU32 Hot[] = {4278190144, 4278190208, 4278190271, 4278190335, 4278206719, 4278223103, 4278239231, 4278255615, 4283826175, 4289396735, 4294967295 }; - const ImU32 Cool[] = {4294967040, 4294960666, 4294954035, 4294947661, 4294941030, 4294934656, 4294928025, 4294921651, 4294915020, 4294908646, 4294902015 }; - const ImU32 Pink[] = {4278190154, 4282532475, 4284308894, 4285690554, 4286879686, 4287870160, 4288794330, 4289651940, 4291685869, 4293392118, 4294967295 }; - const ImU32 Jet[] = {4289331200, 4294901760, 4294923520, 4294945280, 4294967040, 4289396565, 4283826090, 4278255615, 4278233855, 4278212095, 4278190335 }; + const ImU32 Deep[] = {IM_RGB(76,114,176),IM_RGB(221,132,82),IM_RGB(85,168,104),IM_RGB(196,78,82),IM_RGB(129,114,179),IM_RGB(147,120,96),IM_RGB(218,139,195),IM_RGB(140,140,140),IM_RGB(204,185,116),IM_RGB(100,181,205)}; + const ImU32 Dark[] = {IM_RGB(228,26,28),IM_RGB(55,126,184),IM_RGB(77,175,74),IM_RGB(152,78,163),IM_RGB(255,127,0),IM_RGB(255,255,51),IM_RGB(166,86,40),IM_RGB(247,129,191),IM_RGB(153,153,153)}; + const ImU32 Pastel[] = {IM_RGB(251,180,174),IM_RGB(179,205,227),IM_RGB(204,235,197),IM_RGB(222,203,228),IM_RGB(254,217,166),IM_RGB(255,255,204),IM_RGB(229,216,189),IM_RGB(253,218,236),IM_RGB(242,242,242)}; + const ImU32 Paired[] = {IM_RGB(66,206,227),IM_RGB(31,120,180),IM_RGB(178,223,138),IM_RGB(51,160,44),IM_RGB(251,154,153),IM_RGB(227,26,28),IM_RGB(253,191,111),IM_RGB(255,127,0),IM_RGB(202,178,214),IM_RGB(106,61,154),IM_RGB(255,255,153),IM_RGB(177,89,40)}; + const ImU32 Viridis[] = {IM_RGB(68,1,84),IM_RGB(72,36,117),IM_RGB(65,68,135),IM_RGB(53,95,141),IM_RGB(42,120,142),IM_RGB(33,145,140),IM_RGB(34,168,132),IM_RGB(68,191,112),IM_RGB(122,209,81),IM_RGB(189,223,38),IM_RGB(253,231,37)}; + const ImU32 Plasma[] = {IM_RGB(13,8,135),IM_RGB(65,4,157),IM_RGB(106,0,168),IM_RGB(143,13,164),IM_RGB(177,42,144),IM_RGB(204,71,120),IM_RGB(225,100,98),IM_RGB(242,132,75),IM_RGB(252,166,54),IM_RGB(252,206,37),IM_RGB(240,249,33)}; + const ImU32 Hot[] = {IM_RGB(64,0,0),IM_RGB(128,0,0),IM_RGB(191,0,0),IM_RGB(255,0,0),IM_RGB(255,64,0),IM_RGB(255,128,0),IM_RGB(255,191,0),IM_RGB(255,255,0),IM_RGB(255,255,85),IM_RGB(255,255,170),IM_RGB(255,255,255)}; + const ImU32 Cool[] = {IM_RGB(0,255,255),IM_RGB(26,230,255),IM_RGB(51,204,255),IM_RGB(77,179,255),IM_RGB(102,153,255),IM_RGB(128,128,255),IM_RGB(153,102,255),IM_RGB(179,77,255),IM_RGB(204,51,255),IM_RGB(230,26,255),IM_RGB(255,0,255)}; + const ImU32 Pink[] = {IM_RGB(74,0,0),IM_RGB(123,66,66),IM_RGB(158,93,93),IM_RGB(186,114,114),IM_RGB(198,151,132),IM_RGB(208,180,147),IM_RGB(218,206,161),IM_RGB(228,228,174),IM_RGB(237,237,205),IM_RGB(246,246,231),IM_RGB(255,255,255)}; + const ImU32 Jet[] = {IM_RGB(0,0,170),IM_RGB(0,0,255),IM_RGB(0,85,255),IM_RGB(0,170,255),IM_RGB(0,255,255),IM_RGB(85,255,170),IM_RGB(170,255,85),IM_RGB(255,255,0),IM_RGB(255,170,0),IM_RGB(255,85,0),IM_RGB(255,0,0)}; const ImU32 Twilight[] = {IM_RGB(226,217,226),IM_RGB(166,191,202),IM_RGB(109,144,192),IM_RGB(95,88,176),IM_RGB(83,30,124),IM_RGB(47,20,54),IM_RGB(100,25,75),IM_RGB(159,60,80),IM_RGB(192,117,94),IM_RGB(208,179,158),IM_RGB(226,217,226)}; const ImU32 RdBu[] = {IM_RGB(103,0,31),IM_RGB(178,24,43),IM_RGB(214,96,77),IM_RGB(244,165,130),IM_RGB(253,219,199),IM_RGB(247,247,247),IM_RGB(209,229,240),IM_RGB(146,197,222),IM_RGB(67,147,195),IM_RGB(33,102,172),IM_RGB(5,48,97)}; const ImU32 BrBG[] = {IM_RGB(84,48,5),IM_RGB(140,81,10),IM_RGB(191,129,45),IM_RGB(223,194,125),IM_RGB(246,232,195),IM_RGB(245,245,245),IM_RGB(199,234,229),IM_RGB(128,205,193),IM_RGB(53,151,143),IM_RGB(1,102,94),IM_RGB(0,60,48)}; const ImU32 PiYG[] = {IM_RGB(142,1,82),IM_RGB(197,27,125),IM_RGB(222,119,174),IM_RGB(241,182,218),IM_RGB(253,224,239),IM_RGB(247,247,247),IM_RGB(230,245,208),IM_RGB(184,225,134),IM_RGB(127,188,65),IM_RGB(77,146,33),IM_RGB(39,100,25)}; const ImU32 Spectral[] = {IM_RGB(158,1,66),IM_RGB(213,62,79),IM_RGB(244,109,67),IM_RGB(253,174,97),IM_RGB(254,224,139),IM_RGB(255,255,191),IM_RGB(230,245,152),IM_RGB(171,221,164),IM_RGB(102,194,165),IM_RGB(50,136,189),IM_RGB(94,79,162)}; - const ImU32 Greys[] = {IM_COL32_WHITE, IM_COL32_BLACK }; + const ImU32 Greys[] = {IM_COL32_WHITE, IM_COL32_BLACK}; IMPLOT_APPEND_CMAP(Deep, true); IMPLOT_APPEND_CMAP(Dark, true); @@ -1686,8 +1691,10 @@ void PadAndDatumAxesX(ImPlotPlot& plot, float& pad_T, float& pad_B, ImPlotAlignm if (opp) { if (count_T++ > 0) pad_T += K + P; - if (label) - pad_T += T + P; + if (label) { + ImVec2 label_size = ImGui::CalcTextSize(plot.GetAxisLabel(axis)); + pad_T += label_size.y + P; + } if (ticks) pad_T += ImMax(T, axis.Ticker.MaxSize.y) + P + (time ? T + P : 0); axis.Datum1 = plot.CanvasRect.Min.y + pad_T; @@ -1697,8 +1704,10 @@ void PadAndDatumAxesX(ImPlotPlot& plot, float& pad_T, float& pad_B, ImPlotAlignm else { if (count_B++ > 0) pad_B += K + P; - if (label) - pad_B += T + P; + if (label) { + ImVec2 label_size = ImGui::CalcTextSize(plot.GetAxisLabel(axis)); + pad_B += label_size.y + P; + } if (ticks) pad_B += ImMax(T, axis.Ticker.MaxSize.y) + P + (time ? T + P : 0); axis.Datum1 = plot.CanvasRect.Max.y - pad_B; @@ -2026,6 +2035,9 @@ bool UpdateInput(ImPlotPlot& plot) { float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f); float ty = ImRemap(IO.MousePos.y, plot.PlotRect.Min.y, plot.PlotRect.Max.y, 0.0f, 1.0f); + // Track which axis to use as reference for equal aspect + ImPlotAxis* equal_ref_axis = nullptr; + for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) { ImPlotAxis& x_axis = plot.XAxis(i); const bool equal_zoom = axis_equal && x_axis.OrthoAxis != nullptr; @@ -2033,13 +2045,12 @@ bool UpdateInput(ImPlotPlot& plot) { if (x_hov[i] && !x_axis.IsInputLocked() && !equal_locked) { ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID); if (zoom_rate != 0.0f) { - float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f; - const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction); - const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction); + const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate); + const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate); x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l); x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r); - if (axis_equal && x_axis.OrthoAxis != nullptr) - x_axis.OrthoAxis->SetAspect(x_axis.GetAspect()); + if (equal_zoom) + equal_ref_axis = &x_axis; changed = true; } } @@ -2051,17 +2062,21 @@ bool UpdateInput(ImPlotPlot& plot) { if (y_hov[i] && !y_axis.IsInputLocked() && !equal_locked) { ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID); if (zoom_rate != 0.0f) { - float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f; - const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction); - const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction); + const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate); + const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate); y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b); y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t); - if (axis_equal && y_axis.OrthoAxis != nullptr) - y_axis.OrthoAxis->SetAspect(y_axis.GetAspect()); + if (equal_zoom) + equal_ref_axis = &y_axis; changed = true; } } } + + // Apply equal aspect constraint after zooming both axes + if (equal_ref_axis != nullptr && equal_ref_axis->OrthoAxis != nullptr) { + equal_ref_axis->OrthoAxis->SetAspect(equal_ref_axis->GetAspect()); + } } // BOX-SELECTION ---------------------------------------------------------- @@ -2247,6 +2262,8 @@ void SetupAxisTicks(ImAxis idx, double v_min, double v_max, int n_ticks, const c ImPlotContext& gp = *GImPlot; IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked, "Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!"); + IM_ASSERT_USER_ERROR(labels == nullptr || n_ticks >= 2, + "When providing custom labels, n_ticks must be at least 2!"); n_ticks = n_ticks < 2 ? 2 : n_ticks; FillRange(gp.TempDouble1, n_ticks, v_min, v_max); SetupAxisTicks(idx, gp.TempDouble1.Data, n_ticks, labels, show_default); @@ -2624,6 +2641,17 @@ void SetupFinish() { } } + // (4.5) recalc padding now that we have actual X-axis tick labels (handles multi-line labels) + // Save title padding before resetting + const float title_pad = (title_size.x > 0) ? (title_size.y + gp.Style.LabelPadding.y) : 0.0f; + pad_top = title_pad; + pad_bot = 0; + PadAndDatumAxesX(plot,pad_top,pad_bot,gp.CurrentAlignmentH); + // Update AxesRect to account for title padding (was done in step 0) + if (title_size.x > 0) { + plot.AxesRect.Min.y = plot.FrameRect.Min.y + gp.Style.PlotPadding.y + title_pad; + } + // (5) calc plot bb plot.PlotRect = ImRect(plot.CanvasRect.Min + ImVec2(pad_left, pad_top), plot.CanvasRect.Max - ImVec2(pad_right, pad_bot)); @@ -3146,8 +3174,13 @@ void EndPlot() { } // render border +#if IMGUI_VERSION_NUM < 19276 if (render_border) - DrawList.AddRect(plot.PlotRect.Min, plot.PlotRect.Max, GetStyleColorU32(ImPlotCol_PlotBorder), 0, ImDrawFlags_RoundCornersAll, gp.Style.PlotBorderSize); + DrawList.AddRect(plot.PlotRect.Min, plot.PlotRect.Max, GetStyleColorU32(ImPlotCol_PlotBorder), 0, ImDrawFlags_None, gp.Style.PlotBorderSize); +#else + if (render_border) + DrawList.AddRect(plot.PlotRect.Min, plot.PlotRect.Max, GetStyleColorU32(ImPlotCol_PlotBorder), 0, gp.Style.PlotBorderSize, ImDrawFlags_None); +#endif // render tags for (int i = 0; i < gp.Tags.Size; ++i) { @@ -5928,20 +5961,7 @@ void EndCustomContext(bool include_default) #ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS -bool BeginPlot(const char* title, const char* x_label, const char* y1_label, const ImVec2& size, - ImPlotFlags flags, ImPlotAxisFlags x_flags, ImPlotAxisFlags y1_flags, ImPlotAxisFlags y2_flags, ImPlotAxisFlags y3_flags, - const char* y2_label, const char* y3_label) -{ - if (!BeginPlot(title, size, flags)) - return false; - SetupAxis(ImAxis_X1, x_label, x_flags); - SetupAxis(ImAxis_Y1, y1_label, y1_flags); - if (ImHasFlag(flags, ImPlotFlags_YAxis2)) - SetupAxis(ImAxis_Y2, y2_label, y2_flags); - if (ImHasFlag(flags, ImPlotFlags_YAxis3)) - SetupAxis(ImAxis_Y3, y3_label, y3_flags); - return true; -} +// Deprecated method will go in here #endif diff --git a/implot.h b/implot.h index 79e56103..810d8ad9 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.18 WIP +// ImPlot v1.1 WIP // Table of Contents: // @@ -63,9 +63,9 @@ #endif // ImPlot version string. -#define IMPLOT_VERSION "0.18 WIP" +#define IMPLOT_VERSION "1.1 WIP" // ImPlot version integer encoded as XYYZZ (X=major, YY=minor, ZZ=patch). -#define IMPLOT_VERSION_NUM 1801 +#define IMPLOT_VERSION_NUM 10100 // Macro for templated plotting functions; keeps header clean. #define IMPLOT_TMP template IMPLOT_API @@ -96,6 +96,7 @@ typedef int ImPlotItemFlags; // -> ImPlotItemFlags_ typedef int ImPlotLineFlags; // -> ImPlotLineFlags_ typedef int ImPlotScatterFlags; // -> ImPlotScatterFlags typedef int ImPlotBubblesFlags; // -> ImPlotBubblesFlags +typedef int ImPlotPolygonFlags; // -> ImPlotPolygonFlags_ typedef int ImPlotStairsFlags; // -> ImPlotStairsFlags_ typedef int ImPlotShadedFlags; // -> ImPlotShadedFlags_ typedef int ImPlotBarsFlags; // -> ImPlotBarsFlags_ @@ -138,13 +139,18 @@ enum ImAxis_ { // Plotting properties. These provide syntactic sugar for creating ImPlotSpecs from (ImPlotProp,value) pairs. See ImPlotSpec documentation. enum ImPlotProp_ { ImPlotProp_LineColor, // line color (applies to lines, bar edges); IMPLOT_AUTO_COL will use next Colormap color or current item color + ImPlotProp_LineColors, // array of colors for each line; if nullptr, use LineColor for all lines ImPlotProp_LineWeight, // line weight in pixels (applies to lines, bar edges, marker edges) ImPlotProp_FillColor, // fill color (applies to shaded regions, bar faces); IMPLOT_AUTO_COL will use next Colormap color or current item color - ImPlotProp_FillAlpha, // alpha multiplier (applies to FillColor and MarkerFillColor) + ImPlotProp_FillColors, // array of colors for each fill; if nullptr, use FillColor for all fills + ImPlotProp_FillAlpha, // alpha multiplier (applies to FillColor, FillColors, MarkerFillColor, and MarkerFillColors) ImPlotProp_Marker, // marker type; specify ImPlotMarker_Auto to use the next unused marker ImPlotProp_MarkerSize, // size of markers (radius) *in pixels* + ImPlotProp_MarkerSizes, // array of sizes for each marker; if nullptr, use MarkerSize for all markers ImPlotProp_MarkerLineColor, // marker edge color; IMPLOT_AUTO_COL will use LineColor + ImPlotProp_MarkerLineColors, // array of colors for each marker edge; if nullptr, use MarkerLineColor for all markers ImPlotProp_MarkerFillColor, // marker face color; IMPLOT_AUTO_COL will use LineColor + ImPlotProp_MarkerFillColors, // array of colors for each marker face; if nullptr, use MarkerFillColor for all markers ImPlotProp_Size, // size of error bar whiskers (width or height), and digital bars (height) *in pixels* ImPlotProp_Offset, // data index offset ImPlotProp_Stride, // data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX @@ -273,6 +279,12 @@ enum ImPlotBubblesFlags_ { ImPlotBubblesFlags_None = 0, // default }; +// Flags for PlotPolygon. Used by setting ImPlotSpec::Flags. +enum ImPlotPolygonFlags_ { + ImPlotPolygonFlags_None = 0, // default (closed, convex polygon) + ImPlotPolygonFlags_Concave = 1 << 10, // use concave polygon filling (slower but supports concave shapes) +}; + // Flags for PlotStairs. Used by setting ImPlotSpec::Flags. enum ImPlotStairsFlags_ { ImPlotStairsFlags_None = 0, // default @@ -318,10 +330,11 @@ enum ImPlotInfLinesFlags_ { // Flags for PlotPieChart. Used by setting ImPlotSpec::Flags. enum ImPlotPieChartFlags_ { - ImPlotPieChartFlags_None = 0, // default - ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0) - ImPlotPieChartFlags_IgnoreHidden = 1 << 11, // ignore hidden slices when drawing the pie chart (as if they were not there) - ImPlotPieChartFlags_Exploding = 1 << 12 // Explode legend-hovered slice + ImPlotPieChartFlags_None = 0, // default + ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0) + ImPlotPieChartFlags_IgnoreHidden = 1 << 11, // ignore hidden slices when drawing the pie chart (as if they were not there) + ImPlotPieChartFlags_Exploding = 1 << 12, // explode legend-hovered slice + ImPlotPieChartFlags_NoSliceBorder = 1 << 13 // do not draw slice borders }; // Flags for PlotHeatmap. Used by setting ImPlotSpec::Flags. @@ -437,6 +450,8 @@ enum ImPlotMarker_ { ImPlotMarker_Cross, // a cross marker (not fill-able) ImPlotMarker_Plus, // a plus marker (not fill-able) ImPlotMarker_Asterisk, // a asterisk marker (not fill-able) + ImPlotMarker_Vertical, // a vertical line marker (not fill-able) + ImPlotMarker_Horizontal, // a horizontal line marker (not fill-able) ImPlotMarker_COUNT }; @@ -503,13 +518,18 @@ enum ImPlotBin_ { // }); struct ImPlotSpec { ImVec4 LineColor = IMPLOT_AUTO_COL; // line color (applies to lines, bar edges); IMPLOT_AUTO_COL will use next Colormap color or current item color + ImU32* LineColors = nullptr; // array of colors for each line; if nullptr, use LineColor for all lines float LineWeight = 1.0f; // line weight in pixels (applies to lines, bar edges, marker edges) ImVec4 FillColor = IMPLOT_AUTO_COL; // fill color (applies to shaded regions, bar faces); IMPLOT_AUTO_COL will use next Colormap color or current item color - float FillAlpha = 1.0f; // alpha multiplier (applies to FillColor and MarkerFillColor) + ImU32* FillColors = nullptr; // array of colors for each fill; if nullptr, use FillColor for all fills + float FillAlpha = 1.0f; // alpha multiplier (applies to FillColor, FillColors, MarkerFillColor, and MarkerFillColors) ImPlotMarker Marker = ImPlotMarker_None; // marker type; specify ImPlotMarker_Auto to use the next unused marker float MarkerSize = 4; // size of markers (radius) *in pixels* + float* MarkerSizes = nullptr; // array of sizes for each marker; if nullptr, use MarkerSize for all markers ImVec4 MarkerLineColor = IMPLOT_AUTO_COL; // marker edge color; IMPLOT_AUTO_COL will use LineColor + ImU32* MarkerLineColors = nullptr; // array of colors for each marker edge; if nullptr, use MarkerLineColor for all markers ImVec4 MarkerFillColor = IMPLOT_AUTO_COL; // marker face color; IMPLOT_AUTO_COL will use LineColor + ImU32* MarkerFillColors = nullptr; // array of colors for each marker face; if nullptr, use MarkerFillColor for all markers float Size = 4; // size of error bar whiskers (width or height), and digital bars (height) *in pixels* int Offset = 0; // data index offset int Stride = IMPLOT_AUTO; // data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX @@ -553,6 +573,27 @@ struct ImPlotSpec { IM_ASSERT(0 && "User provided an ImPlotProp which cannot be set from scalar value!"); } + // Set a property from a pointer value. + void SetProp(ImPlotProp prop, ImU32* v) { + switch (prop) { + case ImPlotProp_LineColors : LineColors = v; return; + case ImPlotProp_FillColors : FillColors = v; return; + case ImPlotProp_MarkerLineColors : MarkerLineColors = v; return; + case ImPlotProp_MarkerFillColors : MarkerFillColors = v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlotProp which cannot be set from pointer value!"); + } + + // Set a property from a float pointer value. + void SetProp(ImPlotProp prop, float* v) { + switch (prop) { + case ImPlotProp_MarkerSizes : MarkerSizes = v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlotProp which cannot be set from float pointer value!"); + } + // Set a property from an ImVec4 value. void SetProp(ImPlotProp prop, const ImVec4& v) { switch (prop) { @@ -962,6 +1003,9 @@ IMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* da IMPLOT_TMP void PlotBubbles(const char* label_id, const T* values, const T* szs, int count, double xscale=1, double xstart=0, const ImPlotSpec& spec=ImPlotSpec()); IMPLOT_TMP void PlotBubbles(const char* label_id, const T* xs, const T* ys, const T* szs, int count, const ImPlotSpec& spec=ImPlotSpec()); +// Plots a polygon. Points are specified in counter-clockwise order. If concave, make sure to set the Concave flag. +IMPLOT_TMP void PlotPolygon(const char* label_id, const T* xs, const T* ys, int count, const ImPlotSpec& spec=ImPlotSpec()); + // Plots a a stairstep graph. The y value is continued constantly to the right from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i] IMPLOT_TMP void PlotStairs(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, const ImPlotSpec& spec=ImPlotSpec()); IMPLOT_TMP void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, const ImPlotSpec& spec=ImPlotSpec()); @@ -1195,7 +1239,7 @@ IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, int val); IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val); // Undo temporary style variable modification(s). Undo multiple pushes at once by increasing count. IMPLOT_API void PopStyleVar(int count = 1); - + // Gets the last item primary color (i.e. its legend icon color) IMPLOT_API ImVec4 GetLastItemColor(); @@ -1203,10 +1247,10 @@ IMPLOT_API ImVec4 GetLastItemColor(); IMPLOT_API const char* GetStyleColorName(ImPlotCol idx); // Returns the null terminated string name for an ImPlotMarker. IMPLOT_API const char* GetMarkerName(ImPlotMarker idx); - + // Returns the next marker and advances the marker for the current plot. You need to call this between Begin/EndPlot! IMPLOT_API ImPlotMarker NextMarker(); - + //----------------------------------------------------------------------------- // [SECTION] Colormaps //----------------------------------------------------------------------------- @@ -1357,34 +1401,17 @@ IMPLOT_API void EndCustomContext(bool include_default = false); // if include_de #define IMPLOT_DEPRECATED(method) method #endif -enum ImPlotFlagsObsolete_ { - ImPlotFlags_YAxis2 = 1 << 20, - ImPlotFlags_YAxis3 = 1 << 21, -}; - namespace ImPlot { -// OBSOLETED in v0.18 (from February 2026) -// IMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO); // OBSOLETED IN 0.18 // Set ImPlotSpec.LineColor/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, color, ImPlotSpec_LineWeight, weight }. +// OBSOLETED in v1.0 (from February 2026) +// IMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO); // OBSOLETED IN v1.0 // Set ImPlotSpec.LineColor/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, color, ImPlotSpec_LineWeight, weight }. -// IMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);// OBSOLETED IN 0.18 // Set ImPlotSpec.FillColor/FillAlpha or construct ImPlotSpec with { ImPlotSpec_FillColor, color, ImPlotSpec_FillAlpha, alpha }. +// IMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);// OBSOLETED IN v1.0 // Set ImPlotSpec.FillColor/FillAlpha or construct ImPlotSpec with { ImPlotSpec_FillColor, color, ImPlotSpec_FillAlpha, alpha }. -// IMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL); // OBSOLETED IN 0.18 // Set ImPlotSpec.Marker/MarkerSize/MarkerFillColor/LineWeight/MarkerLineColor or construct ImPlotSpec with { ImPlotSpec_Marker, marker, ImPlotSpec_MarkerSize, size, ImPlotSpec_MarkerFillColor, fill_color, ImPlotSpec_LineWeight, weight, ImPlotSpec_MarkerLineColor, outline }. +// IMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL); // OBSOLETED IN v1.0 // Set ImPlotSpec.Marker/MarkerSize/MarkerFillColor/LineWeight/MarkerLineColor or construct ImPlotSpec with { ImPlotSpec_Marker, marker, ImPlotSpec_MarkerSize, size, ImPlotSpec_MarkerFillColor, fill_color, ImPlotSpec_LineWeight, weight, ImPlotSpec_MarkerLineColor, outline }. -// IMPLOT_API void SetNextErrorBarStyle(const ImVec4& col = IMPLOT_AUTO_COL, float size = IMPLOT_AUTO, float weight = IMPLOT_AUTO); // OBSOLETED IN 0.18 // Set ImPlotSpec.LineColor/Size/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, col, ImPlotSpec_Size, size, ImPlotSpec_LineWeight, weight }. +// IMPLOT_API void SetNextErrorBarStyle(const ImVec4& col = IMPLOT_AUTO_COL, float size = IMPLOT_AUTO, float weight = IMPLOT_AUTO); // OBSOLETED IN v1.0 // Set ImPlotSpec.LineColor/Size/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, col, ImPlotSpec_Size, size, ImPlotSpec_LineWeight, weight }. -// OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0 -IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id, - const char* x_label, // = nullptr, - const char* y_label, // = nullptr, - const ImVec2& size = ImVec2(-1,0), - ImPlotFlags flags = ImPlotFlags_None, - ImPlotAxisFlags x_flags = 0, - ImPlotAxisFlags y_flags = 0, - ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault, - ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault, - const char* y2_label = nullptr, - const char* y3_label = nullptr) ); } // namespace ImPlot diff --git a/implot_demo.cpp b/implot_demo.cpp index 88a87e7a..97b06567 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.18 WIP +// ImPlot v1.1 WIP // We define this so that the demo does not accidentally use deprecated API #ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS @@ -35,6 +35,12 @@ #include #include +// Clang warnings with -Weverything +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated +#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated +#endif + #ifdef _MSC_VER #define sprintf sprintf_s #endif @@ -45,6 +51,14 @@ #define CHECKBOX_FLAG(flags, flag) ImGui::CheckboxFlags(#flag, (unsigned int*)&flags, flag) +// Helper to wire demo markers located in code to an interactive browser (e.g. imgui_explorer) +#if IMGUI_VERSION_NUM >= 19263 +namespace ImGui { extern IMGUI_API void DemoMarker(const char* file, int line, const char* section); }; +#define IMGUI_DEMO_MARKER(section) do { ImGui::DemoMarker("implot_demo.cpp", __LINE__, section); } while (0) +#else +#define IMGUI_DEMO_MARKER(section) +#endif + #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Encapsulates examples for customizing ImPlot. @@ -188,6 +202,7 @@ struct HugeTimeData { //----------------------------------------------------------------------------- void Demo_Help() { + IMGUI_DEMO_MARKER("Demo_Help"); ImGui::Text("ABOUT THIS DEMO:"); ImGui::BulletText("Sections below are demonstrating many aspects of the library."); ImGui::BulletText("The \"Tools\" menu above gives access to: Style Editors (ImPlot/ImGui)\n" @@ -261,6 +276,7 @@ void ShowInputMapping() { } void Demo_Config() { + IMGUI_DEMO_MARKER("Config"); ImGui::ShowFontSelector("Font"); ImGui::ShowStyleSelector("ImGui Style"); ImPlot::ShowStyleSelector("ImPlot Style"); @@ -289,6 +305,7 @@ void Demo_Config() { //----------------------------------------------------------------------------- void Demo_LinePlots() { + IMGUI_DEMO_MARKER("Plots/Line Plots"); static float xs1[1001], ys1[1001]; for (int i = 0; i < 1001; ++i) { xs1[i] = i * 0.001f; @@ -313,6 +330,7 @@ void Demo_LinePlots() { //----------------------------------------------------------------------------- void Demo_FilledLinePlots() { + IMGUI_DEMO_MARKER("Plots/Filled Line Plots"); static double xs1[101], ys1[101], ys2[101], ys3[101]; srand(0); for (int i = 0; i < 101; ++i) { @@ -368,6 +386,7 @@ void Demo_FilledLinePlots() { //----------------------------------------------------------------------------- void Demo_ShadedPlots() { + IMGUI_DEMO_MARKER("Plots/Shaded Plots"); static float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001]; srand(0); for (int i = 0; i < 1001; ++i) { @@ -395,6 +414,7 @@ void Demo_ShadedPlots() { //----------------------------------------------------------------------------- void Demo_ScatterPlots() { + IMGUI_DEMO_MARKER("Plots/Scatter Plots"); srand(0); static float xs1[100], ys1[100]; for (int i = 0; i < 100; ++i) { @@ -423,6 +443,7 @@ void Demo_ScatterPlots() { //----------------------------------------------------------------------------- void Demo_BubblePlots() { + IMGUI_DEMO_MARKER("Plots/Bubble Plots"); srand(0); static float xs[20], ys1[20], ys2[20], szs1[20], szs2[20]; for (int i = 0; i < 20; ++i) { @@ -445,7 +466,51 @@ void Demo_BubblePlots() { //----------------------------------------------------------------------------- +void Demo_PolygonPlots() { + IMGUI_DEMO_MARKER("Plots/Polygon Plots"); + // Triangle (convex) + static float tri_xs[3] = {0.5f, 1.0f, 0.0f}; + static float tri_ys[3] = {1.0f, 0.0f, 0.0f}; + + // Pentagon (convex) + static float pent_xs[5], pent_ys[5]; + for (int i = 0; i < 5; ++i) { + float angle = (float)i * 2.0f * 3.14159f / 5.0f - 3.14159f / 2.0f; + pent_xs[i] = 3.0f + 0.8f * cosf(angle); + pent_ys[i] = 0.5f + 0.8f * sinf(angle); + } + + // Star (concave), counter-clockwise + static float star_xs[10], star_ys[10]; + for (int i = 0; i < 10; ++i) { + float angle = (float)i * 2.0f * 3.14159f / 10.0f - 3.14159f / 2.0f; + float radius = (i % 2 == 0) ? 0.8f : 0.3f; + star_xs[i] = 5.5f + radius * cosf(angle); + star_ys[i] = 0.5f + radius * sinf(angle); + } + + if (ImPlot::BeginPlot("Polygon Plot", ImVec2(-1,0), ImPlotFlags_Equal)) { + ImPlot::PlotPolygon("Triangle", tri_xs, tri_ys, 3, { + ImPlotProp_FillAlpha, 0.5f, + }); + ImPlot::PlotPolygon("Pentagon", pent_xs, pent_ys, 5, { + ImPlotProp_FillAlpha, 0.5f, + ImPlotProp_FillColor, ImVec4(0,1,0,1), + }); + ImPlot::PlotPolygon("Star (Concave)", star_xs, star_ys, 10, { + ImPlotProp_FillAlpha, 0.5f, + ImPlotProp_FillColor, ImVec4(1,1,0,1), + ImPlotProp_Flags, ImPlotPolygonFlags_Concave, + }); + + ImPlot::EndPlot(); + } +} + +//----------------------------------------------------------------------------- + void Demo_StairstepPlots() { + IMGUI_DEMO_MARKER("Plots/Stairstep Plots"); static float ys1[21], ys2[21]; for (int i = 0; i < 21; ++i) { ys1[i] = 0.75f + 0.2f * sinf(10 * i * 0.05f); @@ -477,6 +542,7 @@ void Demo_StairstepPlots() { //----------------------------------------------------------------------------- void Demo_BarPlots() { + IMGUI_DEMO_MARKER("Plots/Bar Plots"); static ImS8 data[10] = {1,2,3,4,5,6,7,8,9,10}; if (ImPlot::BeginPlot("Bar Plot")) { ImPlot::PlotBars("Vertical",data,10,0.7,1); @@ -488,6 +554,7 @@ void Demo_BarPlots() { //----------------------------------------------------------------------------- void Demo_BarGroups() { + IMGUI_DEMO_MARKER("Plots/Bar Groups"); static ImS8 data[30] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90, // midterm 80, 62, 56, 99, 55, 78, 88, 78, 90, 100, // final 80, 69, 52, 92, 72, 78, 75, 76, 89, 95}; // course @@ -529,6 +596,7 @@ void Demo_BarGroups() { //----------------------------------------------------------------------------- void Demo_BarStacks() { + IMGUI_DEMO_MARKER("Plots/Bar Stacks"); static ImPlotColormap Liars = -1; if (Liars == -1) { @@ -578,6 +646,7 @@ void Demo_BarStacks() { //----------------------------------------------------------------------------- void Demo_ErrorBars() { + IMGUI_DEMO_MARKER("Plots/Error Bars"); 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}; @@ -613,6 +682,7 @@ void Demo_ErrorBars() { //----------------------------------------------------------------------------- void Demo_StemPlots() { + IMGUI_DEMO_MARKER("Plots/Stem Plots"); static double xs[51], ys1[51], ys2[51]; for (int i = 0; i < 51; ++i) { xs[i] = i * 0.02; @@ -631,6 +701,7 @@ void Demo_StemPlots() { //----------------------------------------------------------------------------- void Demo_InfiniteLines() { + IMGUI_DEMO_MARKER("Plots/Infinite Lines"); static double vals[] = {0.25, 0.5, 0.75}; if (ImPlot::BeginPlot("##Infinite")) { ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoInitialFit,ImPlotAxisFlags_NoInitialFit); @@ -643,6 +714,7 @@ void Demo_InfiniteLines() { //----------------------------------------------------------------------------- void Demo_PieCharts() { + IMGUI_DEMO_MARKER("Plots/Pie Charts"); static const char* labels1[] = {"Frogs","Hogs","Dogs","Logs"}; static float data1[] = {0.15f, 0.30f, 0.2f, 0.05f}; static ImPlotPieChartFlags flags = 0; @@ -651,6 +723,7 @@ void Demo_PieCharts() { CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Normalize); CHECKBOX_FLAG(flags, ImPlotPieChartFlags_IgnoreHidden); CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Exploding); + CHECKBOX_FLAG(flags, ImPlotPieChartFlags_NoSliceBorder); if (ImPlot::BeginPlot("##Pie1", ImVec2(ImGui::GetTextLineHeight()*16,ImGui::GetTextLineHeight()*16), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); @@ -677,6 +750,7 @@ void Demo_PieCharts() { //----------------------------------------------------------------------------- void Demo_Heatmaps() { + IMGUI_DEMO_MARKER("Plots/Heatmaps"); 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}, @@ -744,6 +818,7 @@ void Demo_Heatmaps() { //----------------------------------------------------------------------------- void Demo_Histogram() { + IMGUI_DEMO_MARKER("Plots/Histogram"); static ImPlotHistogramFlags hist_flags = ImPlotHistogramFlags_Density; static int bins = 50; static double mu = 5; @@ -811,6 +886,7 @@ void Demo_Histogram() { //----------------------------------------------------------------------------- void Demo_Histogram2D() { + IMGUI_DEMO_MARKER("Plots/Histogram 2D"); static int count = 50000; static int xybins[2] = {100,100}; @@ -840,6 +916,7 @@ void Demo_Histogram2D() { //----------------------------------------------------------------------------- void Demo_DigitalPlots() { + IMGUI_DEMO_MARKER("Plots/Digital Plots"); ImGui::BulletText("Digital plots do not respond to Y drag and zoom, so that"); ImGui::Indent(); ImGui::Text("you can drag analog plots over the rising/falling digital edge."); @@ -909,6 +986,7 @@ void Demo_DigitalPlots() { //----------------------------------------------------------------------------- void Demo_Images() { + IMGUI_DEMO_MARKER("Plots/Images"); ImGui::BulletText("Below we are displaying the font texture, which is the only texture we have\naccess to in this demo."); ImGui::BulletText("Use the 'ImTextureID' type as storage to pass pointers or identifiers to your\nown texture data."); ImGui::BulletText("See ImGui Wiki page 'Image Loading and Displaying Examples'."); @@ -938,6 +1016,7 @@ void Demo_Images() { //----------------------------------------------------------------------------- void Demo_RealtimePlots() { + IMGUI_DEMO_MARKER("Plots/Realtime Plots"); ImGui::BulletText("Move your mouse to change the data!"); static ScrollingBuffer sdata1, sdata2; static RollingBuffer rdata1, rdata2; @@ -991,6 +1070,7 @@ void Demo_RealtimePlots() { //----------------------------------------------------------------------------- void Demo_MarkersAndText() { + IMGUI_DEMO_MARKER("Plots/Markers and Text"); static ImPlotSpec spec(ImPlotProp_Marker, ImPlotMarker_Auto); ImGui::DragFloat("Marker Size",&spec.MarkerSize,0.1f,2.0f,10.0f,"%.2f px"); ImGui::DragFloat("Marker Weight", &spec.LineWeight,0.05f,0.5f,3.0f,"%.2f px"); @@ -998,7 +1078,7 @@ void Demo_MarkersAndText() { if (ImPlot::BeginPlot("##MarkerStyles", ImVec2(-1,0), ImPlotFlags_CanvasOnly)) { ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); - ImPlot::SetupAxesLimits(0, 10, 0, 12); + ImPlot::SetupAxesLimits(0, 10, -2, 12); ImS8 xs[2] = {1,4}; ImS8 ys[2] = {10,11}; @@ -1021,11 +1101,11 @@ void Demo_MarkersAndText() { ys[0]--; ys[1]--; } - ImPlot::PlotText("Filled Markers", 2.5f, 6.0f); - ImPlot::PlotText("Open Markers", 7.5f, 6.0f); + ImPlot::PlotText("Filled Markers", 2.5f, 5.0f); + ImPlot::PlotText("Open Markers", 7.5f, 5.0f); ImPlot::PushStyleColor(ImPlotCol_InlayText, ImVec4(1,0,1,1)); - ImPlot::PlotText("Vertical Text", 5.0f, 6.0f, ImVec2(0,0), {ImPlotProp_Flags, ImPlotTextFlags_Vertical}); + ImPlot::PlotText("Vertical Text", 5.0f, 5.0f, ImVec2(0,0), {ImPlotProp_Flags, ImPlotTextFlags_Vertical}); ImPlot::PopStyleColor(); ImPlot::EndPlot(); @@ -1035,6 +1115,7 @@ void Demo_MarkersAndText() { //----------------------------------------------------------------------------- void Demo_NaNValues() { + IMGUI_DEMO_MARKER("Plots/NaN Values"); static bool include_nan = true; static ImPlotLineFlags flags = 0; @@ -1061,7 +1142,329 @@ void Demo_NaNValues() { //----------------------------------------------------------------------------- +void Demo_PerIndexColors() { + // Colorful Lines + static float xs1[1001], ys1[1001]; + static ImU32 colors1[1001]; + for (int i = 0; i < 1001; ++i) { + xs1[i] = i * 0.001f; + ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + (float)ImGui::GetTime() / 10)); + // Rainbow colors for f(x) + float hue = (float)i / 1000.0f; + colors1[i] = ImColor::HSV(hue, 0.8f, 0.9f); + } + static double xs2[20], ys2[20]; + static ImU32 colors2[20]; + for (int i = 0; i < 20; ++i) { + xs2[i] = i * 1/19.0f; + ys2[i] = xs2[i] * xs2[i]; + // Colormap colors for g(x) + float t = i / 19.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2[i] = ImGui::GetColorU32(color); + } + if (ImPlot::BeginPlot("Colorful Lines")) { + ImPlot::SetupAxes("x","y"); + ImPlot::PlotLine("f(x)", xs1, ys1, 1001, { + ImPlotProp_LineColors, colors1 + }); + ImPlot::PlotLine("g(x)", xs2, ys2, 20, { + ImPlotProp_Marker, ImPlotMarker_Circle, + ImPlotProp_Flags, ImPlotLineFlags_Segments, + ImPlotProp_LineColors, colors2, + ImPlotProp_MarkerFillColors, colors2, + ImPlotProp_MarkerLineColors, colors2 + }); + ImPlot::EndPlot(); + } + + // Colorful Shaded Plots + static float xs_shaded[1001], ys_shaded[1001], ys1_shaded[1001], ys2_shaded[1001], ys3_shaded[1001], ys4_shaded[1001]; + static ImU32 colors_shaded1[1001], colors_shaded2[1001]; + srand(0); + for (int i = 0; i < 1001; ++i) { + xs_shaded[i] = i * 0.001f; + ys_shaded[i] = 0.25f + 0.25f * sinf(25 * xs_shaded[i]) * sinf(5 * xs_shaded[i]) + RandomRange(-0.01f, 0.01f); + ys1_shaded[i] = ys_shaded[i] + RandomRange(0.1f, 0.12f); + ys2_shaded[i] = ys_shaded[i] - RandomRange(0.1f, 0.12f); + ys3_shaded[i] = 0.75f + 0.2f * sinf(25 * xs_shaded[i]); + ys4_shaded[i] = 0.75f + 0.1f * cosf(25 * xs_shaded[i]); + + // Rainbow colors for Uncertain Data + float hue = i / 1000.0f; + colors_shaded1[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Overlapping + float t = i / 1000.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors_shaded2[i] = ImGui::GetColorU32(color); + } + static ImPlotSpec spec_shaded(ImPlotProp_FillAlpha, 0.25f); + + if (ImPlot::BeginPlot("Colorful Shaded Plots")) { + ImPlot::SetupLegend(ImPlotLocation_NorthWest, ImPlotLegendFlags_Reverse); + ImPlot::PlotShaded("Uncertain Data", xs_shaded, ys1_shaded, ys2_shaded, 1001, { + ImPlotProp_FillColors, colors_shaded1, + ImPlotProp_FillAlpha, spec_shaded.FillAlpha + }); + ImPlot::PlotLine("Uncertain Data", xs_shaded, ys_shaded, 1001, { + ImPlotProp_LineColors, colors_shaded1 + }); + ImPlot::PlotShaded("Overlapping", xs_shaded, ys3_shaded, ys4_shaded, 1001, { + ImPlotProp_FillColors, colors_shaded2, + ImPlotProp_FillAlpha, spec_shaded.FillAlpha + }); + ImPlot::PlotLine("Overlapping", xs_shaded, ys3_shaded, 1001, { + ImPlotProp_LineColors, colors_shaded2 + }); + ImPlot::PlotLine("Overlapping", xs_shaded, ys4_shaded, 1001, { + ImPlotProp_LineColors, colors_shaded2 + }); + ImPlot::EndPlot(); + } + + // Colorful Scatter + srand(0); + static float xs_scatter1[100], ys_scatter1[100]; + static ImU32 colors_scatter1_fill[100], colors_scatter1_line[100]; + static float sizes_scatter1[100]; + for (int i = 0; i < 100; ++i) { + xs_scatter1[i] = i * 0.01f; + ys_scatter1[i] = xs_scatter1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); + // Rainbow hue colors + float hue = i / 99.0f; + colors_scatter1_fill[i] = ImColor::HSV(hue, 0.8f, 0.9f); + colors_scatter1_line[i] = ImColor::HSV(hue, 0.9f, 0.7f); + // Random sizes between 2 and 6 + sizes_scatter1[i] = 2.0f + 4.0f * ((float)rand() / (float)RAND_MAX); + } + static float xs_scatter2[50], ys_scatter2[50]; + static ImU32 colors_scatter2[50]; + static float sizes_scatter2[50]; + for (int i = 0; i < 50; i++) { + xs_scatter2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); + ys_scatter2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); + // Colormap colors (Viridis) + float t = i / 49.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors_scatter2[i] = ImGui::GetColorU32(color); + // Random sizes between 2 and 6 + sizes_scatter2[i] = 2.0f + 4.0f * ((float)rand() / (float)RAND_MAX); + } + + if (ImPlot::BeginPlot("Colorful Scatter", ImVec2(-1,0))) { + ImPlot::PlotScatter("Data 1", xs_scatter1, ys_scatter1, 100, { + ImPlotProp_MarkerFillColors, colors_scatter1_fill, + ImPlotProp_MarkerLineColors, colors_scatter1_line, + ImPlotProp_MarkerSizes, sizes_scatter1 + }); + ImPlot::PlotScatter("Data 2", xs_scatter2, ys_scatter2, 50, { + ImPlotProp_Marker, ImPlotMarker_Square, + ImPlotProp_MarkerFillColors, colors_scatter2, + ImPlotProp_MarkerLineColors, colors_scatter2, + ImPlotProp_MarkerSizes, sizes_scatter2, + ImPlotProp_FillAlpha, 0.5f + }); + ImPlot::EndPlot(); + } + + // Colorful Bubbles + srand(0); + static float xs_bubble[20], ys1_bubble[20], ys2_bubble[20], szs1_bubble[20], szs2_bubble[20]; + static ImU32 colors1_bubble[20], colors2_bubble[20]; + for (int i = 0; i < 20; ++i) { + xs_bubble[i] = i * 0.1f; + ys1_bubble[i] = (float)rand() / (float)RAND_MAX; + ys2_bubble[i] = (float)rand() / (float)RAND_MAX; + + szs1_bubble[i] = 0.02f + 0.08f * ((float)rand() / (float)RAND_MAX); + szs2_bubble[i] = 0.02f + 0.08f * ((float)rand() / (float)RAND_MAX); + + // Rainbow colors for Data 1 + float hue = i / 19.0f; + colors1_bubble[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Data 2 + float t = i / 19.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2_bubble[i] = ImGui::GetColorU32(color); + } + + if (ImPlot::BeginPlot("Colorful Bubbles", ImVec2(-1,0), ImPlotFlags_Equal)) { + ImPlot::PlotBubbles("Data 1", xs_bubble, ys1_bubble, szs1_bubble, 20, { + ImPlotProp_FillAlpha, 0.5f, + ImPlotProp_FillColors, colors1_bubble, + ImPlotProp_LineColors, colors1_bubble + }); + ImPlot::PlotBubbles("Data 2", xs_bubble, ys2_bubble, szs2_bubble, 20, { + ImPlotProp_FillAlpha, 0.5f, + ImPlotProp_LineColor, ImVec4(0,0,0,0.0), + ImPlotProp_FillColors, colors2_bubble + }); + + ImPlot::EndPlot(); + } + + // Colorful Stairstep + static float ys1_stairs[21], ys2_stairs[21]; + static ImU32 colors1_stairs[21], colors2_stairs[21]; + for (int i = 0; i < 21; ++i) { + ys1_stairs[i] = 0.75f + 0.2f * sinf(10 * i * 0.05f); + ys2_stairs[i] = 0.25f + 0.2f * sinf(10 * i * 0.05f); + + // Rainbow colors for Post Step + float hue = i / 20.0f; + colors1_stairs[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Pre Step + float t = i / 20.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2_stairs[i] = ImGui::GetColorU32(color); + } + static ImPlotStairsFlags flags_stairs = 0; + CHECKBOX_FLAG(flags_stairs, ImPlotStairsFlags_Shaded); + + if (ImPlot::BeginPlot("Colorful Stairstep Plot")) { + ImPlot::SetupAxes("x","f(x)"); + ImPlot::SetupAxesLimits(0,1,0,1); + ImPlot::PlotLine("##1", ys1_stairs, 21, 0.05f, 0, { + ImPlotProp_LineColor, ImVec4(0.5f,0.5f,0.5f,1.0f) + }); + ImPlot::PlotLine("##2", ys2_stairs, 21, 0.05f, 0, { + ImPlotProp_LineColor, ImVec4(0.5f,0.5f,0.5f,1.0f) + }); + + ImPlot::PlotStairs("Post Step (default)", ys1_stairs, 21, 0.05f, 0, { + ImPlotProp_Flags, flags_stairs, + ImPlotProp_FillAlpha, 0.25f, + ImPlotProp_Marker, ImPlotMarker_Auto, + ImPlotProp_LineColors, colors1_stairs, + ImPlotProp_FillColors, colors1_stairs, + ImPlotProp_MarkerFillColors, colors1_stairs, + ImPlotProp_MarkerLineColors, colors1_stairs + }); + + ImPlot::PlotStairs("Pre Step", ys2_stairs, 21, 0.05f, 0, { + ImPlotProp_Flags, flags_stairs | ImPlotStairsFlags_PreStep, + ImPlotProp_FillAlpha, 0.25f, + ImPlotProp_Marker, ImPlotMarker_Auto, + ImPlotProp_LineColors, colors2_stairs, + ImPlotProp_FillColors, colors2_stairs, + ImPlotProp_MarkerFillColors, colors2_stairs, + ImPlotProp_MarkerLineColors, colors2_stairs + }); + + ImPlot::EndPlot(); + } + + // Colorful Bar Plots + static ImS8 data_bars[10] = {1,2,3,4,5,6,7,8,9,10}; + static ImU32 colors_bars_v[10], colors_bars_h[10]; + for (int i = 0; i < 10; ++i) { + // Rainbow colors for Vertical + float hue = i / 9.0f; + colors_bars_v[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Horizontal + float t = i / 9.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors_bars_h[i] = ImGui::GetColorU32(color); + } + + if (ImPlot::BeginPlot("Colorful Bar Plot")) { + ImPlot::PlotBars("Vertical", data_bars, 10, 0.7, 1, { + ImPlotProp_FillColors, colors_bars_v, + ImPlotProp_LineColors, colors_bars_v + }); + ImPlot::PlotBars("Horizontal", data_bars, 10, 0.4, 1, { + ImPlotProp_Flags, ImPlotBarsFlags_Horizontal, + ImPlotProp_FillColors, colors_bars_h, + ImPlotProp_LineColors, colors_bars_h + }); + ImPlot::EndPlot(); + } + + // Colorful Stem Plots + static double xs_stems[51], ys1_stems[51], ys2_stems[51]; + static ImU32 colors1_stems[51], colors2_stems[51]; + for (int i = 0; i < 51; ++i) { + xs_stems[i] = i * 0.02; + ys1_stems[i] = 1.0 + 0.5 * sin(25*xs_stems[i])*cos(2*xs_stems[i]); + ys2_stems[i] = 0.5 + 0.25 * sin(10*xs_stems[i]) * sin(xs_stems[i]); + + // Rainbow colors for Stems 1 + float hue = i / 50.0f; + colors1_stems[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Stems 2 + float t = i / 50.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2_stems[i] = ImGui::GetColorU32(color); + } + + if (ImPlot::BeginPlot("Colorful Stem Plots")) { + ImPlot::SetupAxisLimits(ImAxis_X1,0,1.0); + ImPlot::SetupAxisLimits(ImAxis_Y1,0,1.6); + ImPlot::PlotStems("Stems 1", xs_stems, ys1_stems, 51, 0, { + ImPlotProp_LineColors, colors1_stems, + ImPlotProp_MarkerFillColors, colors1_stems, + ImPlotProp_MarkerLineColors, colors1_stems + }); + ImPlot::PlotStems("Stems 2", xs_stems, ys2_stems, 51, 0, { + ImPlotProp_Marker, ImPlotMarker_Circle, + ImPlotProp_LineColors, colors2_stems, + ImPlotProp_MarkerFillColors, colors2_stems, + ImPlotProp_MarkerLineColors, colors2_stems + }); + ImPlot::EndPlot(); + } + + // Colorful Infinite Lines + if (ImPlot::BeginPlot("Colorful Infinite Lines", ImVec2(-1,0))) { + ImPlot::SetupAxes("x","y"); + ImPlot::SetupAxesLimits(0, 10, -1, 10); + + // 1. Constant color infinite lines + static double vals1[5] = {1.0, 2.5, 4.0, 5.5, 7.0}; + ImPlot::PlotInfLines("Const Color", vals1, 5, { + ImPlotProp_LineColor, ImVec4(0.0f, 0.7f, 1.0f, 1.0f), + }); + + // 2. Per-line rainbow colors (horizontal) + static double vals2[8]; + static ImU32 colors_infline_rainbow[8]; + for (int i = 0; i < 8; ++i) { + vals2[i] = 1.0 + i * 1.0; + float t = i / 7.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Jet); + colors_infline_rainbow[i] = ImGui::GetColorU32(color); + } + ImPlot::PlotInfLines("Rainbow Horizontal", vals2, 8, { + ImPlotProp_LineColors, colors_infline_rainbow, + ImPlotProp_Flags, ImPlotInfLinesFlags_Horizontal + }); + + // 3. Per-line colormap colors (vertical) + static double vals3[6]; + static ImU32 colors_infline_viridis[6]; + for (int i = 0; i < 6; ++i) { + vals3[i] = 1.5 + i * 1.5; + float t = i / 5.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Plasma); + colors_infline_viridis[i] = ImGui::GetColorU32(color); + } + ImPlot::PlotInfLines("Plasma Vertical", vals3, 6, { + ImPlotProp_LineColors, colors_infline_viridis, + }); + + ImPlot::EndPlot(); + } +} + +//----------------------------------------------------------------------------- + void Demo_LogScale() { + IMGUI_DEMO_MARKER("Axes/Log Scale"); static double xs[1001], ys1[1001], ys2[1001], ys3[1001]; for (int i = 0; i < 1001; ++i) { xs[i] = i*0.1f; @@ -1083,6 +1486,7 @@ void Demo_LogScale() { //----------------------------------------------------------------------------- void Demo_SymmetricLogScale() { + IMGUI_DEMO_MARKER("Axes/Symmetric Log Scale"); static double xs[1001], ys1[1001], ys2[1001]; for (int i = 0; i < 1001; ++i) { xs[i] = i*0.1f-50; @@ -1100,6 +1504,7 @@ void Demo_SymmetricLogScale() { //----------------------------------------------------------------------------- void Demo_TimeScale() { + IMGUI_DEMO_MARKER("Axes/Time Scale"); static double t_min = 1609459200; // 01/01/2021 @ 12:00:00am (UTC) static double t_max = 1640995200; // 01/01/2022 @ 12:00:00am (UTC) @@ -1157,6 +1562,7 @@ static inline double TransformInverse_Sqrt(double v, void*) { } void Demo_CustomScale() { + IMGUI_DEMO_MARKER("Axes/Custom Scale"); static float v[100]; for (int i = 0; i < 100; ++i) { v[i] = i*0.01f; @@ -1174,6 +1580,7 @@ void Demo_CustomScale() { //----------------------------------------------------------------------------- void Demo_MultipleAxes() { + IMGUI_DEMO_MARKER("Axes/Multiple Axes"); static float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001]; for (int i = 0; i < 1001; ++i) { xs[i] = (i*0.1f); @@ -1232,6 +1639,7 @@ void Demo_MultipleAxes() { //----------------------------------------------------------------------------- void Demo_LinkedAxes() { + IMGUI_DEMO_MARKER("Axes/Linked Axes"); static ImPlotRect lims(0,1,0,1); static bool linkx = true, linky = true; int data[2] = {0,1}; @@ -1261,6 +1669,7 @@ void Demo_LinkedAxes() { //----------------------------------------------------------------------------- void Demo_AxisConstraints() { + IMGUI_DEMO_MARKER("Axes/Axis Constraints"); static float constraints[4] = {-10,10,1,20}; static ImPlotAxisFlags flags; ImGui::DragFloat2("Limits Constraints", &constraints[0], 0.01f); @@ -1280,6 +1689,7 @@ void Demo_AxisConstraints() { //----------------------------------------------------------------------------- void Demo_EqualAxes() { + IMGUI_DEMO_MARKER("Axes/Equal Axes"); ImGui::BulletText("Equal constraint applies to axis pairs (e.g ImAxis_X1/Y1, ImAxis_X2/Y2)"); static double xs1[360], ys1[360]; for (int i = 0; i < 360; ++i) { @@ -1301,6 +1711,7 @@ void Demo_EqualAxes() { //----------------------------------------------------------------------------- void Demo_AutoFittingData() { + IMGUI_DEMO_MARKER("Axes/Auto-Fitting Data"); ImGui::BulletText("The Y-axis has been configured to auto-fit to only the data visible in X-axis range."); ImGui::BulletText("Zoom and pan the X-axis. Disable Stems to see a difference in fit."); ImGui::BulletText("If ImPlotAxisFlags_RangeFit is disabled, the axis will fit ALL data."); @@ -1337,6 +1748,7 @@ ImPlotPoint SinewaveGetter(int i, void* data) { } void Demo_SubplotsSizing() { + IMGUI_DEMO_MARKER("Subplots/Sizing"); static ImPlotSubplotFlags flags = ImPlotSubplotFlags_ShareItems|ImPlotSubplotFlags_NoLegend; ImGui::CheckboxFlags("ImPlotSubplotFlags_NoResize", (unsigned int*)&flags, ImPlotSubplotFlags_NoResize); @@ -1377,6 +1789,7 @@ void Demo_SubplotsSizing() { //----------------------------------------------------------------------------- void Demo_SubplotItemSharing() { + IMGUI_DEMO_MARKER("Subplots/Item Sharing"); static ImPlotSubplotFlags flags = ImPlotSubplotFlags_ShareItems; ImGui::CheckboxFlags("ImPlotSubplotFlags_ShareItems", (unsigned int*)&flags, ImPlotSubplotFlags_ShareItems); ImGui::CheckboxFlags("ImPlotSubplotFlags_ColMajor", (unsigned int*)&flags, ImPlotSubplotFlags_ColMajor); @@ -1421,6 +1834,7 @@ void Demo_SubplotItemSharing() { //----------------------------------------------------------------------------- void Demo_SubplotAxisLinking() { + IMGUI_DEMO_MARKER("Subplots/Axis Linking"); static ImPlotSubplotFlags flags = ImPlotSubplotFlags_LinkRows | ImPlotSubplotFlags_LinkCols; ImGui::CheckboxFlags("ImPlotSubplotFlags_LinkRows", (unsigned int*)&flags, ImPlotSubplotFlags_LinkRows); ImGui::CheckboxFlags("ImPlotSubplotFlags_LinkCols", (unsigned int*)&flags, ImPlotSubplotFlags_LinkCols); @@ -1445,6 +1859,7 @@ void Demo_SubplotAxisLinking() { //----------------------------------------------------------------------------- void Demo_LegendOptions() { + IMGUI_DEMO_MARKER("Tools/Legend Options"); static ImPlotLocation loc = ImPlotLocation_East; ImGui::CheckboxFlags("North", (unsigned int*)&loc, ImPlotLocation_North); ImGui::SameLine(); ImGui::CheckboxFlags("South", (unsigned int*)&loc, ImPlotLocation_South); ImGui::SameLine(); @@ -1491,6 +1906,7 @@ void Demo_LegendOptions() { //----------------------------------------------------------------------------- void Demo_DragPoints() { + IMGUI_DEMO_MARKER("Tools/Drag Points"); ImGui::BulletText("Click and drag each point."); static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None; ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine(); @@ -1544,6 +1960,7 @@ void Demo_DragPoints() { //----------------------------------------------------------------------------- void Demo_DragLines() { + IMGUI_DEMO_MARKER("Tools/Drag Lines"); ImGui::BulletText("Click and drag the horizontal and vertical lines."); static double x1 = 0.2; static double x2 = 0.8; @@ -1577,6 +1994,7 @@ void Demo_DragLines() { //----------------------------------------------------------------------------- void Demo_DragRects() { + IMGUI_DEMO_MARKER("Tools/Drag Rects"); static float x_data[512]; static float y_data1[512]; @@ -1653,6 +2071,7 @@ ImPlotPoint FindCentroid(const ImVector& data, const ImPlotRect& bo //----------------------------------------------------------------------------- void Demo_Querying() { + IMGUI_DEMO_MARKER("Tools/Querying"); static ImVector data; static ImVector rects; static ImPlotRect limits, select; @@ -1714,6 +2133,7 @@ void Demo_Querying() { //----------------------------------------------------------------------------- void Demo_Annotations() { + IMGUI_DEMO_MARKER("Tools/Annotations"); static bool clamp = false; ImGui::Checkbox("Clamp",&clamp); if (ImPlot::BeginPlot("##Annotations")) { @@ -1741,6 +2161,7 @@ void Demo_Annotations() { //----------------------------------------------------------------------------- void Demo_Tags() { + IMGUI_DEMO_MARKER("Tools/Tags"); static bool show = true; ImGui::Checkbox("Show Tags",&show); if (ImPlot::BeginPlot("##Tags")) { @@ -1763,6 +2184,7 @@ void Demo_Tags() { //----------------------------------------------------------------------------- void Demo_DragAndDrop() { + IMGUI_DEMO_MARKER("Tools/Drag and Drop"); ImGui::BulletText("Drag/drop items from the left column."); ImGui::BulletText("Drag/drop items between plots."); ImGui::Indent(); @@ -1942,6 +2364,7 @@ void Demo_DragAndDrop() { //----------------------------------------------------------------------------- void Demo_Tables() { + IMGUI_DEMO_MARKER("Subplots/Tables"); #ifdef IMGUI_HAS_TABLE static ImGuiTableFlags flags = ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable; @@ -2029,6 +2452,7 @@ void Demo_ItemStylingAndSpec() { //----------------------------------------------------------------------------- void Demo_OffsetAndStride() { + IMGUI_DEMO_MARKER("Tools/Offset and Stride"); static const int k_circles = 11; static const int k_points_per = 50; static const int k_size = 2 * k_points_per * k_circles; @@ -2064,6 +2488,7 @@ void Demo_OffsetAndStride() { //----------------------------------------------------------------------------- void Demo_CustomDataAndGetters() { + IMGUI_DEMO_MARKER("Custom/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(); @@ -2114,6 +2539,7 @@ int MetricFormatter(double value, char* buff, int size, void* data) { } void Demo_TickLabels() { + IMGUI_DEMO_MARKER("Axes/Tick Labels"); static bool custom_fmt = true; static bool custom_ticks = false; static bool custom_labels = true; @@ -2153,6 +2579,7 @@ void Demo_TickLabels() { //----------------------------------------------------------------------------- void Demo_CustomStyles() { + IMGUI_DEMO_MARKER("Custom/Custom Styles"); ImPlot::PushColormap(ImPlotColormap_Deep); // normally you wouldn't change the entire style each frame ImPlotStyle backup = ImPlot::GetStyle(); @@ -2176,6 +2603,7 @@ void Demo_CustomStyles() { //----------------------------------------------------------------------------- void Demo_CustomRendering() { + IMGUI_DEMO_MARKER("Custom/Custom Rendering"); if (ImPlot::BeginPlot("##CustomRend")) { ImVec2 cntr = ImPlot::PlotToPixels(ImPlotPoint(0.5f, 0.5f)); ImVec2 rmin = ImPlot::PlotToPixels(ImPlotPoint(0.25f, 0.75f)); @@ -2191,6 +2619,7 @@ void Demo_CustomRendering() { //----------------------------------------------------------------------------- void Demo_LegendPopups() { + IMGUI_DEMO_MARKER("Tools/Legend Popups"); ImGui::BulletText("You can implement legend context menus to inject per-item controls and widgets."); ImGui::BulletText("Right click the legend label/icon to edit custom item attributes."); @@ -2255,6 +2684,7 @@ void Demo_LegendPopups() { //----------------------------------------------------------------------------- void Demo_ColormapWidgets() { + IMGUI_DEMO_MARKER("Tools/Colormap Widgets"); static int cmap = ImPlotColormap_Viridis; if (ImPlot::ColormapButton("Button",ImVec2(0,0),cmap)) { @@ -2281,6 +2711,7 @@ void Demo_ColormapWidgets() { //----------------------------------------------------------------------------- void Demo_CustomPlottersAndTooltips() { + IMGUI_DEMO_MARKER("Custom/Custom Plotters and Tooltips"); ImGui::BulletText("You can create custom plotters or extend ImPlot using implot_internal.h."); double dates[] = {1546300800,1546387200,1546473600,1546560000,1546819200,1546905600,1546992000,1547078400,1547164800,1547424000,1547510400,1547596800,1547683200,1547769600,1547942400,1548028800,1548115200,1548201600,1548288000,1548374400,1548633600,1548720000,1548806400,1548892800,1548979200,1549238400,1549324800,1549411200,1549497600,1549584000,1549843200,1549929600,1550016000,1550102400,1550188800,1550361600,1550448000,1550534400,1550620800,1550707200,1550793600,1551052800,1551139200,1551225600,1551312000,1551398400,1551657600,1551744000,1551830400,1551916800,1552003200,1552262400,1552348800,1552435200,1552521600,1552608000,1552867200,1552953600,1553040000,1553126400,1553212800,1553472000,1553558400,1553644800,1553731200,1553817600,1554076800,1554163200,1554249600,1554336000,1554422400,1554681600,1554768000,1554854400,1554940800,1555027200,1555286400,1555372800,1555459200,1555545600,1555632000,1555891200,1555977600,1556064000,1556150400,1556236800,1556496000,1556582400,1556668800,1556755200,1556841600,1557100800,1557187200,1557273600,1557360000,1557446400,1557705600,1557792000,1557878400,1557964800,1558051200,1558310400,1558396800,1558483200,1558569600,1558656000,1558828800,1558915200,1559001600,1559088000,1559174400,1559260800,1559520000,1559606400,1559692800,1559779200,1559865600,1560124800,1560211200,1560297600,1560384000,1560470400,1560729600,1560816000,1560902400,1560988800,1561075200,1561334400,1561420800,1561507200,1561593600,1561680000,1561939200,1562025600,1562112000,1562198400,1562284800,1562544000,1562630400,1562716800,1562803200,1562889600,1563148800,1563235200,1563321600,1563408000,1563494400,1563753600,1563840000,1563926400,1564012800,1564099200,1564358400,1564444800,1564531200,1564617600,1564704000,1564963200,1565049600,1565136000,1565222400,1565308800,1565568000,1565654400,1565740800,1565827200,1565913600,1566172800,1566259200,1566345600,1566432000,1566518400,1566777600,1566864000,1566950400,1567036800,1567123200,1567296000,1567382400,1567468800,1567555200,1567641600,1567728000,1567987200,1568073600,1568160000,1568246400,1568332800,1568592000,1568678400,1568764800,1568851200,1568937600,1569196800,1569283200,1569369600,1569456000,1569542400,1569801600,1569888000,1569974400,1570060800,1570147200,1570406400,1570492800,1570579200,1570665600,1570752000,1571011200,1571097600,1571184000,1571270400,1571356800,1571616000,1571702400,1571788800,1571875200,1571961600}; double opens[] = {1284.7,1319.9,1318.7,1328,1317.6,1321.6,1314.3,1325,1319.3,1323.1,1324.7,1321.3,1323.5,1322,1281.3,1281.95,1311.1,1315,1314,1313.1,1331.9,1334.2,1341.3,1350.6,1349.8,1346.4,1343.4,1344.9,1335.6,1337.9,1342.5,1337,1338.6,1337,1340.4,1324.65,1324.35,1349.5,1371.3,1367.9,1351.3,1357.8,1356.1,1356,1347.6,1339.1,1320.6,1311.8,1314,1312.4,1312.3,1323.5,1319.1,1327.2,1332.1,1320.3,1323.1,1328,1330.9,1338,1333,1335.3,1345.2,1341.1,1332.5,1314,1314.4,1310.7,1314,1313.1,1315,1313.7,1320,1326.5,1329.2,1314.2,1312.3,1309.5,1297.4,1293.7,1277.9,1295.8,1295.2,1290.3,1294.2,1298,1306.4,1299.8,1302.3,1297,1289.6,1302,1300.7,1303.5,1300.5,1303.2,1306,1318.7,1315,1314.5,1304.1,1294.7,1293.7,1291.2,1290.2,1300.4,1284.2,1284.25,1301.8,1295.9,1296.2,1304.4,1323.1,1340.9,1341,1348,1351.4,1351.4,1343.5,1342.3,1349,1357.6,1357.1,1354.7,1361.4,1375.2,1403.5,1414.7,1433.2,1438,1423.6,1424.4,1418,1399.5,1435.5,1421.25,1434.1,1412.4,1409.8,1412.2,1433.4,1418.4,1429,1428.8,1420.6,1441,1460.4,1441.7,1438.4,1431,1439.3,1427.4,1431.9,1439.5,1443.7,1425.6,1457.5,1451.2,1481.1,1486.7,1512.1,1515.9,1509.2,1522.3,1513,1526.6,1533.9,1523,1506.3,1518.4,1512.4,1508.8,1545.4,1537.3,1551.8,1549.4,1536.9,1535.25,1537.95,1535.2,1556,1561.4,1525.6,1516.4,1507,1493.9,1504.9,1506.5,1513.1,1506.5,1509.7,1502,1506.8,1521.5,1529.8,1539.8,1510.9,1511.8,1501.7,1478,1485.4,1505.6,1511.6,1518.6,1498.7,1510.9,1510.8,1498.3,1492,1497.7,1484.8,1494.2,1495.6,1495.6,1487.5,1491.1,1495.1,1506.4}; @@ -2380,6 +2811,7 @@ void ShowDemoWindow(bool* p_open) { DemoHeader("Shaded Plots##", Demo_ShadedPlots); DemoHeader("Scatter Plots", Demo_ScatterPlots); DemoHeader("Bubble Plots", Demo_BubblePlots); + DemoHeader("Polygon Plots", Demo_PolygonPlots); DemoHeader("Realtime Plots", Demo_RealtimePlots); DemoHeader("Stairstep Plots", Demo_StairstepPlots); DemoHeader("Bar Plots", Demo_BarPlots); @@ -2396,6 +2828,7 @@ void ShowDemoWindow(bool* p_open) { DemoHeader("Images", Demo_Images); DemoHeader("Markers and Text", Demo_MarkersAndText); DemoHeader("NaN Values", Demo_NaNValues); + DemoHeader("Per-Index Colors", Demo_PerIndexColors); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Subplots")) { diff --git a/implot_internal.h b/implot_internal.h index da49cedb..e7783270 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.18 WIP +// ImPlot v1.1 WIP // You may use this file to debug, understand or extend ImPlot features but we // don't provide any guarantee of forward compatibility! @@ -118,7 +118,7 @@ static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? se // Linearly remaps x from [x0 x1] to [y0 y1]. template static inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); } -// Linear rempas x from [x0 x1] to [0 1] +// Linearly remaps x from [x0 x1] to [0 1] template static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); } // Returns always positive modulo (assumes r != 0) diff --git a/implot_items.cpp b/implot_items.cpp index 50ed5c62..807df125 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.18 WIP +// ImPlot v1.1 WIP #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS @@ -684,6 +684,61 @@ struct GetterError { typedef ImPlotPointError value_type; }; +//----------------------------------------------------------------------------- +// [SECTION] Color Getters +//----------------------------------------------------------------------------- + +struct GetterConstColor { + GetterConstColor(ImU32 color, float alpha = 1.0f) { + ImU32 col = color; + if (alpha < 1.0f) { + ImVec4 col_vec = ImGui::ColorConvertU32ToFloat4(col); + col_vec.w *= alpha; + col = ImGui::GetColorU32(col_vec); + } + Color = col; + } + template IMPLOT_INLINE ImU32 operator[](I) const { return Color; } + ImU32 Color; +}; + +struct GetterIdxColor { + GetterIdxColor(const ImU32* data, int count, float alpha = 1.0f) : Data(data), Count(count), Alpha(alpha) { } + template IMPLOT_INLINE ImU32 operator[](I idx) const { + IM_ASSERT(idx >= 0 && idx < Count); + ImU32 col = Data[idx]; + if (Alpha < 1.0f) { + ImVec4 col_vec = ImGui::ColorConvertU32ToFloat4(col); + col_vec.w *= Alpha; + col = ImGui::GetColorU32(col_vec); + } + return col; + } + const ImU32* Data; + const int Count; + const float Alpha; +}; + +//----------------------------------------------------------------------------- +// [SECTION] Size Getters +//----------------------------------------------------------------------------- + +struct GetterConstSize { + GetterConstSize(float size) : Size(size) { } + template IMPLOT_INLINE float operator[](I) const { return Size; } + float Size; +}; + +struct GetterIdxSize { + GetterIdxSize(const float* data, int count) : Data(data), Count(count) { } + template IMPLOT_INLINE float operator[](I idx) const { + IM_ASSERT(idx >= 0 && idx < Count); + return Data[idx]; + } + const float* Data; + const int Count; +}; + //----------------------------------------------------------------------------- // [SECTION] Fitters //----------------------------------------------------------------------------- @@ -918,12 +973,12 @@ struct RendererBase { const int VtxConsumed; }; -template +template struct RendererLineStrip : RendererBase { - RendererLineStrip(const _Getter& getter, ImU32 col, float weight) : + RendererLineStrip(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { P1 = this->Transformer(Getter[0]); @@ -937,24 +992,25 @@ struct RendererLineStrip : RendererBase { P1 = P2; return false; } - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererLineStripSkip : RendererBase { - RendererLineStripSkip(const _Getter& getter, ImU32 col, float weight) : + RendererLineStripSkip(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { P1 = this->Transformer(Getter[0]); @@ -969,25 +1025,26 @@ struct RendererLineStripSkip : RendererBase { P1 = P2; return false; } - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); if (!ImNan(P2.x) && !ImNan(P2.y)) P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererLineSegments1 : RendererBase { - RendererLineSegments1(const _Getter& getter, ImU32 col, float weight) : + RendererLineSegments1(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count / 2, 6, 4), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { } void Init(ImDrawList& draw_list) const { @@ -998,23 +1055,24 @@ struct RendererLineSegments1 : RendererBase { ImVec2 P2 = this->Transformer(Getter[prim*2+1]); if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) return false; - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim*2]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererLineSegments2 : RendererBase { - RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, float weight) : - RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4), + RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, float weight) : + RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) {} void Init(ImDrawList& draw_list) const { @@ -1025,24 +1083,25 @@ struct RendererLineSegments2 : RendererBase { ImVec2 P2 = this->Transformer(Getter2[prim]); if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) return false; - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererBarsFillV : RendererBase { - RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width) : - RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4), + RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double width) : + RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfWidth(width/2) {} void Init(ImDrawList& draw_list) const { @@ -1064,23 +1123,24 @@ struct RendererBarsFillV : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectFill(draw_list,PMin,PMax,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list,PMin,PMax,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfWidth; mutable ImVec2 UV; }; -template +template struct RendererBarsFillH : RendererBase { - RendererBarsFillH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height) : - RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4), + RendererBarsFillH(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double height) : + RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfHeight(height/2) {} void Init(ImDrawList& draw_list) const { @@ -1102,23 +1162,24 @@ struct RendererBarsFillH : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectFill(draw_list,PMin,PMax,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list,PMin,PMax,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfHeight; mutable ImVec2 UV; }; -template +template struct RendererBarsLineV : RendererBase { - RendererBarsLineV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width, float weight) : - RendererBase(ImMin(getter1.Count, getter1.Count), 24, 8), + RendererBarsLineV(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double width, float weight) : + RendererBase(ImMin(getter1.Count, getter2.Count), 24, 8), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfWidth(width/2), Weight(weight) {} @@ -1141,24 +1202,25 @@ struct RendererBarsLineV : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectLine(draw_list,PMin,PMax,Weight,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfWidth; const float Weight; mutable ImVec2 UV; }; -template +template struct RendererBarsLineH : RendererBase { - RendererBarsLineH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height, float weight) : - RendererBase(ImMin(getter1.Count, getter1.Count), 24, 8), + RendererBarsLineH(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double height, float weight) : + RendererBase(ImMin(getter1.Count, getter2.Count), 24, 8), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfHeight(height/2), Weight(weight) {} @@ -1181,24 +1243,25 @@ struct RendererBarsLineH : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectLine(draw_list,PMin,PMax,Weight,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfHeight; const float Weight; mutable ImVec2 UV; }; -template +template struct RendererStairsPre : RendererBase { - RendererStairsPre(const _Getter& getter, ImU32 col, float weight) : + RendererStairsPre(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 12, 8), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { P1 = this->Transformer(Getter[0]); @@ -1212,24 +1275,25 @@ struct RendererStairsPre : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, ImVec2(P1.x - HalfWeight, P1.y), ImVec2(P1.x + HalfWeight, P2.y), Col, UV); - PrimRectFill(draw_list, ImVec2(P1.x, P2.y + HalfWeight), ImVec2(P2.x, P2.y - HalfWeight), Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, ImVec2(P1.x - HalfWeight, P1.y), ImVec2(P1.x + HalfWeight, P2.y), col, UV); + PrimRectFill(draw_list, ImVec2(P1.x, P2.y + HalfWeight), ImVec2(P2.x, P2.y - HalfWeight), col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV; }; -template +template struct RendererStairsPost : RendererBase { - RendererStairsPost(const _Getter& getter, ImU32 col, float weight) : + RendererStairsPost(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 12, 8), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight) * 0.5f) { P1 = this->Transformer(Getter[0]); @@ -1243,24 +1307,25 @@ struct RendererStairsPost : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, UV); - PrimRectFill(draw_list, ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), col, UV); + PrimRectFill(draw_list, ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV; }; -template +template struct RendererStairsPreShaded : RendererBase { - RendererStairsPreShaded(const _Getter& getter, ImU32 col) : + RendererStairsPreShaded(const _Getter& getter, const _GetterColor& getter_color) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col) + GetterColor(getter_color) { P1 = this->Transformer(Getter[0]); Y0 = this->Transformer(ImPlotPoint(0,0)).y; @@ -1276,23 +1341,24 @@ struct RendererStairsPreShaded : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, PMin, PMax, Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, PMin, PMax, col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; float Y0; mutable ImVec2 P1; mutable ImVec2 UV; }; -template +template struct RendererStairsPostShaded : RendererBase { - RendererStairsPostShaded(const _Getter& getter, ImU32 col) : + RendererStairsPostShaded(const _Getter& getter, const _GetterColor& getter_color) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col) + GetterColor(getter_color) { P1 = this->Transformer(Getter[0]); Y0 = this->Transformer(ImPlotPoint(0,0)).y; @@ -1308,12 +1374,13 @@ struct RendererStairsPostShaded : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, PMin, PMax, Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, PMin, PMax, col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; float Y0; mutable ImVec2 P1; mutable ImVec2 UV; @@ -1321,13 +1388,13 @@ struct RendererStairsPostShaded : RendererBase { -template +template struct RendererShaded : RendererBase { - RendererShaded(const _Getter1& getter1, const _Getter2& getter2, ImU32 col) : + RendererShaded(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color) : RendererBase(ImMin(getter1.Count, getter2.Count) - 1, 6, 5), Getter1(getter1), Getter2(getter2), - Col(col) + GetterColor(getter_color) { P11 = this->Transformer(Getter1[0]); P12 = this->Transformer(Getter2[0]); @@ -1344,23 +1411,24 @@ struct RendererShaded : RendererBase { P12 = P22; return false; } + ImU32 col = GetterColor[prim]; const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y); const ImVec2 intersection = intersect == 0 ? ImVec2(0,0) : Intersection(P11,P21,P12,P22); draw_list._VtxWritePtr[0].pos = P11; draw_list._VtxWritePtr[0].uv = UV; - draw_list._VtxWritePtr[0].col = Col; + draw_list._VtxWritePtr[0].col = col; draw_list._VtxWritePtr[1].pos = P21; draw_list._VtxWritePtr[1].uv = UV; - draw_list._VtxWritePtr[1].col = Col; + draw_list._VtxWritePtr[1].col = col; draw_list._VtxWritePtr[2].pos = intersection; draw_list._VtxWritePtr[2].uv = UV; - draw_list._VtxWritePtr[2].col = Col; + draw_list._VtxWritePtr[2].col = col; draw_list._VtxWritePtr[3].pos = P12; draw_list._VtxWritePtr[3].uv = UV; - draw_list._VtxWritePtr[3].col = Col; + draw_list._VtxWritePtr[3].col = col; draw_list._VtxWritePtr[4].pos = P22; draw_list._VtxWritePtr[4].uv = UV; - draw_list._VtxWritePtr[4].col = Col; + draw_list._VtxWritePtr[4].col = col; draw_list._VtxWritePtr += 5; draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + intersect); @@ -1376,7 +1444,7 @@ struct RendererShaded : RendererBase { } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; mutable ImVec2 P11; mutable ImVec2 P12; mutable ImVec2 UV; @@ -1468,19 +1536,26 @@ void RenderPrimitives2(const _Getter1& getter1, const _Getter2& getter2, Args... RenderPrimitivesEx(_Renderer<_Getter1,_Getter2>(getter1,getter2,args...), draw_list, cull_rect); } +template