From 9c44711aa2311125d542ea7ae4d85d898c73f7fe Mon Sep 17 00:00:00 2001 From: Samuele Mazzi Date: Fri, 20 Sep 2024 17:15:23 +0200 Subject: [PATCH 1/2] feat: add `IsPlotChanging()` As pointed out in the `TODO.md` --- TODO.md | 2 +- implot.cpp | 12 ++++++++++++ implot.h | 2 ++ implot_demo.cpp | 19 +++++++++++++++++++ implot_internal.h | 1 + 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index c640f038..65ab2813 100644 --- a/TODO.md +++ b/TODO.md @@ -37,7 +37,6 @@ The list below represents a combination of high-priority work, nice-to-have feat ## Tools / Misc. -- add `IsPlotChanging` to detect change in limits - add ability to extend plot/axis context menus - add LTTB downsampling for lines - add box selection to axes @@ -80,6 +79,7 @@ Ideally every `PlotX` function should use our faster rendering pipeline when it |PlotDummy|-|-|-|-| ## Completed +- add `IsPlotChanging` to detect change in limits - make BeginPlot take fewer args: - make query a tool -> `DragRect` - rework DragLine/Point to use ButtonBehavior diff --git a/implot.cpp b/implot.cpp index 597b043b..ce132341 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2135,6 +2135,8 @@ void SetupAxis(ImAxis idx, const char* label, ImPlotAxisFlags flags) { if (plot.JustCreated || flags != axis.PreviousFlags) axis.Flags = flags; axis.PreviousFlags = flags; + // cache previous range + axis.PreviousRange = ImPlotRange(axis.Range.Min, axis.Range.Max); // enable axis axis.Enabled = true; // set label @@ -3739,6 +3741,16 @@ bool IsPlotHovered() { return gp.CurrentPlot->Hovered; } +bool IsPlotChanging() { + ImPlotContext& gp = *GImPlot; + IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "IsPlotChanging() needs to be called between BeginPlot() and EndPlot()!"); + SetupLock(); + ImPlotPlot& plot = *gp.CurrentPlot; + bool differentX = plot.Axes[plot.CurrentX].Range.Min != plot.Axes[plot.CurrentX].PreviousRange.Min || plot.Axes[plot.CurrentX].Range.Max != plot.Axes[plot.CurrentX].PreviousRange.Max; + bool differentY = plot.Axes[plot.CurrentY].Range.Min != plot.Axes[plot.CurrentY].PreviousRange.Min || plot.Axes[plot.CurrentY].Range.Max != plot.Axes[plot.CurrentY].PreviousRange.Max; + return differentX || differentY; +} + bool IsAxisHovered(ImAxis axis) { ImPlotContext& gp = *GImPlot; IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "IsPlotXAxisHovered() needs to be called between BeginPlot() and EndPlot()!"); diff --git a/implot.h b/implot.h index 30543312..1ee23518 100644 --- a/implot.h +++ b/implot.h @@ -982,6 +982,8 @@ IMPLOT_API ImPlotRect GetPlotLimits(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = // Returns true if the plot area in the current plot is hovered. IMPLOT_API bool IsPlotHovered(); +// Returns true if the limits of the current plot are changing. +IMPLOT_API bool IsPlotChanging(); // Returns true if the axis label area in the current plot is hovered. IMPLOT_API bool IsAxisHovered(ImAxis axis); // Returns true if the bounding frame of a subplot is hovered. diff --git a/implot_demo.cpp b/implot_demo.cpp index c72ffd04..14703702 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -2128,6 +2128,24 @@ void Demo_ColormapWidgets() { //----------------------------------------------------------------------------- +void Demo_PlotLimitsChanging() { + unsigned int lin[10] = {8,8,9,7,8,8,8,9,7,8}; + unsigned int bar[10] = {1,2,5,3,4,1,2,5,3,4}; + unsigned int dot[10] = {7,6,6,7,8,5,6,5,8,7}; + + if (ImPlot::BeginPlot("##LimitsChanging")) { + ImPlot::SetupAxes( "x-axis", "y-axis"); + ImPlot::SetupAxesLimits(-0.5f, 9.5f, 0, 10); + ImPlot::PlotBars("Bars", bar, 10, 0.5f); + ImPlot::PlotLine("Line", lin, 10); + bool is_changing = ImPlot::IsPlotChanging(); + ImGui::Text("Axes are changing: %s", (is_changing ? "true" : "false")); + ImPlot::EndPlot(); + } +} + +//----------------------------------------------------------------------------- + void Demo_CustomPlottersAndTooltips() { 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}; @@ -2277,6 +2295,7 @@ void ShowDemoWindow(bool* p_open) { DemoHeader("Legend Options", Demo_LegendOptions); DemoHeader("Legend Popups", Demo_LegendPopups); DemoHeader("Colormap Widgets", Demo_ColormapWidgets); + DemoHeader("Plot limits changing", Demo_PlotLimitsChanging); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Custom")) { diff --git a/implot_internal.h b/implot_internal.h index cd05478f..b32861a0 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -627,6 +627,7 @@ struct ImPlotAxis ImPlotAxisFlags Flags; ImPlotAxisFlags PreviousFlags; ImPlotRange Range; + ImPlotRange PreviousRange; ImPlotCond RangeCond; ImPlotScale Scale; ImPlotRange FitExtents; From 9478e2f380218efd4c054cc1f5ee57fea9bb05f2 Mon Sep 17 00:00:00 2001 From: Samuele Mazzi Date: Thu, 26 Dec 2024 17:50:16 +0100 Subject: [PATCH 2/2] Rename `IsPlotChanging` to `IsAxisRangeChanging` and define `PreviousRange` in `SetupFinish` --- TODO.md | 3 ++- implot.cpp | 17 ++++++++++------- implot.h | 4 ++-- implot_demo.cpp | 5 ++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/TODO.md b/TODO.md index 65ab2813..2a78e52d 100644 --- a/TODO.md +++ b/TODO.md @@ -79,7 +79,8 @@ Ideally every `PlotX` function should use our faster rendering pipeline when it |PlotDummy|-|-|-|-| ## Completed -- add `IsPlotChanging` to detect change in limits +- add `IsAxisRangeChanging` to detect change in limits +- add exploding to `PlotPieChart` (on legend hover) - make BeginPlot take fewer args: - make query a tool -> `DragRect` - rework DragLine/Point to use ButtonBehavior diff --git a/implot.cpp b/implot.cpp index ce132341..8674a472 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2135,8 +2135,6 @@ void SetupAxis(ImAxis idx, const char* label, ImPlotAxisFlags flags) { if (plot.JustCreated || flags != axis.PreviousFlags) axis.Flags = flags; axis.PreviousFlags = flags; - // cache previous range - axis.PreviousRange = ImPlotRange(axis.Range.Min, axis.Range.Max); // enable axis axis.Enabled = true; // set label @@ -2632,6 +2630,11 @@ void SetupFinish() { } } + // cache previous ranges + for(int i = 0; i < ImAxis_COUNT; i++) { + plot.Axes[i].PreviousRange = ImPlotRange(plot.Axes[i].Range.Min, plot.Axes[i].Range.Max); + } + // INPUT ------------------------------------------------------------------ if (!ImHasFlag(plot.Flags, ImPlotFlags_NoInputs)) UpdateInput(plot); @@ -3741,14 +3744,14 @@ bool IsPlotHovered() { return gp.CurrentPlot->Hovered; } -bool IsPlotChanging() { +bool IsAxisRangeChanging(ImAxis axis) { ImPlotContext& gp = *GImPlot; - IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "IsPlotChanging() needs to be called between BeginPlot() and EndPlot()!"); + IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "IsAxisRangeChanging() needs to be called between BeginPlot() and EndPlot()!"); SetupLock(); ImPlotPlot& plot = *gp.CurrentPlot; - bool differentX = plot.Axes[plot.CurrentX].Range.Min != plot.Axes[plot.CurrentX].PreviousRange.Min || plot.Axes[plot.CurrentX].Range.Max != plot.Axes[plot.CurrentX].PreviousRange.Max; - bool differentY = plot.Axes[plot.CurrentY].Range.Min != plot.Axes[plot.CurrentY].PreviousRange.Min || plot.Axes[plot.CurrentY].Range.Max != plot.Axes[plot.CurrentY].PreviousRange.Max; - return differentX || differentY; + bool isMinDifferent = plot.Axes[axis].Range.Min != plot.Axes[axis].PreviousRange.Min; + bool isMaxDifferent = plot.Axes[axis].Range.Max != plot.Axes[axis].PreviousRange.Max; + return isMinDifferent || isMaxDifferent; } bool IsAxisHovered(ImAxis axis) { diff --git a/implot.h b/implot.h index 1ee23518..d3b166f3 100644 --- a/implot.h +++ b/implot.h @@ -982,8 +982,8 @@ IMPLOT_API ImPlotRect GetPlotLimits(ImAxis x_axis = IMPLOT_AUTO, ImAxis y_axis = // Returns true if the plot area in the current plot is hovered. IMPLOT_API bool IsPlotHovered(); -// Returns true if the limits of the current plot are changing. -IMPLOT_API bool IsPlotChanging(); +// Returns true if the limits of the selected axis are changing. +IMPLOT_API bool IsAxisRangeChanging(ImAxis axis); // Returns true if the axis label area in the current plot is hovered. IMPLOT_API bool IsAxisHovered(ImAxis axis); // Returns true if the bounding frame of a subplot is hovered. diff --git a/implot_demo.cpp b/implot_demo.cpp index 14703702..e489bb6c 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -2131,15 +2131,14 @@ void Demo_ColormapWidgets() { void Demo_PlotLimitsChanging() { unsigned int lin[10] = {8,8,9,7,8,8,8,9,7,8}; unsigned int bar[10] = {1,2,5,3,4,1,2,5,3,4}; - unsigned int dot[10] = {7,6,6,7,8,5,6,5,8,7}; if (ImPlot::BeginPlot("##LimitsChanging")) { ImPlot::SetupAxes( "x-axis", "y-axis"); ImPlot::SetupAxesLimits(-0.5f, 9.5f, 0, 10); ImPlot::PlotBars("Bars", bar, 10, 0.5f); ImPlot::PlotLine("Line", lin, 10); - bool is_changing = ImPlot::IsPlotChanging(); - ImGui::Text("Axes are changing: %s", (is_changing ? "true" : "false")); + bool is_changing = ImPlot::IsAxisRangeChanging(ImAxis_X1); + ImGui::Text("Axis X1 is changing: %s", (is_changing ? "true" : "false")); ImPlot::EndPlot(); } }