From bce306bd65a36e213a1471adc247b694b9d28c58 Mon Sep 17 00:00:00 2001 From: ozlb Date: Wed, 29 Apr 2020 16:32:35 +0200 Subject: [PATCH 01/16] PlotDigital --- implot.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++------ implot.h | 17 ++++++---- 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/implot.cpp b/implot.cpp index ffa5208..31092b8 100644 --- a/implot.cpp +++ b/implot.cpp @@ -49,6 +49,7 @@ ImPlotStyle::ImPlotStyle() { MarkerWeight = 1; ErrorBarSize = 5; ErrorBarWeight = 1.5; + DigitalBitHeight = 7; Colors[ImPlotCol_Line] = IM_COL_AUTO; Colors[ImPlotCol_Fill] = IM_COL_AUTO; @@ -397,9 +398,9 @@ struct ImPlotContext { ImPlotStyle Style; ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() - ImNextPlotData NextPlotData; - - + ImNextPlotData NextPlotData; + // Digital plot item count + int DigitalPlotItemCnt; }; /// Global plot context @@ -907,6 +908,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons gp.Extents.Max.y = -INFINITY; // clear item names gp._LegendLabels.Buf.resize(0); + // reset digital plot items count + gp.DigitalPlotItemCnt = 0; return true; } @@ -1296,12 +1299,13 @@ struct ImPlotStyleVarInfo { static const ImPlotStyleVarInfo GPlotStyleVarInfo[] = { - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight - { ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight) } // ImPlotStyleVar_ErrorBarWeight + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight + { ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight + { ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight) } // ImPlotStyleVar_DigitalBitHeight }; static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) @@ -1690,6 +1694,80 @@ void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* dat ImGui::PopClipRect(); } +//////////////////////////////////////////////////////////////// + +void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { + ImPlotGetterData data(xs,ys,stride); + PlotDigital(label_id, &ImPlotGetter2D, (void*)&data, count, offset); +} + +void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset) +{ + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() Needs to be called between BeginPlot() and EndPlot()!"); + + ImPlotItem* item = gp.RegisterItem(label_id); + if (!item->Show) + return; + + ImDrawList & DrawList = *ImGui::GetWindowDrawList(); + + const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; + + ImU32 col_line = gp.Style.Colors[ImPlotCol_Line].w == -1 ? GetColorU32(item->Color) : GetColorU32(gp.Style.Colors[ImPlotCol_Line]); + + if (gp.Style.Colors[ImPlotCol_Line].w != -1) + item->Color = gp.Style.Colors[ImPlotCol_Line]; + + // find data extents + if (gp.FitThisFrame) { + for (int i = 0; i < count; ++i) { + ImVec2 p = getter(data, i); + gp.FitPoint(p); + } + } + + ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); + bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); + + const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; + + // render digital signals as "pixel bases" rectangles + if (count > 1 && rend_line) { + const int segments = count - 1; + int i1 = offset; + for (int s = 0; s < segments; ++s) { + const int i2 = (i1 + 1) % count; + ImVec2 itemData1 = getter(data, i1); + ImVec2 itemData2 = getter(data, i2); + i1 = i2; + const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); + int pixY_0 = line_weight; + int pixY_1 = gp.Style.DigitalBitHeight; + int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label + int pixY_chOffset = pixY_1 + 3; //3 pixels between channels + + float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - ((itemData1.y == 0.0) ? pixY_0 : pixY_1) - pixY_Offset); + float y2 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); + float l = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); + float r = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); + + ImVec2 cl, cr; + cl.x = l; + cl.y = y1; + cr.x = r; + cr.y = y2; + if (!cull || gp.BB_Grid.Contains(cl) || gp.BB_Grid.Contains(cr)) { + DrawList.AddRectFilled({l, y1}, {r, y2}, col_line); + } + } + gp.DigitalPlotItemCnt++; + } + + ImGui::PopClipRect(); +} + +//////////////////////////////////////////////////////////////// + static ImVec2 ImPlotGetterBarV(void* data, int idx) { ImPlotGetterData* data_1d = (ImPlotGetterData*)data; return ImVec2((float)idx + data_1d->XShift, ImStrideIndex(data_1d->Ys, idx, data_1d->Stride)); @@ -1898,4 +1976,4 @@ void PlotLabel(const char* text, float x, float y, bool vertical, const ImVec2& PopClipRect(); } -} // namespace ImGui \ No newline at end of file +} // namespace ImGui diff --git a/implot.h b/implot.h index ec8bcb3..58cf48d 100644 --- a/implot.h +++ b/implot.h @@ -81,12 +81,13 @@ enum ImPlotCol_ { }; enum ImPlotStyleVar_ { - ImPlotStyleVar_LineWeight, // float, line weight in pixels - ImPlotStyleVar_Marker, // int, marker specification - ImPlotStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") - ImPlotStyleVar_MarkerWeight, // float, outline weight of markers in pixels - ImPlotStyleVar_ErrorBarSize, // float, error bar whisker width in pixels - ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels + ImPlotStyleVar_LineWeight, // float, line weight in pixels + ImPlotStyleVar_Marker, // int, marker specification + ImPlotStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") + ImPlotStyleVar_MarkerWeight, // float, outline weight of markers in pixels + ImPlotStyleVar_ErrorBarSize, // float, error bar whisker width in pixels + ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels + ImPlotStyleVar_DigitalBitHeight, // int, digital channels bit height (at 1) ImPlotStyleVar_COUNT }; @@ -120,6 +121,7 @@ struct ImPlotStyle { float MarkerWeight; // = 1, outline weight of markers in pixels float ErrorBarSize; // = 5, error bar whisker width in pixels float ErrorBarWeight; // = 1.5, error bar whisker weight in pixels + int DigitalBitHeight; // = 7, digital channels bit height (at 1) ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors ImPlotStyle(); }; @@ -177,6 +179,9 @@ ImPlotRange GetPlotQuery(); void Plot(const char* label_id, const float* values, int count, int offset = 0, int stride = sizeof(float)); void Plot(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); +// Plots digital channels. +void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float) + sizeof(bool)); +void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); // Plots vertical bars. void PlotBar(const char* label_id, const float* values, int count, float width = 0.67f, float shift = 0, int offset = 0, int stride = sizeof(float)); void PlotBar(const char* label_id, const float* xs, const float* ys, int count, float width, int offset = 0, int stride = sizeof(float)); From 3ba6dfa204b0a3bd01bfa0ddaeac296c55006b36 Mon Sep 17 00:00:00 2001 From: ozlb Date: Wed, 29 Apr 2020 17:00:19 +0200 Subject: [PATCH 02/16] Update implot_demo.cpp --- implot_demo.cpp | 90 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index af231ce..351bd63 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -384,37 +384,58 @@ void ShowImPlotDemoWindow(bool* p_open) { ImGui::EndPlot(); } } - - - + //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Drag and Drop")) { static bool paused = false; static bool init = true; - static ScrollingData data[10]; - static bool show[10]; + #define K_PLOT_ANALOG_CH_COUNT 4 + #define K_PLOT_DIGITAL_CH_COUNT 8 + static ScrollingData dataAnalog[K_PLOT_ANALOG_CH_COUNT]; + static ScrollingData dataDigital[K_PLOT_DIGITAL_CH_COUNT]; + static bool showAnalog[K_PLOT_ANALOG_CH_COUNT]; + static bool showDigital[K_PLOT_DIGITAL_CH_COUNT]; if (init) { - for (int i = 0; i < 10; ++i) { - show[i] = false; - data[i].AddPoint(0, 0.25f + 0.5f * (float)rand() / float(RAND_MAX)); + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + showAnalog[i] = false; + dataAnalog[i].AddPoint(0, 0.25f + 0.5f * (float)rand() / float(RAND_MAX)); + } + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + showDigital[i] = false; + dataDigital[i].AddPoint(0, false); } init = false; } ImGui::BulletText("Drag data items from the left column onto the plot."); + static int bitHeight = 7; + ImGui::SetNextItemWidth(100); + ImGui::DragInt("Customize Bit Hieght", &bitHeight, 0.2, 5, 50); ImGui::BeginGroup(); if (ImGui::Button("Clear", {100, 0})) { - for (int i = 0; i < 10; ++i) - show[i] = false; + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) + showAnalog[i] = false; + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) + showDigital[i] = false; } if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) paused = !paused; ImGui::Separator(); - for (int i = 0; i < 10; ++i) { - char label[8]; - sprintf(label, "data_%d", i); + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + char label[32]; + sprintf(label, "analog_data_%d", i); ImGui::Selectable(label, false, 0, {100, 0}); if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); + ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int)); ImGui::TextUnformatted(label); ImGui::EndDragDropSource(); } @@ -424,29 +445,48 @@ void ShowImPlotDemoWindow(bool* p_open) { static float t = 0; if (!paused) { t += ImGui::GetIO().DeltaTime; - for (int i = 0; i < 10; ++i) { - data[i].AddPoint(t, data[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX))); + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + dataAnalog[i].AddPoint(t, dataAnalog[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX))); } + int i = 0; + dataDigital[i++].AddPoint(t, sin(t) > 0.45); + dataDigital[i++].AddPoint(t, sin(t) < 0.45); + dataDigital[i++].AddPoint(t, sin(t) > 0.83); + dataDigital[i++].AddPoint(t, sin(t) < 0.17); } - ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); + ImGui::SetNextPlotRangeX(t - 10.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always); if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { - for (int i = 0; i < 10; ++i) { - if (show[i]) { - char label[8]; - sprintf(label, "data_%d", i); - ImGui::Plot(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(float)); + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + if (showDigital[i]) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitHeight, bitHeight); + ImGui::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float)); + ImGui::PopPlotStyleVar(); + } + } + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + if (showAnalog[i]) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::Plot(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float)); } } ImGui::EndPlot(); } if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_PLOT")) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT")) { int i = *(int*)payload->Data; - show[i] = true; + showAnalog[i] = true; + } + else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT")) { + int i = *(int*)payload->Data; + showDigital[i] = true; } ImGui::EndDragDropTarget(); } } + //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Custom Styles")) { static ImVec4 my_palette[3] = { @@ -483,4 +523,4 @@ void ShowImPlotDemoWindow(bool* p_open) { } -} // namespace ImGui \ No newline at end of file +} // namespace ImGui From 6e860842e1897991888e4c5c6edb03b150c82cc1 Mon Sep 17 00:00:00 2001 From: ozlb Date: Thu, 30 Apr 2020 15:00:08 +0200 Subject: [PATCH 03/16] Update implot_demo.cpp --- implot_demo.cpp | 1067 ++++++++++++++++++++++++++--------------------- 1 file changed, 596 insertions(+), 471 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index 351bd63..b4a8cd4 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -29,498 +29,623 @@ namespace { struct ScrollingData { - int MaxSize = 1000; - int Offset = 0; - ImVector Data; - ScrollingData() { Data.reserve(MaxSize); } - void AddPoint(float x, float y) { - if (Data.size() < MaxSize) - Data.push_back(ImVec2(x,y)); - else { - Data[Offset] = ImVec2(x,y); - Offset = (Offset + 1) % MaxSize; - } - } + int MaxSize = 1000; + int Offset = 0; + ImVector Data; + ScrollingData() { Data.reserve(MaxSize); } + void AddPoint(float x, float y) { + if (Data.size() < MaxSize) + Data.push_back(ImVec2(x,y)); + else { + Data[Offset] = ImVec2(x,y); + Offset = (Offset + 1) % MaxSize; + } + } + void Erase() { + if (Data.size() > 0) { + Data.clear(); + Offset = 0; + } + } }; struct RollingData { - float Span = 10.0f; - ImVector Data; - RollingData() { Data.reserve(1000); } - void AddPoint(float x, float y) { - float xmod = ImFmod(x, Span); - if (!Data.empty() && xmod < Data.back().x) - Data.shrink(0); - Data.push_back(ImVec2(xmod, y)); - } + float Span = 10.0f; + ImVector Data; + RollingData() { Data.reserve(1000); } + void AddPoint(float x, float y) { + float xmod = ImFmod(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() { + + } }; } namespace ImGui { - + void ShowImPlotDemoWindow(bool* p_open) { - ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos; - ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x + 650, main_viewport_pos.y + 20), ImGuiCond_FirstUseEver); - ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); - ImGui::Begin("ImPlot Demo", p_open); - ImGui::Text("ImPlot says hello. (0.1 WIP)"); - 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::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::BulletText("Right click and drag to box select data."); - 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(); - ImGui::BulletText("Hold Alt to expand query horizontally."); - ImGui::BulletText("Hold Shift to expand query vertically."); - ImGui::Unindent(); - ImGui::BulletText("Double left click to fit all visible data."); - ImGui::BulletText("Double right click to open the plot context menu."); - ImGui::BulletText("Click legend label icons to show/hide plot items."); - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Line Plots")) { - static float xs1[1001], ys1[1001]; - for (int i = 0; i < 1001; ++i) { - xs1[i] = i * 0.001f; - ys1[i] = 0.5f + 0.5f * sin(50 * xs1[i]); - } - static float xs2[11], ys2[11]; - for (int i = 0; i < 11; ++i) { - xs2[i] = i * 0.1f; - ys2[i] = xs2[i] * xs2[i]; - } - if (ImGui::BeginPlot("Line Plot", "x", "f(x)", {-1,300})) { - ImGui::Plot("sin(50*x)", xs1, ys1, 1001); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::Plot("x^2", xs2, ys2, 11); - ImGui::PopPlotStyleVar(); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Scatter Plots")) { - srand(0); - static float xs1[100], ys1[100]; - for (int i = 0; i < 100; ++i) { - xs1[i] = i * 0.01f; - ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); - } - static float xs2[50], ys2[50]; - for (int i = 0; i < 50; i++) { - xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); - ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); - } - if (ImGui::BeginPlot("Scatter Plot", NULL, NULL, {-1,300})) { - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); - ImGui::Plot("Data 1", xs1, ys1, 100); - ImGui::PopPlotStyleVar(2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4{1,0,0,0.25f}); - ImGui::Plot("Data 2", xs2, ys2, 50); - ImGui::PopPlotColor(); - ImGui::PopPlotStyleVar(2); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Bar Plots")) { - static bool horz = false; - ImGui::Checkbox("Horizontal",&horz); - if (horz) - ImGui::SetNextPlotRange(0, 110, -0.5f, 9.5f, ImGuiCond_Always); - else - ImGui::SetNextPlotRange(-0.5f, 9.5f, 0, 110, ImGuiCond_Always); - if (ImGui::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score", {-1, 300})) { - static float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90}; - static float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100}; - static float grade[10] = {80, 69, 52, 92, 72, 78, 75, 76, 89, 95}; - if (horz) { - ImGui::PlotBarH("Midterm Exam", midtm, 10, 0.2f, -0.2f); - ImGui::PlotBarH("Final Exam", final, 10, 0.2f, 0); - ImGui::PlotBarH("Course Grade", grade, 10, 0.2f, 0.2f); - } - else { - ImGui::PlotBar("Midterm Exam", midtm, 10, 0.2f, -0.2f); - ImGui::PlotBar("Final Exam", final, 10, 0.2f, 0); - ImGui::PlotBar("Course Grade", grade, 10, 0.2f, 0.2f); - } - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Error Bars")) { - float xs[5] = {1,2,3,4,5}; - float lin[5] = {8,8,9,7,8}; - float bar[5] = {1,2,5,3,4}; - float err1[5] = {0.2, 0.4, 0.2, 0.6, 0.4}; - float err2[5] = {0.4, 0.2, 0.4, 0.8, 0.6}; - ImGui::SetNextPlotRange(0, 6, 0, 10); - if (ImGui::BeginPlot("##ErrorBars",NULL,NULL,ImVec2(-1,300))) { + static DemoData data; - ImGui::PlotBar("Bar", xs, bar, 5, 0.5f); - ImGui::PlotErrorBars("Bar", xs, bar, err1, 5); + //ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos; + //ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x + 650, main_viewport_pos.y + 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); + ImGui::Begin("ImPlot Demo", p_open); + ImGui::Text("ImPlot says hello. (0.1 WIP)"); + 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::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::BulletText("Right click and drag to box select data."); + 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(); + ImGui::BulletText("Hold Alt to expand query horizontally."); + ImGui::BulletText("Hold Shift to expand query vertically."); + ImGui::Unindent(); + ImGui::BulletText("Double left click to fit all visible data."); + ImGui::BulletText("Double right click to open the plot context menu."); + ImGui::BulletText("Click legend label icons to show/hide plot items."); + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Line Plots")) { + static float xs1[1001], ys1[1001]; + for (int i = 0; i < 1001; ++i) { + xs1[i] = i * 0.001f; + ys1[i] = 0.5f + 0.5f * sin(50 * xs1[i]); + } + static float xs2[11], ys2[11]; + for (int i = 0; i < 11; ++i) { + xs2[i] = i * 0.1f; + ys2[i] = xs2[i] * xs2[i]; + } + if (ImGui::BeginPlot("Line Plot", "x", "f(x)", {-1,300})) { + ImGui::Plot("sin(50*x)", xs1, ys1, 1001); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::Plot("x^2", xs2, ys2, 11); + ImGui::PopPlotStyleVar(); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Scatter Plots")) { + srand(0); + static float xs1[100], ys1[100]; + for (int i = 0; i < 100; ++i) { + xs1[i] = i * 0.01f; + ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); + } + static float xs2[50], ys2[50]; + for (int i = 0; i < 50; i++) { + xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); + ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); + } + if (ImGui::BeginPlot("Scatter Plot", NULL, NULL, {-1,300})) { + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); + ImGui::Plot("Data 1", xs1, ys1, 100); + ImGui::PopPlotStyleVar(2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4{1,0,0,0.25f}); + ImGui::Plot("Data 2", xs2, ys2, 50); + ImGui::PopPlotColor(); + ImGui::PopPlotStyleVar(2); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Bar Plots")) { + static bool horz = false; + ImGui::Checkbox("Horizontal",&horz); + if (horz) + ImGui::SetNextPlotRange(0, 110, -0.5f, 9.5f, ImGuiCond_Always); + else + ImGui::SetNextPlotRange(-0.5f, 9.5f, 0, 110, ImGuiCond_Always); + if (ImGui::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score", {-1, 300})) { + static float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90}; + static float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100}; + static float grade[10] = {80, 69, 52, 92, 72, 78, 75, 76, 89, 95}; + if (horz) { + ImGui::PlotBarH("Midterm Exam", midtm, 10, 0.2f, -0.2f); + ImGui::PlotBarH("Final Exam", final, 10, 0.2f, 0); + ImGui::PlotBarH("Course Grade", grade, 10, 0.2f, 0.2f); + } + else { + ImGui::PlotBar("Midterm Exam", midtm, 10, 0.2f, -0.2f); + ImGui::PlotBar("Final Exam", final, 10, 0.2f, 0); + ImGui::PlotBar("Course Grade", grade, 10, 0.2f, 0.2f); + } + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Error Bars")) { + float xs[5] = {1,2,3,4,5}; + float lin[5] = {8,8,9,7,8}; + float bar[5] = {1,2,5,3,4}; + float err1[5] = {0.2, 0.4, 0.2, 0.6, 0.4}; + float err2[5] = {0.4, 0.2, 0.4, 0.8, 0.6}; + ImGui::SetNextPlotRange(0, 6, 0, 10); + if (ImGui::BeginPlot("##ErrorBars",NULL,NULL,ImVec2(-1,300))) { - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); - ImGui::PushPlotColor(ImPlotCol_ErrorBar, ImVec4(1,0,0,1)); - ImGui::PlotErrorBars("Line", xs, lin, err1, err2, 5); - ImGui::Plot("Line", xs, lin, 5); - ImGui::PopPlotStyleVar(2); - ImGui::PopPlotColor(); + ImGui::PlotBar("Bar", xs, bar, 5, 0.5f); + ImGui::PlotErrorBars("Bar", xs, bar, err1, 5); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Realtime Plots")) { - ImGui::BulletText("Move your mouse to change the data!"); - static bool paused = false; - static ScrollingData sdata1, sdata2; - static RollingData rdata1, rdata2; - ImVec2 mouse = ImGui::GetMousePos(); - static float t = 0; - if (!paused) { - 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); - } - ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); - static int rt_axis = ImAxisFlags_Default & ~ImAxisFlags_TickLabels; - if (ImGui::BeginPlot("##Scrolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { - ImGui::Plot("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), sdata1.Offset, 2 * sizeof(float)); - ImGui::Plot("Data 2", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), sdata2.Offset, 2 * sizeof(float)); - ImGui::EndPlot(); - } - ImGui::SetNextPlotRangeX(0, 10, ImGuiCond_Always); - if (ImGui::BeginPlot("##Rolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { - ImGui::Plot("Data 1", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 2 * sizeof(float)); - ImGui::Plot("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float)); - ImGui::EndPlot(); - } - } + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); + ImGui::PushPlotColor(ImPlotCol_ErrorBar, ImVec4(1,0,0,1)); + ImGui::PlotErrorBars("Line", xs, lin, err1, err2, 5); + ImGui::Plot("Line", xs, lin, 5); + ImGui::PopPlotStyleVar(2); + ImGui::PopPlotColor(); - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Markers and Labels")) { - ImGui::SetNextPlotRange(0, 10, 0, 12); - if (ImGui::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,300), 0, 0, 0)) { - float xs[2] = {1,4}; - float ys[2] = {10,11}; - // filled - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::Plot("Circle##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; - ImGui::Plot("Square##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; - ImGui::Plot("Diamond##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; - ImGui::Plot("Up##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; - ImGui::Plot("Down##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; - ImGui::Plot("Left##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; - ImGui::Plot("Right##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; - ImGui::Plot("Cross##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; - ImGui::Plot("Plus##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; - ImGui::Plot("Asterisk##Fill", xs, ys, 2); - ImGui::PopPlotStyleVar(10); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Realtime Plots")) { + ImGui::BulletText("Move your mouse to change the data!"); + static bool paused = false; + static ScrollingData sdata1, sdata2; + static RollingData rdata1, rdata2; + ImVec2 mouse = ImGui::GetMousePos(); + static float t = 0; + if (!paused) { + 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); + } + ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); + static int rt_axis = ImAxisFlags_Default & ~ImAxisFlags_TickLabels; + if (ImGui::BeginPlot("##Scrolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { + ImGui::Plot("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), sdata1.Offset, 2 * sizeof(float)); + ImGui::Plot("Data 2", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), sdata2.Offset, 2 * sizeof(float)); + ImGui::EndPlot(); + } + ImGui::SetNextPlotRangeX(0, 10, ImGuiCond_Always); + if (ImGui::BeginPlot("##Rolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { + ImGui::Plot("Data 1", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 2 * sizeof(float)); + ImGui::Plot("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float)); + ImGui::EndPlot(); + } + } - xs[0] = 6; xs[1] = 9; - ys[0] = 10; ys[1] = 11; - ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(0,0,0,0)); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::Plot("Circle", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; - ImGui::Plot("Square", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; - ImGui::Plot("Diamond", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; - ImGui::Plot("Up", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; - ImGui::Plot("Down", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; - ImGui::Plot("Left", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; - ImGui::Plot("Right", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; - ImGui::Plot("Cross", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; - ImGui::Plot("Plus", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; - ImGui::Plot("Asterisk", xs, ys, 2); - ImGui::PopPlotColor(); - ImGui::PopPlotStyleVar(10); + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Markers and Labels")) { + ImGui::SetNextPlotRange(0, 10, 0, 12); + if (ImGui::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,300), 0, 0, 0)) { + float xs[2] = {1,4}; + float ys[2] = {10,11}; + // filled + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::Plot("Circle##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; + ImGui::Plot("Square##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; + ImGui::Plot("Diamond##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; + ImGui::Plot("Up##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; + ImGui::Plot("Down##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; + ImGui::Plot("Left##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; + ImGui::Plot("Right##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; + ImGui::Plot("Cross##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; + ImGui::Plot("Plus##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; + ImGui::Plot("Asterisk##Fill", xs, ys, 2); + ImGui::PopPlotStyleVar(10); - xs[0] = 5; xs[1] = 5; - ys[0] = 1; ys[1] = 11; + xs[0] = 6; xs[1] = 9; + ys[0] = 10; ys[1] = 11; + ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(0,0,0,0)); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::Plot("Circle", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; + ImGui::Plot("Square", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; + ImGui::Plot("Diamond", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; + ImGui::Plot("Up", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; + ImGui::Plot("Down", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; + ImGui::Plot("Left", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; + ImGui::Plot("Right", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; + ImGui::Plot("Cross", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; + ImGui::Plot("Plus", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; + ImGui::Plot("Asterisk", xs, ys, 2); + ImGui::PopPlotColor(); + ImGui::PopPlotStyleVar(10); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 8); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerWeight, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle | ImMarker_Cross); - ImGui::PushPlotColor(ImPlotCol_MarkerOutline, ImVec4(0,0,0,1)); - ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(1,1,1,1)); - ImGui::PushPlotColor(ImPlotCol_Line, ImVec4(0,0,0,1)); - ImGui::Plot("Circle|Cross", xs, ys, 2); - ImGui::PopPlotStyleVar(4); - ImGui::PopPlotColor(3); + xs[0] = 5; xs[1] = 5; + ys[0] = 1; ys[1] = 11; - ImGui::PlotLabel("Filled Markers", 1.5, 11.75); - ImGui::PlotLabel("Open Markers", 6.75, 11.75); - ImGui::PlotLabel("Fancy Markers", 4.5, 4.25, true); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 8); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerWeight, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle | ImMarker_Cross); + ImGui::PushPlotColor(ImPlotCol_MarkerOutline, ImVec4(0,0,0,1)); + ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(1,1,1,1)); + ImGui::PushPlotColor(ImPlotCol_Line, ImVec4(0,0,0,1)); + ImGui::Plot("Circle|Cross", xs, ys, 2); + ImGui::PopPlotStyleVar(4); + ImGui::PopPlotColor(3); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Log Scale")) { - 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); - ys1[i] = sin(xs[i]) + 1; - ys2[i] = log(xs[i]); - ys3[i] = pow(10.0f, xs[i]); - } - ImGui::SetNextPlotRange(0.1f, 100, 0, 10); - if (ImGui::BeginPlot("Log Plot", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_Default | ImAxisFlags_LogScale )) { - ImGui::Plot("f(x) = x", xs, xs, 1001); - ImGui::Plot("f(x) = sin(x)+1", xs, ys1, 1001); - ImGui::Plot("f(x) = log(x)", xs, ys2, 1001); - ImGui::Plot("f(x) = 10^x", xs, ys3, 21); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Querying")) { - ImGui::BulletText("Ctrl + click in the plot area to draw points."); - 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()); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); - if (data.size() > 0) - ImGui::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float)); - if (ImGui::IsPlotQueried() && data.size() > 0) { - ImPlotRange range = ImGui::GetPlotQuery(); - int cnt = 0; - ImVec2 avg; - for (int i = 0; i < data.size(); ++i) { - if (range.Contains(data[i])) { - avg.x += data[i].x; - avg.y += data[i].y; - cnt++; - } - } - if (cnt > 0) { - avg.x = avg.x / cnt; - avg.y = avg.y / cnt; - ImGui::Plot("Average", &avg.x, &avg.y, 1); - } - } - ImGui::PopPlotStyleVar(2); - range = ImGui::GetPlotRange(); - query = ImGui::GetPlotQuery(); - ImGui::EndPlot(); - } - 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")) { - static bool paused = false; - static bool init = true; - #define K_PLOT_ANALOG_CH_COUNT 4 - #define K_PLOT_DIGITAL_CH_COUNT 8 - static ScrollingData dataAnalog[K_PLOT_ANALOG_CH_COUNT]; - static ScrollingData dataDigital[K_PLOT_DIGITAL_CH_COUNT]; - static bool showAnalog[K_PLOT_ANALOG_CH_COUNT]; - static bool showDigital[K_PLOT_DIGITAL_CH_COUNT]; - if (init) { - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - showAnalog[i] = false; - dataAnalog[i].AddPoint(0, 0.25f + 0.5f * (float)rand() / float(RAND_MAX)); - } - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { - showDigital[i] = false; - dataDigital[i].AddPoint(0, false); - } - init = false; - } - ImGui::BulletText("Drag data items from the left column onto the plot."); - static int bitHeight = 7; - ImGui::SetNextItemWidth(100); - ImGui::DragInt("Customize Bit Hieght", &bitHeight, 0.2, 5, 50); - ImGui::BeginGroup(); - if (ImGui::Button("Clear", {100, 0})) { - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) - showAnalog[i] = false; - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) - showDigital[i] = false; - } - if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) - paused = !paused; - ImGui::Separator(); - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - char label[32]; - sprintf(label, "analog_data_%d", i); - ImGui::Selectable(label, false, 0, {100, 0}); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int)); - ImGui::TextUnformatted(label); - ImGui::EndDragDropSource(); - } - } - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { - char label[32]; - sprintf(label, "digital_data_%d", i); - ImGui::Selectable(label, false, 0, {100, 0}); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int)); - ImGui::TextUnformatted(label); - ImGui::EndDragDropSource(); - } - } - ImGui::EndGroup(); - ImGui::SameLine(); - static float t = 0; - if (!paused) { - t += ImGui::GetIO().DeltaTime; - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - dataAnalog[i].AddPoint(t, dataAnalog[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX))); - } - int i = 0; - dataDigital[i++].AddPoint(t, sin(t) > 0.45); - dataDigital[i++].AddPoint(t, sin(t) < 0.45); - dataDigital[i++].AddPoint(t, sin(t) > 0.83); - dataDigital[i++].AddPoint(t, sin(t) < 0.17); - } + ImGui::PlotLabel("Filled Markers", 1.5, 11.75); + ImGui::PlotLabel("Open Markers", 6.75, 11.75); + ImGui::PlotLabel("Fancy Markers", 4.5, 4.25, true); + + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Log Scale")) { + 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); + ys1[i] = sin(xs[i]) + 1; + ys2[i] = log(xs[i]); + ys3[i] = pow(10.0f, xs[i]); + } + ImGui::SetNextPlotRange(0.1f, 100, 0, 10); + if (ImGui::BeginPlot("Log Plot", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_Default | ImAxisFlags_LogScale )) { + ImGui::Plot("f(x) = x", xs, xs, 1001); + ImGui::Plot("f(x) = sin(x)+1", xs, ys1, 1001); + ImGui::Plot("f(x) = log(x)", xs, ys2, 1001); + ImGui::Plot("f(x) = 10^x", xs, ys3, 21); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Querying")) { + ImGui::BulletText("Ctrl + click in the plot area to draw points."); + 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()); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); + if (data.size() > 0) + ImGui::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float)); + if (ImGui::IsPlotQueried() && data.size() > 0) { + ImPlotRange range = ImGui::GetPlotQuery(); + int cnt = 0; + ImVec2 avg; + for (int i = 0; i < data.size(); ++i) { + if (range.Contains(data[i])) { + avg.x += data[i].x; + avg.y += data[i].y; + cnt++; + } + } + if (cnt > 0) { + avg.x = avg.x / cnt; + avg.y = avg.y / cnt; + ImGui::Plot("Average", &avg.x, &avg.y, 1); + } + } + ImGui::PopPlotStyleVar(2); + range = ImGui::GetPlotRange(); + query = ImGui::GetPlotQuery(); + ImGui::EndPlot(); + } + 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")) { + srand(10000000 * ImGui::GetTime()); + static bool paused = false; + static bool init = true; + static ScrollingData data[10]; + static bool show[10]; + if (init) { + for (int i = 0; i < 10; ++i) { + show[i] = false; + } + init = false; + } + ImGui::BulletText("Drag data items from the left column onto the plot."); + ImGui::BeginGroup(); + if (ImGui::Button("Clear", {100, 0})) { + for (int i = 0; i < 10; ++i) { + show[i] = false; + data[i].Data.shrink(0); + data[i].Offset = 0; + } + } + if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) + paused = !paused; + ImGui::Separator(); + for (int i = 0; i < 10; ++i) { + char label[8]; + sprintf(label, "data_%d", i); + ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + ImGui::EndGroup(); + ImGui::SameLine(); + static float t = 0; + if (!paused) { + t += ImGui::GetIO().DeltaTime; + for (int i = 0; i < 10; ++i) { + if (show[i]) + data[i].AddPoint(t, data[i].Data.empty() ? + 0.25f + 0.5f * (float)rand() / float(RAND_MAX) : + data[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX))); + } + } + ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); + if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { + for (int i = 0; i < 10; ++i) { + if (show[i]) { + char label[8]; + sprintf(label, "data_%d", i); + ImGui::Plot(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(float)); + } + } + ImGui::EndPlot(); + } + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_PLOT")) { + int i = *(int*)payload->Data; + show[i] = true; + } + ImGui::EndDragDropTarget(); + } + } + + if (ImGui::CollapsingHeader("Digital")) { + + static int bitHeight = 7; + ImGui::SetNextItemWidth(100); + ImGui::DragInt("Bit Hieght", &bitHeight, 0.2, 5, 50); + /// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. + //void SetNextPlotRangeX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once); + static bool paused = false; + #define K_PLOT_DIGITAL_CH_COUNT 8 + #define K_PLOT_ANALOG_CH_COUNT 4 + static ScrollingData dataDigital[K_PLOT_DIGITAL_CH_COUNT]; + static ScrollingData dataAnalog[K_PLOT_ANALOG_CH_COUNT]; + static bool showDigital[K_PLOT_DIGITAL_CH_COUNT]; + static bool showAnalog[K_PLOT_ANALOG_CH_COUNT]; + + ImGui::BulletText("Drag data items from the left column onto the plot."); + ImGui::BeginGroup(); + if (ImGui::Button("Clear", {100, 0})) { + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) + showDigital[i] = false; + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) + showAnalog[i] = false; + } + if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) + paused = !paused; + ImGui::Separator(); + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::Checkbox(label, &showDigital[i]); + //ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + char label[32]; + sprintf(label, "analog_data_%d", i); + ImGui::Checkbox(label, &showAnalog[i]); + //ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + ImGui::EndGroup(); + ImGui::SameLine(); + static float t = 0; + if (true) { + t += ImGui::GetIO().DeltaTime; + + //purge inactive signals + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + if (!showDigital[i]) + dataDigital[i].Erase(); + } + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + if (!showAnalog[i]) + dataAnalog[i].Erase(); + } + + //digital signal values + int i = 0; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) > 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) < 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) > 0.83); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) < 0.17); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) > 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) < 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) > 0.83); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) < 0.17); + + //Analog signal values + i = 0; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, cos(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t) * cos(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t) - cos(t)); + i++; + + } ImGui::SetNextPlotRangeX(t - 10.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always); - if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { - if (showDigital[i]) { - char label[32]; - sprintf(label, "digital_data_%d", i); - ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitHeight, bitHeight); - ImGui::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float)); - ImGui::PopPlotStyleVar(); - } - } - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - if (showAnalog[i]) { - char label[32]; - sprintf(label, "digital_data_%d", i); - ImGui::Plot(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float)); - } - } - ImGui::EndPlot(); - } - if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT")) { - int i = *(int*)payload->Data; - showAnalog[i] = true; - } - else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT")) { - int i = *(int*)payload->Data; - showDigital[i] = true; - } - ImGui::EndDragDropTarget(); - } - } + if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + if (showDigital[i]) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitHeight, bitHeight); + ImGui::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float)); + ImGui::PopPlotStyleVar(); + } + } + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + if (showAnalog[i]) { + char label[32]; + sprintf(label, "analog_data_%d", i); + if (dataAnalog[i].Data.size() > 0) + ImGui::Plot(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float)); + } + } + ImGui::EndPlot(); + } + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT")) { + int i = *(int*)payload->Data; + showDigital[i] = true; + } + else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT")) { + int i = *(int*)payload->Data; + showAnalog[i] = true; + } + ImGui::EndDragDropTarget(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Custom Styles")) { + static ImVec4 my_palette[3] = { + {0.000f, 0.980f, 0.604f, 1.0f}, + {0.996f, 0.278f, 0.380f, 1.0f}, + {(0.1176470593F), (0.5647059083F), (1.0F), (1.0F)}, + }; + ImGui::SetPlotPalette(my_palette, 3); + ImGui::PushPlotColor(ImPlotCol_FrameBg, IM_COL32(32,51,77,255)); + ImGui::PushPlotColor(ImPlotCol_PlotBg, {0,0,0,0}); + ImGui::PushPlotColor(ImPlotCol_PlotBorder, {0,0,0,0}); + ImGui::PushPlotColor(ImPlotCol_XAxis, IM_COL32(192, 192, 192, 192)); + ImGui::PushPlotColor(ImPlotCol_YAxis, IM_COL32(192, 192, 192, 192)); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); + ImGui::SetNextPlotRange(-0.5f, 9.5f, -0.5f, 9.5f); + if (ImGui::BeginPlot("##Custom", NULL, NULL, {-1,300}, ImPlotFlags_Default & ~ImPlotFlags_Legend, 0)) { + float lin[10] = {8,8,9,7,8,8,8,9,7,8}; + float bar[10] = {1,2,5,3,4,1,2,5,3,4}; + float dot[10] = {7,6,6,7,8,5,6,5,8,7}; + ImGui::PlotBar("Bar", bar, 10, 0.5f); + ImGui::Plot("Line", lin, 10); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); + ImGui::Plot("Dot", dot, 10); + ImGui::PopPlotStyleVar(2); + ImGui::EndPlot(); + } + ImGui::PopPlotColor(5); + ImGui::PopPlotStyleVar(); + ImGui::RestorePlotPalette(); + } + //------------------------------------------------------------------------- + // if (ImGui::CollapsingHeader("Benchmark")) { + + // } + //------------------------------------------------------------------------- + ImGui::End(); - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Custom Styles")) { - static ImVec4 my_palette[3] = { - {0.000f, 0.980f, 0.604f, 1.0f}, - {0.996f, 0.278f, 0.380f, 1.0f}, - {(0.1176470593F), (0.5647059083F), (1.0F), (1.0F)}, - }; - ImGui::SetPlotPalette(my_palette, 3); - ImGui::PushPlotColor(ImPlotCol_FrameBg, IM_COL32(32,51,77,255)); - ImGui::PushPlotColor(ImPlotCol_PlotBg, {0,0,0,0}); - ImGui::PushPlotColor(ImPlotCol_PlotBorder, {0,0,0,0}); - ImGui::PushPlotColor(ImPlotCol_XAxis, IM_COL32(192, 192, 192, 192)); - ImGui::PushPlotColor(ImPlotCol_YAxis, IM_COL32(192, 192, 192, 192)); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); - ImGui::SetNextPlotRange(-0.5f, 9.5f, -0.5f, 9.5f); - if (ImGui::BeginPlot("##Custom", NULL, NULL, {-1,300}, ImPlotFlags_Default & ~ImPlotFlags_Legend, 0)) { - float lin[10] = {8,8,9,7,8,8,8,9,7,8}; - float bar[10] = {1,2,5,3,4,1,2,5,3,4}; - float dot[10] = {7,6,6,7,8,5,6,5,8,7}; - ImGui::PlotBar("Bar", bar, 10, 0.5f); - ImGui::Plot("Line", lin, 10); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); - ImGui::Plot("Dot", dot, 10); - ImGui::PopPlotStyleVar(2); - ImGui::EndPlot(); - } - ImGui::PopPlotColor(5); - ImGui::PopPlotStyleVar(); - ImGui::RestorePlotPalette(); - } - //------------------------------------------------------------------------- - ImGui::End(); - } } // namespace ImGui From a13de8ec9846f6416a01cb73cc653617b5c0ec4d Mon Sep 17 00:00:00 2001 From: ozlb Date: Thu, 30 Apr 2020 15:01:28 +0200 Subject: [PATCH 04/16] Update implot.cpp --- implot.cpp | 105 ++++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/implot.cpp b/implot.cpp index 31092b8..2710f7d 100644 --- a/implot.cpp +++ b/implot.cpp @@ -1701,69 +1701,68 @@ void PlotDigital(const char* label_id, const float* xs, const float* ys, int cou PlotDigital(label_id, &ImPlotGetter2D, (void*)&data, count, offset); } -void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset) -{ - IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() Needs to be called between BeginPlot() and EndPlot()!"); +void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset) { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() Needs to be called between BeginPlot() and EndPlot()!"); - ImPlotItem* item = gp.RegisterItem(label_id); - if (!item->Show) - return; + ImPlotItem* item = gp.RegisterItem(label_id); + if (!item->Show) + return; - ImDrawList & DrawList = *ImGui::GetWindowDrawList(); + ImDrawList & DrawList = *ImGui::GetWindowDrawList(); - const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; + const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; - ImU32 col_line = gp.Style.Colors[ImPlotCol_Line].w == -1 ? GetColorU32(item->Color) : GetColorU32(gp.Style.Colors[ImPlotCol_Line]); + if (gp.Style.Colors[ImPlotCol_Line].w != -1) + item->Color = gp.Style.Colors[ImPlotCol_Line]; - if (gp.Style.Colors[ImPlotCol_Line].w != -1) - item->Color = gp.Style.Colors[ImPlotCol_Line]; + // find data extents + if (gp.FitThisFrame) { + for (int i = 0; i < count; ++i) { + ImVec2 p = getter(data, i); + gp.FitPoint(p); + } + } - // find data extents - if (gp.FitThisFrame) { - for (int i = 0; i < count; ++i) { - ImVec2 p = getter(data, i); - gp.FitPoint(p); - } - } + ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); + bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); - ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); - bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); + const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; - const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; + // render digital signals as "pixel bases" rectangles + if (count > 1 && rend_line) { + const int segments = count - 1; + int i1 = offset; + for (int s = 0; s < segments; ++s) { + const int i2 = (i1 + 1) % count; + ImVec2 itemData1 = getter(data, i1); + ImVec2 itemData2 = getter(data, i2); + i1 = i2; + const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); + int pixY_0 = line_weight; + int pixY_1 = gp.Style.DigitalBitHeight; + int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label + int pixY_chOffset = pixY_1 + 3; //3 pixels between channels - // render digital signals as "pixel bases" rectangles - if (count > 1 && rend_line) { - const int segments = count - 1; - int i1 = offset; - for (int s = 0; s < segments; ++s) { - const int i2 = (i1 + 1) % count; - ImVec2 itemData1 = getter(data, i1); - ImVec2 itemData2 = getter(data, i2); - i1 = i2; - const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); - int pixY_0 = line_weight; - int pixY_1 = gp.Style.DigitalBitHeight; - int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label - int pixY_chOffset = pixY_1 + 3; //3 pixels between channels + float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - ((itemData1.y == 0.0) ? pixY_0 : pixY_1) - pixY_Offset); + float y2 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); + float l = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); + float r = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); + + ImVec2 cl, cr; + cl.x = l; + cl.y = y1; + cr.x = r; + cr.y = y2; + if (!cull || gp.BB_Grid.Contains(cl) || gp.BB_Grid.Contains(cr)) { + auto colAlpha = item->Color; + colAlpha.w = item->Highlight ? 1.0 : 0.9; + DrawList.AddRectFilled({l, y1}, {r, y2}, GetColorU32(colAlpha)); + } + } + gp.DigitalPlotItemCnt++; + } - float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - ((itemData1.y == 0.0) ? pixY_0 : pixY_1) - pixY_Offset); - float y2 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); - float l = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); - float r = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); - - ImVec2 cl, cr; - cl.x = l; - cl.y = y1; - cr.x = r; - cr.y = y2; - if (!cull || gp.BB_Grid.Contains(cl) || gp.BB_Grid.Contains(cr)) { - DrawList.AddRectFilled({l, y1}, {r, y2}, col_line); - } - } - gp.DigitalPlotItemCnt++; - } - - ImGui::PopClipRect(); + ImGui::PopClipRect(); } //////////////////////////////////////////////////////////////// From f8db7405da8d6b1a5fb180f9449956b3732a624d Mon Sep 17 00:00:00 2001 From: ozlb Date: Thu, 30 Apr 2020 15:45:03 +0200 Subject: [PATCH 05/16] resolved conflicts with latest version --- implot.cpp | 211 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 146 insertions(+), 65 deletions(-) diff --git a/implot.cpp b/implot.cpp index 2710f7d..af24751 100644 --- a/implot.cpp +++ b/implot.cpp @@ -222,7 +222,7 @@ struct ImPlotAxis { /// Holds Plot state information that must persist between frames struct ImPlot { ImPlot() { - Selecting = Querying = Queried = false; + Selecting = Querying = Queried = DraggingQuery = false; SelectStart = QueryStart = ImVec2(0,0); Flags = ImPlotFlags_Default; ColorIdx = 0; @@ -235,7 +235,8 @@ struct ImPlot { bool Querying; bool Queried; ImVec2 QueryStart; - ImRect QueryRect; + ImRect QueryRect; // relative to BB_grid!! + bool DraggingQuery; ImPlotRange QueryRange; ImPlotAxis XAxis; ImPlotAxis YAxis; @@ -656,7 +657,57 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons const bool hov_y_axis_region = yAxisRegion_bb.Contains(IO.MousePos); // legend hovered from last frame - const bool hov_legend = HasFlag(plot.Flags, ImPlotFlags_Legend) ? gp.Hov_Frame && plot.BB_Legend.Contains(IO.MousePos) : false; + const bool hov_legend = HasFlag(plot.Flags, ImPlotFlags_Legend) ? gp.Hov_Frame && plot.BB_Legend.Contains(IO.MousePos) : false; + + bool hov_query = false; + if (plot.Queried && !plot.Querying) { + ImRect bb_query; + if (HasFlag(plot.Flags, ImPlotFlags_PixelQuery)) { + bb_query = plot.QueryRect; + bb_query.Min += gp.BB_Grid.Min; + bb_query.Max += gp.BB_Grid.Min; + } + else { + gp.UpdateTransforms(); + ImVec2 p1 = gp.ToPixels(plot.QueryRange.XMin, plot.QueryRange.YMin); + ImVec2 p2 = gp.ToPixels(plot.QueryRange.XMax, plot.QueryRange.YMax); + bb_query.Min = ImVec2(ImMin(p1.x,p2.x), ImMin(p1.y,p2.y)); + bb_query.Max = ImVec2(ImMax(p1.x,p2.x), ImMax(p1.y,p2.y)); + } + hov_query = bb_query.Contains(IO.MousePos); + } + + // QUERY DRAG ------------------------------------------------------------- + if (plot.DraggingQuery && (IO.MouseReleased[0] || !IO.MouseDown[0])) { + plot.DraggingQuery = false; + } + if (plot.DraggingQuery) { + SetMouseCursor(ImGuiMouseCursor_ResizeAll); + if (!HasFlag(plot.Flags, ImPlotFlags_PixelQuery)) { + ImVec2 p1 = gp.ToPixels(plot.QueryRange.XMin, plot.QueryRange.YMin); + ImVec2 p2 = gp.ToPixels(plot.QueryRange.XMax, plot.QueryRange.YMax); + plot.QueryRect.Min = ImVec2(ImMin(p1.x,p2.x), ImMin(p1.y,p2.y)) + IO.MouseDelta; + plot.QueryRect.Max = ImVec2(ImMax(p1.x,p2.x), ImMax(p1.y,p2.y)) + IO.MouseDelta; + p1 = gp.FromPixels(plot.QueryRect.Min); + p2 = gp.FromPixels(plot.QueryRect.Max); + plot.QueryRect.Min -= gp.BB_Grid.Min; + plot.QueryRect.Max -= gp.BB_Grid.Min; + 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); + } + else { + plot.QueryRect.Min += IO.MouseDelta; + plot.QueryRect.Max += IO.MouseDelta; + } + } + if (gp.Hov_Frame && hov_query && !plot.DraggingQuery && !plot.Selecting && !hov_legend) { + SetMouseCursor(ImGuiMouseCursor_ResizeAll); + if (IO.MouseDown[0] && !plot.XAxis.Dragging && !plot.YAxis.Dragging) { + plot.DraggingQuery = true; + } + } // DRAG INPUT ------------------------------------------------------------- @@ -696,9 +747,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); } // start drag - if (gp.Hov_Frame && hov_x_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend) + if (gp.Hov_Frame && hov_x_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) plot.XAxis.Dragging = true; - if (gp.Hov_Frame && hov_y_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend) + if (gp.Hov_Frame && hov_y_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) plot.YAxis.Dragging = true; // SCROLL INPUT ----------------------------------------------------------- @@ -762,12 +813,14 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons // 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.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.QueryRect.Min -= gp.BB_Grid.Min; + plot.QueryRect.Max -= gp.BB_Grid.Min; plot.QueryRange.XMin = ImMin(p1.x, p2.x); plot.QueryRange.XMax = ImMax(p1.x, p2.x); plot.QueryRange.YMin = ImMin(p1.y, p2.y); @@ -811,7 +864,7 @@ 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) + if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && gp.Hov_Grid && !hov_legend && !hov_query) gp.FitThisFrame = true; else gp.FitThisFrame = false; @@ -1081,8 +1134,8 @@ void EndPlot() { 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); + DrawList.AddRectFilled(plot.QueryRect.Min + gp.BB_Grid.Min, plot.QueryRect.Max + gp.BB_Grid.Min, gp.Col_QryBg); + DrawList.AddRect( plot.QueryRect.Min + gp.BB_Grid.Min, plot.QueryRect.Max + gp.BB_Grid.Min, gp.Col_QryBd); } } else if (plot.Queried) { @@ -1245,6 +1298,35 @@ void SetNextPlotRangeY(float y_min, float y_max, ImGuiCond cond) { gp.NextPlotData.YMax = y_max; } +ImVec2 GetPlotPos() { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotPos() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.BB_Grid.Min; +} + +ImVec2 GetPlotSize() { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotSize() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.BB_Grid.GetSize(); +} + +ImVec2 PixelsToPlot(const ImVec2& pix) { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PixelsToPlot() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.FromPixels(pix); +} + +ImVec2 PlotToPixels(const ImVec2& plt) { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() Needs to be called between BeginPlot() and EndPlot()!"); + return gp.ToPixels(plt); +} + +void PushPlotClipRect() { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PushPlotClipRect() Needs to be called between BeginPlot() and EndPlot()!"); + PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); +} + +void PopPlotClipRect() { + PopClipRect(); +} + bool IsPlotHovered() { IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotHovered() Needs to be called between BeginPlot() and EndPlot()!"); return gp.Hov_Grid; @@ -1276,8 +1358,8 @@ ImPlotRange GetPlotQuery() { 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); + ImVec2 p1 = gp.FromPixels(plot.QueryRect.Min + gp.BB_Grid.Min); + ImVec2 p2 = gp.FromPixels(plot.QueryRect.Max + gp.BB_Grid.Min); plot.QueryRange.XMin = ImMin(p1.x, p2.x); plot.QueryRange.XMax = ImMax(p1.x, p2.x); plot.QueryRange.YMin = ImMin(p1.y, p2.y); @@ -1558,8 +1640,7 @@ void Plot(const char* label_id, const float* xs, const float* ys, int count, int Plot(label_id, &ImPlotGetter2D, (void*)&data, count, offset); } -void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset) -{ +void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset) { IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Plot() Needs to be called between BeginPlot() and EndPlot()!"); ImPlotItem* item = gp.RegisterItem(label_id); @@ -1702,67 +1783,67 @@ void PlotDigital(const char* label_id, const float* xs, const float* ys, int cou } void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset) { - IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() Needs to be called between BeginPlot() and EndPlot()!"); + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() Needs to be called between BeginPlot() and EndPlot()!"); - ImPlotItem* item = gp.RegisterItem(label_id); - if (!item->Show) - return; + ImPlotItem* item = gp.RegisterItem(label_id); + if (!item->Show) + return; - ImDrawList & DrawList = *ImGui::GetWindowDrawList(); + ImDrawList & DrawList = *ImGui::GetWindowDrawList(); - const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; + const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; - if (gp.Style.Colors[ImPlotCol_Line].w != -1) - item->Color = gp.Style.Colors[ImPlotCol_Line]; + if (gp.Style.Colors[ImPlotCol_Line].w != -1) + item->Color = gp.Style.Colors[ImPlotCol_Line]; - // find data extents - if (gp.FitThisFrame) { - for (int i = 0; i < count; ++i) { - ImVec2 p = getter(data, i); - gp.FitPoint(p); - } - } + // find data extents + if (gp.FitThisFrame) { + for (int i = 0; i < count; ++i) { + ImVec2 p = getter(data, i); + gp.FitPoint(p); + } + } - ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); - bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); + ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); + bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); - const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; + const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; - // render digital signals as "pixel bases" rectangles - if (count > 1 && rend_line) { - const int segments = count - 1; - int i1 = offset; - for (int s = 0; s < segments; ++s) { - const int i2 = (i1 + 1) % count; - ImVec2 itemData1 = getter(data, i1); - ImVec2 itemData2 = getter(data, i2); - i1 = i2; - const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); - int pixY_0 = line_weight; - int pixY_1 = gp.Style.DigitalBitHeight; - int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label - int pixY_chOffset = pixY_1 + 3; //3 pixels between channels + // render digital signals as "pixel bases" rectangles + if (count > 1 && rend_line) { + const int segments = count - 1; + int i1 = offset; + for (int s = 0; s < segments; ++s) { + const int i2 = (i1 + 1) % count; + ImVec2 itemData1 = getter(data, i1); + ImVec2 itemData2 = getter(data, i2); + i1 = i2; + const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); + int pixY_0 = line_weight; + int pixY_1 = gp.Style.DigitalBitHeight; + int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label + int pixY_chOffset = pixY_1 + 3; //3 pixels between channels - float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - ((itemData1.y == 0.0) ? pixY_0 : pixY_1) - pixY_Offset); - float y2 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); - float l = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); - float r = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); - - ImVec2 cl, cr; - cl.x = l; - cl.y = y1; - cr.x = r; - cr.y = y2; - if (!cull || gp.BB_Grid.Contains(cl) || gp.BB_Grid.Contains(cr)) { - auto colAlpha = item->Color; - colAlpha.w = item->Highlight ? 1.0 : 0.9; - DrawList.AddRectFilled({l, y1}, {r, y2}, GetColorU32(colAlpha)); - } - } - gp.DigitalPlotItemCnt++; - } + float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - ((itemData1.y == 0.0) ? pixY_0 : pixY_1) - pixY_Offset); + float y2 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); + float l = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); + float r = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); + + ImVec2 cl, cr; + cl.x = l; + cl.y = y1; + cr.x = r; + cr.y = y2; + if (!cull || gp.BB_Grid.Contains(cl) || gp.BB_Grid.Contains(cr)) { + auto colAlpha = item->Color; + colAlpha.w = item->Highlight ? 1.0 : 0.9; + DrawList.AddRectFilled({l, y1}, {r, y2}, GetColorU32(colAlpha)); + } + } + gp.DigitalPlotItemCnt++; + } - ImGui::PopClipRect(); + ImGui::PopClipRect(); } //////////////////////////////////////////////////////////////// From 0043525bd161119ee9ef863e9c006cdfbb2439ed Mon Sep 17 00:00:00 2001 From: ozlb Date: Thu, 30 Apr 2020 15:46:18 +0200 Subject: [PATCH 06/16] resolved conflicts with latest version --- implot.h | 77 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/implot.h b/implot.h index 58cf48d..444c198 100644 --- a/implot.h +++ b/implot.h @@ -81,13 +81,13 @@ enum ImPlotCol_ { }; enum ImPlotStyleVar_ { - ImPlotStyleVar_LineWeight, // float, line weight in pixels - ImPlotStyleVar_Marker, // int, marker specification - ImPlotStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") - ImPlotStyleVar_MarkerWeight, // float, outline weight of markers in pixels - ImPlotStyleVar_ErrorBarSize, // float, error bar whisker width in pixels - ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels - ImPlotStyleVar_DigitalBitHeight, // int, digital channels bit height (at 1) + ImPlotStyleVar_LineWeight, // float, line weight in pixels + ImPlotStyleVar_Marker, // int, marker specification + ImPlotStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") + ImPlotStyleVar_MarkerWeight, // float, outline weight of markers in pixels + ImPlotStyleVar_ErrorBarSize, // float, error bar whisker width in pixels + ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels + ImPlotStyleVar_DigitalBitHeight, // int, digital channels bit height (at 1) ImPlotStyleVar_COUNT }; @@ -149,28 +149,6 @@ bool BeginPlot(const char* title_id, // of an if statement conditioned on BeginPlot(). void EndPlot(); -/// Set the axes ranges of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes will be locked. -void SetNextPlotRange(float x_min, float x_max, float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once); -/// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. -void SetNextPlotRangeX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once); -/// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. -void SetNextPlotRangeY(float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once); - -//----------------------------------------------------------------------------- -// Plot Queries -//----------------------------------------------------------------------------- - -/// Returns true if the plot area in the current or most recent plot is hovered. -bool IsPlotHovered(); -/// Returns the mouse position in x,y coordinates of the current or most recent plot. -ImVec2 GetPlotMousePos(); -/// Returns the current or most recent plot axis range. -ImPlotRange GetPlotRange(); -/// Returns true if the current or most recent plot is being queried. -bool IsPlotQueried(); -/// Returns the current or most recent plot querey range. -ImPlotRange GetPlotQuery(); - //----------------------------------------------------------------------------- // Plot Items //----------------------------------------------------------------------------- @@ -197,6 +175,21 @@ void PlotErrorBars(const char* label_id, ImVec4 (*getter)(void* data, int idx), // Plots a text label at point x,y. void PlotLabel(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); +//----------------------------------------------------------------------------- +// Plot Queries +//----------------------------------------------------------------------------- + +/// Returns true if the plot area in the current or most recent plot is hovered. +bool IsPlotHovered(); +/// Returns the mouse position in x,y coordinates of the current or most recent plot. +ImVec2 GetPlotMousePos(); +/// Returns the current or most recent plot axis range. +ImPlotRange GetPlotRange(); +/// Returns true if the current or most recent plot is being queried. +bool IsPlotQueried(); +/// Returns the current or most recent plot querey range. +ImPlotRange GetPlotQuery(); + //----------------------------------------------------------------------------- // Plot Styling //----------------------------------------------------------------------------- @@ -223,6 +216,32 @@ void PushPlotStyleVar(ImPlotStyleVar idx, int val); // Undo temporary style modification. void PopPlotStyleVar(int count = 1); +//----------------------------------------------------------------------------- +// Plot Utils +//----------------------------------------------------------------------------- + +/// Set the axes ranges of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes will be locked. +void SetNextPlotRange(float x_min, float x_max, float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once); +/// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. +void SetNextPlotRangeX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once); +/// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. +void SetNextPlotRangeY(float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once); + +// Get the current Plot position (top-left) in pixels. +ImVec2 GetPlotPos(); +// Get the curent Plot size in pixels. +ImVec2 GetPlotSize(); + +// Convert pixels to a position in the current plot's coordinate system. +ImVec2 PixelsToPlot(const ImVec2& pix); +// Convert a position in the current plot's coordinate system to pixels. +ImVec2 PlotToPixels(const ImVec2& plt); + +// Push clip rect for rendering to current plot area +void PushPlotClipRect(); +// Pop plot clip rect +void PopPlotClipRect(); + //----------------------------------------------------------------------------- // Demo //----------------------------------------------------------------------------- From 4596a10183cb2d3e159276df002e116b451cc982 Mon Sep 17 00:00:00 2001 From: ozlb Date: Thu, 30 Apr 2020 15:47:14 +0200 Subject: [PATCH 07/16] resolved conflicts with latest version --- implot_demo.cpp | 1180 ++++++++++++++++++++++++----------------------- 1 file changed, 597 insertions(+), 583 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index b4a8cd4..b0be5ac 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -29,623 +29,637 @@ namespace { struct ScrollingData { - int MaxSize = 1000; - int Offset = 0; - ImVector Data; - ScrollingData() { Data.reserve(MaxSize); } - void AddPoint(float x, float y) { - if (Data.size() < MaxSize) - Data.push_back(ImVec2(x,y)); - else { - Data[Offset] = ImVec2(x,y); - Offset = (Offset + 1) % MaxSize; - } - } - void Erase() { - if (Data.size() > 0) { - Data.clear(); - Offset = 0; - } - } + int MaxSize = 1000; + int Offset = 0; + ImVector Data; + ScrollingData() { Data.reserve(MaxSize); } + void AddPoint(float x, float y) { + if (Data.size() < MaxSize) + Data.push_back(ImVec2(x,y)); + else { + Data[Offset] = ImVec2(x,y); + Offset = (Offset + 1) % MaxSize; + } + } + void Erase() { + if (Data.size() > 0) { + Data.clear(); + Offset = 0; + } + } }; struct RollingData { - float Span = 10.0f; - ImVector Data; - RollingData() { Data.reserve(1000); } - void AddPoint(float x, float y) { - float xmod = ImFmod(x, Span); - if (!Data.empty() && xmod < Data.back().x) - Data.shrink(0); - Data.push_back(ImVec2(xmod, y)); - } + float Span = 10.0f; + ImVector Data; + RollingData() { Data.reserve(1000); } + void AddPoint(float x, float y) { + float xmod = ImFmod(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() { + DemoData() { - } + } }; } namespace ImGui { - + void ShowImPlotDemoWindow(bool* p_open) { - static DemoData data; + static DemoData data; - //ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos; - //ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x + 650, main_viewport_pos.y + 20), ImGuiCond_FirstUseEver); - ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); - ImGui::Begin("ImPlot Demo", p_open); - ImGui::Text("ImPlot says hello. (0.1 WIP)"); - 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::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::BulletText("Right click and drag to box select data."); - 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(); - ImGui::BulletText("Hold Alt to expand query horizontally."); - ImGui::BulletText("Hold Shift to expand query vertically."); - ImGui::Unindent(); - ImGui::BulletText("Double left click to fit all visible data."); - ImGui::BulletText("Double right click to open the plot context menu."); - ImGui::BulletText("Click legend label icons to show/hide plot items."); - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Line Plots")) { - static float xs1[1001], ys1[1001]; - for (int i = 0; i < 1001; ++i) { - xs1[i] = i * 0.001f; - ys1[i] = 0.5f + 0.5f * sin(50 * xs1[i]); - } - static float xs2[11], ys2[11]; - for (int i = 0; i < 11; ++i) { - xs2[i] = i * 0.1f; - ys2[i] = xs2[i] * xs2[i]; - } - if (ImGui::BeginPlot("Line Plot", "x", "f(x)", {-1,300})) { - ImGui::Plot("sin(50*x)", xs1, ys1, 1001); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::Plot("x^2", xs2, ys2, 11); - ImGui::PopPlotStyleVar(); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Scatter Plots")) { - srand(0); - static float xs1[100], ys1[100]; - for (int i = 0; i < 100; ++i) { - xs1[i] = i * 0.01f; - ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); - } - static float xs2[50], ys2[50]; - for (int i = 0; i < 50; i++) { - xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); - ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); - } - if (ImGui::BeginPlot("Scatter Plot", NULL, NULL, {-1,300})) { - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); - ImGui::Plot("Data 1", xs1, ys1, 100); - ImGui::PopPlotStyleVar(2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4{1,0,0,0.25f}); - ImGui::Plot("Data 2", xs2, ys2, 50); - ImGui::PopPlotColor(); - ImGui::PopPlotStyleVar(2); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Bar Plots")) { - static bool horz = false; - ImGui::Checkbox("Horizontal",&horz); - if (horz) - ImGui::SetNextPlotRange(0, 110, -0.5f, 9.5f, ImGuiCond_Always); - else - ImGui::SetNextPlotRange(-0.5f, 9.5f, 0, 110, ImGuiCond_Always); - if (ImGui::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score", {-1, 300})) { - static float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90}; - static float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100}; - static float grade[10] = {80, 69, 52, 92, 72, 78, 75, 76, 89, 95}; - if (horz) { - ImGui::PlotBarH("Midterm Exam", midtm, 10, 0.2f, -0.2f); - ImGui::PlotBarH("Final Exam", final, 10, 0.2f, 0); - ImGui::PlotBarH("Course Grade", grade, 10, 0.2f, 0.2f); - } - else { - ImGui::PlotBar("Midterm Exam", midtm, 10, 0.2f, -0.2f); - ImGui::PlotBar("Final Exam", final, 10, 0.2f, 0); - ImGui::PlotBar("Course Grade", grade, 10, 0.2f, 0.2f); - } - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Error Bars")) { - float xs[5] = {1,2,3,4,5}; - float lin[5] = {8,8,9,7,8}; - float bar[5] = {1,2,5,3,4}; - float err1[5] = {0.2, 0.4, 0.2, 0.6, 0.4}; - float err2[5] = {0.4, 0.2, 0.4, 0.8, 0.6}; - ImGui::SetNextPlotRange(0, 6, 0, 10); - if (ImGui::BeginPlot("##ErrorBars",NULL,NULL,ImVec2(-1,300))) { + ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos; + ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x + 650, main_viewport_pos.y + 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); + ImGui::Begin("ImPlot Demo", p_open); + ImGui::Text("ImPlot says hello. (0.1 WIP)"); + 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::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::BulletText("Right click and drag to box select data."); + 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(); + ImGui::BulletText("Hold Alt to expand query horizontally."); + ImGui::BulletText("Hold Shift to expand query vertically."); + ImGui::Unindent(); + ImGui::BulletText("Double left click to fit all visible data."); + ImGui::BulletText("Double right click to open the plot context menu."); + ImGui::BulletText("Click legend label icons to show/hide plot items."); + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Line Plots")) { + static float xs1[1001], ys1[1001]; + for (int i = 0; i < 1001; ++i) { + xs1[i] = i * 0.001f; + ys1[i] = 0.5f + 0.5f * sin(50 * xs1[i]); + } + static float xs2[11], ys2[11]; + for (int i = 0; i < 11; ++i) { + xs2[i] = i * 0.1f; + ys2[i] = xs2[i] * xs2[i]; + } + if (ImGui::BeginPlot("Line Plot", "x", "f(x)", {-1,300})) { + ImGui::Plot("sin(50*x)", xs1, ys1, 1001); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::Plot("x^2", xs2, ys2, 11); + ImGui::PopPlotStyleVar(); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Scatter Plots")) { + srand(0); + static float xs1[100], ys1[100]; + for (int i = 0; i < 100; ++i) { + xs1[i] = i * 0.01f; + ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); + } + static float xs2[50], ys2[50]; + for (int i = 0; i < 50; i++) { + xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); + ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); + } + if (ImGui::BeginPlot("Scatter Plot", NULL, NULL, {-1,300})) { + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); + ImGui::Plot("Data 1", xs1, ys1, 100); + ImGui::PopPlotStyleVar(2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4{1,0,0,0.25f}); + ImGui::Plot("Data 2", xs2, ys2, 50); + ImGui::PopPlotColor(); + ImGui::PopPlotStyleVar(2); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Bar Plots")) { + static bool horz = false; + ImGui::Checkbox("Horizontal",&horz); + if (horz) + ImGui::SetNextPlotRange(0, 110, -0.5f, 9.5f, ImGuiCond_Always); + else + ImGui::SetNextPlotRange(-0.5f, 9.5f, 0, 110, ImGuiCond_Always); + if (ImGui::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score", {-1, 300})) { + static float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90}; + static float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100}; + static float grade[10] = {80, 69, 52, 92, 72, 78, 75, 76, 89, 95}; + if (horz) { + ImGui::PlotBarH("Midterm Exam", midtm, 10, 0.2f, -0.2f); + ImGui::PlotBarH("Final Exam", final, 10, 0.2f, 0); + ImGui::PlotBarH("Course Grade", grade, 10, 0.2f, 0.2f); + } + else { + ImGui::PlotBar("Midterm Exam", midtm, 10, 0.2f, -0.2f); + ImGui::PlotBar("Final Exam", final, 10, 0.2f, 0); + ImGui::PlotBar("Course Grade", grade, 10, 0.2f, 0.2f); + } + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Error Bars")) { + float xs[5] = {1,2,3,4,5}; + float lin[5] = {8,8,9,7,8}; + float bar[5] = {1,2,5,3,4}; + float err1[5] = {0.2, 0.4, 0.2, 0.6, 0.4}; + float err2[5] = {0.4, 0.2, 0.4, 0.8, 0.6}; + ImGui::SetNextPlotRange(0, 6, 0, 10); + if (ImGui::BeginPlot("##ErrorBars",NULL,NULL,ImVec2(-1,300))) { - ImGui::PlotBar("Bar", xs, bar, 5, 0.5f); - ImGui::PlotErrorBars("Bar", xs, bar, err1, 5); + ImGui::PlotBar("Bar", xs, bar, 5, 0.5f); + ImGui::PlotErrorBars("Bar", xs, bar, err1, 5); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); - ImGui::PushPlotColor(ImPlotCol_ErrorBar, ImVec4(1,0,0,1)); - ImGui::PlotErrorBars("Line", xs, lin, err1, err2, 5); - ImGui::Plot("Line", xs, lin, 5); - ImGui::PopPlotStyleVar(2); - ImGui::PopPlotColor(); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 3); + ImGui::PushPlotColor(ImPlotCol_ErrorBar, ImVec4(1,0,0,1)); + ImGui::PlotErrorBars("Line", xs, lin, err1, err2, 5); + ImGui::Plot("Line", xs, lin, 5); + ImGui::PopPlotStyleVar(2); + ImGui::PopPlotColor(); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Realtime Plots")) { - ImGui::BulletText("Move your mouse to change the data!"); - static bool paused = false; - static ScrollingData sdata1, sdata2; - static RollingData rdata1, rdata2; - ImVec2 mouse = ImGui::GetMousePos(); - static float t = 0; - if (!paused) { - 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); - } - ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); - static int rt_axis = ImAxisFlags_Default & ~ImAxisFlags_TickLabels; - if (ImGui::BeginPlot("##Scrolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { - ImGui::Plot("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), sdata1.Offset, 2 * sizeof(float)); - ImGui::Plot("Data 2", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), sdata2.Offset, 2 * sizeof(float)); - ImGui::EndPlot(); - } - ImGui::SetNextPlotRangeX(0, 10, ImGuiCond_Always); - if (ImGui::BeginPlot("##Rolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { - ImGui::Plot("Data 1", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 2 * sizeof(float)); - ImGui::Plot("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float)); - ImGui::EndPlot(); - } - } + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Realtime Plots")) { + ImGui::BulletText("Move your mouse to change the data!"); + static bool paused = false; + static ScrollingData sdata1, sdata2; + static RollingData rdata1, rdata2; + ImVec2 mouse = ImGui::GetMousePos(); + static float t = 0; + if (!paused) { + 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); + } + ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); + static int rt_axis = ImAxisFlags_Default & ~ImAxisFlags_TickLabels; + if (ImGui::BeginPlot("##Scrolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { + ImGui::Plot("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), sdata1.Offset, 2 * sizeof(float)); + ImGui::Plot("Data 2", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), sdata2.Offset, 2 * sizeof(float)); + ImGui::EndPlot(); + } + ImGui::SetNextPlotRangeX(0, 10, ImGuiCond_Always); + if (ImGui::BeginPlot("##Rolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) { + ImGui::Plot("Data 1", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 2 * sizeof(float)); + ImGui::Plot("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float)); + ImGui::EndPlot(); + } + } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Markers and Labels")) { - ImGui::SetNextPlotRange(0, 10, 0, 12); - if (ImGui::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,300), 0, 0, 0)) { - float xs[2] = {1,4}; - float ys[2] = {10,11}; - // filled - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::Plot("Circle##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; - ImGui::Plot("Square##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; - ImGui::Plot("Diamond##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; - ImGui::Plot("Up##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; - ImGui::Plot("Down##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; - ImGui::Plot("Left##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; - ImGui::Plot("Right##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; - ImGui::Plot("Cross##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; - ImGui::Plot("Plus##Fill", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; - ImGui::Plot("Asterisk##Fill", xs, ys, 2); - ImGui::PopPlotStyleVar(10); + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Markers and Labels")) { + ImGui::SetNextPlotRange(0, 10, 0, 12); + if (ImGui::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,300), 0, 0, 0)) { + float xs[2] = {1,4}; + float ys[2] = {10,11}; + // filled + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::Plot("Circle##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; + ImGui::Plot("Square##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; + ImGui::Plot("Diamond##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; + ImGui::Plot("Up##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; + ImGui::Plot("Down##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; + ImGui::Plot("Left##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; + ImGui::Plot("Right##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; + ImGui::Plot("Cross##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; + ImGui::Plot("Plus##Fill", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; + ImGui::Plot("Asterisk##Fill", xs, ys, 2); + ImGui::PopPlotStyleVar(10); - xs[0] = 6; xs[1] = 9; - ys[0] = 10; ys[1] = 11; - ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(0,0,0,0)); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); - ImGui::Plot("Circle", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; - ImGui::Plot("Square", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; - ImGui::Plot("Diamond", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; - ImGui::Plot("Up", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; - ImGui::Plot("Down", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; - ImGui::Plot("Left", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; - ImGui::Plot("Right", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; - ImGui::Plot("Cross", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; - ImGui::Plot("Plus", xs, ys, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; - ImGui::Plot("Asterisk", xs, ys, 2); - ImGui::PopPlotColor(); - ImGui::PopPlotStyleVar(10); + xs[0] = 6; xs[1] = 9; + ys[0] = 10; ys[1] = 11; + ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(0,0,0,0)); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle); + ImGui::Plot("Circle", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); ys[0]--; ys[1]--; + ImGui::Plot("Square", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); ys[0]--; ys[1]--; + ImGui::Plot("Diamond", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Up); ys[0]--; ys[1]--; + ImGui::Plot("Up", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Down); ys[0]--; ys[1]--; + ImGui::Plot("Down", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Left); ys[0]--; ys[1]--; + ImGui::Plot("Left", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Right); ys[0]--; ys[1]--; + ImGui::Plot("Right", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Cross); ys[0]--; ys[1]--; + ImGui::Plot("Cross", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Plus); ys[0]--; ys[1]--; + ImGui::Plot("Plus", xs, ys, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Asterisk); ys[0]--; ys[1]--; + ImGui::Plot("Asterisk", xs, ys, 2); + ImGui::PopPlotColor(); + ImGui::PopPlotStyleVar(10); - xs[0] = 5; xs[1] = 5; - ys[0] = 1; ys[1] = 11; + xs[0] = 5; xs[1] = 5; + ys[0] = 1; ys[1] = 11; - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 8); - ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerWeight, 2); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle | ImMarker_Cross); - ImGui::PushPlotColor(ImPlotCol_MarkerOutline, ImVec4(0,0,0,1)); - ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(1,1,1,1)); - ImGui::PushPlotColor(ImPlotCol_Line, ImVec4(0,0,0,1)); - ImGui::Plot("Circle|Cross", xs, ys, 2); - ImGui::PopPlotStyleVar(4); - ImGui::PopPlotColor(3); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerSize, 8); + ImGui::PushPlotStyleVar(ImPlotStyleVar_MarkerWeight, 2); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Circle | ImMarker_Cross); + ImGui::PushPlotColor(ImPlotCol_MarkerOutline, ImVec4(0,0,0,1)); + ImGui::PushPlotColor(ImPlotCol_MarkerFill, ImVec4(1,1,1,1)); + ImGui::PushPlotColor(ImPlotCol_Line, ImVec4(0,0,0,1)); + ImGui::Plot("Circle|Cross", xs, ys, 2); + ImGui::PopPlotStyleVar(4); + ImGui::PopPlotColor(3); - ImGui::PlotLabel("Filled Markers", 1.5, 11.75); - ImGui::PlotLabel("Open Markers", 6.75, 11.75); - ImGui::PlotLabel("Fancy Markers", 4.5, 4.25, true); + ImGui::PlotLabel("Filled Markers", 1.5, 11.75); + ImGui::PlotLabel("Open Markers", 6.75, 11.75); + ImGui::PlotLabel("Fancy Markers", 4.5, 4.25, true); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Log Scale")) { - 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); - ys1[i] = sin(xs[i]) + 1; - ys2[i] = log(xs[i]); - ys3[i] = pow(10.0f, xs[i]); - } - ImGui::SetNextPlotRange(0.1f, 100, 0, 10); - if (ImGui::BeginPlot("Log Plot", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_Default | ImAxisFlags_LogScale )) { - ImGui::Plot("f(x) = x", xs, xs, 1001); - ImGui::Plot("f(x) = sin(x)+1", xs, ys1, 1001); - ImGui::Plot("f(x) = log(x)", xs, ys2, 1001); - ImGui::Plot("f(x) = 10^x", xs, ys3, 21); - ImGui::EndPlot(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Querying")) { - ImGui::BulletText("Ctrl + click in the plot area to draw points."); - 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()); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); - if (data.size() > 0) - ImGui::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float)); - if (ImGui::IsPlotQueried() && data.size() > 0) { - ImPlotRange range = ImGui::GetPlotQuery(); - int cnt = 0; - ImVec2 avg; - for (int i = 0; i < data.size(); ++i) { - if (range.Contains(data[i])) { - avg.x += data[i].x; - avg.y += data[i].y; - cnt++; - } - } - if (cnt > 0) { - avg.x = avg.x / cnt; - avg.y = avg.y / cnt; - ImGui::Plot("Average", &avg.x, &avg.y, 1); - } - } - ImGui::PopPlotStyleVar(2); - range = ImGui::GetPlotRange(); - query = ImGui::GetPlotQuery(); - ImGui::EndPlot(); - } - 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(); - } - } + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Log Scale")) { + 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); + ys1[i] = sin(xs[i]) + 1; + ys2[i] = log(xs[i]); + ys3[i] = pow(10.0f, xs[i]); + } + ImGui::SetNextPlotRange(0.1f, 100, 0, 10); + if (ImGui::BeginPlot("Log Plot", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_Default | ImAxisFlags_LogScale )) { + ImGui::Plot("f(x) = x", xs, xs, 1001); + ImGui::Plot("f(x) = sin(x)+1", xs, ys1, 1001); + ImGui::Plot("f(x) = log(x)", xs, ys2, 1001); + ImGui::Plot("f(x) = 10^x", xs, ys3, 21); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Querying")) { + ImGui::BulletText("Ctrl + click in the plot area to draw points."); + 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()); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Diamond); + if (data.size() > 0) + ImGui::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float)); + if (ImGui::IsPlotQueried() && data.size() > 0) { + ImPlotRange range = ImGui::GetPlotQuery(); + int cnt = 0; + ImVec2 avg; + for (int i = 0; i < data.size(); ++i) { + if (range.Contains(data[i])) { + avg.x += data[i].x; + avg.y += data[i].y; + cnt++; + } + } + if (cnt > 0) { + avg.x = avg.x / cnt; + avg.y = avg.y / cnt; + ImGui::Plot("Average", &avg.x, &avg.y, 1); + } + } + ImGui::PopPlotStyleVar(2); + range = ImGui::GetPlotRange(); + query = ImGui::GetPlotQuery(); + ImGui::EndPlot(); + } + 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")) { - srand(10000000 * ImGui::GetTime()); - static bool paused = false; - static bool init = true; - static ScrollingData data[10]; - static bool show[10]; - if (init) { - for (int i = 0; i < 10; ++i) { - show[i] = false; - } - init = false; - } - ImGui::BulletText("Drag data items from the left column onto the plot."); - ImGui::BeginGroup(); - if (ImGui::Button("Clear", {100, 0})) { - for (int i = 0; i < 10; ++i) { - show[i] = false; - data[i].Data.shrink(0); - data[i].Offset = 0; - } - } - if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) - paused = !paused; - ImGui::Separator(); - for (int i = 0; i < 10; ++i) { - char label[8]; - sprintf(label, "data_%d", i); - ImGui::Selectable(label, false, 0, {100, 0}); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); - ImGui::TextUnformatted(label); - ImGui::EndDragDropSource(); - } - } - ImGui::EndGroup(); - ImGui::SameLine(); - static float t = 0; - if (!paused) { - t += ImGui::GetIO().DeltaTime; - for (int i = 0; i < 10; ++i) { - if (show[i]) - data[i].AddPoint(t, data[i].Data.empty() ? - 0.25f + 0.5f * (float)rand() / float(RAND_MAX) : - data[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX))); - } - } - ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); - if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { - for (int i = 0; i < 10; ++i) { - if (show[i]) { - char label[8]; - sprintf(label, "data_%d", i); - ImGui::Plot(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(float)); - } - } - ImGui::EndPlot(); - } - if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_PLOT")) { - int i = *(int*)payload->Data; - show[i] = true; - } - ImGui::EndDragDropTarget(); - } - } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Drag and Drop")) { + srand(10000000 * ImGui::GetTime()); + static bool paused = false; + static bool init = true; + static ScrollingData data[10]; + static bool show[10]; + if (init) { + for (int i = 0; i < 10; ++i) { + show[i] = false; + } + init = false; + } + ImGui::BulletText("Drag data items from the left column onto the plot."); + ImGui::BeginGroup(); + if (ImGui::Button("Clear", {100, 0})) { + for (int i = 0; i < 10; ++i) { + show[i] = false; + data[i].Data.shrink(0); + data[i].Offset = 0; + } + } + if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) + paused = !paused; + ImGui::Separator(); + for (int i = 0; i < 10; ++i) { + char label[8]; + sprintf(label, "data_%d", i); + ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + ImGui::EndGroup(); + ImGui::SameLine(); + static float t = 0; + if (!paused) { + t += ImGui::GetIO().DeltaTime; + for (int i = 0; i < 10; ++i) { + if (show[i]) + data[i].AddPoint(t, data[i].Data.empty() ? + 0.25f + 0.5f * (float)rand() / float(RAND_MAX) : + data[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX))); + } + } + ImGui::SetNextPlotRangeX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); + if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { + for (int i = 0; i < 10; ++i) { + if (show[i]) { + char label[8]; + sprintf(label, "data_%d", i); + ImGui::Plot(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(float)); + } + } + ImGui::EndPlot(); + } + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_PLOT")) { + int i = *(int*)payload->Data; + show[i] = true; + } + ImGui::EndDragDropTarget(); + } + } - if (ImGui::CollapsingHeader("Digital")) { + if (ImGui::CollapsingHeader("Digital")) { - static int bitHeight = 7; - ImGui::SetNextItemWidth(100); - ImGui::DragInt("Bit Hieght", &bitHeight, 0.2, 5, 50); - /// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. - //void SetNextPlotRangeX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once); - static bool paused = false; - #define K_PLOT_DIGITAL_CH_COUNT 8 - #define K_PLOT_ANALOG_CH_COUNT 4 - static ScrollingData dataDigital[K_PLOT_DIGITAL_CH_COUNT]; - static ScrollingData dataAnalog[K_PLOT_ANALOG_CH_COUNT]; - static bool showDigital[K_PLOT_DIGITAL_CH_COUNT]; - static bool showAnalog[K_PLOT_ANALOG_CH_COUNT]; + static int bitHeight = 7; + ImGui::SetNextItemWidth(100); + ImGui::DragInt("Bit Hieght", &bitHeight, 0.2, 5, 50); + /// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked. + //void SetNextPlotRangeX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once); + static bool paused = false; + #define K_PLOT_DIGITAL_CH_COUNT 8 + #define K_PLOT_ANALOG_CH_COUNT 8 + static ScrollingData dataDigital[K_PLOT_DIGITAL_CH_COUNT]; + static ScrollingData dataAnalog[K_PLOT_ANALOG_CH_COUNT]; + static bool showDigital[K_PLOT_DIGITAL_CH_COUNT]; + static bool showAnalog[K_PLOT_ANALOG_CH_COUNT]; - ImGui::BulletText("Drag data items from the left column onto the plot."); - ImGui::BeginGroup(); - if (ImGui::Button("Clear", {100, 0})) { - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) - showDigital[i] = false; - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) - showAnalog[i] = false; - } - if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) - paused = !paused; - ImGui::Separator(); - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { - char label[32]; - sprintf(label, "digital_data_%d", i); - ImGui::Checkbox(label, &showDigital[i]); - //ImGui::Selectable(label, false, 0, {100, 0}); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int)); - ImGui::TextUnformatted(label); - ImGui::EndDragDropSource(); - } - } - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - char label[32]; - sprintf(label, "analog_data_%d", i); - ImGui::Checkbox(label, &showAnalog[i]); - //ImGui::Selectable(label, false, 0, {100, 0}); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int)); - ImGui::TextUnformatted(label); - ImGui::EndDragDropSource(); - } - } - ImGui::EndGroup(); - ImGui::SameLine(); - static float t = 0; - if (true) { - t += ImGui::GetIO().DeltaTime; + ImGui::BulletText("Drag data items from the left column onto the plot."); + ImGui::BeginGroup(); + if (ImGui::Button("Clear", {100, 0})) { + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) + showDigital[i] = false; + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) + showAnalog[i] = false; + } + if (ImGui::Button(paused ? "Resume" : "Pause", {100,0})) + paused = !paused; + ImGui::Separator(); + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::Checkbox(label, &showDigital[i]); + //ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + char label[32]; + sprintf(label, "analog_data_%d", i); + ImGui::Checkbox(label, &showAnalog[i]); + //ImGui::Selectable(label, false, 0, {100, 0}); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImGui::EndDragDropSource(); + } + } + ImGui::EndGroup(); + ImGui::SameLine(); + static float t = 0; + if (true) { + t += ImGui::GetIO().DeltaTime; - //purge inactive signals - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { - if (!showDigital[i]) - dataDigital[i].Erase(); - } - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - if (!showAnalog[i]) - dataAnalog[i].Erase(); - } + //digital signal values + int i = 0; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) > 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) < 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) > 0.83); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, sin(t) < 0.17); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) > 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) < 0.45); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) > 0.83); + i++; + if (showDigital[i]) + dataDigital[i].AddPoint(t, cos(t) < 0.17); - //digital signal values - int i = 0; - if (showDigital[i]) - dataDigital[i].AddPoint(t, sin(t) > 0.45); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, sin(t) < 0.45); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, sin(t) > 0.83); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, sin(t) < 0.17); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, cos(t) > 0.45); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, cos(t) < 0.45); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, cos(t) > 0.83); - i++; - if (showDigital[i]) - dataDigital[i].AddPoint(t, cos(t) < 0.17); + //Analog signal values + i = 0; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, cos(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t) * cos(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t) - cos(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, cos(t) - sin(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, sin(t) + cos(t)); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, (sin(t) + cos(t)) / (sin(t) * cos(t))); + i++; + if (showAnalog[i]) + dataAnalog[i].AddPoint(t, (cos(t) + cos(t)) / (cos(t) * cos(t))); + i++; - //Analog signal values - i = 0; - if (showAnalog[i]) - dataAnalog[i].AddPoint(t, sin(t)); - i++; - if (showAnalog[i]) - dataAnalog[i].AddPoint(t, cos(t)); - i++; - if (showAnalog[i]) - dataAnalog[i].AddPoint(t, sin(t) * cos(t)); - i++; - if (showAnalog[i]) - dataAnalog[i].AddPoint(t, sin(t) - cos(t)); - i++; - - } - ImGui::SetNextPlotRangeX(t - 10.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always); - if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { - for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { - if (showDigital[i]) { - char label[32]; - sprintf(label, "digital_data_%d", i); - ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitHeight, bitHeight); - ImGui::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float)); - ImGui::PopPlotStyleVar(); - } - } - for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { - if (showAnalog[i]) { - char label[32]; - sprintf(label, "analog_data_%d", i); - if (dataAnalog[i].Data.size() > 0) - ImGui::Plot(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float)); - } - } - ImGui::EndPlot(); - } - if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT")) { - int i = *(int*)payload->Data; - showDigital[i] = true; - } - else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT")) { - int i = *(int*)payload->Data; - showAnalog[i] = true; - } - ImGui::EndDragDropTarget(); - } - } - //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Custom Styles")) { - static ImVec4 my_palette[3] = { - {0.000f, 0.980f, 0.604f, 1.0f}, - {0.996f, 0.278f, 0.380f, 1.0f}, - {(0.1176470593F), (0.5647059083F), (1.0F), (1.0F)}, - }; - ImGui::SetPlotPalette(my_palette, 3); - ImGui::PushPlotColor(ImPlotCol_FrameBg, IM_COL32(32,51,77,255)); - ImGui::PushPlotColor(ImPlotCol_PlotBg, {0,0,0,0}); - ImGui::PushPlotColor(ImPlotCol_PlotBorder, {0,0,0,0}); - ImGui::PushPlotColor(ImPlotCol_XAxis, IM_COL32(192, 192, 192, 192)); - ImGui::PushPlotColor(ImPlotCol_YAxis, IM_COL32(192, 192, 192, 192)); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); - ImGui::SetNextPlotRange(-0.5f, 9.5f, -0.5f, 9.5f); - if (ImGui::BeginPlot("##Custom", NULL, NULL, {-1,300}, ImPlotFlags_Default & ~ImPlotFlags_Legend, 0)) { - float lin[10] = {8,8,9,7,8,8,8,9,7,8}; - float bar[10] = {1,2,5,3,4,1,2,5,3,4}; - float dot[10] = {7,6,6,7,8,5,6,5,8,7}; - ImGui::PlotBar("Bar", bar, 10, 0.5f); - ImGui::Plot("Line", lin, 10); - ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); - ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); - ImGui::Plot("Dot", dot, 10); - ImGui::PopPlotStyleVar(2); - ImGui::EndPlot(); - } - ImGui::PopPlotColor(5); - ImGui::PopPlotStyleVar(); - ImGui::RestorePlotPalette(); - } - //------------------------------------------------------------------------- - // if (ImGui::CollapsingHeader("Benchmark")) { - - // } - //------------------------------------------------------------------------- - ImGui::End(); - + } + ImGui::SetNextPlotRangeX(t - 60.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always); + if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) { + for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) { + if (showDigital[i]) { + char label[32]; + sprintf(label, "digital_data_%d", i); + ImGui::PushPlotStyleVar(ImPlotStyleVar_DigitalBitHeight, bitHeight); + ImGui::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float)); + ImGui::PopPlotStyleVar(); + } + } + for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { + if (showAnalog[i]) { + char label[32]; + sprintf(label, "analog_data_%d", i); + if (dataAnalog[i].Data.size() > 0) + ImGui::Plot(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float)); + } + } + ImGui::EndPlot(); + } + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT")) { + int i = *(int*)payload->Data; + showDigital[i] = true; + } + else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT")) { + int i = *(int*)payload->Data; + showAnalog[i] = true; + } + ImGui::EndDragDropTarget(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Custom Styles")) { + static ImVec4 my_palette[3] = { + {0.000f, 0.980f, 0.604f, 1.0f}, + {0.996f, 0.278f, 0.380f, 1.0f}, + {(0.1176470593F), (0.5647059083F), (1.0F), (1.0F)}, + }; + ImGui::SetPlotPalette(my_palette, 3); + ImGui::PushPlotColor(ImPlotCol_FrameBg, IM_COL32(32,51,77,255)); + ImGui::PushPlotColor(ImPlotCol_PlotBg, {0,0,0,0}); + ImGui::PushPlotColor(ImPlotCol_PlotBorder, {0,0,0,0}); + ImGui::PushPlotColor(ImPlotCol_XAxis, IM_COL32(192, 192, 192, 192)); + ImGui::PushPlotColor(ImPlotCol_YAxis, IM_COL32(192, 192, 192, 192)); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2); + ImGui::SetNextPlotRange(-0.5f, 9.5f, -0.5f, 9.5f); + if (ImGui::BeginPlot("##Custom", NULL, NULL, {-1,300}, ImPlotFlags_Default & ~ImPlotFlags_Legend, 0)) { + float lin[10] = {8,8,9,7,8,8,8,9,7,8}; + float bar[10] = {1,2,5,3,4,1,2,5,3,4}; + float dot[10] = {7,6,6,7,8,5,6,5,8,7}; + ImGui::PlotBar("Bar", bar, 10, 0.5f); + ImGui::Plot("Line", lin, 10); + ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0); + ImGui::PushPlotStyleVar(ImPlotStyleVar_Marker, ImMarker_Square); + ImGui::Plot("Dot", dot, 10); + ImGui::PopPlotStyleVar(2); + ImGui::EndPlot(); + } + ImGui::PopPlotColor(5); + ImGui::PopPlotStyleVar(); + ImGui::RestorePlotPalette(); + } + if (ImGui::CollapsingHeader("Custom Rendering")) { + if (ImGui::BeginPlot("##CustomRend",NULL,NULL,{-1,300})) { + ImVec2 cntr = ImGui::PlotToPixels({0.5f, 0.5f}); + ImVec2 rmin = ImGui::PlotToPixels({0.25f, 0.75f}); + ImVec2 rmax = ImGui::PlotToPixels({0.75f, 0.25f}); + ImGui::PushPlotClipRect(); + ImGui::GetWindowDrawList()->AddCircleFilled(cntr,20,IM_COL32(255,255,0,255),20); + ImGui::GetWindowDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255)); + ImGui::PopPlotClipRect(); + ImGui::EndPlot(); + } + } + //------------------------------------------------------------------------- + // if (ImGui::CollapsingHeader("Benchmark")) { + + // } + //------------------------------------------------------------------------- + ImGui::End(); + } } // namespace ImGui From 2338c9b4c9c65ddcf73c6c04bf6f2a828047d963 Mon Sep 17 00:00:00 2001 From: ozlb Date: Mon, 4 May 2020 09:09:33 +0200 Subject: [PATCH 08/16] Curors Cursors query handling --- implot.cpp | 236 ++++++++++++++++++++++++++++++++++++++++++++++-- implot.h | 17 ++-- implot_demo.cpp | 16 ++-- 3 files changed, 248 insertions(+), 21 deletions(-) diff --git a/implot.cpp b/implot.cpp index 9047c0e..a54c973 100644 --- a/implot.cpp +++ b/implot.cpp @@ -26,8 +26,8 @@ #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include -#include +#include "implot.h" +#include "imgui_internal.h" #define IM_NORMALIZE2F_OVER_ZERO(VX, VY) \ { \ @@ -62,7 +62,8 @@ ImPlotStyle::ImPlotStyle() { Colors[ImPlotCol_XAxis] = IM_COL_AUTO; Colors[ImPlotCol_YAxis] = IM_COL_AUTO; Colors[ImPlotCol_Selection] = ImVec4(1,1,0,1); - Colors[ImPlotCol_Query] = ImVec4(0,1,0,1); + Colors[ImPlotCol_Query] = ImVec4(0,1,0,1); + Colors[ImPlotCol_Cursors] = ImVec4(1,0,0,1); } ImPlotRange::ImPlotRange() { @@ -223,7 +224,9 @@ struct ImPlotAxis { struct ImPlot { ImPlot() { Selecting = Querying = Queried = DraggingQuery = false; + DraggingCursor[0] = DraggingCursor[1] = false; SelectStart = QueryStart = ImVec2(0,0); + CursorsRange = ImPlotRange(); Flags = ImPlotFlags_Default; ColorIdx = 0; } @@ -238,6 +241,9 @@ struct ImPlot { ImRect QueryRect; // relative to BB_grid!! bool DraggingQuery; ImPlotRange QueryRange; + bool DraggingCursor[2]; + ImRect CursorRect[2]; // relative to BB_grid!! + ImPlotRange CursorsRange; ImPlotAxis XAxis; ImPlotAxis YAxis; ImPlotFlags Flags; @@ -314,6 +320,7 @@ struct ImPlotContext { Col_Txt, Col_TxtDis, Col_SlctBg, Col_SlctBd, Col_QryBg, Col_QryBd, + Col_Cursors, Col_XMajor, Col_XMinor, Col_XTxt, Col_YMajor, Col_YMinor, Col_YTxt; @@ -599,6 +606,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons gp.Col_QryBg = GetColorU32(gp.Style.Colors[ImPlotCol_Query] * ImVec4(1,1,1,0.25f)); gp.Col_QryBd = GetColorU32(gp.Style.Colors[ImPlotCol_Query]); + gp.Col_Cursors = GetColorU32(gp.Style.Colors[ImPlotCol_Cursors]); + // BB AND HOVER ----------------------------------------------------------- // frame @@ -710,6 +719,56 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons } } + //CURSORS + bool hov_cursor[2]; + for (size_t i = 0; i < 2; i++) + { + hov_cursor[i] = plot.CursorRect[i].Contains(IO.MousePos); + //x limits + bool xAtMax = false; + if (plot.CursorRect[i].Min.x <= gp.BB_Grid.Min.x) { + plot.CursorRect[i].Min.x = gp.BB_Grid.Min.x; + } + if (plot.CursorRect[i].Max.x >= (gp.BB_Grid.Max.x)) { + plot.CursorRect[i].Max.x = gp.BB_Grid.Max.x; + xAtMax = true; + } + //min cursor "line" width + if ((plot.CursorRect[i].Max.x - plot.CursorRect[i].Min.x) < 2) { + if (xAtMax) + plot.CursorRect[i].Min.x = plot.CursorRect[i].Max.x - 2; + else + plot.CursorRect[i].Max.x = plot.CursorRect[i].Min.x + 2; + } + //y locked to min max grid + plot.CursorRect[i].Min.y = gp.BB_Grid.Min.y; + plot.CursorRect[i].Max.y = gp.BB_Grid.Max.y; + // CURSOR1 DRAG ------------------------------------------------------------- + if (plot.DraggingCursor[i] && (IO.MouseReleased[0] || !IO.MouseDown[0])) { + plot.DraggingCursor[i] = false; + } + if (plot.DraggingCursor[i]) { + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); + plot.CursorRect[i].Min += IO.MouseDelta; + plot.CursorRect[i].Max += IO.MouseDelta; + //x limits + //if (plot.CursorRect[i].Min.x < gp.BB_Grid.Min.x) plot.CursorRect[i].Min.x = gp.BB_Grid.Min.x; + //if (plot.CursorRect[i].Max.x > (gp.BB_Grid.Max.x - 10)) plot.CursorRect[i].Max.x = gp.BB_Grid.Max.x - 10; + } + if (gp.Hov_Frame && hov_cursor[i] && !plot.DraggingCursor[i] && !plot.Selecting && !plot.DraggingQuery && !hov_legend) { + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); + if (IO.MouseDown[0] && !plot.XAxis.Dragging && !plot.YAxis.Dragging) { + //allow only one cursor dragging per time + if (i==0) + plot.DraggingCursor[i] = !plot.DraggingCursor[1]; + else + plot.DraggingCursor[i] = !plot.DraggingCursor[0]; + } + } + } + plot.CursorsRange.XMin = gp.FromPixels(plot.CursorRect[0].Min).x; + plot.CursorsRange.XMax = gp.FromPixels(plot.CursorRect[1].Max).x; + // DRAG INPUT ------------------------------------------------------------- // end drags @@ -748,9 +807,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); } // start drag - if (gp.Hov_Frame && hov_x_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) + if (gp.Hov_Frame && hov_x_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery && !hov_cursor[0] && !plot.DraggingCursor[0] && !hov_cursor[1] && !plot.DraggingCursor[1]) plot.XAxis.Dragging = true; - if (gp.Hov_Frame && hov_y_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) + if (gp.Hov_Frame && hov_y_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery && !hov_cursor[0] && !plot.DraggingCursor[0] && !hov_cursor[1] && !plot.DraggingCursor[1]) plot.YAxis.Dragging = true; // SCROLL INPUT ----------------------------------------------------------- @@ -866,7 +925,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons // DOUBLE CLICK ----------------------------------------------------------- - if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && (hov_x_axis_region || hov_y_axis_region) && !hov_legend && !hov_query) { + if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && (hov_x_axis_region || hov_y_axis_region) && !hov_legend && !hov_query && !hov_cursor[0] && !hov_cursor[1]) { gp.FitThisFrame = true; gp.FitX = hov_x_axis_region; gp.FitY = hov_y_axis_region; @@ -1045,6 +1104,9 @@ void PlotContextMenu(ImPlot& plot) { if (ImGui::MenuItem("Pixel Query",NULL,HasFlag(plot.Flags, ImPlotFlags_PixelQuery))) { FlipFlag(plot.Flags, ImPlotFlags_PixelQuery); } + if (ImGui::MenuItem("Show cursors",NULL,HasFlag(plot.Flags, ImPlotFlags_Cursors))) { + FlipFlag(plot.Flags, ImPlotFlags_Cursors); + } if (ImGui::MenuItem("Crosshairs",NULL,HasFlag(plot.Flags, ImPlotFlags_Crosshairs))) { FlipFlag(plot.Flags, ImPlotFlags_Crosshairs); } @@ -1155,6 +1217,12 @@ void EndPlot() { DrawList.AddRect( Min, Max, gp.Col_QryBd); } + //render cursors + if (HasFlag(plot.Flags, ImPlotFlags_Cursors)) { + DrawList.AddRectFilled(plot.CursorRect[0].Min, plot.CursorRect[0].Max, gp.Col_Cursors); + DrawList.AddRectFilled(plot.CursorRect[1].Min, plot.CursorRect[1].Max, gp.Col_Cursors); + } + // render legend const float txt_ht = GetTextLineHeight(); const ImVec2 legend_offset(10, 10); @@ -1376,6 +1444,12 @@ ImPlotRange GetPlotQuery() { return plot.QueryRange; } +ImPlotRange GetPlotCursors() { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotCursors() Needs to be called between BeginPlot() and EndPlot()!"); + ImPlot& plot = *gp.CurrentPlot; + return plot.CursorsRange; +} + //============================================================================= // STYLING //============================================================================= @@ -1712,7 +1786,7 @@ void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* dat float dy = p2.y - p1.y; IM_NORMALIZE2F_OVER_ZERO(dx, dy); dx *= (line_weight * 0.5f); - dy *= (line_weight * 0.5f); + dy *= (line_weight * 0.5f); DrawList._VtxWritePtr[0].pos.x = p1.x + dy; DrawList._VtxWritePtr[0].pos.y = p1.y - dx; DrawList._VtxWritePtr[0].uv = uv; @@ -1783,6 +1857,154 @@ void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* dat ImGui::PopClipRect(); } +void PlotP(const char* label_id, const float* xs, const float* ys, int count, int offset) { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotP() Needs to be called between BeginPlot() and EndPlot()!"); + + ImPlotItem* item = gp.RegisterItem(label_id); + if (!item->Show) + return; + + ImDrawList &DrawList = *ImGui::GetWindowDrawList(); + + const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; + const bool rend_mk_line = gp.Style.Colors[ImPlotCol_MarkerOutline].w != 0 && gp.Style.MarkerWeight > 0; + const bool rend_mk_fill = gp.Style.Colors[ImPlotCol_MarkerFill].w != 0; + + ImU32 col_line = gp.Style.Colors[ImPlotCol_Line].w == -1 ? GetColorU32(item->Color) : GetColorU32(gp.Style.Colors[ImPlotCol_Line]); + ImU32 col_mk_line = gp.Style.Colors[ImPlotCol_MarkerOutline].w == -1 ? col_line : GetColorU32(gp.Style.Colors[ImPlotCol_MarkerOutline]); + ImU32 col_mk_fill = gp.Style.Colors[ImPlotCol_MarkerFill].w == -1 ? col_line : GetColorU32(gp.Style.Colors[ImPlotCol_MarkerFill]); + + if (gp.Style.Colors[ImPlotCol_Line].w != -1) + item->Color = gp.Style.Colors[ImPlotCol_Line]; + + // find data extents + if (gp.FitThisFrame) { + for (int i = 0; i < count; ++i) { + ImVec2 p = {xs[i], ys[i]}; + gp.FitPoint(p); + } + } + + ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); + bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); + + const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; + + // render line segments + if (count > 1 && rend_line) { + const int segments = count - 1; + int i1 = offset; + ImVec2 p1, p2; + if (HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased)) { + for (int s = 0; s < segments; ++s) { + const int i2 = (i1 + 1) % count; + p1 = gp.ToPixels({xs[i1], ys[i1]}); + p2 = gp.ToPixels({xs[i2], ys[i2]}); + i1 = i2; + while (((s+1) < segments) && (round(p2.x) == round(p1.x))) { + const int i2 = (i1 + 1) % count; + p2 = ImMax(p2, gp.ToPixels({xs[i2], ys[i2]})); + i1 = i2; + s++; + } + if (!cull || gp.BB_Grid.Contains(p1) || gp.BB_Grid.Contains(p2)) + DrawList.AddLine(p1, p2, col_line, line_weight); + } + } + else { + const int idx_count = segments * 6; + const int vtx_count = segments * 4; + const ImVec2 uv = DrawList._Data->TexUvWhitePixel; + DrawList.PrimReserve(idx_count, vtx_count); + int segments_culled = 0; + for (int s = 0; s < segments; ++s) { + const int i2 = (i1 + 1) % count; + p1 = gp.ToPixels({xs[i1], ys[i1]}); + p2 = gp.ToPixels({xs[i2], ys[i2]}); + i1 = i2; + while (((s+1) < segments) && (round(p2.x) == round(p1.x))) { + segments_culled++; + const int i2 = (i1 + 1) % count; + p2 = ImMax(p2, gp.ToPixels({xs[i2], ys[i2]})); + i1 = i2; + s++; + } + if (!cull || gp.BB_Grid.Contains(p1) || gp.BB_Grid.Contains(p2)) { + float dx = p2.x - p1.x; + float dy = p2.y - p1.y; + IM_NORMALIZE2F_OVER_ZERO(dx, dy); + dx *= (line_weight * 0.5f); + dy *= (line_weight * 0.5f); + DrawList._VtxWritePtr[0].pos.x = p1.x + dy; + DrawList._VtxWritePtr[0].pos.y = p1.y - dx; + DrawList._VtxWritePtr[0].uv = uv; + DrawList._VtxWritePtr[0].col = col_line; + DrawList._VtxWritePtr[1].pos.x = p2.x + dy; + DrawList._VtxWritePtr[1].pos.y = p2.y - dx; + DrawList._VtxWritePtr[1].uv = uv; + DrawList._VtxWritePtr[1].col = col_line; + DrawList._VtxWritePtr[2].pos.x = p2.x - dy; + DrawList._VtxWritePtr[2].pos.y = p2.y + dx; + DrawList._VtxWritePtr[2].uv = uv; + DrawList._VtxWritePtr[2].col = col_line; + DrawList._VtxWritePtr[3].pos.x = p1.x - dy; + DrawList._VtxWritePtr[3].pos.y = p1.y + dx; + DrawList._VtxWritePtr[3].uv = uv; + DrawList._VtxWritePtr[3].col = col_line; + DrawList._VtxWritePtr += 4; + DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx); + DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); + DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2); + DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx); + DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2); + DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); + DrawList._IdxWritePtr += 6; + DrawList._VtxCurrentIdx += 4; + } + else { + segments_culled++; + } + } + if (segments_culled > 0) + DrawList.PrimUnreserve(segments_culled * 6, segments_culled * 4); + } + } + + // render markers + if (gp.Style.Marker != ImMarker_None) { + int idx = offset; + for (int i = 0; i < count; ++i) { + ImVec2 c; + c = gp.ToPixels({xs[idx], ys[idx]}); + idx = (idx + 1) % count; + if (!cull || gp.BB_Grid.Contains(c)) { + // TODO: Optimize the loop and if statements, this is atrocious + if (HasFlag(gp.Style.Marker, ImMarker_Circle)) + MakerCircle(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Square)) + MarkerSquare(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Diamond)) + MarkerDiamond(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Up)) + MarkerUp(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Down)) + MarkerDown(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Left)) + MarkerLeft(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Right)) + MarkerRight(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Cross)) + MarkerCross(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Plus)) + MarkerPlus(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + if (HasFlag(gp.Style.Marker, ImMarker_Asterisk)) + MarkerAsterisk(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); + } + } + } + ImGui::PopClipRect(); +} + //////////////////////////////////////////////////////////////// void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { diff --git a/implot.h b/implot.h index 72de746..bee59ef 100644 --- a/implot.h +++ b/implot.h @@ -23,7 +23,7 @@ // ImPlot v0.1 WIP #pragma once -#include +#include "imgui.h" //----------------------------------------------------------------------------- // Basic types and flags @@ -43,10 +43,11 @@ enum ImPlotFlags_ { ImPlotFlags_Selection = 1 << 3, // the user will be able to box-select with right-mouse 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 + ImPlotFlags_Cursors = 1 << 6, // show cursors + ImPlotFlags_Crosshairs = 1 << 7, // the default mouse cursor will be replaced with a crosshair when hovered + ImPlotFlags_CullData = 1 << 8, // plot data outside the plot area will be culled from rendering + ImPlotFlags_AntiAliased = 1 << 9, // lines and fills will be anti-aliased (not recommended) + ImPlotFlags_Default = ImPlotFlags_MousePos | ImPlotFlags_Legend | ImPlotFlags_Highlight | ImPlotFlags_Selection | ImPlotFlags_ContextMenu | ImPlotFlags_Cursors | ImPlotFlags_CullData }; // Options for plot axes (X and Y) @@ -77,6 +78,7 @@ enum ImPlotCol_ { ImPlotCol_YAxis, // x-axis grid/label color (defaults to ImGuiCol_Text) ImPlotCol_Selection, // box-selection color (defaults to yellow) ImPlotCol_Query, // box-query color (defaults to green) + ImPlotCol_Cursors, // cursor colors (defaults to red) ImPlotCol_COUNT }; @@ -157,6 +159,7 @@ void EndPlot(); void Plot(const char* label_id, const float* values, int count, int offset = 0, int stride = sizeof(float)); void Plot(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); +void PlotP(const char* label_id, const float* xs, const float* ys, int count, int offset = 0); // Plots digital channels. void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float) + sizeof(bool)); void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); @@ -189,6 +192,8 @@ ImPlotRange GetPlotRange(); bool IsPlotQueried(); /// Returns the current or most recent plot querey range. ImPlotRange GetPlotQuery(); +/// Returns the current cursors range. +ImPlotRange GetPlotCursors(); //----------------------------------------------------------------------------- // Plot Styling @@ -249,4 +254,4 @@ void PopPlotClipRect(); // Shows the ImPlot demo. Add implot_demo.cpp to your sources! void ShowImPlotDemoWindow(bool* p_open = NULL); -} // namespace ImGui \ No newline at end of file +} // namespace ImGui diff --git a/implot_demo.cpp b/implot_demo.cpp index 78844aa..fd9de1d 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -22,9 +22,9 @@ // ImPlot v0.1 WIP -#include -#include -#include +#include "implot.h" +#include "imgui_internal.h" +#include namespace { @@ -59,7 +59,7 @@ struct RollingData { ImVector Data; RollingData() { Data.reserve(1000); } void AddPoint(float x, float y) { - float xmod = fmodf(x, Span); + float xmod = ImFmod(x, Span); if (!Data.empty() && xmod < Data.back().x) Data.shrink(0); Data.push_back(ImVec2(xmod, y)); @@ -89,10 +89,10 @@ namespace ImGui { void ShowImPlotDemoWindow(bool* p_open) { - static DemoData data; + //static DemoData data; - ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos; - ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x + 650, main_viewport_pos.y + 20), ImGuiCond_FirstUseEver); + //ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos; + //ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x + 650, main_viewport_pos.y + 20), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); ImGui::Begin("ImPlot Demo", p_open); ImGui::Text("ImPlot says hello. (0.1 WIP)"); @@ -687,7 +687,7 @@ void ShowImPlotDemoWindow(bool* p_open) { 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::PlotP(buff, items[i].Xs, items[i].Ys, 1000, 0); ImGui::PopPlotColor(); } ImGui::EndPlot(); From 33ffd8e5c6498bad86f50851584c88d9047f5f9b Mon Sep 17 00:00:00 2001 From: ozlb Date: Mon, 4 May 2020 09:26:52 +0200 Subject: [PATCH 09/16] Cleanup and pixel density optimization --- implot.cpp | 161 ++++-------------------------------------------- implot.h | 7 +-- implot_demo.cpp | 2 +- 3 files changed, 17 insertions(+), 153 deletions(-) diff --git a/implot.cpp b/implot.cpp index a54c973..962e923 100644 --- a/implot.cpp +++ b/implot.cpp @@ -1766,6 +1766,12 @@ void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* dat p1 = gp.ToPixels(getter(data, i1)); p2 = gp.ToPixels(getter(data, i2)); i1 = i2; + while (((s+1) < segments) && (round(p2.x) == round(p1.x))) { + const int i2 = (i1 + 1) % count; + p2 = ImMax(p2, gp.ToPixels(getter(data, i2))); + i1 = i2; + s++; + } if (!cull || gp.BB_Grid.Contains(p1) || gp.BB_Grid.Contains(p2)) DrawList.AddLine(p1, p2, col_line, line_weight); } @@ -1781,6 +1787,13 @@ void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* dat p1 = gp.ToPixels(getter(data, i1)); p2 = gp.ToPixels(getter(data, i2)); i1 = i2; + while (((s+1) < segments) && (round(p2.x) == round(p1.x))) { + segments_culled++; + const int i2 = (i1 + 1) % count; + p2 = ImMax(p2, gp.ToPixels(getter(data, i2))); + i1 = i2; + s++; + } if (!cull || gp.BB_Grid.Contains(p1) || gp.BB_Grid.Contains(p2)) { float dx = p2.x - p1.x; float dy = p2.y - p1.y; @@ -1857,154 +1870,6 @@ void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* dat ImGui::PopClipRect(); } -void PlotP(const char* label_id, const float* xs, const float* ys, int count, int offset) { - IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotP() Needs to be called between BeginPlot() and EndPlot()!"); - - ImPlotItem* item = gp.RegisterItem(label_id); - if (!item->Show) - return; - - ImDrawList &DrawList = *ImGui::GetWindowDrawList(); - - const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; - const bool rend_mk_line = gp.Style.Colors[ImPlotCol_MarkerOutline].w != 0 && gp.Style.MarkerWeight > 0; - const bool rend_mk_fill = gp.Style.Colors[ImPlotCol_MarkerFill].w != 0; - - ImU32 col_line = gp.Style.Colors[ImPlotCol_Line].w == -1 ? GetColorU32(item->Color) : GetColorU32(gp.Style.Colors[ImPlotCol_Line]); - ImU32 col_mk_line = gp.Style.Colors[ImPlotCol_MarkerOutline].w == -1 ? col_line : GetColorU32(gp.Style.Colors[ImPlotCol_MarkerOutline]); - ImU32 col_mk_fill = gp.Style.Colors[ImPlotCol_MarkerFill].w == -1 ? col_line : GetColorU32(gp.Style.Colors[ImPlotCol_MarkerFill]); - - if (gp.Style.Colors[ImPlotCol_Line].w != -1) - item->Color = gp.Style.Colors[ImPlotCol_Line]; - - // find data extents - if (gp.FitThisFrame) { - for (int i = 0; i < count; ++i) { - ImVec2 p = {xs[i], ys[i]}; - gp.FitPoint(p); - } - } - - ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true); - bool cull = HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_CullData); - - const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; - - // render line segments - if (count > 1 && rend_line) { - const int segments = count - 1; - int i1 = offset; - ImVec2 p1, p2; - if (HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased)) { - for (int s = 0; s < segments; ++s) { - const int i2 = (i1 + 1) % count; - p1 = gp.ToPixels({xs[i1], ys[i1]}); - p2 = gp.ToPixels({xs[i2], ys[i2]}); - i1 = i2; - while (((s+1) < segments) && (round(p2.x) == round(p1.x))) { - const int i2 = (i1 + 1) % count; - p2 = ImMax(p2, gp.ToPixels({xs[i2], ys[i2]})); - i1 = i2; - s++; - } - if (!cull || gp.BB_Grid.Contains(p1) || gp.BB_Grid.Contains(p2)) - DrawList.AddLine(p1, p2, col_line, line_weight); - } - } - else { - const int idx_count = segments * 6; - const int vtx_count = segments * 4; - const ImVec2 uv = DrawList._Data->TexUvWhitePixel; - DrawList.PrimReserve(idx_count, vtx_count); - int segments_culled = 0; - for (int s = 0; s < segments; ++s) { - const int i2 = (i1 + 1) % count; - p1 = gp.ToPixels({xs[i1], ys[i1]}); - p2 = gp.ToPixels({xs[i2], ys[i2]}); - i1 = i2; - while (((s+1) < segments) && (round(p2.x) == round(p1.x))) { - segments_culled++; - const int i2 = (i1 + 1) % count; - p2 = ImMax(p2, gp.ToPixels({xs[i2], ys[i2]})); - i1 = i2; - s++; - } - if (!cull || gp.BB_Grid.Contains(p1) || gp.BB_Grid.Contains(p2)) { - float dx = p2.x - p1.x; - float dy = p2.y - p1.y; - IM_NORMALIZE2F_OVER_ZERO(dx, dy); - dx *= (line_weight * 0.5f); - dy *= (line_weight * 0.5f); - DrawList._VtxWritePtr[0].pos.x = p1.x + dy; - DrawList._VtxWritePtr[0].pos.y = p1.y - dx; - DrawList._VtxWritePtr[0].uv = uv; - DrawList._VtxWritePtr[0].col = col_line; - DrawList._VtxWritePtr[1].pos.x = p2.x + dy; - DrawList._VtxWritePtr[1].pos.y = p2.y - dx; - DrawList._VtxWritePtr[1].uv = uv; - DrawList._VtxWritePtr[1].col = col_line; - DrawList._VtxWritePtr[2].pos.x = p2.x - dy; - DrawList._VtxWritePtr[2].pos.y = p2.y + dx; - DrawList._VtxWritePtr[2].uv = uv; - DrawList._VtxWritePtr[2].col = col_line; - DrawList._VtxWritePtr[3].pos.x = p1.x - dy; - DrawList._VtxWritePtr[3].pos.y = p1.y + dx; - DrawList._VtxWritePtr[3].uv = uv; - DrawList._VtxWritePtr[3].col = col_line; - DrawList._VtxWritePtr += 4; - DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx); - DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); - DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2); - DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx); - DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2); - DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); - DrawList._IdxWritePtr += 6; - DrawList._VtxCurrentIdx += 4; - } - else { - segments_culled++; - } - } - if (segments_culled > 0) - DrawList.PrimUnreserve(segments_culled * 6, segments_culled * 4); - } - } - - // render markers - if (gp.Style.Marker != ImMarker_None) { - int idx = offset; - for (int i = 0; i < count; ++i) { - ImVec2 c; - c = gp.ToPixels({xs[idx], ys[idx]}); - idx = (idx + 1) % count; - if (!cull || gp.BB_Grid.Contains(c)) { - // TODO: Optimize the loop and if statements, this is atrocious - if (HasFlag(gp.Style.Marker, ImMarker_Circle)) - MakerCircle(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Square)) - MarkerSquare(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Diamond)) - MarkerDiamond(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Up)) - MarkerUp(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Down)) - MarkerDown(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Left)) - MarkerLeft(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Right)) - MarkerRight(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Cross)) - MarkerCross(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Plus)) - MarkerPlus(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - if (HasFlag(gp.Style.Marker, ImMarker_Asterisk)) - MarkerAsterisk(DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); - } - } - } - ImGui::PopClipRect(); -} - //////////////////////////////////////////////////////////////// void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { diff --git a/implot.h b/implot.h index bee59ef..1d6189a 100644 --- a/implot.h +++ b/implot.h @@ -159,10 +159,6 @@ void EndPlot(); void Plot(const char* label_id, const float* values, int count, int offset = 0, int stride = sizeof(float)); void Plot(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); void Plot(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); -void PlotP(const char* label_id, const float* xs, const float* ys, int count, int offset = 0); -// Plots digital channels. -void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float) + sizeof(bool)); -void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); // Plots vertical bars. void PlotBar(const char* label_id, const float* values, int count, float width = 0.67f, float shift = 0, int offset = 0, int stride = sizeof(float)); void PlotBar(const char* label_id, const float* xs, const float* ys, int count, float width, int offset = 0, int stride = sizeof(float)); @@ -177,6 +173,9 @@ void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const void PlotErrorBars(const char* label_id, ImVec4 (*getter)(void* data, int idx), void* data, int count, int offset = 0); // Plots a text label at point x,y. void PlotLabel(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); +// Plots digital channels. +void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float) + sizeof(bool)); +void PlotDigital(const char* label_id, ImVec2 (*getter)(void* data, int idx), void* data, int count, int offset = 0); //----------------------------------------------------------------------------- // Plot Queries diff --git a/implot_demo.cpp b/implot_demo.cpp index fd9de1d..d4767ec 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -687,7 +687,7 @@ void ShowImPlotDemoWindow(bool* p_open) { for (int i = 0; i < 100; ++i) { sprintf(buff, "item_%d",i); ImGui::PushPlotColor(ImPlotCol_Line, items[i].Col); - ImGui::PlotP(buff, items[i].Xs, items[i].Ys, 1000, 0); + ImGui::Plot(buff, items[i].Xs, items[i].Ys, 1000, 0, 2 * sizeof(float)); ImGui::PopPlotColor(); } ImGui::EndPlot(); From 52ae8ff8cd948182012d86d6b000324fd9f6f5b0 Mon Sep 17 00:00:00 2001 From: ozlb Date: Mon, 4 May 2020 14:17:39 +0200 Subject: [PATCH 10/16] PlotDigitalEx optimization --- implot.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/implot.cpp b/implot.cpp index 63038b9..9c3f3ba 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2314,6 +2314,15 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of // render digital signals as "pixel bases" rectangles if (count > 1 && rend_line) { + // + const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); + int pixY_0 = line_weight; + int pixY_1 = gp.Style.DigitalBitHeight; + int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label + int pixY_chOffset = pixY_1 + 3; //3 pixels between channels + ImVec2 pMin, pMax; + float y0 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_0 - pixY_Offset); + float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_1 - pixY_Offset); const int segments = count - 1; int i1 = offset; for (int s = 0; s < segments; ++s) { @@ -2321,26 +2330,22 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of ImVec2 itemData1 = getter(i1); ImVec2 itemData2 = getter(i2); i1 = i2; - const float mx = (gp.PixelRange.Max.x - gp.PixelRange.Min.x) / (gp.CurrentPlot->XAxis.Max - gp.CurrentPlot->XAxis.Min); - int pixY_0 = line_weight; - int pixY_1 = gp.Style.DigitalBitHeight; - int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label - int pixY_chOffset = pixY_1 + 3; //3 pixels between channels - - float y1 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - ((itemData1.y == 0.0) ? pixY_0 : pixY_1) - pixY_Offset); - float y2 = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); - float l = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); - float r = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); - - ImVec2 cl, cr; - cl.x = l; - cl.y = y1; - cr.x = r; - cr.y = y2; - if (!cull || gp.BB_Grid.Contains(cl) || gp.BB_Grid.Contains(cr)) { + pMin.x = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); + pMin.y = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); + pMax.x = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); + pMax.y = (itemData1.y == 0.0) ? y0 : y1; + while (((s+1) < segments) && (round(pMin.x) == round(pMax.x))) { + const int i2 = (i1 + 1) % count; + ImVec2 itemData2 = getter(i2); + pMax.x = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); + pMax.y = (itemData1.y == 0.0) ? y0 : y1; + i1 = i2; + s++; + } + if (!cull || gp.BB_Grid.Contains(pMin) || gp.BB_Grid.Contains(pMax)) { auto colAlpha = item->Color; colAlpha.w = item->Highlight ? 1.0 : 0.9; - DrawList.AddRectFilled({l, y1}, {r, y2}, GetColorU32(colAlpha)); + DrawList.AddRectFilled(pMin, pMax, GetColorU32(colAlpha)); } } gp.DigitalPlotItemCnt++; From d539dc9a70d2cfacb31413f30a96562e054d146e Mon Sep 17 00:00:00 2001 From: ozlb Date: Mon, 4 May 2020 15:16:04 +0200 Subject: [PATCH 11/16] Plot only one rectangle for same digital state plot only one rectangle for same digital state, do not extend plot outside plot range --- implot.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/implot.cpp b/implot.cpp index 9c3f3ba..6156026 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2333,15 +2333,19 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of pMin.x = gp.PixelRange.Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Min); pMin.y = (gp.PixelRange.Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_Offset); pMax.x = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); - pMax.y = (itemData1.y == 0.0) ? y0 : y1; - while (((s+1) < segments) && (round(pMin.x) == round(pMax.x))) { + pMax.y = ((int) itemData1.y == 0) ? y0 : y1; + //plot only one rectangle for same digital state + while (((s+2) < segments) && ((int) itemData1.y == (int) itemData2.y)) { const int i2 = (i1 + 1) % count; - ImVec2 itemData2 = getter(i2); + itemData2 = getter(i2); pMax.x = gp.PixelRange.Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Min); - pMax.y = (itemData1.y == 0.0) ? y0 : y1; i1 = i2; s++; - } + } + //do not extend plot outside plot range + if (pMin.x < gp.PixelRange.Min.x) pMin.x = gp.PixelRange.Min.x; + if (pMax.x > gp.PixelRange.Max.x) pMax.x = gp.PixelRange.Max.x; + //plot a rectangle that extends up to x2 with y1 height if (!cull || gp.BB_Grid.Contains(pMin) || gp.BB_Grid.Contains(pMax)) { auto colAlpha = item->Color; colAlpha.w = item->Highlight ? 1.0 : 0.9; From 0f76571e8965bdba755e88ea3ffe7df99b5abedf Mon Sep 17 00:00:00 2001 From: ozlb Date: Tue, 5 May 2020 06:25:01 +0200 Subject: [PATCH 12/16] Update implot.cpp --- implot.cpp | 85 ++++-------------------------------------------------- 1 file changed, 5 insertions(+), 80 deletions(-) diff --git a/implot.cpp b/implot.cpp index 6156026..06ff1ba 100644 --- a/implot.cpp +++ b/implot.cpp @@ -63,7 +63,6 @@ ImPlotStyle::ImPlotStyle() { Colors[ImPlotCol_YAxis] = IM_COL_AUTO; Colors[ImPlotCol_Selection] = ImVec4(1,1,0,1); Colors[ImPlotCol_Query] = ImVec4(0,1,0,1); - Colors[ImPlotCol_Cursors] = ImVec4(1,0,0,1); } ImPlotRange::ImPlotRange() { @@ -242,9 +241,7 @@ struct ImPlotAxis { struct ImPlot { ImPlot() { Selecting = Querying = Queried = DraggingQuery = false; - DraggingCursor[0] = DraggingCursor[1] = false; SelectStart = QueryStart = ImVec2(0,0); - CursorsRange = ImPlotRange(); Flags = ImPlotFlags_Default; ColorIdx = 0; } @@ -259,9 +256,7 @@ struct ImPlot { ImRect QueryRect; // relative to BB_grid!! bool DraggingQuery; ImPlotRange QueryRange; - bool DraggingCursor[2]; - ImRect CursorRect[2]; // relative to BB_grid!! - ImPlotRange CursorsRange; + ImPlotAxis XAxis; ImPlotAxis YAxis; inline ImPlotAxis& Axis(int idx) { return (&XAxis)[idx]; } @@ -309,7 +304,6 @@ struct ImPlotContext { Col_Txt, Col_TxtDis, Col_SlctBg, Col_SlctBd, Col_QryBg, Col_QryBd, - Col_Cursors, Col_XMajor, Col_XMinor, Col_XTxt, Col_YMajor, Col_YMinor, Col_YTxt; // Tick marks @@ -693,8 +687,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons gp.Col_QryBg = GetColorU32(gp.Style.Colors[ImPlotCol_Query] * ImVec4(1,1,1,0.25f)); gp.Col_QryBd = GetColorU32(gp.Style.Colors[ImPlotCol_Query]); - gp.Col_Cursors = GetColorU32(gp.Style.Colors[ImPlotCol_Cursors]); - // BB AND HOVER ----------------------------------------------------------- // frame @@ -807,56 +799,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons } } - //CURSORS - bool hov_cursor[2]; - for (size_t i = 0; i < 2; i++) - { - hov_cursor[i] = plot.CursorRect[i].Contains(IO.MousePos); - //x limits - bool xAtMax = false; - if (plot.CursorRect[i].Min.x <= gp.BB_Grid.Min.x) { - plot.CursorRect[i].Min.x = gp.BB_Grid.Min.x; - } - if (plot.CursorRect[i].Max.x >= (gp.BB_Grid.Max.x)) { - plot.CursorRect[i].Max.x = gp.BB_Grid.Max.x; - xAtMax = true; - } - //min cursor "line" width - if ((plot.CursorRect[i].Max.x - plot.CursorRect[i].Min.x) < 2) { - if (xAtMax) - plot.CursorRect[i].Min.x = plot.CursorRect[i].Max.x - 2; - else - plot.CursorRect[i].Max.x = plot.CursorRect[i].Min.x + 2; - } - //y locked to min max grid - plot.CursorRect[i].Min.y = gp.BB_Grid.Min.y; - plot.CursorRect[i].Max.y = gp.BB_Grid.Max.y; - // CURSOR1 DRAG ------------------------------------------------------------- - if (plot.DraggingCursor[i] && (IO.MouseReleased[0] || !IO.MouseDown[0])) { - plot.DraggingCursor[i] = false; - } - if (plot.DraggingCursor[i]) { - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); - plot.CursorRect[i].Min += IO.MouseDelta; - plot.CursorRect[i].Max += IO.MouseDelta; - //x limits - //if (plot.CursorRect[i].Min.x < gp.BB_Grid.Min.x) plot.CursorRect[i].Min.x = gp.BB_Grid.Min.x; - //if (plot.CursorRect[i].Max.x > (gp.BB_Grid.Max.x - 10)) plot.CursorRect[i].Max.x = gp.BB_Grid.Max.x - 10; - } - if (gp.Hov_Frame && hov_cursor[i] && !plot.DraggingCursor[i] && !plot.Selecting && !plot.DraggingQuery && !hov_legend) { - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); - if (IO.MouseDown[0] && !plot.XAxis.Dragging && !plot.YAxis.Dragging) { - //allow only one cursor dragging per time - if (i==0) - plot.DraggingCursor[i] = !plot.DraggingCursor[1]; - else - plot.DraggingCursor[i] = !plot.DraggingCursor[0]; - } - } - } - plot.CursorsRange.XMin = PixelsToPlot(plot.CursorRect[0].Min).x; - plot.CursorsRange.XMax = PixelsToPlot(plot.CursorRect[1].Max).x; - // DRAG INPUT ------------------------------------------------------------- // end drags @@ -895,9 +837,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); } // start drag - if (gp.Hov_Frame && hov_x_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery && !hov_cursor[0] && !plot.DraggingCursor[0] && !hov_cursor[1] && !plot.DraggingCursor[1]) + if (gp.Hov_Frame && hov_x_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) plot.XAxis.Dragging = true; - if (gp.Hov_Frame && hov_y_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery && !hov_cursor[0] && !plot.DraggingCursor[0] && !hov_cursor[1] && !plot.DraggingCursor[1]) + if (gp.Hov_Frame && hov_y_axis_region && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) plot.YAxis.Dragging = true; // SCROLL INPUT ----------------------------------------------------------- @@ -1012,7 +954,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons // DOUBLE CLICK ----------------------------------------------------------- - if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && (hov_x_axis_region || hov_y_axis_region) && !hov_legend && !hov_query && !hov_cursor[0] && !hov_cursor[1]) { + if ( IO.MouseDoubleClicked[0] && gp.Hov_Frame && (hov_x_axis_region || hov_y_axis_region) && !hov_legend && !hov_query) { gp.FitThisFrame = true; gp.FitX = hov_x_axis_region; gp.FitY = hov_y_axis_region; @@ -1188,9 +1130,6 @@ void PlotContextMenu(ImPlot& plot) { if (ImGui::MenuItem("Pixel Query",NULL,HasFlag(plot.Flags, ImPlotFlags_PixelQuery))) { FlipFlag(plot.Flags, ImPlotFlags_PixelQuery); } - if (ImGui::MenuItem("Show cursors",NULL,HasFlag(plot.Flags, ImPlotFlags_Cursors))) { - FlipFlag(plot.Flags, ImPlotFlags_Cursors); - } if (ImGui::MenuItem("Crosshairs",NULL,HasFlag(plot.Flags, ImPlotFlags_Crosshairs))) { FlipFlag(plot.Flags, ImPlotFlags_Crosshairs); } @@ -1237,12 +1176,10 @@ void EndPlot() { // AXIS STATES ------------------------------------------------------------ - const bool flip_x = HasFlag(plot.XAxis.Flags, ImAxisFlags_Invert); const bool lock_x_min = HasFlag(plot.XAxis.Flags, ImAxisFlags_LockMin); const bool lock_x_max = HasFlag(plot.XAxis.Flags, ImAxisFlags_LockMax); const bool lock_x = (lock_x_min && lock_x_max) || (gp.NextPlotData.HasXRange && gp.NextPlotData.XRangeCond == ImGuiCond_Always); - const bool flip_y = HasFlag(plot.YAxis.Flags, ImAxisFlags_Invert); const bool lock_y_min = HasFlag(plot.YAxis.Flags, ImAxisFlags_LockMin); const bool lock_y_max = HasFlag(plot.YAxis.Flags, ImAxisFlags_LockMax); const bool lock_y = (lock_y_min && lock_y_max) || (gp.NextPlotData.HasYRange && gp.NextPlotData.YRangeCond == ImGuiCond_Always); @@ -1301,12 +1238,6 @@ void EndPlot() { DrawList.AddRect( Min, Max, gp.Col_QryBd); } - //render cursors - if (HasFlag(plot.Flags, ImPlotFlags_Cursors)) { - DrawList.AddRectFilled(plot.CursorRect[0].Min, plot.CursorRect[0].Max, gp.Col_Cursors); - DrawList.AddRectFilled(plot.CursorRect[1].Min, plot.CursorRect[1].Max, gp.Col_Cursors); - } - // render legend const float txt_ht = GetTextLineHeight(); const ImVec2 legend_offset(10, 10); @@ -1519,12 +1450,6 @@ ImPlotRange GetPlotQuery() { return plot.QueryRange; } -ImPlotRange GetPlotCursors() { - IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotCursors() Needs to be called between BeginPlot() and EndPlot()!"); - ImPlot& plot = *gp.CurrentPlot; - return plot.CursorsRange; -} - //----------------------------------------------------------------------------- // STYLING //----------------------------------------------------------------------------- @@ -2230,7 +2155,7 @@ inline void DrawPieSlice(ImDrawList& DrawList, const ImVec2& center, float radiu } -void PlotPieChart(char** label_ids, float* values, int count, const ImVec2& center, float radius, bool show_percents, float angle0) { +void PlotPieChart(const char** label_ids, float* values, int count, const ImVec2& center, float radius, bool show_percents, float angle0) { IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotPieChart() Needs to be called between BeginPlot() and EndPlot()!"); ImDrawList & DrawList = *GetWindowDrawList(); From a956e9849d94c204eab4439b5162afe5cef02d20 Mon Sep 17 00:00:00 2001 From: ozlb Date: Tue, 5 May 2020 06:25:24 +0200 Subject: [PATCH 13/16] Update implot.h --- implot.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/implot.h b/implot.h index c70c72f..6eb67c9 100644 --- a/implot.h +++ b/implot.h @@ -43,11 +43,10 @@ enum ImPlotFlags_ { ImPlotFlags_Selection = 1 << 3, // the user will be able to box-select with right-mouse 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_Cursors = 1 << 6, // show cursors - ImPlotFlags_Crosshairs = 1 << 7, // the default mouse cursor will be replaced with a crosshair when hovered - ImPlotFlags_CullData = 1 << 8, // plot data outside the plot area will be culled from rendering - ImPlotFlags_AntiAliased = 1 << 9, // lines and fills will be anti-aliased (not recommended) - ImPlotFlags_NoChild = 1 << 10, // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications) + 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_NoChild = 1 << 9, // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications) ImPlotFlags_Default = ImPlotFlags_MousePos | ImPlotFlags_Legend | ImPlotFlags_Highlight | ImPlotFlags_Selection | ImPlotFlags_ContextMenu | ImPlotFlags_CullData }; @@ -79,7 +78,6 @@ enum ImPlotCol_ { ImPlotCol_YAxis, // x-axis grid/label color (defaults to ImGuiCol_Text) ImPlotCol_Selection, // box-selection color (defaults to yellow) ImPlotCol_Query, // box-query color (defaults to green) - ImPlotCol_Cursors, // cursor colors (defaults to red) ImPlotCol_COUNT }; @@ -174,7 +172,7 @@ void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset = 0, int stride = sizeof(float)); void PlotErrorBars(const char* label_id, ImVec4 (*getter)(void* data, int idx), void* data, int count, int offset = 0); // Plots a pie chart. If the sum of values > 1, each value will be normalized. Center and radius are in plot coordinates. -void PlotPieChart(char** label_ids, float* values, int count, const ImVec2& center, float radius, bool show_percents = true, float angle0 = 90); +void PlotPieChart(const char** label_ids, float* values, int count, const ImVec2& center, float radius, bool show_percents = true, float angle0 = 90); // Plots a text label at point x,y. void PlotLabel(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); // Plots digital channels. @@ -195,8 +193,6 @@ ImPlotRange GetPlotRange(); bool IsPlotQueried(); /// Returns the current or most recent plot querey range. ImPlotRange GetPlotQuery(); -/// Returns the current cursors range. -ImPlotRange GetPlotCursors(); //----------------------------------------------------------------------------- // Plot Styling From f98cda45bddb98bbc0e41848c0cc0b42b960a938 Mon Sep 17 00:00:00 2001 From: ozlb Date: Tue, 5 May 2020 06:25:47 +0200 Subject: [PATCH 14/16] Update implot_demo.cpp --- implot_demo.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/implot_demo.cpp b/implot_demo.cpp index 43ab874..2b91691 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -218,7 +218,7 @@ void ShowImPlotDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Pie Charts")) { - static char* labels1[] = {"Frogs","Hogs","Dogs","Logs"}; + static const char* labels1[] = {"Frogs","Hogs","Dogs","Logs"}; static float pre_normalized[] = {0.15f, 0.30f, 0.45f, 0.10f}; ImVec2 center(0.5f,0.5f); // in plot units, not pixels float radius = 0.4f; // in plot units, not pixels @@ -239,7 +239,7 @@ void ShowImPlotDemoWindow(bool* p_open) { }; ImGui::SetPlotPalette(YlOrRd, 5); SetNextPlotRange(0,1,0,1,ImGuiCond_Always); - static char* labels2[] = {"One","Two","Three","Four","Five"}; + static const char* labels2[] = {"One","Two","Three","Four","Five"}; static float not_normalized[] = {1,2,3,4,5}; if (ImGui::BeginPlot("##Pie2", NULL, NULL, ImVec2(250,250), ImPlotFlags_Legend, 0, 0)) { ImGui::PlotPieChart(labels2, not_normalized, 5, center, radius); @@ -550,7 +550,6 @@ void ShowImPlotDemoWindow(bool* p_open) { char label[32]; sprintf(label, "digital_data_%d", i); ImGui::Checkbox(label, &showDigital[i]); - //ImGui::Selectable(label, false, 0, {100, 0}); if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int)); ImGui::TextUnformatted(label); @@ -561,7 +560,6 @@ void ShowImPlotDemoWindow(bool* p_open) { char label[32]; sprintf(label, "analog_data_%d", i); ImGui::Checkbox(label, &showAnalog[i]); - //ImGui::Selectable(label, false, 0, {100, 0}); if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int)); ImGui::TextUnformatted(label); From 5e3b283f5e71798bd173491796abdfc3c8666e3f Mon Sep 17 00:00:00 2001 From: ozlb Date: Tue, 5 May 2020 08:56:25 +0200 Subject: [PATCH 15/16] Update implot.cpp --- implot.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/implot.cpp b/implot.cpp index 06ff1ba..9bd0c58 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2269,6 +2269,8 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of } //do not extend plot outside plot range if (pMin.x < gp.PixelRange.Min.x) pMin.x = gp.PixelRange.Min.x; + if (pMax.x < gp.PixelRange.Min.x) pMax.x = gp.PixelRange.Min.x; + if (pMin.x > gp.PixelRange.Max.x) pMin.x = gp.PixelRange.Max.x; if (pMax.x > gp.PixelRange.Max.x) pMax.x = gp.PixelRange.Max.x; //plot a rectangle that extends up to x2 with y1 height if (!cull || gp.BB_Grid.Contains(pMin) || gp.BB_Grid.Contains(pMax)) { From 1d900f123bff8114197552d5c78479802b304978 Mon Sep 17 00:00:00 2001 From: ozlb Date: Tue, 5 May 2020 14:26:20 +0200 Subject: [PATCH 16/16] Fix rectangles accumulated at min pos Fix rectangles accumulated at gp.PixelRange.Min.x position --- implot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implot.cpp b/implot.cpp index 9bd0c58..57bf432 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2273,7 +2273,7 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of if (pMin.x > gp.PixelRange.Max.x) pMin.x = gp.PixelRange.Max.x; if (pMax.x > gp.PixelRange.Max.x) pMax.x = gp.PixelRange.Max.x; //plot a rectangle that extends up to x2 with y1 height - if (!cull || gp.BB_Grid.Contains(pMin) || gp.BB_Grid.Contains(pMax)) { + if ((pMax.x > pMin.x) && (!cull || gp.BB_Grid.Contains(pMin) || gp.BB_Grid.Contains(pMax))) { auto colAlpha = item->Color; colAlpha.w = item->Highlight ? 1.0 : 0.9; DrawList.AddRectFilled(pMin, pMax, GetColorU32(colAlpha));