From 363d4691224b4c9e54bc9d27cf6a5f1f020ab3a5 Mon Sep 17 00:00:00 2001 From: Evan Pezent Date: Tue, 28 Apr 2020 20:17:26 -0500 Subject: [PATCH] better query --- implot.cpp | 308 ++++++++++++++++++++++++++---------------------- implot.h | 12 +- implot_demo.cpp | 49 +++++++- 3 files changed, 221 insertions(+), 148 deletions(-) diff --git a/implot.cpp b/implot.cpp index 838fbbb..ffa5208 100644 --- a/implot.cpp +++ b/implot.cpp @@ -106,7 +106,7 @@ inline float ConstrainInf(float val) { } inline float ConstrainLog(float val) { - return val <= 0 ? 0.1 : val; + return val <= 0 ? 0.001 : val; } inline bool NanOrInf(float val) { @@ -221,9 +221,8 @@ struct ImPlotAxis { /// Holds Plot state information that must persist between frames struct ImPlot { ImPlot() { - Selecting = false; - Querying = false; - SelectStart = {0,0}; + Selecting = Querying = Queried = false; + SelectStart = QueryStart = ImVec2(0,0); Flags = ImPlotFlags_Default; ColorIdx = 0; } @@ -231,8 +230,12 @@ struct ImPlot { ImRect BB_Legend; bool Selecting; - bool Querying; ImVec2 SelectStart; + bool Querying; + bool Queried; + ImVec2 QueryStart; + ImRect QueryRect; + ImPlotRange QueryRange; ImPlotAxis XAxis; ImPlotAxis YAxis; ImPlotFlags Flags; @@ -255,15 +258,12 @@ struct ImNextPlotData { struct ImPlotContext { ImPlotContext() { CurrentPlot = NULL; - PreviousPlot = NULL; RestorePlotPalette(); } /// ALl Plots ImPool Plots; /// Current Plot ImPlot* CurrentPlot; - /// Previous Plot - ImPlot* PreviousPlot; // Legend ImVector _LegendIndices; @@ -397,7 +397,9 @@ struct ImPlotContext { ImPlotStyle Style; ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() - ImNextPlotData NextPlotData; + ImNextPlotData NextPlotData; + + }; /// Global plot context @@ -723,62 +725,87 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons } } - // BOX-SELECTION ---------------------------------------------------------- + // BOX-SELECTION AND QUERY ------------------------------------------------ // confirm selection - if ((plot.Selecting || plot.Querying) && IO.MouseReleased[1]) { - if (plot.Selecting && HasFlag(plot.Flags, ImPlotFlags_Selection)) { - gp.UpdateTransforms(); - ImVec2 select_size = plot.SelectStart - IO.MousePos; - if (ImFabs(select_size.x) > 2 && ImFabs(select_size.y) > 2) { - ImVec2 p1 = gp.FromPixels(plot.SelectStart); - ImVec2 p2 = gp.FromPixels(IO.MousePos); - if (!lock_x_min && !IO.KeyAlt) - plot.XAxis.Min = ImMin(p1.x, p2.x); - if (!lock_x_max && !IO.KeyAlt) - plot.XAxis.Max = ImMax(p1.x, p2.x); - if (!lock_y_min && !IO.KeyShift) - plot.YAxis.Min = ImMin(p1.y, p2.y); - if (!lock_y_max && !IO.KeyShift) - plot.YAxis.Max = ImMax(p1.y, p2.y); - } - } + if (plot.Selecting && (IO.MouseReleased[1] || !IO.MouseDown[1])) { + gp.UpdateTransforms(); + ImVec2 select_size = plot.SelectStart - IO.MousePos; + if (HasFlag(plot.Flags, ImPlotFlags_Selection) && ImFabs(select_size.x) > 2 && ImFabs(select_size.y) > 2) { + ImVec2 p1 = gp.FromPixels(plot.SelectStart); + ImVec2 p2 = gp.FromPixels(IO.MousePos); + if (!lock_x_min && !IO.KeyAlt) + plot.XAxis.Min = ImMin(p1.x, p2.x); + if (!lock_x_max && !IO.KeyAlt) + plot.XAxis.Max = ImMax(p1.x, p2.x); + if (!lock_y_min && !IO.KeyShift) + plot.YAxis.Min = ImMin(p1.y, p2.y); + if (!lock_y_max && !IO.KeyShift) + plot.YAxis.Max = ImMax(p1.y, p2.y); + } plot.Selecting = false; - plot.Querying = false; - } - if (plot.Querying && IO.MouseReleased[2]) { - plot.Querying = false; } // bad selection - if (plot.Selecting && (!HasFlag(plot.Flags, ImPlotFlags_Selection) || lock_plot) && ImLengthSqr(plot.SelectStart - IO.MousePos) > 4) { + if (plot.Selecting && (!HasFlag(plot.Flags, ImPlotFlags_Selection) || lock_plot) && ImLengthSqr(plot.SelectStart - IO.MousePos) > 4) { ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); } - // toggle between select/query - if (plot.Selecting && IO.KeyCtrl) { - plot.Selecting = false; - plot.Querying = true; - } - if (plot.Querying && !IO.KeyCtrl && !IO.MouseDown[2]) { - plot.Selecting = true; - plot.Querying = false; - } // cancel selection - if ((plot.Selecting || plot.Querying) && (IO.MouseClicked[0] || IO.MouseDown[0])) { + if (plot.Selecting && (IO.MouseClicked[0] || IO.MouseDown[0])) { plot.Selecting = false; - plot.Querying = false; } // begin selection or query if (gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[1]) { plot.SelectStart = IO.MousePos; - if (IO.KeyCtrl) - plot.Querying = true; - else - plot.Selecting = true; + plot.Selecting = true; + } + // update query + if (plot.Querying) { + gp.UpdateTransforms(); + plot.QueryRect.Min.x = IO.KeyAlt ? gp.BB_Grid.Min.x : ImMin(plot.QueryStart.x, IO.MousePos.x); + plot.QueryRect.Max.x = IO.KeyAlt ? gp.BB_Grid.Max.x : ImMax(plot.QueryStart.x, IO.MousePos.x); + plot.QueryRect.Min.y = IO.KeyShift ? gp.BB_Grid.Min.y : ImMin(plot.QueryStart.y, IO.MousePos.y); + plot.QueryRect.Max.y = IO.KeyShift ? gp.BB_Grid.Max.y : ImMax(plot.QueryStart.y, IO.MousePos.y); + ImVec2 p1 = gp.FromPixels(plot.QueryRect.Min); + ImVec2 p2 = gp.FromPixels(plot.QueryRect.Max); + plot.QueryRange.XMin = ImMin(p1.x, p2.x); + plot.QueryRange.XMax = ImMax(p1.x, p2.x); + plot.QueryRange.YMin = ImMin(p1.y, p2.y); + plot.QueryRange.YMax = ImMax(p1.y, p2.y); + } + // end query + if (plot.Querying && (IO.MouseReleased[2] || IO.MouseReleased[1])) { + plot.Querying = false; + if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) { + plot.Queried = true; + } + else { + plot.Queried = false; + plot.QueryRange = ImPlotRange(); + } } // begin query - if (gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[2]) { - plot.SelectStart = IO.MousePos; + if ((gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[2])) { + plot.QueryRect = ImRect(0,0,0,0); + plot.QueryRange = ImPlotRange(); plot.Querying = true; + plot.Queried = true; + plot.QueryStart = IO.MousePos; + } + // toggle between select/query + if (plot.Selecting && IO.KeyCtrl) { + plot.Selecting = false; + plot.QueryRect = ImRect(0,0,0,0); + plot.QueryRange = ImPlotRange(); + plot.Querying = true; + plot.Queried = true; + plot.QueryStart = plot.SelectStart; + } + if (plot.Querying && !IO.KeyCtrl && !IO.MouseDown[2]) { + plot.Selecting = true; + plot.Querying = false; + plot.Queried = false; + plot.QueryRect = ImRect(0,0,0,0); + plot.QueryRange = ImPlotRange(); } // DOUBLE CLICK ----------------------------------------------------------- @@ -948,27 +975,29 @@ void PlotContextMenu(ImPlot& plot) { } ImGui::Separator(); if ((ImGui::BeginMenu("Settings"))) { + if (ImGui::MenuItem("Box Select",NULL,HasFlag(plot.Flags, ImPlotFlags_Selection))) { + FlipFlag(plot.Flags, ImPlotFlags_Selection); + } + if (ImGui::MenuItem("Pixel Query",NULL,HasFlag(plot.Flags, ImPlotFlags_PixelQuery))) { + FlipFlag(plot.Flags, ImPlotFlags_PixelQuery); + } + if (ImGui::MenuItem("Crosshairs",NULL,HasFlag(plot.Flags, ImPlotFlags_Crosshairs))) { + FlipFlag(plot.Flags, ImPlotFlags_Crosshairs); + } + if (ImGui::MenuItem("Mouse Position",NULL,HasFlag(plot.Flags, ImPlotFlags_MousePos))) { + FlipFlag(plot.Flags, ImPlotFlags_MousePos); + } if (ImGui::MenuItem("Cull Data",NULL,HasFlag(plot.Flags, ImPlotFlags_CullData))) { FlipFlag(plot.Flags, ImPlotFlags_CullData); } if (ImGui::MenuItem("Anti-Aliased Lines",NULL,HasFlag(plot.Flags, ImPlotFlags_AntiAliased))) { FlipFlag(plot.Flags, ImPlotFlags_AntiAliased); } - if (ImGui::MenuItem("Mouse Position",NULL,HasFlag(plot.Flags, ImPlotFlags_MousePos))) { - FlipFlag(plot.Flags, ImPlotFlags_MousePos); - } - if (ImGui::MenuItem("Selection Box",NULL,HasFlag(plot.Flags, ImPlotFlags_Selection))) { - FlipFlag(plot.Flags, ImPlotFlags_Selection); - } ImGui::EndMenu(); } if (ImGui::MenuItem("Legend",NULL,HasFlag(plot.Flags, ImPlotFlags_Legend))) { FlipFlag(plot.Flags, ImPlotFlags_Legend); } - - if (ImGui::MenuItem("Crosshairs",NULL,HasFlag(plot.Flags, ImPlotFlags_Crosshairs))) { - FlipFlag(plot.Flags, ImPlotFlags_Crosshairs); - } #if 0 if (ImGui::BeginMenu("Metrics")) { ImGui::PushItemWidth(75); @@ -1014,6 +1043,54 @@ void EndPlot() { PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); + // render ticks + if (HasFlag(plot.XAxis.Flags, ImAxisFlags_TickMarks)) { + for (auto &xt : gp.XTicks) + DrawList.AddLine({xt.PixelPos, gp.BB_Grid.Max.y},{xt.PixelPos, gp.BB_Grid.Max.y - (xt.Major ? 10.0f : 5.0f)}, gp.Col_Border, 1); + } + if (HasFlag(plot.YAxis.Flags, ImAxisFlags_TickMarks)) { + for (auto &yt : gp.YTicks) + DrawList.AddLine({gp.BB_Grid.Min.x, yt.PixelPos}, {gp.BB_Grid.Min.x + (yt.Major ? 10.0f : 5.0f), yt.PixelPos}, gp.Col_Border, 1); + } + + // render selection/query + if (plot.Selecting) { + ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart)); + if (plot.Selecting && !lock_plot && HasFlag(plot.Flags, ImPlotFlags_Selection)) { + if (IO.KeyAlt && IO.KeyShift && select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { + DrawList.AddRectFilled(gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBg); + DrawList.AddRect( gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBd); + } + else if ((lock_x || IO.KeyAlt) && select_bb.GetHeight() > 2) { + DrawList.AddRectFilled(ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBg); + DrawList.AddRect( ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBd); + } + else if ((lock_y || IO.KeyShift) && select_bb.GetWidth() > 2) { + DrawList.AddRectFilled(ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBg); + DrawList.AddRect( ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBd); + } + else if (select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { + DrawList.AddRectFilled(select_bb.Min, select_bb.Max, gp.Col_SlctBg); + DrawList.AddRect( select_bb.Min, select_bb.Max, gp.Col_SlctBd); + } + } + } + + if (plot.Querying || (HasFlag(plot.Flags, ImPlotFlags_PixelQuery) && plot.Queried)) { + if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) { + DrawList.AddRectFilled(plot.QueryRect.Min, plot.QueryRect.Max, gp.Col_QryBg); + DrawList.AddRect( plot.QueryRect.Min, plot.QueryRect.Max, gp.Col_QryBd); + } + } + else if (plot.Queried) { + ImVec2 p1 = gp.ToPixels(plot.QueryRange.XMin, plot.QueryRange.YMin); + ImVec2 p2 = gp.ToPixels(plot.QueryRange.XMax, plot.QueryRange.YMax); + ImVec2 Min(ImMin(p1.x,p2.x), ImMin(p1.y,p2.y)); + ImVec2 Max(ImMax(p1.x,p2.x), ImMax(p1.y,p2.y)); + DrawList.AddRectFilled(Min, Max, gp.Col_QryBg); + DrawList.AddRect( Min, Max, gp.Col_QryBd); + } + // render legend const float txt_ht = GetTextLineHeight(); const ImVec2 legend_offset(10, 10); @@ -1072,57 +1149,6 @@ void EndPlot() { } } - // render ticks - if (HasFlag(plot.XAxis.Flags, ImAxisFlags_TickMarks)) { - for (auto &xt : gp.XTicks) - DrawList.AddLine({xt.PixelPos, gp.BB_Grid.Max.y},{xt.PixelPos, gp.BB_Grid.Max.y - (xt.Major ? 10.0f : 5.0f)}, gp.Col_Border, 1); - } - if (HasFlag(plot.YAxis.Flags, ImAxisFlags_TickMarks)) { - for (auto &yt : gp.YTicks) - DrawList.AddLine({gp.BB_Grid.Min.x, yt.PixelPos}, {gp.BB_Grid.Min.x + (yt.Major ? 10.0f : 5.0f), yt.PixelPos}, gp.Col_Border, 1); - } - - // render selection/query - if (plot.Selecting || plot.Querying) { - ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart)); - if (plot.Selecting && !lock_plot && HasFlag(plot.Flags, ImPlotFlags_Selection)) { - if (IO.KeyAlt && IO.KeyShift && select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { - DrawList.AddRectFilled(gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBg); - DrawList.AddRect( gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBd); - } - else if ((lock_x || IO.KeyAlt) && select_bb.GetHeight() > 2) { - DrawList.AddRectFilled(ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBg); - DrawList.AddRect( ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBd); - } - else if ((lock_y || IO.KeyShift) && select_bb.GetWidth() > 2) { - DrawList.AddRectFilled(ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBg); - DrawList.AddRect( ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBd); - } - else if (select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { - DrawList.AddRectFilled(select_bb.Min, select_bb.Max, gp.Col_SlctBg); - DrawList.AddRect( select_bb.Min, select_bb.Max, gp.Col_SlctBd); - } - } - else if (plot.Querying && select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { - if (IO.KeyAlt && IO.KeyShift && select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { - DrawList.AddRectFilled(gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_QryBg); - DrawList.AddRect( gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_QryBd); - } - else if (IO.KeyAlt && select_bb.GetHeight() > 2) { - DrawList.AddRectFilled(ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_QryBg); - DrawList.AddRect( ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_QryBd); - } - else if (IO.KeyShift && select_bb.GetWidth() > 2) { - DrawList.AddRectFilled(ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_QryBg); - DrawList.AddRect( ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_QryBd); - } - else if (select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) { - DrawList.AddRectFilled(select_bb.Min, select_bb.Max, gp.Col_QryBg); - DrawList.AddRect( select_bb.Min, select_bb.Max, gp.Col_QryBd); - } - } - } - // render crosshairs if (HasFlag(plot.Flags, ImPlotFlags_Crosshairs) && gp.Hov_Grid && gp.Hov_Frame && !(plot.XAxis.Dragging || plot.YAxis.Dragging) && !plot.Selecting && !plot.Querying && !hov_legend) { @@ -1158,7 +1184,7 @@ void EndPlot() { // FIT DATA -------------------------------------------------------------- - if (gp.FitThisFrame && gp.VisibleItemCount > 0) { + if (gp.FitThisFrame && (gp.VisibleItemCount > 0 || plot.Queried)) { if (!HasFlag(plot.XAxis.Flags, ImAxisFlags_LockMin) && !NanOrInf(gp.Extents.Min.x)) plot.XAxis.Min = gp.Extents.Min.x; if (!HasFlag(plot.XAxis.Flags, ImAxisFlags_LockMax) && !NanOrInf(gp.Extents.Max.x)) @@ -1182,7 +1208,6 @@ void EndPlot() { // Reset legend items gp._LegendIndices.shrink(0); // Null current plot/data - gp.PreviousPlot = gp.CurrentPlot; gp.CurrentPlot = NULL; // Reset next plot data gp.NextPlotData = ImNextPlotData(); @@ -1217,44 +1242,45 @@ void SetNextPlotRangeY(float y_min, float y_max, ImGuiCond cond) { gp.NextPlotData.YMax = y_max; } -bool IsPlotHovered() { return gp.Hov_Grid; } -ImVec2 GetPlotMousePos() { return gp.LastMousePos; } +bool IsPlotHovered() { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotHovered() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.Hov_Grid; +} +ImVec2 GetPlotMousePos() { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotMousePos() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.LastMousePos; +} + ImPlotRange GetPlotRange() { - ImPlot* plt = gp.CurrentPlot ? gp.CurrentPlot : gp.PreviousPlot ? gp.PreviousPlot : NULL; - if (plt == NULL) - return ImPlotRange(); + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotRange() Needs to be called between BeginPlot() and EndPlot()!"); + ImPlot& plot = *gp.CurrentPlot; ImPlotRange range; - range.XMin = plt->XAxis.Min; - range.XMax = plt->XAxis.Max; - range.YMin = plt->YAxis.Min; - range.YMax = plt->YAxis.Max; + range.XMin = plot.XAxis.Min; + range.XMax = plot.XAxis.Max; + range.YMin = plot.YAxis.Min; + range.YMax = plot.YAxis.Max; return range; } bool IsPlotQueried() { - if (gp.CurrentPlot) { - return gp.CurrentPlot->Querying; - } - else if (gp.PreviousPlot) { - return gp.PreviousPlot->Querying; - } - return false; + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotQueried() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.CurrentPlot->Queried; } ImPlotRange GetPlotQuery() { - ImPlot* plt = gp.CurrentPlot ? gp.CurrentPlot : gp.PreviousPlot ? gp.PreviousPlot : NULL; - if (plt == NULL) - return ImPlotRange(); - ImVec2 p1 = gp.FromPixels(plt->SelectStart); - ImVec2 p2 = gp.FromPixels(ImGui::GetIO().MousePos); - - ImPlotRange range; - range.XMin = ImGui::GetIO().KeyAlt ? plt->XAxis.Min : ImMin(p1.x, p2.x); - range.XMax = ImGui::GetIO().KeyAlt ? plt->XAxis.Max : ImMax(p1.x, p2.x); - range.YMin = ImGui::GetIO().KeyShift ? plt->YAxis.Min : ImMin(p1.y, p2.y); - range.YMax = ImGui::GetIO().KeyShift ? plt->YAxis.Max : ImMax(p1.y, p2.y); - return range; + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() Needs to be called between BeginPlot() and EndPlot()!"); + ImPlot& plot = *gp.CurrentPlot; + if (HasFlag(plot.Flags, ImPlotFlags_PixelQuery)) { + gp.UpdateTransforms(); + ImVec2 p1 = gp.FromPixels(plot.QueryRect.Min); + ImVec2 p2 = gp.FromPixels(plot.QueryRect.Max); + plot.QueryRange.XMin = ImMin(p1.x, p2.x); + plot.QueryRange.XMax = ImMax(p1.x, p2.x); + plot.QueryRange.YMin = ImMin(p1.y, p2.y); + plot.QueryRange.YMax = ImMax(p1.y, p2.y); + } + return plot.QueryRange; } //============================================================================= @@ -1872,4 +1898,4 @@ void PlotLabel(const char* text, float x, float y, bool vertical, const ImVec2& PopClipRect(); } -} // namespace ImGui +} // namespace ImGui \ No newline at end of file diff --git a/implot.h b/implot.h index b77ae56..be9c098 100644 --- a/implot.h +++ b/implot.h @@ -41,10 +41,11 @@ enum ImPlotFlags_ { ImPlotFlags_Legend = 1 << 1, // a legend will be displayed in the top-left ImPlotFlags_Highlight = 1 << 2, // plot items will be highlighted when their legend entry is hovered ImPlotFlags_Selection = 1 << 3, // the user will be able to box-select with right-mouse - ImPlotFlags_ContextMenu = 1 << 4, // the user will be able to open a context menu with double-right click - ImPlotFlags_Crosshairs = 1 << 5, // the default mouse cursor will be replaced with a crosshair when hovered - ImPlotFlags_CullData = 1 << 6, // plot data outside the plot area will be culled from rendering - ImPlotFlags_AntiAliased = 1 << 7, // lines and fills will be anti-aliased (not recommended) + ImPlotFlags_PixelQuery = 1 << 4, // query ranges will not change their pixel position if the plot is scrolled/zoomed + ImPlotFlags_ContextMenu = 1 << 5, // the user will be able to open a context menu with double-right click + ImPlotFlags_Crosshairs = 1 << 6, // the default mouse cursor will be replaced with a crosshair when hovered + ImPlotFlags_CullData = 1 << 7, // plot data outside the plot area will be culled from rendering + ImPlotFlags_AntiAliased = 1 << 8, // lines and fills will be anti-aliased (not recommended) ImPlotFlags_Default = ImPlotFlags_MousePos | ImPlotFlags_Legend | ImPlotFlags_Highlight | ImPlotFlags_Selection | ImPlotFlags_ContextMenu | ImPlotFlags_CullData }; @@ -224,4 +225,7 @@ void PopPlotStyleVar(int count = 1); // Shows the ImPlot demo. Add implot_demo.cpp to your sources! void ShowImPlotDemoWindow(bool* p_open = NULL); +// Shows the ImPlot benchmarking test. Add implot_demo.cpp to your sources! +void ShowImPlotBenchmarkWindow(bool * p_open = NULL); + } // namespace ImGui \ No newline at end of file diff --git a/implot_demo.cpp b/implot_demo.cpp index 2716d33..af231ce 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -76,6 +76,7 @@ void ShowImPlotDemoWindow(bool* p_open) { ImGui::Indent(); ImGui::BulletText("Hold Alt to expand box selection horizontally."); ImGui::BulletText("Hold Shift to expand box selection vertically."); + ImGui::BulletText("Left click while box selecting to cancel the selection."); ImGui::Unindent(); ImGui::BulletText("Middle click (or Ctrl + right click) and drag to create a query range."); ImGui::Indent(); @@ -290,7 +291,7 @@ void ShowImPlotDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Log Scale")) { - ImGui::BulletText("Open the plot context menu (double right click) to scales."); + ImGui::BulletText("Open the plot context menu (double right click) to change scales."); static float xs[1001], ys1[1001], ys2[1001], ys3[1001]; for (int i = 0; i < 1001; ++i) { xs[i] = (float)(i*0.1f); @@ -313,6 +314,7 @@ void ShowImPlotDemoWindow(bool* p_open) { ImGui::BulletText("Middle click (or Ctrl + right click) and drag to query points."); ImGui::BulletText("Hold the Alt and/or Shift keys to expand the query range."); static ImVector data; + ImPlotRange range, query; if (ImGui::BeginPlot("##Drawing", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_GridLines, ImAxisFlags_GridLines)) { if (ImGui::IsPlotHovered() && ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyCtrl) data.push_back(ImGui::GetPlotMousePos()); @@ -338,11 +340,52 @@ void ShowImPlotDemoWindow(bool* p_open) { } } ImGui::PopPlotStyleVar(2); + range = ImGui::GetPlotRange(); + query = ImGui::GetPlotQuery(); ImGui::EndPlot(); } - ImPlotRange range = ImGui::GetPlotRange(); - ImGui::Text("The current plot range is: [%g,%g,%g,%g]", range.XMin, range.XMax, range.YMin, range.YMax); + ImGui::Text("The current plot range is: [%g,%g,%g,%g]", range.XMin, range.XMax, range.YMin, range.YMax); + ImGui::Text("The current query range is: [%g,%g,%g,%g]", query.XMin, query.XMax, query.YMin, query.YMax); } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Views")) { + // mimic's soulthread's imgui_plot demo + static float x_data[512]; + static float y_data1[512]; + static float y_data2[512]; + static float y_data3[512]; + static float sampling_freq = 44100; + static float freq = 500; + for (size_t i = 0; i < 512; ++i) { + const float t = i / sampling_freq; + x_data[i] = t; + const float arg = 2 * 3.14 * freq * t; + y_data1[i] = sin(arg); + y_data2[i] = y_data1[i] * -0.6 + sin(2 * arg) * 0.4; + y_data3[i] = y_data2[i] * -0.6 + sin(3 * arg) * 0.4; + } + ImGui::BulletText("Query the first plot to render a subview in the second plot."); + ImGui::BulletText("Toggle \"Pixel Query\" in the context menu and then pan the plot."); + ImGui::SetNextPlotRange(0,0.01f,-1,1); + ImAxisFlags flgs = ImAxisFlags_Default & ~ImAxisFlags_TickLabels; + ImPlotRange query; + if (ImGui::BeginPlot("##View1",NULL,NULL,ImVec2(-1,150), ImPlotFlags_Default, flgs, flgs)) { + ImGui::Plot("Signal 1", x_data, y_data1, 512); + ImGui::Plot("Signal 2", x_data, y_data2, 512); + ImGui::Plot("Signal 3", x_data, y_data3, 512); + query = ImGui::GetPlotQuery(); + ImGui::EndPlot(); + } + ImGui::SetNextPlotRange(query.XMin, query.XMax, query.YMin, query.YMax, ImGuiCond_Always); + if (ImGui::BeginPlot("##View2",NULL,NULL,ImVec2(-1,150), 0, 0, 0)) { + ImGui::Plot("Signal 1", x_data, y_data1, 512); + ImGui::Plot("Signal 2", x_data, y_data2, 512); + ImGui::Plot("Signal 3", x_data, y_data3, 512); + ImGui::EndPlot(); + } + } + + //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Drag and Drop")) {