diff --git a/implot.cpp b/implot.cpp index 1383654..c270a2c 100644 --- a/implot.cpp +++ b/implot.cpp @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.3 WIP +// ImPlot v0.4 WIP /* @@ -88,6 +88,7 @@ ImPlotStyle::ImPlotStyle() { Marker = ImPlotMarker_None; MarkerSize = 4; MarkerWeight = 1; + FillAlpha = 1; ErrorBarSize = 5; ErrorBarWeight = 1.5; DigitalBitHeight = 8; @@ -177,6 +178,11 @@ inline T Remap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); } +// Returns always positive modulo +inline int PosMod(int l, int r) { + return (l % r + r) % r; +} + // Turns NANs to 0s inline double ConstrainNan(double val) { return isnan(val) ? 0 : val; @@ -235,6 +241,11 @@ inline ImVec2 CalcTextSizeVertical(const char *text) { return ImVec2(sz.y, sz.x); } +/// Returns white or black text given background color +inline ImU32 CalcTextColor(const ImVec4& bg) { + return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.729 ? IM_COL32_BLACK : IM_COL32_WHITE; +} + } // private namespace //----------------------------------------------------------------------------- @@ -2240,57 +2251,13 @@ struct LineRenderer { static const int VtxConsumed = 4; }; -template -struct LineFillRenderer { - LineFillRenderer(Getter _getter, Transformer _transformer, ImU32 col, float zero) : - getter(_getter), - transformer(_transformer), - Col(col), - Zero(zero) - { - Prims = getter.Count - 1; - p1 = transformer(getter(0)); - } - inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { - ImVec2 p2 = transformer(getter(prim + 1)); - const int crosses_zero = (p1.y > Zero && p2.y < Zero) || (p1.y < Zero && p2.y > Zero); // could do y*y < 0 earlier on - const float xmid = p1.x + (p2.x - p1.x) / (p2.y-p1.y) * (Zero - p1.y); - DrawList._VtxWritePtr[0].pos = p1; - DrawList._VtxWritePtr[0].uv = uv; - DrawList._VtxWritePtr[0].col = Col; - DrawList._VtxWritePtr[1].pos = p2; - DrawList._VtxWritePtr[1].uv = uv; - DrawList._VtxWritePtr[1].col = Col; - DrawList._VtxWritePtr[2].pos = ImVec2(xmid, Zero); - DrawList._VtxWritePtr[2].uv = uv; - DrawList._VtxWritePtr[2].col = Col; - DrawList._VtxWritePtr[3].pos = ImVec2(p1.x, Zero); - DrawList._VtxWritePtr[3].uv = uv; - DrawList._VtxWritePtr[3].col = Col; - DrawList._VtxWritePtr[4].pos = ImVec2(p2.x, Zero);; - DrawList._VtxWritePtr[4].uv = uv; - DrawList._VtxWritePtr[4].col = Col; - DrawList._VtxWritePtr += 5; - DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx); - DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1 + crosses_zero); - DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); - DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); - DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - crosses_zero); - DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4); - DrawList._IdxWritePtr += 6; - DrawList._VtxCurrentIdx += 5; - p1 = p2; - return true; - } - Getter getter; - Transformer transformer; - int Prims; - ImU32 Col; - float Zero; - ImVec2 p1; - static const int IdxConsumed = 6; - static const int VtxConsumed = 5; -}; +inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) { + float v1 = (a1.x * a2.y - a1.y * a2.x); + float v2 = (b1.x * b2.y - b1.y * b2.x); + float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x)); + return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, + (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3); +} template struct ShadedRenderer { @@ -2309,32 +2276,36 @@ struct ShadedRenderer { inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { ImVec2 p21 = transformer(getter1(prim+1)); ImVec2 p22 = transformer(getter2(prim+1)); + const int intersect = (p11.y > p12.y && p22.y > p21.y) || (p12.y > p11.y && p21.y > p22.y); + ImVec2 intersection = Intersection(p11,p21,p12,p22); DrawList._VtxWritePtr[0].pos = p11; DrawList._VtxWritePtr[0].uv = uv; DrawList._VtxWritePtr[0].col = Col; - DrawList._VtxWritePtr[1].pos = p12; + DrawList._VtxWritePtr[1].pos = p21; DrawList._VtxWritePtr[1].uv = uv; DrawList._VtxWritePtr[1].col = Col; - DrawList._VtxWritePtr[2].pos = p21; + DrawList._VtxWritePtr[2].pos = intersection; DrawList._VtxWritePtr[2].uv = uv; DrawList._VtxWritePtr[2].col = Col; - DrawList._VtxWritePtr[3].pos = p22; + DrawList._VtxWritePtr[3].pos = p12; DrawList._VtxWritePtr[3].uv = uv; DrawList._VtxWritePtr[3].col = Col; - DrawList._VtxWritePtr += 4; + DrawList._VtxWritePtr[4].pos = p22; + DrawList._VtxWritePtr[4].uv = uv; + DrawList._VtxWritePtr[4].col = Col; + DrawList._VtxWritePtr += 5; DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx); - DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); - DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2); + DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1 + intersect); + DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); - DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2); - DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); + DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - intersect); + DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4); DrawList._IdxWritePtr += 6; - DrawList._VtxCurrentIdx += 4; + DrawList._VtxCurrentIdx += 5; p11 = p21; p12 = p22; return true; } - Getter1 getter1; Getter2 getter2; Transformer transformer; @@ -2342,7 +2313,7 @@ struct ShadedRenderer { ImU32 Col; ImVec2 p11, p12; static const int IdxConsumed = 6; - static const int VtxConsumed = 4; + static const int VtxConsumed = 5; }; // struct RectRenderer { @@ -2416,38 +2387,10 @@ inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList, bool cull) DrawList.PrimUnreserve(prims_culled * Renderer::IdxConsumed, prims_culled * Renderer::VtxConsumed); } -template -inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col, bool cull) { - if (HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased)) { - ImVec2 p1 = transformer(getter(0)); - for (int i = 0; i < getter.Count; ++i) { - ImVec2 p2 = transformer(getter(i)); - if (!cull || gp.BB_Plot.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2)))) - DrawList.AddLine(p1, p2, col, line_weight); - p1 = p2; - } - } - else { - RenderPrimitives(LineRenderer(getter, transformer, col, line_weight), DrawList, cull); - } -} - -template -inline void RenderLineFill(Getter getter, Transformer transformer, ImDrawList& DrawList, ImU32 col_fill) { - // TODO: Culling - float zero = transformer(0,0).y; - RenderPrimitives(LineFillRenderer(getter,transformer,col_fill,zero), DrawList, false); - // RenderPrimitives(getter, transformer, LineFillRenderer(col_fill, zero), DrawList, false); -} - //----------------------------------------------------------------------------- // GETTERS //----------------------------------------------------------------------------- -inline int PosMod(int l, int r) { - return (l % r + r) % r; -} - template inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) { idx = PosMod(offset + idx, count); @@ -2489,6 +2432,26 @@ struct GetterXsYs { } }; +template +struct GetterXsYRef { + GetterXsYRef(const T* xs, T y_ref, int count, int offset, int stride) { + Xs = xs; + YRef = y_ref; + Count = count; + Offset = PosMod(offset, count);; + Stride = stride; + } + const T* Xs; + T YRef; + int Count; + int Offset; + int Stride; + inline ImPlotPoint operator()(int idx) { + return ImPlotPoint(OffsetAndStride(Xs, idx, Count, Offset, Stride), YRef); + } +}; + + struct GetterImVec2 { GetterImVec2(const ImVec2* data, int count, int offset) { Data = data; @@ -2531,10 +2494,26 @@ struct GetterFuncPtrImPlotPoint { // PLOT //----------------------------------------------------------------------------- +template +inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col, bool cull) { + if (HasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased)) { + ImVec2 p1 = transformer(getter(0)); + for (int i = 0; i < getter.Count; ++i) { + ImVec2 p2 = transformer(getter(i)); + if (!cull || gp.BB_Plot.Overlaps(ImRect(ImMin(p1, p2), ImMax(p1, p2)))) + DrawList.AddLine(p1, p2, col, line_weight); + p1 = p2; + } + } + else { + RenderPrimitives(LineRenderer(getter, transformer, col, line_weight), DrawList, cull); + } +} + template inline void PlotEx(const char* label_id, Getter getter) { - IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Plot() needs to be called between BeginPlot() and EndPlot()!"); + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotEx() needs to be called between BeginPlot() and EndPlot()!"); ImPlotState* plot = gp.CurrentPlot; const int y_axis = plot->CurrentYAxis; @@ -2545,7 +2524,6 @@ inline void PlotEx(const char* label_id, Getter getter) ImDrawList & DrawList = *ImGui::GetWindowDrawList(); const bool rend_line = gp.Style.Colors[ImPlotCol_Line].w != 0 && gp.Style.LineWeight > 0; - const bool rend_fill = gp.Style.Colors[ImPlotCol_Fill].w > 0; ImU32 col_line = gp.Style.Colors[ImPlotCol_Line].w == -1 ? ImGui::GetColorU32(item->Color) : ImGui::GetColorU32(gp.Style.Colors[ImPlotCol_Line]); @@ -2560,26 +2538,8 @@ inline void PlotEx(const char* label_id, Getter getter) ImPlotPoint p = getter(i); FitPoint(p); } - if (rend_fill) { - ImPlotPoint p1 = getter(0); - ImPlotPoint p2 = getter(getter.Count - 1); - p1.y = 0; p2.y = 0; - FitPoint(p1); FitPoint(p2); - } } PushPlotClipRect(); - // render fill - if (getter.Count > 1 && rend_fill) { - const ImU32 col_fill = ImGui::GetColorU32(gp.Style.Colors[ImPlotCol_Fill]); - if (HasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && HasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) - RenderLineFill(getter, TransformerLogLog(y_axis), DrawList, col_fill); - else if (HasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale)) - RenderLineFill(getter, TransformerLogLin(y_axis), DrawList, col_fill); - else if (HasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) - RenderLineFill(getter, TransformerLinLog(y_axis), DrawList, col_fill); - else - RenderLineFill(getter, TransformerLinLin(y_axis), DrawList, col_fill); - } // render line if (getter.Count > 1 && rend_line) { const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; @@ -2628,7 +2588,6 @@ void PlotLine(const char* label_id, const ImVec2* data, int count, int offset) { return PlotEx(label_id, getter); } - //----------------------------------------------------------------------------- // double @@ -2655,47 +2614,6 @@ void PlotLine(const char* label_id, ImPlotPoint (*getter_func)(void* data, int i return PlotEx(label_id, getter); } -//----------------------------------------------------------------------------- -// PLOT SHADED -//----------------------------------------------------------------------------- - -void PlotShaded(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset, int stride) { - IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotShaded() needs to be called between BeginPlot() and EndPlot()!"); - - ImPlotState* plot = gp.CurrentPlot; - const int y_axis = plot->CurrentYAxis; - ImPlotItem* item = RegisterItem(label_id); - if (!item->Show) - return; - - GetterXsYs getter1(xs, ys1, count, offset, stride); - GetterXsYs getter2(xs, ys2, count, offset, stride); - - ImDrawList & DrawList = *ImGui::GetWindowDrawList(); - - ImVec4 col_fill = gp.Style.Colors[ImPlotCol_Fill].w == -1 ? (item->Color) : (gp.Style.Colors[ImPlotCol_Fill]); - col_fill.w *= gp.Style.FillAlpha; - - if (gp.Style.Colors[ImPlotCol_Fill].w != -1) - item->Color = gp.Style.Colors[ImPlotCol_Fill]; - - bool cull = HasFlag(plot->Flags, ImPlotFlags_CullData); - - if (gp.FitThisFrame) { - for (int i = 0; i < count; ++i) { - ImPlotPoint p1 = getter1(i); - ImPlotPoint p2 = getter2(i); - FitPoint(p1); - FitPoint(p2); - } - } - - PushPlotClipRect(); - RenderPrimitives(ShadedRenderer,GetterXsYs,TransformerLinLin>(getter1,getter2,TransformerLinLin(y_axis), ImGui::GetColorU32(col_fill)), DrawList, false); - PopPlotClipRect(); -} - - //----------------------------------------------------------------------------- // PLOT SCATTER //----------------------------------------------------------------------------- @@ -2761,6 +2679,81 @@ void PlotScatter(const char* label_id, ImPlotPoint (*getter)(void* data, int idx PopStyleVar(vars); } +//----------------------------------------------------------------------------- +// PLOT SHADED +//----------------------------------------------------------------------------- + +template +inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotShaded() needs to be called between BeginPlot() and EndPlot()!"); + + ImPlotState* plot = gp.CurrentPlot; + const int y_axis = plot->CurrentYAxis; + ImPlotItem* item = RegisterItem(label_id); + if (!item->Show) + return; + + ImDrawList & DrawList = *ImGui::GetWindowDrawList(); + + ImVec4 col_fill = gp.Style.Colors[ImPlotCol_Fill].w == -1 ? (item->Color) : (gp.Style.Colors[ImPlotCol_Fill]); + col_fill.w *= gp.Style.FillAlpha; + + if (gp.Style.Colors[ImPlotCol_Fill].w != -1) + item->Color = gp.Style.Colors[ImPlotCol_Fill]; + + bool cull = HasFlag(plot->Flags, ImPlotFlags_CullData); + + if (gp.FitThisFrame) { + for (int i = 0; i < ImMin(getter1.Count, getter2.Count); ++i) { + ImPlotPoint p1 = getter1(i); + ImPlotPoint p2 = getter2(i); + FitPoint(p1); + FitPoint(p2); + } + } + + PushPlotClipRect(); + if (HasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && HasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) + RenderPrimitives(ShadedRenderer(getter1,getter2,TransformerLogLog(y_axis), ImGui::GetColorU32(col_fill)), DrawList, false); + else if (HasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale)) + RenderPrimitives(ShadedRenderer(getter1,getter2,TransformerLogLin(y_axis), ImGui::GetColorU32(col_fill)), DrawList, false); + else if (HasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) + RenderPrimitives(ShadedRenderer(getter1,getter2,TransformerLinLog(y_axis), ImGui::GetColorU32(col_fill)), DrawList, false); + else + RenderPrimitives(ShadedRenderer(getter1,getter2,TransformerLinLin(y_axis), ImGui::GetColorU32(col_fill)), DrawList, false); + PopPlotClipRect(); +} + +//----------------------------------------------------------------------------- +// float + +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); + PlotShadedEx(label_id, getter1, getter2); +} + +void PlotShaded(const char* label_id, const float* xs, const float* ys, int count, float y_ref, int offset, int stride) { + GetterXsYs getter1(xs, ys, count, offset, stride); + GetterXsYRef getter2(xs, y_ref, count, offset, stride); + PlotShadedEx(label_id, getter1, getter2); +} + +//----------------------------------------------------------------------------- +// double + +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); + PlotShadedEx(label_id, getter1, getter2); +} + +void PlotShaded(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride) { + GetterXsYs getter1(xs, ys, count, offset, stride); + GetterXsYRef getter2(xs, y_ref, count, offset, stride); + PlotShadedEx(label_id, getter1, getter2); +} + //----------------------------------------------------------------------------- // PLOT BAR V //----------------------------------------------------------------------------- @@ -3239,7 +3232,10 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value char buff[32]; sprintf(buff, fmt, values[i]); ImVec2 size = ImGui::CalcTextSize(buff); - DrawList.AddText(px - size * 0.5f, ImGui::GetColorU32(ImGuiCol_Text), buff); + float t = (float)Remap(values[i], scale_min, scale_max, T(0), T(1)); + ImVec4 color = LerpColormap(t); + ImU32 col = CalcTextColor(color); + DrawList.AddText(px - size * 0.5f, col, buff); i++; } } diff --git a/implot.h b/implot.h index e3635f8..f3a3a02 100644 --- a/implot.h +++ b/implot.h @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// ImPlot v0.3 WIP +// ImPlot v0.4 WIP #pragma once #include "imgui.h" @@ -211,10 +211,6 @@ void PlotLine(const char* label_id, const ImVec2* data, int count, int offset = void PlotLine(const char* label_id, const ImPlotPoint* data, int count, int offset = 0); void PlotLine(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. Intersecting lines are not currently supported. -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 standard 2D scatter plot. void PlotScatter(const char* label_id, const float* values, int count, int offset = 0, int stride = sizeof(float)); void PlotScatter(const char* label_id, const double* values, int count, int offset = 0, int stride = sizeof(double)); @@ -224,6 +220,12 @@ void PlotScatter(const char* label_id, const ImVec2* data, int count, int offset void PlotScatter(const char* label_id, const ImPlotPoint* data, int count, int offset = 0); 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* 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)); + // Plots a vertical bar graph. 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)); void PlotBars(const char* label_id, const double* values, int count, double width = 0.67f, double shift = 0, int offset = 0, int stride = sizeof(double)); diff --git a/implot_demo.cpp b/implot_demo.cpp index 717562b..59a66f4 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -137,7 +137,7 @@ void ShowDemoWindow(bool* p_open) { ImGui::EndMenuBar(); } //------------------------------------------------------------------------- - ImGui::Text("ImPlot says hello. (0.3 WIP)"); + ImGui::Text("ImPlot says hello. (0.4 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."); @@ -198,7 +198,32 @@ void ShowDemoWindow(bool* p_open) { } } //------------------------------------------------------------------------- - if (ImGui::CollapsingHeader("Filled Plots")) { + if (ImGui::CollapsingHeader("Shaded Plots")) { + static t_float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001]; + srand(0); + for (int i = 0; i < 1001; ++i) { + xs[i] = i * 0.001f; + ys[i] = 0.25f + 0.25f * Sin(25 * xs[i]) * Sin(5 * xs[i]) + RandomRange(-0.01f, 0.01f); + ys1[i] = ys[i] + RandomRange(0.1f, 0.12f); + ys2[i] = ys[i] - RandomRange(0.1f, 0.12f); + ys3[i] = 0.75f + 0.2f * Sin(25 * xs[i]); + ys4[i] = 0.75f + 0.1f * Cos(25 * xs[i]); + } + static float alpha = 0.25f; + ImGui::DragFloat("Alpha",&alpha,0.01f,0,1); + if (ImPlot::BeginPlot("Shaded Plots")) { + ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha); + ImPlot::PlotShaded("Uncertain Data",xs,ys1,ys2,1001); + ImPlot::PlotLine("Uncertain Data", xs, ys, 1001); + ImPlot::PlotShaded("Overlapping",xs,ys3,ys4,1001); + ImPlot::PlotLine("Overlapping",xs,ys3,1001); + ImPlot::PlotLine("Overlapping",xs,ys4,1001); + ImPlot::PopStyleVar(); + ImPlot::EndPlot(); + } + } + //------------------------------------------------------------------------- + if (ImGui::CollapsingHeader("Filled Plots")) { static t_float xs1[101], ys1[101], ys2[101], ys3[101]; srand(0); for (int i = 0; i < 101; ++i) { @@ -207,39 +232,26 @@ void ShowDemoWindow(bool* p_open) { ys2[i] = RandomRange(275,350); ys3[i] = RandomRange(150,225); } + static bool show_lines = true; + static bool show_fills = true; + static float fill_ref = 0; + ImGui::Checkbox("Lines",&show_lines); ImGui::SameLine(); + ImGui::Checkbox("Fills",&show_fills); + ImGui::DragFloat("Reference",&fill_ref, 1, -100, 500); ImPlot::SetNextPlotLimits(0,100,0,500); if (ImPlot::BeginPlot("Stock Prices", "Days", "Price")) { - ImPlot::PushStyleColor(ImPlotCol_Line, ImVec4(1,1,0,1)); - ImPlot::PushStyleColor(ImPlotCol_Fill, ImVec4(1,1,0,0.25f)); - ImPlot::PlotLine("Stock 1", xs1, ys1, 101); - ImPlot::PopStyleColor(2); - ImPlot::PushStyleColor(ImPlotCol_Line, ImVec4(1,0,1,1)); - ImPlot::PushStyleColor(ImPlotCol_Fill, ImVec4(1,0,1,0.25f)); - ImPlot::PlotLine("Stock 2", xs1, ys2, 101); - ImPlot::PopStyleColor(2); - ImPlot::PushStyleColor(ImPlotCol_Line, ImVec4(1,0,0,1)); - ImPlot::PushStyleColor(ImPlotCol_Fill, ImVec4(1,0,0,0.25f)); - ImPlot::PlotLine("Stock 3", xs1, ys3, 101); - ImPlot::PopStyleColor(2); - ImPlot::EndPlot(); - } - } - if (ImGui::CollapsingHeader("Shaded Plots")) { - static double xs[1001], ys[1001], ys1[1001], ys2[1001]; - srand(0); - for (int i = 0; i < 1001; ++i) { - xs[i] = i * 0.001f; - ys[i] = 0.5f + 0.25f * Sin(25 * xs[i]) * Sin(5 * xs[i]) + RandomRange(-0.01f, 0.01f); - ys1[i] = ys[i] + RandomRange(0.1f, 0.12f); - ys2[i] = ys[i] - RandomRange(0.1f, 0.12f); - } - static float alpha = 0.25f; - ImGui::DragFloat("Alpha",&alpha,0.01f,0,1); - if (ImPlot::BeginPlot("Shaded Plots")) { - ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha); - ImPlot::PlotShaded("Uncertain Data",xs,ys1,ys2,1001); - ImPlot::PlotLine("Uncertain Data", xs, ys, 1001); - ImPlot::PopStyleVar(); + if (show_fills) { + ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f); + ImPlot::PlotShaded("Stock 1", xs1, ys1, 101, fill_ref); + ImPlot::PlotShaded("Stock 2", xs1, ys2, 101, fill_ref); + ImPlot::PlotShaded("Stock 3", xs1, ys3, 101, fill_ref); + ImPlot::PopStyleVar(); + } + if (show_lines) { + ImPlot::PlotLine("Stock 1", xs1, ys1, 101); + ImPlot::PlotLine("Stock 2", xs1, ys2, 101); + ImPlot::PlotLine("Stock 3", xs1, ys3, 101); + } ImPlot::EndPlot(); } } @@ -731,6 +743,7 @@ void ShowDemoWindow(bool* p_open) { } ImGui::EndGroup(); ImGui::SameLine(); + srand(ImGui::GetTime()*10000000); static t_float t = 0; if (!paused) { t += ImGui::GetIO().DeltaTime;