From 9deca4e422a4249caa9f6a12faaffe1ea429d584 Mon Sep 17 00:00:00 2001 From: epezent Date: Thu, 20 Aug 2020 23:01:21 -0500 Subject: [PATCH] add overloads for PlotShaded, ImPlotStyleVar_PlotPadding, and ImGui Tables API demo section --- implot.cpp | 42 +++++++++++++++++++++---------- implot.h | 10 ++++++-- implot_demo.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++--- implot_internal.h | 3 ++- implot_items.cpp | 25 +++++++++++++++++- 5 files changed, 124 insertions(+), 20 deletions(-) diff --git a/implot.cpp b/implot.cpp index 5ea473f..c32aaeb 100644 --- a/implot.cpp +++ b/implot.cpp @@ -88,6 +88,7 @@ ImPlotStyle::ImPlotStyle() { ErrorBarWeight = 1.5f; DigitalBitHeight = 8; DigitalBitGap = 4; + PlotPadding = ImVec2(8,8); Colors[ImPlotCol_Line] = IMPLOT_COL_AUTO; Colors[ImPlotCol_Fill] = IMPLOT_COL_AUTO; @@ -660,7 +661,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons ImGui::RenderFrame(gp.BB_Frame.Min, gp.BB_Frame.Max, gp.Col_Frame, true, Style.FrameRounding); // canvas bb - gp.BB_Canvas = ImRect(gp.BB_Frame.Min + Style.WindowPadding, gp.BB_Frame.Max - Style.WindowPadding); + gp.BB_Canvas = ImRect(gp.BB_Frame.Min + gp.Style.PlotPadding, gp.BB_Frame.Max - gp.Style.PlotPadding); // adaptive divisions int x_divisions = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetWidth())); @@ -1719,15 +1720,16 @@ 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, FillAlpha) }, // ImPlotStyleVar_FillAlpha - { 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, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap) } // ImPlotStyleVar_DigitalBitGap + { 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, FillAlpha) }, // ImPlotStyleVar_FillAlpha + { 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, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding }; static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) @@ -1801,6 +1803,20 @@ void PushStyleVar(ImPlotStyleVar idx, int val) { IM_ASSERT(0 && "Called PushStyleVar() int variant but variable is not a int!"); } +void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) +{ + ImPlotContext& gp = *GImPlot; + const ImPlotStyleVarInfo* var_info = GetPlotStyleVarInfo(idx); + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) + { + ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&gp.Style); + gp.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; + return; + } + IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!"); +} + void PopStyleVar(int count) { ImPlotContext& gp = *GImPlot; while (count > 0) { @@ -1883,16 +1899,16 @@ void ShowColormapScale(double scale_min, double scale_max, float height) { const float bar_w = 20; ImDrawList &DrawList = *Window->DrawList; - ImVec2 size(bar_w + txt_off + max_width + 2 * Style.WindowPadding.x, height); + ImVec2 size(bar_w + txt_off + max_width + 2 * gp.Style.PlotPadding.x, height); ImRect bb_frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + size); ImGui::ItemSize(bb_frame); if (!ImGui::ItemAdd(bb_frame, 0, &bb_frame)) return; ImGui::RenderFrame(bb_frame.Min, bb_frame.Max, ImGui::GetColorU32(ImGuiCol_FrameBg)); - ImRect bb_grad(bb_frame.Min + Style.WindowPadding, bb_frame.Min + ImVec2(bar_w + Style.WindowPadding.x, height - Style.WindowPadding.y)); + ImRect bb_grad(bb_frame.Min + gp.Style.PlotPadding, bb_frame.Min + ImVec2(bar_w + gp.Style.PlotPadding.x, height - gp.Style.PlotPadding.y)); int num_cols = GetColormapSize(); - float h_step = (height - 2 * Style.WindowPadding.y) / (num_cols - 1); + float h_step = (height - 2 * gp.Style.PlotPadding.y) / (num_cols - 1); for (int i = 0; i < num_cols-1; ++i) { ImRect rect(bb_grad.Min.x, bb_grad.Min.y + h_step * i, bb_grad.Max.x, bb_grad.Min.y + h_step * (i + 1)); ImU32 col1 = ImGui::GetColorU32(GetColormapColor(num_cols - 1 - i)); diff --git a/implot.h b/implot.h index 6db25b5..6d67842 100644 --- a/implot.h +++ b/implot.h @@ -102,6 +102,7 @@ enum ImPlotStyleVar_ { ImPlotStyleVar_ErrorBarWeight, // float, error bar whisker weight in pixels ImPlotStyleVar_DigitalBitHeight, // float, digital channels bit height (at 1) in pixels ImPlotStyleVar_DigitalBitGap, // float, digital channels bit padding gap in pixels + ImPlotStyleVar_PlotPadding, // ImVec2, padding between widget frame and plot area and/or labels ImPlotStyleVar_COUNT }; @@ -174,6 +175,7 @@ struct ImPlotStyle { float ErrorBarWeight; // = 1.5, error bar whisker weight in pixels float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels float DigitalBitGap; // = 4, digital channels bit padding gap in pixels + ImVec2 PlotPadding; // = (8,8), padding between widget frame and plot area and/or labels ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors ImPlotStyle(); }; @@ -259,10 +261,12 @@ void PlotScatter(const char* label_id, const ImPlotPoint* data, int count, int o void PlotScatter(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0); // Plots a shaded (filled) region between two lines, or a line and a horizontal reference. -void PlotShaded(const char* label_id, const float* xs, const float* ys1, const float* ys2, int count, int offset = 0, int stride = sizeof(float)); -void PlotShaded(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset = 0, int stride = sizeof(double)); +void PlotShaded(const char* label_id, const float* values, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float)); +void PlotShaded(const char* label_id, const double* values, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double)); void PlotShaded(const char* label_id, const float* xs, const float* ys, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float)); void PlotShaded(const char* label_id, const double* xs, const double* ys, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double)); +void PlotShaded(const char* label_id, const float* xs, const float* ys1, const float* ys2, int count, int offset = 0, int stride = sizeof(float)); +void PlotShaded(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset = 0, int stride = sizeof(double)); // Plots a vertical bar graph. #width and #shift are in X units. void PlotBars(const char* label_id, const float* values, int count, float width = 0.67f, float shift = 0, int offset = 0, int stride = sizeof(float)); @@ -356,6 +360,8 @@ void PopStyleColor(int count = 1); void PushStyleVar(ImPlotStyleVar idx, float val); // Temporarily modify a style variable of int type. Don't forget to call PopStyleVar! void PushStyleVar(ImPlotStyleVar idx, int val); +// Temporarily modify a style variable of ImVec2 type. Don't forget to call PopStyleVar! +void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val); // Undo temporary style modification. void PopStyleVar(int count = 1); diff --git a/implot_demo.cpp b/implot_demo.cpp index 7e5339d..d1303d8 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -33,9 +33,12 @@ namespace MyImPlot { -// Example for Custom Plotters and Tooltips section. Plots a candlestick chart for financial data. See implementatoin at bottom. +// Example for Custom Plotters and Tooltips section. Plots a candlestick chart for financial data. See implementation at bottom. void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip = true, float width_percent = 0.25f, ImVec4 bullCol = ImVec4(0,1,0,1), ImVec4 bearCol = ImVec4(1,0,0,1)); +// Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom. +void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size); + } namespace ImPlot { @@ -404,7 +407,7 @@ void ShowDemoWindow(bool* p_open) { ImGui::SameLine(); ImGui::LabelText("##Colormap Index", "%s", cmap_names[map]); ImGui::SetNextItemWidth(225); - ImGui::DragFloat("Max",&scale_max,0.01f,0.1f,20); + ImGui::DragFloatRange2("Min / Max",&scale_min, &scale_max, 0.01f, -20, 20); static ImPlotAxisFlags axes_flags = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax | ImPlotAxisFlags_TickLabels; static const char* xlabels[] = {"C1","C2","C3","C4","C5","C6","C7"}; static const char* ylabels[] = {"R1","R2","R3","R4","R5","R6","R7"}; @@ -915,6 +918,45 @@ void ShowDemoWindow(bool* p_open) { ImGui::EndDragDropTarget(); } } + if (ImGui::CollapsingHeader("Tables")) { +#ifdef IMGUI_HAS_TABLE + static ImGuiTableFlags flags = ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_RowBg; + static bool anim = true; + static int offset = 0; + ImGui::BulletText("Plots can be used inside of ImGui tables."); + ImGui::Checkbox("Animate",&anim); + if (anim) + offset = (offset + 1) % 100; + if (ImGui::BeginTable("##table", 3, flags, ImVec2(-1,0))) { + ImGui::TableSetupColumn("Electrode", ImGuiTableColumnFlags_WidthFixed, 75.0f); + ImGui::TableSetupColumn("Voltage", ImGuiTableColumnFlags_WidthFixed, 75.0f); + ImGui::TableSetupColumn("EMG Signal"); + ImGui::TableAutoHeaders(); + ImPlot::SetColormap(ImPlotColormap_Cool, 10); + + for (int row = 0; row < 10; row++) + { + ImGui::TableNextRow(); + static float data[100]; + srand(row); + for (int i = 0; i < 100; ++i) + data[i] = RandomRange(0,10); + ImGui::TableSetColumnIndex(0); + ImGui::Text("EMG %d", row); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%.3f V", data[offset]); + ImGui::TableSetColumnIndex(2); + ImGui::PushID(row); + MyImPlot::Sparkline("##spark",data,100,0,11.0f,offset,ImPlot::GetColormapColor(row),ImVec2(-1, 35)); + ImGui::PopID(); + } + ImPlot::SetColormap(ImPlotColormap_Default); + ImGui::EndTable(); + } +#else + ImGui::BulletText("You need to merge the ImGui 'tables' branch for this section."); +#endif + } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Offset and Stride")) { static const int k_circles = 11; @@ -1036,7 +1078,7 @@ void ShowDemoWindow(bool* p_open) { MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 50, tooltip); ImPlot::EndPlot(); } - } + } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Benchmark")) { static const int n_items = 100; @@ -1142,4 +1184,20 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens } } +// Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom. +void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) { + ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0)); + ImPlot::SetNextPlotLimits(0, count - 1, min_v, max_v, ImGuiCond_Always); + if (ImPlot::BeginPlot(id,0,0,size,ImPlotFlags_NoChild,0,0,0,0)) { + ImPlot::PushStyleColor(ImPlotCol_Line, col); + ImPlot::PlotLine(id, values, count, offset); + ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f); + ImPlot::PlotShaded(id, values, count, 0, offset); + ImPlot::PopStyleVar(); + ImPlot::PopStyleColor(); + ImPlot::EndPlot(); + } + ImPlot::PopStyleVar(); +} + } diff --git a/implot_internal.h b/implot_internal.h index 1fd8cd1..de076dd 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -63,7 +63,8 @@ extern ImPlotContext* GImPlot; // Current implicit context pointer // [SECTION] Macros and Constants //----------------------------------------------------------------------------- -// Constants can be changed unless stated otherwise +// Constants can be changed unless stated otherwise. We may move some of these +// to ImPlotStyleVar_ over time. // Default plot frame width when requested width is auto (i.e. 0). This is not the plot area width! #define IMPLOT_DEFAULT_W 400 diff --git a/implot_items.cpp b/implot_items.cpp index 795559f..a97a4dc 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -88,7 +88,18 @@ struct GetterXsYs { } }; -/// Interprets an array of X points as ImPlotPoints where the Y value is a constant reference value +// Always returns a constant Y reference value where the X value is the index +template +struct GetterYRef { + GetterYRef(T y_ref, int count) { YRef = y_ref; Count = count; } + inline ImPlotPoint operator()(int idx) { + return ImPlotPoint((T)idx, YRef); + } + T YRef; + int Count; +}; + +// Interprets an array of X points as ImPlotPoints where the Y value is a constant reference value template struct GetterXsYRef { GetterXsYRef(const T* xs, T y_ref, int count, int offset, int stride) { @@ -799,6 +810,12 @@ inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) } // float + +void PlotShaded(const char* label_id, const float* values, int count, float y_ref, int offset, int stride) { + GetterYs getter1(values,count,offset,stride); + GetterYRef getter2(y_ref, count); + PlotShadedEx(label_id, getter1, getter2);} + void PlotShaded(const char* label_id, const float* xs, const float* ys1, const float* ys2, int count, int offset, int stride) { GetterXsYs getter1(xs, ys1, count, offset, stride); GetterXsYs getter2(xs, ys2, count, offset, stride); @@ -812,6 +829,12 @@ void PlotShaded(const char* label_id, const float* xs, const float* ys, int coun } // double +void PlotShaded(const char* label_id, const double* values, int count, double y_ref, int offset, int stride) { + GetterYs getter1(values,count,offset,stride); + GetterYRef getter2(y_ref, count); + PlotShadedEx(label_id, getter1, getter2); +} + void PlotShaded(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset, int stride) { GetterXsYs getter1(xs, ys1, count, offset, stride); GetterXsYs getter2(xs, ys2, count, offset, stride);