1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-22 18:28:53 -05:00

misc clean up, experimental rect rendering, center PlotText

This commit is contained in:
epezent 2020-08-17 18:31:30 -05:00
parent d7e3cc78ac
commit 2bc716d2b6
5 changed files with 229 additions and 227 deletions

View File

@ -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. 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. 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/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/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. - 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.

View File

@ -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 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 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 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 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 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, 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); 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 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 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 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, 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); 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 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 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 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)); 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 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 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 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)); 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. // 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 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.
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 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); 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, 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); 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. // Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImGui::PushStyleColor(ImGuiCol_Text, ...).
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, ...).
void PlotText(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); 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)); void PlotText(const char* text, double x, double y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0));

View File

@ -538,11 +538,11 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::PopStyleVar(6); ImPlot::PopStyleVar(6);
ImPlot::PopStyleColor(3); ImPlot::PopStyleColor(3);
ImPlot::PlotText("Filled Markers", 1.5, 11.75); ImPlot::PlotText("Filled Markers", 2.5f, 6.0f);
ImPlot::PlotText("Open Markers", 6.75, 11.75); ImPlot::PlotText("Open Markers", 7.5f, 6.0f);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0,1,0,1)); 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(); ImGui::PopStyleColor();
ImPlot::SetColormap(ImPlotColormap_Default); ImPlot::SetColormap(ImPlotColormap_Default);
@ -993,7 +993,6 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Custom Rendering")) { if (ImGui::CollapsingHeader("Custom Rendering")) {
static t_float xs[] = {0.1f,0.2f,0.3f,0.4f};
if (ImPlot::BeginPlot("##CustomRend")) { if (ImPlot::BeginPlot("##CustomRend")) {
ImVec2 cntr = ImPlot::PlotToPixels(ImPlotPoint(0.5f, 0.5f)); ImVec2 cntr = ImPlot::PlotToPixels(ImPlotPoint(0.5f, 0.5f));
ImVec2 rmin = ImPlot::PlotToPixels(ImPlotPoint(0.25f, 0.75f)); 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()->AddCircleFilled(cntr,20,IM_COL32(255,255,0,255),20);
ImGui::GetWindowDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255)); ImGui::GetWindowDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255));
ImPlot::PopPlotClipRect(); ImPlot::PopPlotClipRect();
ImPlot::PlotRects("rects", xs, xs, 4);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }

View File

@ -541,4 +541,14 @@ inline ImVec4 GetErrorBarColor() {
return ColorIsAuto(ImPlotCol_ErrorBar) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : GImPlot->Style.Colors[ImPlotCol_ErrorBar]; 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 } // namespace ImPlot

View File

