diff --git a/implot.cpp b/implot.cpp index dc1cf90..32a9e9f 100644 --- a/implot.cpp +++ b/implot.cpp @@ -31,6 +31,7 @@ Below is a change-log of API breaking changes only. If you are using one of the When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files. You can read releases logs https://github.com/epezent/implot/releases for more details. +- 2020/08/17 (0.5) - PlotText was changed so that text is centered horizontally and vertically about the desired point. - 2020/08/16 (0.5) - An ImPlotContext must be explicitly created and destroyed now with `CreateContext` and `DestroyContext`. Previously, the context was statically initialized in this source file. - 2020/06/13 (0.4) - The flags `ImPlotAxisFlag_Adaptive` and `ImPlotFlags_Cull` were removed. Both are now done internally by default. - 2020/06/03 (0.3) - The signature and behavior of PlotPieChart was changed so that data with sum less than 1 can optionally be normalized. The label format can now be specified as well. diff --git a/implot.h b/implot.h index c88f9db..a9a8b04 100644 --- a/implot.h +++ b/implot.h @@ -263,37 +263,33 @@ void PlotShaded(const char* label_id, const double* xs, const double* ys1, const 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. +// 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)); 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)); void PlotBars(const char* label_id, const float* xs, const float* ys, int count, float width, int offset = 0, int stride = sizeof(float)); void PlotBars(const char* label_id, const double* xs, const double* ys, int count, double width, int offset = 0, int stride = sizeof(double)); void PlotBars(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double width, int offset = 0); -// Plots a horizontal bar graph. +// Plots a horizontal bar graph. # height and # shift are in Y units. void PlotBarsH(const char* label_id, const float* values, int count, float height = 0.67f, float shift = 0, int offset = 0, int stride = sizeof(float)); void PlotBarsH(const char* label_id, const double* values, int count, double height = 0.67f, double shift = 0, int offset = 0, int stride = sizeof(double)); void PlotBarsH(const char* label_id, const float* xs, const float* ys, int count, float height, int offset = 0, int stride = sizeof(float)); void PlotBarsH(const char* label_id, const double* xs, const double* ys, int count, double height, int offset = 0, int stride = sizeof(double)); void PlotBarsH(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset = 0); -// Plots vertical error bar. The label_id should match the label_id of the associated line or bar plot. +// Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot. void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset = 0, int stride = sizeof(float)); void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset = 0, int stride = sizeof(double)); 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, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double)); -// Plots horizontal error bars. The label_id should match the label_id of the associated line or bar plot. +// Plots horizontal error bars. The label_id should be the same as the label_id of the associated line or bar plot. void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset = 0, int stride = sizeof(float)); void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset = 0, int stride = sizeof(double)); void PlotErrorBarsH(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 PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double)); -// Plots a vertical candlestick chart for financial data. -void PlotCandlestick(const char* label_id, const float* xs, const float* opens, const float* closes, const float* lows, const float* highs, int count, float width1 = 2, float width2 = 10, int offset = 0, int stride = sizeof(float)); - - -// Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot coordinates. +// Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. void PlotPieChart(const char** label_ids, const float* values, int count, float x, float y, float radius, bool normalize = false, const char* label_fmt = "%.1f", float angle0 = 90); void PlotPieChart(const char** label_ids, const double* values, int count, double x, double y, double radius, bool normalize = false, const char* label_fmt = "%.1f", double angle0 = 90); @@ -306,12 +302,7 @@ void PlotDigital(const char* label_id, const float* xs, const float* ys, int cou void PlotDigital(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double)); void PlotDigital(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0); -// Plots axis-aligned, filled rectangles. Every two consecutive points defines opposite corners of a single rectangle. -void PlotRects(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); -void PlotRects(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double)); -void PlotRects(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0); - -// Plots a text label at point x,y. Text color can be changed with ImGui::PushStyleColor(ImGuiCol_Text, ...). +// Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImGui::PushStyleColor(ImGuiCol_Text, ...). void PlotText(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); void PlotText(const char* text, double x, double y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); diff --git a/implot_demo.cpp b/implot_demo.cpp index 38ae14d..39097e4 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -538,11 +538,11 @@ void ShowDemoWindow(bool* p_open) { ImPlot::PopStyleVar(6); ImPlot::PopStyleColor(3); - ImPlot::PlotText("Filled Markers", 1.5, 11.75); - ImPlot::PlotText("Open Markers", 6.75, 11.75); + ImPlot::PlotText("Filled Markers", 2.5f, 6.0f); + ImPlot::PlotText("Open Markers", 7.5f, 6.0f); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0,1,0,1)); - ImPlot::PlotText("Fancy Markers", 4.5, 4.25, true); + ImPlot::PlotText("Fancy Markers", 5.0f, 6.0f, true); ImGui::PopStyleColor(); ImPlot::SetColormap(ImPlotColormap_Default); @@ -993,7 +993,6 @@ void ShowDemoWindow(bool* p_open) { } //------------------------------------------------------------------------- if (ImGui::CollapsingHeader("Custom Rendering")) { - static t_float xs[] = {0.1f,0.2f,0.3f,0.4f}; if (ImPlot::BeginPlot("##CustomRend")) { ImVec2 cntr = ImPlot::PlotToPixels(ImPlotPoint(0.5f, 0.5f)); ImVec2 rmin = ImPlot::PlotToPixels(ImPlotPoint(0.25f, 0.75f)); @@ -1002,7 +1001,6 @@ void ShowDemoWindow(bool* p_open) { ImGui::GetWindowDrawList()->AddCircleFilled(cntr,20,IM_COL32(255,255,0,255),20); ImGui::GetWindowDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255)); ImPlot::PopPlotClipRect(); - ImPlot::PlotRects("rects", xs, xs, 4); ImPlot::EndPlot(); } } diff --git a/implot_internal.h b/implot_internal.h index ec74e12..f272c15 100644 --- a/implot_internal.h +++ b/implot_internal.h @@ -541,4 +541,14 @@ inline ImVec4 GetErrorBarColor() { return ColorIsAuto(ImPlotCol_ErrorBar) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : GImPlot->Style.Colors[ImPlotCol_ErrorBar]; } +//----------------------------------------------------------------------------- +// [SECTION] Internal / Experimental Plotters +// No guarantee of forward compatibility here! +//----------------------------------------------------------------------------- + +// Plots axis-aligned, filled rectangles. Every two consecutive points defines opposite corners of a single rectangle. +void PlotRects(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); +void PlotRects(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double)); +void PlotRects(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0); + } // namespace ImPlot \ No newline at end of file diff --git a/implot_items.cpp b/implot_items.cpp index cbc1537..febfd0a 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -48,6 +48,10 @@ namespace ImPlot { // GETTERS //----------------------------------------------------------------------------- +// Getters can be thought of as iterators that convert user data (e.g. raw arrays) +// to ImPlotPoints + +// Interprets an array of Y points as ImPlotPoints where the X value is the index template struct GetterYs { GetterYs(const T* ys, int count, int offset, int stride) { @@ -65,6 +69,7 @@ struct GetterYs { } }; +// Interprets separate arrays for X and Y points as ImPlotPoints template struct GetterXsYs { GetterXsYs(const T* xs, const T* ys, int count, int offset, int stride) { @@ -83,6 +88,7 @@ struct GetterXsYs { } }; +/// 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) { @@ -102,6 +108,7 @@ struct GetterXsYRef { } }; +// Interprets an array of ImVec2 points as ImPlotPoints struct GetterImVec2 { GetterImVec2(const ImVec2* data, int count, int offset) { Data = data; @@ -114,6 +121,7 @@ struct GetterImVec2 { int Offset; }; +// Interprets an array of ImPlotPoints as ImPlotPoints (essentially a pass through) struct GetterImPlotPoint { GetterImPlotPoint(const ImPlotPoint* data, int count, int offset) { Data = data; @@ -126,6 +134,7 @@ struct GetterImPlotPoint { int Offset; }; +/// Interprets a user's function pointer as ImPlotPoints struct GetterFuncPtrImPlotPoint { GetterFuncPtrImPlotPoint(ImPlotPoint (*g)(void* data, int idx), void* d, int count, int offset) { getter = g; @@ -172,6 +181,9 @@ struct GetterError { // TRANSFORMERS //----------------------------------------------------------------------------- +// Transforms convert points in plot space (i.e. ImPlotPoint) to pixel space (i.e. ImVec2) + +// Transforms points for linear x and linear y space struct TransformerLinLin { TransformerLinLin(int y_axis) : YAxis(y_axis) {} @@ -185,6 +197,7 @@ struct TransformerLinLin { int YAxis; }; +// Transforms points for log x and linear y space struct TransformerLogLin { TransformerLogLin(int y_axis) : YAxis(y_axis) {} @@ -200,6 +213,7 @@ struct TransformerLogLin { int YAxis; }; +// Transforms points for linear x and log y space struct TransformerLinLog { TransformerLinLog(int y_axis) : YAxis(y_axis) {} @@ -214,6 +228,7 @@ struct TransformerLinLog { int YAxis; }; +// Transforms points for log x and log y space struct TransformerLogLog { TransformerLogLog(int y_axis) : YAxis(y_axis) {} @@ -232,9 +247,174 @@ struct TransformerLogLog { }; //----------------------------------------------------------------------------- -// RENDERERS +// PRIMITIVE RENDERERS //----------------------------------------------------------------------------- +template +struct LineRenderer { + inline LineRenderer(TGetter getter, TTransformer transformer, ImU32 col, float weight) : + Getter(getter), + Transformer(transformer) + { + Prims = Getter.Count - 1; + Col = col; + Weight = weight; + P1 = Transformer(Getter(0)); + } + inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { + ImPlotContext& gp = *GImPlot; + ImVec2 P2 = Transformer(Getter(prim + 1)); + if (!gp.BB_Plot.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { + P1 = P2; + return false; + } + float dx = P2.x - P1.x; + float dy = P2.y - P1.y; + IM_NORMALIZE2F_OVER_ZERO(dx, dy); + dx *= (Weight * 0.5f); + dy *= (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; + 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; + 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; + 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; + 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; + P1 = P2; + return true; + } + TGetter Getter; + TTransformer Transformer; + int Prims; + ImU32 Col; + float Weight; + ImVec2 P1; + static const int IdxConsumed = 6; + static const int VtxConsumed = 4; +}; + +template +struct ShadedRenderer { + ShadedRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col) : + Getter1(getter1), + Getter2(getter2), + Transformer(transformer), + Col(col) + { + Prims = ImMin(Getter1.Count, Getter2.Count) - 1; + P11 = Transformer(Getter1(0)); + P12 = Transformer(Getter2(0)); + } + + inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { + // TODO: Culling + 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 = P21; + DrawList._VtxWritePtr[1].uv = uv; + DrawList._VtxWritePtr[1].col = Col; + DrawList._VtxWritePtr[2].pos = intersection; + DrawList._VtxWritePtr[2].uv = uv; + DrawList._VtxWritePtr[2].col = Col; + DrawList._VtxWritePtr[3].pos = P12; + DrawList._VtxWritePtr[3].uv = uv; + DrawList._VtxWritePtr[3].col = Col; + 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 + intersect); + DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); + DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); + DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - intersect); + DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4); + DrawList._IdxWritePtr += 6; + DrawList._VtxCurrentIdx += 5; + P11 = P21; + P12 = P22; + return true; + } + TGetter1 Getter1; + TGetter2 Getter2; + TTransformer Transformer; + int Prims; + ImU32 Col; + ImVec2 P11, P12; + static const int IdxConsumed = 6; + static const int VtxConsumed = 5; +}; + +template +struct RectRenderer { + inline RectRenderer(TGetter getter, TTransformer transformer, ImU32 col) : + Getter(getter), + Transformer(transformer) + { + Prims = Getter.Count / 2; + Col = col; + } + inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { + // TODO: Culling + ImVec2 P1 = Transformer(Getter(2*prim)); + ImVec2 P2 = Transformer(Getter(2*prim+1)); + DrawList._VtxWritePtr[0].pos = P1; + DrawList._VtxWritePtr[0].uv = uv; + DrawList._VtxWritePtr[0].col = Col; + DrawList._VtxWritePtr[1].pos.x = P1.x; + DrawList._VtxWritePtr[1].pos.y = P2.y; + DrawList._VtxWritePtr[1].uv = uv; + DrawList._VtxWritePtr[1].col = Col; + DrawList._VtxWritePtr[2].pos = P2; + DrawList._VtxWritePtr[2].uv = uv; + DrawList._VtxWritePtr[2].col = Col; + DrawList._VtxWritePtr[3].pos.x = P2.x; + DrawList._VtxWritePtr[3].pos.y = P1.y; + DrawList._VtxWritePtr[3].uv = uv; + DrawList._VtxWritePtr[3].col = Col; + DrawList._VtxWritePtr += 4; + DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx); + DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); + 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 += 6; + DrawList._VtxCurrentIdx += 4; + return true; + } + TGetter Getter; + TTransformer Transformer; + int Prims; + ImU32 Col; + static const int IdxConsumed = 6; + static const int VtxConsumed = 4; +}; + +// Stupid way of calculating maximum index size of ImDrawIdx without integer overflow issues template struct MaxIdx { static const unsigned int Value; }; template <> const unsigned int MaxIdx::Value = 65535; @@ -278,6 +458,27 @@ inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList) { 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) { + ImPlotContext& gp = *GImPlot; + if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased)) { + ImVec2 p1 = transformer(getter(0)); + for (int i = 0; i < getter.Count; ++i) { + ImVec2 p2 = transformer(getter(i)); + if (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); + } +} + +//----------------------------------------------------------------------------- +// MARKER RENDERERS +//----------------------------------------------------------------------------- + inline void TransformMarker(ImVec2* points, int n, const ImVec2& c, float s) { for (int i = 0; i < n; ++i) { points[i].x = c.x + points[i].x * s; @@ -392,187 +593,6 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr } } -template -struct LineRenderer { - inline LineRenderer(TGetter getter, TTransformer transformer, ImU32 col, float weight) : - Getter(getter), - Transformer(transformer) - { - Prims = Getter.Count - 1; - Col = col; - Weight = weight; - P1 = Transformer(Getter(0)); - } - inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { - ImPlotContext& gp = *GImPlot; - ImVec2 P2 = Transformer(Getter(prim + 1)); - if (!gp.BB_Plot.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { - P1 = P2; - return false; - } - float dx = P2.x - P1.x; - float dy = P2.y - P1.y; - IM_NORMALIZE2F_OVER_ZERO(dx, dy); - dx *= (Weight * 0.5f); - dy *= (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; - 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; - 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; - 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; - 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; - P1 = P2; - return true; - } - TGetter Getter; - TTransformer Transformer; - int Prims; - ImU32 Col; - float Weight; - ImVec2 P1; - static const int IdxConsumed = 6; - static const int VtxConsumed = 4; -}; - -template -inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { - ImPlotContext& gp = *GImPlot; - if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased)) { - ImVec2 p1 = transformer(getter(0)); - for (int i = 0; i < getter.Count; ++i) { - ImVec2 p2 = transformer(getter(i)); - if (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); - } -} - -template -struct ShadedRenderer { - ShadedRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col) : - Getter1(getter1), - Getter2(getter2), - Transformer(transformer), - Col(col) - { - Prims = ImMin(Getter1.Count, Getter2.Count) - 1; - P11 = Transformer(Getter1(0)); - P12 = Transformer(Getter2(0)); - } - - inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { - // TODO: Culling - 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 = P21; - DrawList._VtxWritePtr[1].uv = uv; - DrawList._VtxWritePtr[1].col = Col; - DrawList._VtxWritePtr[2].pos = intersection; - DrawList._VtxWritePtr[2].uv = uv; - DrawList._VtxWritePtr[2].col = Col; - DrawList._VtxWritePtr[3].pos = P12; - DrawList._VtxWritePtr[3].uv = uv; - DrawList._VtxWritePtr[3].col = Col; - 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 + intersect); - DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3); - DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); - DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - intersect); - DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4); - DrawList._IdxWritePtr += 6; - DrawList._VtxCurrentIdx += 5; - P11 = P21; - P12 = P22; - return true; - } - TGetter1 Getter1; - TGetter2 Getter2; - TTransformer Transformer; - int Prims; - ImU32 Col; - ImVec2 P11, P12; - static const int IdxConsumed = 6; - static const int VtxConsumed = 5; -}; - -template -struct RectRenderer { - inline RectRenderer(TGetter getter, TTransformer transformer, ImU32 col) : - Getter(getter), - Transformer(transformer) - { - Prims = Getter.Count / 2; - Col = col; - } - inline bool operator()(ImDrawList& DrawList, ImVec2 uv, int prim) { - // TODO: Culling - ImVec2 P1 = Transformer(Getter(2*prim)); - ImVec2 P2 = Transformer(Getter(2*prim+1)); - DrawList._VtxWritePtr[0].pos = P1; - DrawList._VtxWritePtr[0].uv = uv; - DrawList._VtxWritePtr[0].col = Col; - DrawList._VtxWritePtr[1].pos.x = P1.x; - DrawList._VtxWritePtr[1].pos.y = P2.y; - DrawList._VtxWritePtr[1].uv = uv; - DrawList._VtxWritePtr[1].col = Col; - DrawList._VtxWritePtr[2].pos = P2; - DrawList._VtxWritePtr[2].uv = uv; - DrawList._VtxWritePtr[2].col = Col; - DrawList._VtxWritePtr[3].pos.x = P2.x; - DrawList._VtxWritePtr[3].pos.y = P1.y; - DrawList._VtxWritePtr[3].uv = uv; - DrawList._VtxWritePtr[3].col = Col; - DrawList._VtxWritePtr += 4; - DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx); - DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1); - 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 += 6; - DrawList._VtxCurrentIdx += 4; - return true; - } - TGetter Getter; - TTransformer Transformer; - int Prims; - ImU32 Col; - static const int IdxConsumed = 6; - static const int VtxConsumed = 4; -}; - //----------------------------------------------------------------------------- // PLOT LINES / MARKERS //----------------------------------------------------------------------------- @@ -687,7 +707,6 @@ inline int PushScatterStyle() { return vars; } - // float void PlotScatter(const char* label_id, const float* values, int count, int offset, int stride) { int vars = PushScatterStyle(); @@ -707,7 +726,6 @@ void PlotScatter(const char* label_id, const ImVec2* data, int count, int offset PopStyleVar(vars); } - // double void PlotScatter(const char* label_id, const double* values, int count, int offset, int stride) { int vars = PushScatterStyle(); @@ -780,7 +798,6 @@ inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) 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); @@ -794,7 +811,6 @@ void PlotShaded(const char* label_id, const float* xs, const float* ys, int coun 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); @@ -866,7 +882,6 @@ void PlotBars(const char* label_id, const float* xs, const float* ys, int count, PlotBarsEx(label_id, getter, width); } - // double void PlotBars(const char* label_id, const double* values, int count, double width, double shift, int offset, int stride) { GetterBarV getter(values,shift,count,offset,stride); @@ -878,7 +893,6 @@ void PlotBars(const char* label_id, const double* xs, const double* ys, int coun PlotBarsEx(label_id, getter, width); } - // custom void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width, int offset) { GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset); @@ -934,7 +948,6 @@ void PlotBarsHEx(const char* label_id, Getter getter, THeight height) { PopPlotClipRect(); } - // float void PlotBarsH(const char* label_id, const float* values, int count, float height, float shift, int offset, int stride) { GetterBarH getter(values,shift,count,offset,stride); @@ -946,7 +959,6 @@ void PlotBarsH(const char* label_id, const float* xs, const float* ys, int count PlotBarsHEx(label_id, getter, height); } - // double void PlotBarsH(const char* label_id, const double* values, int count, double height, double shift, int offset, int stride) { GetterBarH getter(values,shift,count,offset,stride); @@ -958,7 +970,6 @@ void PlotBarsH(const char* label_id, const double* xs, const double* ys, int cou PlotBarsHEx(label_id, getter, height); } - // custom void PlotBarsH(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height, int offset) { GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset); @@ -1007,7 +1018,6 @@ void PlotErrorBarsEx(const char* label_id, Getter getter) { PopPlotClipRect(); } - // float void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { GetterError getter(xs, ys, err, err, count, offset, stride); @@ -1019,7 +1029,6 @@ void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const PlotErrorBarsEx(label_id, getter); } - // double void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { GetterError getter(xs, ys, err, err, count, offset, stride); @@ -1073,7 +1082,6 @@ void PlotErrorBarsHEx(const char* label_id, Getter getter) { PopPlotClipRect(); } - // float void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { GetterError getter(xs, ys, err, err, count, offset, stride); @@ -1085,7 +1093,6 @@ void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, cons PlotErrorBarsHEx(label_id, getter); } - // double void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { GetterError getter(xs, ys, err, err, count, offset, stride); @@ -1097,14 +1104,6 @@ void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, co PlotErrorBarsHEx(label_id, getter); } -//----------------------------------------------------------------------------- -// PLOT CANDLESTICK -//----------------------------------------------------------------------------- - -void PlotCandlestick(const char* label_id, const float* xs, const float* opens, const float* closes, const float* lows, const float* highs, int count, float width1 = 2, float width2 = 10, int offset = 0, int stride = sizeof(float)) { - -} - //----------------------------------------------------------------------------- // PLOT PIE CHART //----------------------------------------------------------------------------- @@ -1176,7 +1175,6 @@ void PlotPieChartEx(const char** label_ids, const T* values, int count, T x, T y PopPlotClipRect(); } - // float void PlotPieChart(const char** label_ids, const float* values, int count, float x, float y, float radius, bool normalize, const char* fmt, float angle0) { return PlotPieChartEx(label_ids, values, count, x, y, radius, normalize, fmt, angle0); @@ -1429,12 +1427,16 @@ void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!"); ImDrawList & DrawList = *ImGui::GetWindowDrawList(); PushPlotClipRect(); - ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + pixel_offset; ImU32 colTxt = ImGui::GetColorU32(ImGuiCol_Text); - if (vertical) + if (vertical) { + ImVec2 ctr = CalcTextSizeVertical(text) * 0.5f; + ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + ImVec2(-ctr.x, ctr.y) + pixel_offset; AddTextVertical(&DrawList, text, pos, colTxt); - else + } + else { + ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) - ImGui::CalcTextSize(text) * 0.5f + pixel_offset; DrawList.AddText(pos, colTxt, text); + } PopPlotClipRect(); }