diff --git a/README.md b/README.md index 0d86569..8e67076 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # ImPlot ImPlot is an immediate mode plotting widget for [Dear ImGui](https://github.com/ocornut/imgui). It aims to provide a first-class API that will make ImGui users feel right at home. ImPlot is well suited for visualizing program data in real-time and requires minimal code to integrate. Just like ImGui, it does not burden the end user with GUI state managment, avoids STL containers and C++ headers, and has no external dependencies except for ImGui itself. - + + + + ## Features @@ -39,10 +42,6 @@ Consult `implot_demo.cpp` for a comprehensive example of ImPlot's features. Just add `implot.h`, `implot.cpp`, and optionally `implot_demo.cpp` to your sources. This assumes you already have an ImGui-ready environment. If not, consider trying [mahi-gui](https://github.com/mahilab/mahi-gui), which bundles ImGui, ImPlot, and several other packages for you. -## Special Notes -- By default, no anti-aliasing is done on line plots for performance reasons. If you use 4x MSAA, then you likely won't even notice. However, you can re-enable AA with the `ImPlotFlags_AntiAliased` flag. -- If you plan to render several thousands lines or points, then you should consider enabling 32-bit indices by uncommenting `#define ImDrawIdx unsigned int` in your `imconfig.h` file, OR handling the `ImGuiBackendFlags_RendererHasVtxOffset` flag in your renderer (the official OpenGL3 renderer supports this). If you fail to do this, then you may at some point hit the maximum number of indices that can be rendered. - ## FAQ **Q: Why?** @@ -81,8 +80,6 @@ A: Not currently. Use your OS's screen capturing mechanisms if you need to captu A: Yes, you can use the C binding, [cimplot](https://github.com/cimgui/cimplot) with most high level languages. -## Gallery - - - - +## Special Notes +- By default, no anti-aliasing is done on line plots for performance reasons. If you use 4x MSAA, then you likely won't even notice. However, you can re-enable AA with the `ImPlotFlags_AntiAliased` flag. +- If you plan to render several thousands lines or points, then you should consider enabling 32-bit indices by uncommenting `#define ImDrawIdx unsigned int` in your `imconfig.h` file, OR handling the `ImGuiBackendFlags_RendererHasVtxOffset` flag in your renderer (the official OpenGL3 renderer supports this). If you fail to do this, then you may at some point hit the maximum number of indices that can be rendered. diff --git a/implot.cpp b/implot.cpp index af24751..9047c0e 100644 --- a/implot.cpp +++ b/implot.cpp @@ -260,6 +260,7 @@ struct ImNextPlotData { struct ImPlotContext { ImPlotContext() { CurrentPlot = NULL; + FitThisFrame = FitX = FitY = false; RestorePlotPalette(); } /// ALl Plots @@ -388,7 +389,7 @@ struct ImPlotContext { // Data extents ImRect Extents; - bool FitThisFrame; + bool FitThisFrame; bool FitX; bool FitY; int VisibleItemCount; // Render flags bool RenderX, RenderY; @@ -864,10 +865,17 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons // DOUBLE CLICK ----------------------------------------------------------- - if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && gp.Hov_Grid && !hov_legend && !hov_query) + + if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && (hov_x_axis_region || hov_y_axis_region) && !hov_legend && !hov_query) { gp.FitThisFrame = true; - else + gp.FitX = hov_x_axis_region; + gp.FitY = hov_y_axis_region; + } + else { gp.FitThisFrame = false; + gp.FitX = false; + gp.FitY = false; + } // FOCUS ------------------------------------------------------------------ @@ -1241,13 +1249,13 @@ void EndPlot() { // FIT DATA -------------------------------------------------------------- if (gp.FitThisFrame && (gp.VisibleItemCount > 0 || plot.Queried)) { - if (!HasFlag(plot.XAxis.Flags, ImAxisFlags_LockMin) && !NanOrInf(gp.Extents.Min.x)) + if (gp.FitX && !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)) + if (gp.FitX && !HasFlag(plot.XAxis.Flags, ImAxisFlags_LockMax) && !NanOrInf(gp.Extents.Max.x)) plot.XAxis.Max = gp.Extents.Max.x; - if (!HasFlag(plot.YAxis.Flags, ImAxisFlags_LockMin) && !NanOrInf(gp.Extents.Min.y)) + if (gp.FitY && !HasFlag(plot.YAxis.Flags, ImAxisFlags_LockMin) && !NanOrInf(gp.Extents.Min.y)) plot.YAxis.Min = gp.Extents.Min.y; - if (!HasFlag(plot.YAxis.Flags, ImAxisFlags_LockMax) && !NanOrInf(gp.Extents.Max.y)) + if (gp.FitY && !HasFlag(plot.YAxis.Flags, ImAxisFlags_LockMax) && !NanOrInf(gp.Extents.Max.y)) plot.YAxis.Max = gp.Extents.Max.y; } diff --git a/implot.h b/implot.h index 444c198..72de746 100644 --- a/implot.h +++ b/implot.h @@ -249,4 +249,4 @@ void PopPlotClipRect(); // Shows the ImPlot demo. Add implot_demo.cpp to your sources! void ShowImPlotDemoWindow(bool* p_open = NULL); -} // namespace ImGui +} // namespace ImGui \ No newline at end of file diff --git a/implot_demo.cpp b/implot_demo.cpp index b0be5ac..78844aa 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -23,11 +23,16 @@ // ImPlot v0.1 WIP #include -#include -#include +#include +#include namespace { +float RandomRange( float min, float max ) { + float scale = rand() / (float) RAND_MAX; + return min + scale * ( max - min ); +} + struct ScrollingData { int MaxSize = 1000; int Offset = 0; @@ -54,18 +59,28 @@ struct RollingData { ImVector Data; RollingData() { Data.reserve(1000); } void AddPoint(float x, float y) { - float xmod = ImFmod(x, Span); + float xmod = fmodf(x, Span); if (!Data.empty() && xmod < Data.back().x) Data.shrink(0); Data.push_back(ImVec2(xmod, y)); } }; -// Put big data here -struct DemoData { - DemoData() { - - } +struct BenchmarkItem { + BenchmarkItem() { + float y = RandomRange(0,1); + Xs = new float[1000]; + Ys = new float[1000]; + for (int i = 0; i < 1000; ++i) { + Xs[i] = i*0.001f; + Ys[i] = y + RandomRange(-0.01f,0.01f); + } + Col = ImVec4(RandomRange(0,1),RandomRange(0,1),RandomRange(0,1),1); + } + ~BenchmarkItem() { delete Xs; delete Ys; } + float* Xs; + float* Ys; + ImVec4 Col; }; } @@ -84,9 +99,13 @@ void ShowImPlotDemoWindow(bool* p_open) { if (ImGui::CollapsingHeader("Help")) { ImGui::Text("USER GUIDE:"); ImGui::BulletText("Left click and drag within the plot area to pan X and Y axes."); - ImGui::BulletText("Left click and drag on an axis to pan an individual axis."); + ImGui::Indent(); + ImGui::BulletText("Left click and drag on an axis to pan an individual axis."); + ImGui::Unindent(); ImGui::BulletText("Scroll in the plot area to zoom both X any Y axes."); - ImGui::BulletText("Scroll on an axis to zoom an individual axis."); + ImGui::Indent(); + ImGui::BulletText("Scroll on an axis to zoom an individual axis."); + ImGui::Unindent(); ImGui::BulletText("Right click and drag to box select data."); ImGui::Indent(); ImGui::BulletText("Hold Alt to expand box selection horizontally."); @@ -99,6 +118,9 @@ void ShowImPlotDemoWindow(bool* p_open) { ImGui::BulletText("Hold Shift to expand query vertically."); ImGui::Unindent(); ImGui::BulletText("Double left click to fit all visible data."); + ImGui::Indent(); + ImGui::BulletText("Double left click on an axis to fit the individual axis."); + ImGui::Unindent(); ImGui::BulletText("Double right click to open the plot context menu."); ImGui::BulletText("Click legend label icons to show/hide plot items."); } @@ -201,6 +223,7 @@ void ShowImPlotDemoWindow(bool* p_open) { //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Realtime Plots")) { ImGui::BulletText("Move your mouse to change the data!"); + ImGui::BulletText("This example assumes 60 FPS. Higher FPS requires larger buffer size."); static bool paused = false; static ScrollingData sdata1, sdata2; static RollingData rdata1, rdata2; @@ -654,9 +677,22 @@ void ShowImPlotDemoWindow(bool* p_open) { } } //------------------------------------------------------------------------- - // if (ImGui::CollapsingHeader("Benchmark")) { - - // } + if (ImGui::CollapsingHeader("Benchmark")) { + static const int n_items = 100; + static BenchmarkItem items[n_items]; + ImGui::BulletText("Make sure VSync is disabled."); + ImGui::BulletText("%d lines with %d points each @ %.3f FPS.",n_items,1000,ImGui::GetIO().Framerate); + if (ImGui::BeginPlot("##Bench",NULL,NULL,{-1,300})) { + char buff[16]; + for (int i = 0; i < 100; ++i) { + sprintf(buff, "item_%d",i); + ImGui::PushPlotColor(ImPlotCol_Line, items[i].Col); + ImGui::Plot(buff, items[i].Xs, items[i].Ys, 1000); + ImGui::PopPlotColor(); + } + ImGui::EndPlot(); + } + } //------------------------------------------------------------------------- ImGui::End();