@ -48,6 +48,10 @@ namespace ImPlot {
// GETTERS // 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 <typename T> template <typename T>
struct GetterYs { struct GetterYs {
GetterYs(const T* ys, int count, int offset, int stride) { 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 <typename T> template <typename T>
struct GetterXsYs { struct GetterXsYs {
GetterXsYs(const T* xs, const T* ys, int count, int offset, int stride) { 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 <typename T> template <typename T>
struct GetterXsYRef { struct GetterXsYRef {
GetterXsYRef(const T* xs, T y_ref, int count, int offset, int stride) { 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 { struct GetterImVec2 {
GetterImVec2(const ImVec2* data, int count, int offset) { GetterImVec2(const ImVec2* data, int count, int offset) {
Data = data; Data = data;
@ -114,6 +121,7 @@ struct GetterImVec2 {
int Offset; int Offset;
}; };
// Interprets an array of ImPlotPoints as ImPlotPoints (essentially a pass through)
struct GetterImPlotPoint { struct GetterImPlotPoint {
GetterImPlotPoint(const ImPlotPoint* data, int count, int offset) { GetterImPlotPoint(const ImPlotPoint* data, int count, int offset) {
Data = data; Data = data;
@ -126,6 +134,7 @@ struct GetterImPlotPoint {
int Offset; int Offset;
}; };
/// Interprets a user's function pointer as ImPlotPoints
struct GetterFuncPtrImPlotPoint { struct GetterFuncPtrImPlotPoint {
GetterFuncPtrImPlotPoint(ImPlotPoint (*g)(void* data, int idx), void* d, int count, int offset) { GetterFuncPtrImPlotPoint(ImPlotPoint (*g)(void* data, int idx), void* d, int count, int offset) {
getter = g; getter = g;
@ -172,6 +181,9 @@ struct GetterError {
// TRANSFORMERS // 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 { struct TransformerLinLin {
TransformerLinLin(int y_axis) : YAxis(y_axis) {} TransformerLinLin(int y_axis) : YAxis(y_axis) {}
@ -185,6 +197,7 @@ struct TransformerLinLin {
int YAxis; int YAxis;
}; };
// Transforms points for log x and linear y space
struct TransformerLogLin { struct TransformerLogLin {
TransformerLogLin(int y_axis) : YAxis(y_axis) {} TransformerLogLin(int y_axis) : YAxis(y_axis) {}
@ -200,6 +213,7 @@ struct TransformerLogLin {
int YAxis; int YAxis;
}; };
// Transforms points for linear x and log y space
struct TransformerLinLog { struct TransformerLinLog {
TransformerLinLog(int y_axis) : YAxis(y_axis) {} TransformerLinLog(int y_axis) : YAxis(y_axis) {}
@ -214,6 +228,7 @@ struct TransformerLinLog {
int YAxis; int YAxis;
}; };
// Transforms points for log x and log y space
struct TransformerLogLog { struct TransformerLogLog {
TransformerLogLog(int y_axis) : YAxis(y_axis) {} TransformerLogLog(int y_axis) : YAxis(y_axis) {}
@ -232,9 +247,174 @@ struct TransformerLogLog {
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// RENDERERS // PRIMITIVE RENDERERS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename TGetter, typename TTransformer>
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 <typename TGetter1, typename TGetter2, typename TTransformer>
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 <typename TGetter, typename TTransformer>
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 <typename T> template <typename T>
struct MaxIdx { static const unsigned int Value; }; struct MaxIdx { static const unsigned int Value; };
template <> const unsigned int MaxIdx<unsigned short>::Value = 65535; template <> const unsigned int MaxIdx<unsigned short>::Value = 65535;
@ -278,6 +458,27 @@ inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList) {
DrawList.PrimUnreserve(prims_culled * Renderer::IdxConsumed, prims_culled * Renderer::VtxConsumed); DrawList.PrimUnreserve(prims_culled * Renderer::IdxConsumed, prims_culled * Renderer::VtxConsumed);
} }
template <typename Getter, typename Transformer>
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>(getter, transformer, col, line_weight), DrawList);
}
}
//-----------------------------------------------------------------------------
// MARKER RENDERERS
//-----------------------------------------------------------------------------
inline void TransformMarker(ImVec2* points, int n, const ImVec2& c, float s) { inline void TransformMarker(ImVec2* points, int n, const ImVec2& c, float s) {
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
points[i].x = c.x + points[i].x * s; points[i].x = c.x + points[i].x * s;
@ -392,187 +593,6 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr
} }
} }
template <typename TGetter, typename TTransformer>
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 <typename Getter, typename Transformer>
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>(getter, transformer, col, line_weight), DrawList);
}
}
template <typename TGetter1, typename TGetter2, typename TTransformer>
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 <typename TGetter, typename TTransformer>
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 // PLOT LINES / MARKERS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -687,7 +707,6 @@ inline int PushScatterStyle() {
return vars; return vars;
} }
// float // float
void PlotScatter(const char* label_id, const float* values, int count, int offset, int stride) { void PlotScatter(const char* label_id, const float* values, int count, int offset, int stride) {
int vars = PushScatterStyle(); int vars = PushScatterStyle();
@ -707,7 +726,6 @@ void PlotScatter(const char* label_id, const ImVec2* data, int count, int offset
PopStyleVar(vars); PopStyleVar(vars);
} }
// double // double
void PlotScatter(const char* label_id, const double* values, int count, int offset, int stride) { void PlotScatter(const char* label_id, const double* values, int count, int offset, int stride) {
int vars = PushScatterStyle(); int vars = PushScatterStyle();
@ -780,7 +798,6 @@ inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2)
PopPlotClipRect(); PopPlotClipRect();
} }
// float // float
void PlotShaded(const char* label_id, const float* xs, const float* ys1, const float* ys2, int count, int offset, int stride) { void PlotShaded(const char* label_id, const float* xs, const float* ys1, const float* ys2, int count, int offset, int stride) {
GetterXsYs<float> getter1(xs, ys1, count, offset, stride); GetterXsYs<float> 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); PlotShadedEx(label_id, getter1, getter2);
} }
// double // double
void PlotShaded(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset, int stride) { void PlotShaded(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset, int stride) {
GetterXsYs<double> getter1(xs, ys1, count, offset, stride); GetterXsYs<double> 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); PlotBarsEx(label_id, getter, width);
} }
// double // double
void PlotBars(const char* label_id, const double* values, int count, double width, double shift, int offset, int stride) { void PlotBars(const char* label_id, const double* values, int count, double width, double shift, int offset, int stride) {
GetterBarV<double> getter(values,shift,count,offset,stride); GetterBarV<double> 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); PlotBarsEx(label_id, getter, width);
} }
// custom // custom
void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width, int offset) { 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); GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset);
@ -934,7 +948,6 @@ void PlotBarsHEx(const char* label_id, Getter getter, THeight height) {
PopPlotClipRect(); PopPlotClipRect();
} }
// float // float
void PlotBarsH(const char* label_id, const float* values, int count, float height, float shift, int offset, int stride) { void PlotBarsH(const char* label_id, const float* values, int count, float height, float shift, int offset, int stride) {
GetterBarH<float> getter(values,shift,count,offset,stride); GetterBarH<float> 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); PlotBarsHEx(label_id, getter, height);
} }
// double // double
void PlotBarsH(const char* label_id, const double* values, int count, double height, double shift, int offset, int stride) { void PlotBarsH(const char* label_id, const double* values, int count, double height, double shift, int offset, int stride) {
GetterBarH<double> getter(values,shift,count,offset,stride); GetterBarH<double> 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); PlotBarsHEx(label_id, getter, height);
} }
// custom // custom
void PlotBarsH(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height, int offset) { 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); GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset);
@ -1007,7 +1018,6 @@ void PlotErrorBarsEx(const char* label_id, Getter getter) {
PopPlotClipRect(); PopPlotClipRect();
} }
// float // float
void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) {
GetterError<float> getter(xs, ys, err, err, count, offset, stride); GetterError<float> 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); PlotErrorBarsEx(label_id, getter);
} }
// double // double
void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) {
GetterError<double> getter(xs, ys, err, err, count, offset, stride); GetterError<double> getter(xs, ys, err, err, count, offset, stride);
@ -1073,7 +1082,6 @@ void PlotErrorBarsHEx(const char* label_id, Getter getter) {
PopPlotClipRect(); PopPlotClipRect();
} }
// float // float
void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) {
GetterError<float> getter(xs, ys, err, err, count, offset, stride); GetterError<float> 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); PlotErrorBarsHEx(label_id, getter);
} }
// double // double
void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) {
GetterError<double> getter(xs, ys, err, err, count, offset, stride); GetterError<double> 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); 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 // PLOT PIE CHART
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1176,7 +1175,6 @@ void PlotPieChartEx(const char** label_ids, const T* values, int count, T x, T y
PopPlotClipRect(); PopPlotClipRect();
} }
// float // 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) { 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); 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()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & DrawList = *ImGui::GetWindowDrawList(); ImDrawList & DrawList = *ImGui::GetWindowDrawList();
PushPlotClipRect(); PushPlotClipRect();
ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + pixel_offset;
ImU32 colTxt = ImGui::GetColorU32(ImGuiCol_Text); 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); 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); DrawList.AddText(pos, colTxt, text);
}
PopPlotClipRect(); PopPlotClipRect();
} }