diff --git a/implot.h b/implot.h index a31c8b6b..6a1c8d7b 100644 --- a/implot.h +++ b/implot.h @@ -871,6 +871,12 @@ IMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys, int c IMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_API void PlotShadedG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0); +// Plots a shaded (filled) region between two lines, only if the second line is higher than the first one +IMPLOT_TMP void PlotShadedClip(const char* label_id, const T* values, int count, double yref=0, double xscale=1, double xstart=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); +IMPLOT_TMP void PlotShadedClip(const char* label_id, const T* xs, const T* ys, int count, double yref=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); +IMPLOT_TMP void PlotShadedClip(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T)); +IMPLOT_API void PlotShadedClipG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0); + // Plots a bar graph. Vertical by default. #bar_size and #shift are in plot units. IMPLOT_TMP void PlotBars(const char* label_id, const T* values, int count, double bar_size=0.67, double shift=0, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T)); diff --git a/implot_demo.cpp b/implot_demo.cpp index dbd7d7b7..b6739afc 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -384,6 +384,19 @@ void Demo_ShadedPlots() { ImPlot::PopStyleVar(); ImPlot::EndPlot(); } + if (ImPlot::BeginPlot("Shaded Clip Plots")) { + ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha); + ImPlot::SetNextLineStyle(ImVec4(0.0f,1.0f,0.0f,0.25f)); + ImPlot::SetNextFillStyle(ImVec4(0.0f,1.0f,0.0f,0.25f)); + ImPlot::PlotLine("Overlapping",xs,ys4,1001); + ImPlot::PlotShadedClip("Overlapping",xs,ys3,ys4,1001); + ImPlot::SetNextLineStyle(ImVec4(1.0f,0.0f,0.0f,0.25f)); + ImPlot::SetNextFillStyle(ImVec4(1.0f,0.0f,0.0f,0.25f)); + ImPlot::PlotLine("Overlapping",xs,ys3,1001); + ImPlot::PlotShadedClip("Overlapping",xs,ys4,ys3,1001); + ImPlot::PopStyleVar(); + ImPlot::EndPlot(); + } } //----------------------------------------------------------------------------- diff --git a/implot_items.cpp b/implot_items.cpp index 72811ee6..7bb4576f 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -1351,6 +1351,53 @@ struct RendererRectC : RendererBase { mutable ImVec2 UV; }; +template +struct RendererShadedClip : RendererShaded<_Getter1, _Getter2> { + RendererShadedClip(const _Getter1& getter1, const _Getter2& getter2, ImU32 col) : + RendererShaded<_Getter1, _Getter2>(getter1, getter2, col) + {} + + IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { + ImVec2 P21 = this->Transformer(this->Getter1(prim+1)); + ImVec2 P22 = this->Transformer(this->Getter2(prim+1)); + ImRect rect(ImMin(ImMin(ImMin(this->P11,this->P12),P21),P22), ImMax(ImMax(ImMax(this->P11,this->P12),P21),P22)); + if (!cull_rect.Overlaps(rect)) { + this->P11 = P21; + this->P12 = P22; + return false; + } + const int intersect = (this->P11.y > this->P12.y && P22.y > P21.y) || (this->P12.y > this->P11.y && P21.y > P22.y); + ImVec2 intersection = Intersection(this->P11,P21,this->P12,P22); + draw_list._VtxWritePtr[0].pos = this->P11; + draw_list._VtxWritePtr[0].uv = this->UV; + draw_list._VtxWritePtr[0].col = this->Col; + draw_list._VtxWritePtr[1].pos = P21; + draw_list._VtxWritePtr[1].uv = this->UV; + draw_list._VtxWritePtr[1].col = this->Col; + draw_list._VtxWritePtr[2].pos = intersection; + draw_list._VtxWritePtr[2].uv = this->UV; + draw_list._VtxWritePtr[2].col = this->Col; + draw_list._VtxWritePtr[3].pos = this->P12; + draw_list._VtxWritePtr[3].uv = this->UV; + draw_list._VtxWritePtr[3].col = this->Col; + draw_list._VtxWritePtr[4].pos = P22; + draw_list._VtxWritePtr[4].uv = this->UV; + draw_list._VtxWritePtr[4].col = this->Col; + draw_list._VtxWritePtr += 5; + draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); + draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + intersect); + draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0 + 3 * (this->P11.y >= this->P12.y) ); + draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); + draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3 - intersect); + draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + 3 * (P21.y >= P22.y) ); + draw_list._IdxWritePtr += 6; + draw_list._VtxCurrentIdx += 5; + this->P11 = P21; + this->P12 = P22; + return true; + } +}; + //----------------------------------------------------------------------------- // [SECTION] RenderPrimitives //----------------------------------------------------------------------------- @@ -1798,6 +1845,67 @@ void PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, I PlotShadedEx(label_id, getter1, getter2, flags); } +//----------------------------------------------------------------------------- +// [SECTION] PlotShadedClip +//----------------------------------------------------------------------------- + +// NEW +template +void PlotShadedClipEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) { + if (BeginItemEx(label_id, Fitter2(getter1,getter2), flags, ImPlotCol_Fill)) { + const ImPlotNextItemData& s = GetItemData(); + if (s.RenderFill) { + const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); + RenderPrimitives2(getter1,getter2,col); + } + EndItem(); + } +} + +template +void PlotShadedClip(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride) { + if (!(y_ref > -DBL_MAX)) + y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min; + if (!(y_ref < DBL_MAX)) + y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max; + GetterXY> getter1(IndexerLin(xscale,x0),IndexerIdx(values,count,offset,stride),count); + GetterXY getter2(IndexerLin(xscale,x0),IndexerConst(y_ref),count); + PlotShadedClipEx(label_id, getter1, getter2, flags); +} + +template +void PlotShadedClip(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride) { + if (y_ref == -HUGE_VAL) + y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min; + if (y_ref == HUGE_VAL) + y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max; + GetterXY,IndexerIdx> getter1(IndexerIdx(xs,count,offset,stride),IndexerIdx(ys,count,offset,stride),count); + GetterXY,IndexerConst> getter2(IndexerIdx(xs,count,offset,stride),IndexerConst(y_ref),count); + PlotShadedClipEx(label_id, getter1, getter2, flags); +} + + +template +void PlotShadedClip(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride) { + GetterXY,IndexerIdx> getter1(IndexerIdx(xs,count,offset,stride),IndexerIdx(ys1,count,offset,stride),count); + GetterXY,IndexerIdx> getter2(IndexerIdx(xs,count,offset,stride),IndexerIdx(ys2,count,offset,stride),count); + PlotShadedClipEx(label_id, getter1, getter2, flags); +} + +#define INSTANTIATE_MACRO(T) \ + template IMPLOT_API void PlotShadedClip(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride); \ + template IMPLOT_API void PlotShadedClip(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride); \ + template IMPLOT_API void PlotShadedClip(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride); +CALL_INSTANTIATE_FOR_NUMERIC_TYPES() +#undef INSTANTIATE_MACRO + +// custom +void PlotShadedClipG(const char* label_id, ImPlotGetter getter_func1, void* data1, ImPlotGetter getter_func2, void* data2, int count, ImPlotShadedFlags flags) { + GetterFuncPtr getter1(getter_func1, data1, count); + GetterFuncPtr getter2(getter_func2, data2, count); + PlotShadedClipEx(label_id, getter1, getter2, flags); +} + //----------------------------------------------------------------------------- // [SECTION] PlotBars //-----------------------------------------------------------------------------