1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-10-09 23:57:26 -04:00

code cleanup, define magic numbers, add minimum plot size constraint, misc improvements to tick mark labels

This commit is contained in:
epezent 2020-08-19 00:04:05 -05:00
parent 0926677b52
commit 53c867f414
4 changed files with 188 additions and 158 deletions

View File

@ -231,7 +231,7 @@ void Reset(ImPlotContext* ctx) {
ctx->FitX = false; ctx->FitX = false;
ctx->ExtentsX.Min = HUGE_VAL; ctx->ExtentsX.Min = HUGE_VAL;
ctx->ExtentsX.Max = -HUGE_VAL; ctx->ExtentsX.Max = -HUGE_VAL;
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
ctx->ExtentsY[i].Min = HUGE_VAL; ctx->ExtentsY[i].Min = HUGE_VAL;
ctx->ExtentsY[i].Max = -HUGE_VAL; ctx->ExtentsY[i].Max = -HUGE_VAL;
ctx->FitY[i] = false; ctx->FitY[i] = false;
@ -278,7 +278,7 @@ void FitPoint(const ImPlotPoint& p) {
void UpdateTransformCache() { void UpdateTransformCache() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
// get pixels for transforms // get pixels for transforms
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
gp.PixelRange[i] = ImRect(ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Max.x : gp.BB_Plot.Min.x, gp.PixelRange[i] = ImRect(ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Max.x : gp.BB_Plot.Min.x,
ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.y : gp.BB_Plot.Max.y, ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.y : gp.BB_Plot.Max.y,
ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.x : gp.BB_Plot.Max.x, ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.x : gp.BB_Plot.Max.x,
@ -287,7 +287,7 @@ void UpdateTransformCache() {
gp.My[i] = (gp.PixelRange[i].Max.y - gp.PixelRange[i].Min.y) / gp.CurrentPlot->YAxis[i].Range.Size(); gp.My[i] = (gp.PixelRange[i].Max.y - gp.PixelRange[i].Min.y) / gp.CurrentPlot->YAxis[i].Range.Size();
} }
gp.LogDenX = ImLog10(gp.CurrentPlot->XAxis.Range.Max / gp.CurrentPlot->XAxis.Range.Min); gp.LogDenX = ImLog10(gp.CurrentPlot->XAxis.Range.Max / gp.CurrentPlot->XAxis.Range.Min);
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
gp.LogDenY[i] = ImLog10(gp.CurrentPlot->YAxis[i].Range.Max / gp.CurrentPlot->YAxis[i].Range.Min); gp.LogDenY[i] = ImLog10(gp.CurrentPlot->YAxis[i].Range.Max / gp.CurrentPlot->YAxis[i].Range.Min);
} }
gp.Mx = (gp.PixelRange[0].Max.x - gp.PixelRange[0].Min.x) / gp.CurrentPlot->XAxis.Range.Size(); gp.Mx = (gp.PixelRange[0].Max.x - gp.PixelRange[0].Min.x) / gp.CurrentPlot->XAxis.Range.Size();
@ -416,7 +416,7 @@ void AddDefaultTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logs
double major2 = ImPow(10, (double)(e + 1)); double major2 = ImPow(10, (double)(e + 1));
double interval = (major2 - major1) / 9; double interval = (major2 - major1) / 9;
if (major1 >= (range.Min - DBL_EPSILON) && major1 <= (range.Max + DBL_EPSILON)) if (major1 >= (range.Min - DBL_EPSILON) && major1 <= (range.Max + DBL_EPSILON))
out.push_back(ImPlotTick(major1, true)); out.push_back(ImPlotTick(major1, true, true));
for (int i = 1; i < 9; ++i) { for (int i = 1; i < 9; ++i) {
double minor = major1 + i * interval; double minor = major1 + i * interval;
if (minor >= (range.Min - DBL_EPSILON) && minor <= (range.Max + DBL_EPSILON)) if (minor >= (range.Min - DBL_EPSILON) && minor <= (range.Max + DBL_EPSILON))
@ -425,17 +425,17 @@ void AddDefaultTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logs
} }
} }
else { else {
const double nice_range = NiceNum(range.Size() * 0.99, 0); const double nice_range = NiceNum(range.Size() * 0.99, false);
const double interval = NiceNum(nice_range / (nMajor - 1), 1); const double interval = NiceNum(nice_range / (nMajor - 1), true);
const double graphmin = floor(range.Min / interval) * interval; const double graphmin = floor(range.Min / interval) * interval;
const double graphmax = ceil(range.Max / interval) * interval; const double graphmax = ceil(range.Max / interval) * interval;
for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) { for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) {
if (major >= range.Min && major <= range.Max) if (range.Contains(major))
out.push_back(ImPlotTick(major, true)); out.push_back(ImPlotTick(major, true, true));
for (int i = 1; i < nMinor; ++i) { for (int i = 1; i < nMinor; ++i) {
double minor = major + i * interval / nMinor; double minor = major + i * interval / nMinor;
if (minor >= range.Min && minor <= range.Max) if (range.Contains(minor))
out.push_back(ImPlotTick(minor, false)); out.push_back(ImPlotTick(minor, false, true));
} }
} }
} }
@ -443,11 +443,11 @@ void AddDefaultTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logs
void AddCustomTicks(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer) { void AddCustomTicks(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer) {
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
ImPlotTick tick(values[i],false); ImPlotTick tick(values[i],false, true);
tick.TextOffset = buffer.size(); tick.BufferOffset = buffer.size();
if (labels != NULL) { if (labels != NULL) {
buffer.append(labels[i], labels[i] + strlen(labels[i]) + 1); buffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
tick.Size = ImGui::CalcTextSize(labels[i]); tick.LabelSize = ImGui::CalcTextSize(labels[i]);
tick.Labeled = true; tick.Labeled = true;
} }
ticks.push_back(tick); ticks.push_back(tick);
@ -458,26 +458,40 @@ void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& b
char temp[32]; char temp[32];
for (int t = 0; t < ticks.Size; t++) { for (int t = 0; t < ticks.Size; t++) {
ImPlotTick *tk = &ticks[t]; ImPlotTick *tk = &ticks[t];
if (tk->RenderLabel && !tk->Labeled) { if (tk->ShowLabel && !tk->Labeled) {
tk->TextOffset = buffer.size(); tk->BufferOffset = buffer.size();
if (scientific) if (scientific)
sprintf(temp, "%.0e", tk->PlotPos); sprintf(temp, "%.0e", tk->PlotPos);
else else
sprintf(temp, "%.10g", tk->PlotPos); sprintf(temp, "%.10g", tk->PlotPos);
buffer.append(temp, temp + strlen(temp) + 1); buffer.append(temp, temp + strlen(temp) + 1);
tk->Size = ImGui::CalcTextSize(buffer.Buf.Data + tk->TextOffset); tk->LabelSize = ImGui::CalcTextSize(buffer.Buf.Data + tk->BufferOffset);
tk->Labeled = true; tk->Labeled = true;
} }
} }
} }
float MaxTickLabelWidth(ImVector<ImPlotTick>& ticks) { float MaxTickLabelWidth(const ImVector<ImPlotTick>& ticks) {
float w = 0; float w = 0;
for (int i = 0; i < ticks.Size; ++i) for (int i = 0; i < ticks.Size; ++i)
w = ticks[i].Size.x > w ? ticks[i].Size.x : w; w = (ticks[i].ShowLabel && ticks[i].LabelSize.x > w) ? ticks[i].LabelSize.x : w;
return w; return w;
} }
float SumTickLabelWidth(const ImVector<ImPlotTick>& ticks) {
float sum = 0;
for (int i = 0; i < ticks.Size; ++i)
sum += ticks[i].ShowLabel ? ticks[i].LabelSize.x : 0;
return sum;
}
float SumTickLabelHeight(const ImVector<ImPlotTick>& ticks) {
float sum = 0;
for (int i = 0; i < ticks.Size; ++i)
sum += ticks[i].ShowLabel ? ticks[i].LabelSize.y : 0;
return sum;
}
class YPadCalculator { class YPadCalculator {
public: public:
YPadCalculator(const ImPlotAxisState* axis_states, const float* max_label_widths, float txt_off) YPadCalculator(const ImPlotAxisState* axis_states, const float* max_label_widths, float txt_off)
@ -512,10 +526,11 @@ class YPadCalculator {
void UpdateAxisColor(int axis_flag, ImPlotAxisColor* col) { void UpdateAxisColor(int axis_flag, ImPlotAxisColor* col) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
const ImVec4 col_Axis = gp.Style.Colors[axis_flag].w == -1 ? ImGui::GetStyle().Colors[ImGuiCol_Text] * ImVec4(1, 1, 1, 0.25f) : gp.Style.Colors[axis_flag]; const ImVec4 col_axis = gp.Style.Colors[axis_flag].w == -1 ? ImGui::GetStyle().Colors[ImGuiCol_Text] * ImVec4(1, 1, 1, 0.25f) : gp.Style.Colors[axis_flag];
col->Major = ImGui::GetColorU32(col_Axis); col->Major = ImGui::GetColorU32(col_axis);
col->Minor = ImGui::GetColorU32(col_Axis * ImVec4(1, 1, 1, 0.25f)); col->Minor = ImGui::GetColorU32(col_axis * ImVec4(1, 1, 1, 0.25f));
col->Txt = ImGui::GetColorU32(ImVec4(col_Axis.x, col_Axis.y, col_Axis.z, 1)); col->MajTxt = ImGui::GetColorU32(ImVec4(col_axis.x, col_axis.y, col_axis.z, 1));
col->MinTxt = ImGui::GetColorU32(ImVec4(col_axis.x, col_axis.y, col_axis.z, 0.8f));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -573,10 +588,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.YAxis[2].PreviousFlags = y3_flags; plot.YAxis[2].PreviousFlags = y3_flags;
// capture scroll with a child region // capture scroll with a child region
const float default_w = 400;
const float default_h = 300;
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoChild)) { if (!ImHasFlag(plot.Flags, ImPlotFlags_NoChild)) {
ImGui::BeginChild(title, ImVec2(size.x == 0 ? default_w : size.x, size.y == 0 ? default_h : size.y)); ImGui::BeginChild(title, ImVec2(size.x == 0 ? IMPLOT_DEFAULT_W : size.x, size.y == 0 ? IMPLOT_DEFAULT_H : size.y));
Window = ImGui::GetCurrentWindow(); Window = ImGui::GetCurrentWindow();
Window->ScrollMax.y = 1.0f; Window->ScrollMax.y = 1.0f;
gp.ChildWindowMade = true; gp.ChildWindowMade = true;
@ -590,16 +603,14 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// NextPlotData ----------------------------------------------------------- // NextPlotData -----------------------------------------------------------
if (gp.NextPlotData.HasXRange) { if (gp.NextPlotData.HasXRange) {
if (just_created || gp.NextPlotData.XRangeCond == ImGuiCond_Always) if (just_created || gp.NextPlotData.XRangeCond == ImGuiCond_Always) {
{
plot.XAxis.Range = gp.NextPlotData.X; plot.XAxis.Range = gp.NextPlotData.X;
} }
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.NextPlotData.HasYRange[i]) { if (gp.NextPlotData.HasYRange[i]) {
if (just_created || gp.NextPlotData.YRangeCond[i] == ImGuiCond_Always) if (just_created || gp.NextPlotData.YRangeCond[i] == ImGuiCond_Always) {
{
plot.YAxis[i].Range = gp.NextPlotData.Y[i]; plot.YAxis[i].Range = gp.NextPlotData.Y[i];
} }
} }
@ -619,7 +630,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.XAxis.Range.Min = ConstrainNan(ConstrainInf(plot.XAxis.Range.Min)); plot.XAxis.Range.Min = ConstrainNan(ConstrainInf(plot.XAxis.Range.Min));
plot.XAxis.Range.Max = ConstrainNan(ConstrainInf(plot.XAxis.Range.Max)); plot.XAxis.Range.Max = ConstrainNan(ConstrainInf(plot.XAxis.Range.Max));
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
plot.YAxis[i].Range.Min = ConstrainNan(ConstrainInf(plot.YAxis[i].Range.Min)); plot.YAxis[i].Range.Min = ConstrainNan(ConstrainInf(plot.YAxis[i].Range.Min));
plot.YAxis[i].Range.Max = ConstrainNan(ConstrainInf(plot.YAxis[i].Range.Max)); plot.YAxis[i].Range.Max = ConstrainNan(ConstrainInf(plot.YAxis[i].Range.Max));
} }
@ -628,7 +639,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.XAxis.Range.Min = ConstrainLog(plot.XAxis.Range.Min); plot.XAxis.Range.Min = ConstrainLog(plot.XAxis.Range.Min);
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale)) if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale))
plot.XAxis.Range.Max = ConstrainLog(plot.XAxis.Range.Max); plot.XAxis.Range.Max = ConstrainLog(plot.XAxis.Range.Max);
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale)) if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
plot.YAxis[i].Range.Min = ConstrainLog(plot.YAxis[i].Range.Min); plot.YAxis[i].Range.Min = ConstrainLog(plot.YAxis[i].Range.Min);
if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale)) if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
@ -637,7 +648,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (plot.XAxis.Range.Max <= plot.XAxis.Range.Min) if (plot.XAxis.Range.Max <= plot.XAxis.Range.Min)
plot.XAxis.Range.Max = plot.XAxis.Range.Min + DBL_EPSILON; plot.XAxis.Range.Max = plot.XAxis.Range.Min + DBL_EPSILON;
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (plot.YAxis[i].Range.Max <= plot.YAxis[i].Range.Min) if (plot.YAxis[i].Range.Max <= plot.YAxis[i].Range.Min)
plot.YAxis[i].Range.Max = plot.YAxis[i].Range.Min + DBL_EPSILON; plot.YAxis[i].Range.Max = plot.YAxis[i].Range.Min + DBL_EPSILON;
} }
@ -663,7 +674,11 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// BB AND HOVER ----------------------------------------------------------- // BB AND HOVER -----------------------------------------------------------
// frame // frame
const ImVec2 frame_size = ImGui::CalcItemSize(size, default_w, default_h); ImVec2 frame_size = ImGui::CalcItemSize(size, IMPLOT_DEFAULT_W, IMPLOT_DEFAULT_H);
if (frame_size.x < IMPLOT_MIN_W && size.x < 0.0f)
frame_size.x = IMPLOT_MIN_W;
if (frame_size.y < IMPLOT_MIN_H && size.y < 0.0f)
frame_size.y = IMPLOT_MIN_H;
gp.BB_Frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size); gp.BB_Frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);
ImGui::ItemSize(gp.BB_Frame); ImGui::ItemSize(gp.BB_Frame);
if (!ImGui::ItemAdd(gp.BB_Frame, 0, &gp.BB_Frame)) { if (!ImGui::ItemAdd(gp.BB_Frame, 0, &gp.BB_Frame)) {
@ -678,15 +693,15 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// adaptive divisions // adaptive divisions
int x_divisions = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetWidth())); int x_divisions = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetWidth()));
int y_divisions[MAX_Y_AXES]; int y_divisions[IMPLOT_Y_AXES];
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
y_divisions[i] = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetHeight())); y_divisions[i] = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetHeight()));
} }
gp.RenderX = (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_GridLines) || gp.RenderX = (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_GridLines) ||
ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks) || ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks) ||
ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels)) && x_divisions > 1; ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels)) && x_divisions > 1;
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
gp.RenderY[i] = gp.RenderY[i] =
gp.Y[i].Present && gp.Y[i].Present &&
(ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_GridLines) || (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_GridLines) ||
@ -695,10 +710,10 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
} }
// get ticks // get ticks
if (gp.RenderX && gp.NextPlotData.ShowDefaultTicksX) if (gp.RenderX && gp.NextPlotData.ShowDefaultTicksX)
AddDefaultTicks(plot.XAxis.Range, x_divisions, 10, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTicks); AddDefaultTicks(plot.XAxis.Range, x_divisions, IMPLOT_SUB_DIV, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTicks);
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.RenderY[i] && gp.NextPlotData.ShowDefaultTicksY[i]) { if (gp.RenderY[i] && gp.NextPlotData.ShowDefaultTicksY[i]) {
AddDefaultTicks(plot.YAxis[i].Range, y_divisions[i], 10, ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale), gp.YTicks[i]); AddDefaultTicks(plot.YAxis[i].Range, y_divisions[i], IMPLOT_SUB_DIV, ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale), gp.YTicks[i]);
} }
} }
@ -706,8 +721,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels)) if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels))
LabelTicks(gp.XTicks, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_Scientific), gp.XTickLabels); LabelTicks(gp.XTicks, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_Scientific), gp.XTickLabels);
float max_label_width[MAX_Y_AXES] = {}; float max_label_width[IMPLOT_Y_AXES] = {};
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.Y[i].Present && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickLabels)) { if (gp.Y[i].Present && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickLabels)) {
LabelTicks(gp.YTicks[i], ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_Scientific), gp.YTickLabels[i]); LabelTicks(gp.YTicks[i], ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_Scientific), gp.YTickLabels[i]);
max_label_width[i] = MaxTickLabelWidth(gp.YTicks[i]); max_label_width[i] = MaxTickLabelWidth(gp.YTicks[i]);
@ -716,12 +731,11 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// grid bb // grid bb
const ImVec2 title_size = ImGui::CalcTextSize(title, NULL, true); const ImVec2 title_size = ImGui::CalcTextSize(title, NULL, true);
const float txt_off = 5;
const float txt_height = ImGui::GetTextLineHeight(); const float txt_height = ImGui::GetTextLineHeight();
const float pad_top = title_size.x > 0.0f ? txt_height + txt_off : 0; const float pad_top = title_size.x > 0.0f ? txt_height + IMPLOT_LABEL_PAD : 0;
const float pad_bot = (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels) ? txt_height + txt_off : 0) + (x_label ? txt_height + txt_off : 0); const float pad_bot = (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels) ? txt_height + IMPLOT_LABEL_PAD : 0) + (x_label ? txt_height + IMPLOT_LABEL_PAD : 0);
YPadCalculator y_axis_pad(gp.Y, max_label_width, txt_off); YPadCalculator y_axis_pad(gp.Y, max_label_width, IMPLOT_LABEL_PAD);
const float pad_left = y_axis_pad(0) + (y_label ? txt_height + txt_off : 0); const float pad_left = y_axis_pad(0) + (y_label ? txt_height + IMPLOT_LABEL_PAD : 0);
const float pad_right = y_axis_pad(1) + y_axis_pad(2); const float pad_right = y_axis_pad(1) + y_axis_pad(2);
gp.BB_Plot = ImRect(gp.BB_Canvas.Min + ImVec2(pad_left, pad_top), gp.BB_Canvas.Max - ImVec2(pad_right, pad_bot)); gp.BB_Plot = ImRect(gp.BB_Canvas.Min + ImVec2(pad_left, pad_top), gp.BB_Canvas.Max - ImVec2(pad_right, pad_bot));
gp.Hov_Plot = gp.BB_Plot.Contains(IO.MousePos); gp.Hov_Plot = gp.BB_Plot.Contains(IO.MousePos);
@ -742,7 +756,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
gp.BB_Plot.Max.x : gp.BB_Plot.Max.x :
(gp.AxisLabelReference[1] + y_axis_pad(1) + 6); (gp.AxisLabelReference[1] + y_axis_pad(1) + 6);
ImRect yAxisRegion_bb[MAX_Y_AXES]; ImRect yAxisRegion_bb[IMPLOT_Y_AXES];
yAxisRegion_bb[0] = ImRect(ImVec2(gp.BB_Frame.Min.x, gp.BB_Plot.Min.y), ImVec2(gp.BB_Plot.Min.x + 6, gp.BB_Plot.Max.y - 10)); yAxisRegion_bb[0] = ImRect(ImVec2(gp.BB_Frame.Min.x, gp.BB_Plot.Min.y), ImVec2(gp.BB_Plot.Min.x + 6, gp.BB_Plot.Max.y - 10));
// The auxiliary y axes are off to the right of the BB grid. // The auxiliary y axes are off to the right of the BB grid.
yAxisRegion_bb[1] = ImRect(ImVec2(gp.BB_Plot.Max.x - 6, gp.BB_Plot.Min.y), gp.BB_Plot.Max + ImVec2(y_axis_pad(1), -10)); yAxisRegion_bb[1] = ImRect(ImVec2(gp.BB_Plot.Max.x - 6, gp.BB_Plot.Min.y), gp.BB_Plot.Max + ImVec2(y_axis_pad(1), -10));
@ -793,7 +807,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.XAxis.Dragging = false; plot.XAxis.Dragging = false;
G.IO.MouseDragMaxDistanceSqr[0] = 0; G.IO.MouseDragMaxDistanceSqr[0] = 0;
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (plot.YAxis[i].Dragging && (IO.MouseReleased[gp.InputMap.PanButton] || !IO.MouseDown[gp.InputMap.PanButton])) { if (plot.YAxis[i].Dragging && (IO.MouseReleased[gp.InputMap.PanButton] || !IO.MouseDown[gp.InputMap.PanButton])) {
plot.YAxis[i].Dragging = false; plot.YAxis[i].Dragging = false;
G.IO.MouseDragMaxDistanceSqr[0] = 0; G.IO.MouseDragMaxDistanceSqr[0] = 0;
@ -812,7 +826,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (!gp.X.LockMax) if (!gp.X.LockMax)
plot.XAxis.Range.Max = gp.X.Invert ? plot_tl.x : plot_br.x; plot.XAxis.Range.Max = gp.X.Invert ? plot_tl.x : plot_br.x;
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (!gp.Y[i].Lock && plot.YAxis[i].Dragging) { if (!gp.Y[i].Lock && plot.YAxis[i].Dragging) {
ImPlotPoint plot_tl = PixelsToPlot(gp.BB_Plot.Min - IO.MouseDelta, i); ImPlotPoint plot_tl = PixelsToPlot(gp.BB_Plot.Min - IO.MouseDelta, i);
ImPlotPoint plot_br = PixelsToPlot(gp.BB_Plot.Max - IO.MouseDelta, i); ImPlotPoint plot_br = PixelsToPlot(gp.BB_Plot.Max - IO.MouseDelta, i);
@ -828,7 +842,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (!gp.X.Lock && plot.XAxis.Dragging) { if (!gp.X.Lock && plot.XAxis.Dragging) {
direction |= (1 << 1); direction |= (1 << 1);
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (!gp.Y[i].Present) { continue; } if (!gp.Y[i].Present) { continue; }
if (!gp.Y[i].Lock && plot.YAxis[i].Dragging) { if (!gp.Y[i].Lock && plot.YAxis[i].Dragging) {
direction |= (1 << 2); direction |= (1 << 2);
@ -836,26 +850,22 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
} }
} }
if (IO.MouseDragMaxDistanceSqr[0] > 5) { if (IO.MouseDragMaxDistanceSqr[0] > 5) {
if (direction == 0) { if (direction == 0)
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
} else if (direction == (1 << 1))
else if (direction == (1 << 1)) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
} else if (direction == (1 << 2))
else if (direction == (1 << 2)) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
} else
else {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
} }
} }
}
// start drag // start drag
if (!drag_in_progress && gp.Hov_Frame && IO.MouseClicked[gp.InputMap.PanButton] && ImHasFlag(IO.KeyMods, gp.InputMap.PanMod) && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) { if (!drag_in_progress && gp.Hov_Frame && IO.MouseClicked[gp.InputMap.PanButton] && ImHasFlag(IO.KeyMods, gp.InputMap.PanMod) && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) {
if (plot.XAxis.Hovered) { if (plot.XAxis.Hovered) {
plot.XAxis.Dragging = true; plot.XAxis.Dragging = true;
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (plot.YAxis[i].Hovered) { if (plot.YAxis[i].Hovered) {
plot.YAxis[i].Dragging = true; plot.YAxis[i].Dragging = true;
} }
@ -866,7 +876,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (gp.Hov_Frame && (plot.XAxis.Hovered || any_hov_y_axis_region) && IO.MouseWheel != 0) { if (gp.Hov_Frame && (plot.XAxis.Hovered || any_hov_y_axis_region) && IO.MouseWheel != 0) {
UpdateTransformCache(); UpdateTransformCache();
float zoom_rate = 0.1f; float zoom_rate = IMPLOT_ZOOM_RATE;
if (IO.MouseWheel > 0) if (IO.MouseWheel > 0)
zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate)); zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate));
float tx = ImRemap(IO.MousePos.x, gp.BB_Plot.Min.x, gp.BB_Plot.Max.x, 0.0f, 1.0f); float tx = ImRemap(IO.MousePos.x, gp.BB_Plot.Min.x, gp.BB_Plot.Max.x, 0.0f, 1.0f);
@ -881,7 +891,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (!gp.X.LockMax) if (!gp.X.LockMax)
plot.XAxis.Range.Max = gp.X.Invert ? plot_tl.x : plot_br.x; plot.XAxis.Range.Max = gp.X.Invert ? plot_tl.x : plot_br.x;
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (plot.YAxis[i].Hovered && !gp.Y[i].Lock) { if (plot.YAxis[i].Hovered && !gp.Y[i].Lock) {
ImPlotAxisScale axis_scale(i, tx, ty, zoom_rate); ImPlotAxisScale axis_scale(i, tx, ty, zoom_rate);
const ImPlotPoint& plot_tl = axis_scale.Min; const ImPlotPoint& plot_tl = axis_scale.Min;
@ -907,7 +917,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.XAxis.Range.Min = ImMin(p1.x, p2.x); plot.XAxis.Range.Min = ImMin(p1.x, p2.x);
if (!gp.X.LockMax && IO.KeyMods != gp.InputMap.HorizontalMod) if (!gp.X.LockMax && IO.KeyMods != gp.InputMap.HorizontalMod)
plot.XAxis.Range.Max = ImMax(p1.x, p2.x); plot.XAxis.Range.Max = ImMax(p1.x, p2.x);
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
p1 = PixelsToPlot(plot.SelectStart, i); p1 = PixelsToPlot(plot.SelectStart, i);
p2 = PixelsToPlot(IO.MousePos, i); p2 = PixelsToPlot(IO.MousePos, i);
if (!gp.Y[i].LockMin && IO.KeyMods != gp.InputMap.VerticalMod) if (!gp.Y[i].LockMin && IO.KeyMods != gp.InputMap.VerticalMod)
@ -945,13 +955,11 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// end query // end query
if (plot.Querying && (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton])) { if (plot.Querying && (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton])) {
plot.Querying = false; plot.Querying = false;
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) { if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2)
plot.Queried = true; plot.Queried = true;
} else
else {
plot.Queried = false; plot.Queried = false;
} }
}
// begin query // begin query
if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && gp.Hov_Frame && gp.Hov_Plot && IO.MouseClicked[gp.InputMap.QueryButton] && ImHasFlag(IO.KeyMods, gp.InputMap.QueryMod)) { if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && gp.Hov_Frame && gp.Hov_Plot && IO.MouseClicked[gp.InputMap.QueryButton] && ImHasFlag(IO.KeyMods, gp.InputMap.QueryMod)) {
@ -980,17 +988,15 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if ( IO.MouseDoubleClicked[gp.InputMap.FitButton] && gp.Hov_Frame && (plot.XAxis.Hovered || any_hov_y_axis_region) && !hov_legend && !hov_query) { if ( IO.MouseDoubleClicked[gp.InputMap.FitButton] && gp.Hov_Frame && (plot.XAxis.Hovered || any_hov_y_axis_region) && !hov_legend && !hov_query) {
gp.FitThisFrame = true; gp.FitThisFrame = true;
gp.FitX = plot.XAxis.Hovered; gp.FitX = plot.XAxis.Hovered;
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++)
gp.FitY[i] = plot.YAxis[i].Hovered; gp.FitY[i] = plot.YAxis[i].Hovered;
} }
}
else { else {
gp.FitThisFrame = false; gp.FitThisFrame = false;
gp.FitX = false; gp.FitX = false;
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++)
gp.FitY[i] = false; gp.FitY[i] = false;
} }
}
// FOCUS ------------------------------------------------------------------ // FOCUS ------------------------------------------------------------------
@ -1001,7 +1007,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
UpdateTransformCache(); UpdateTransformCache();
// set mouse position // set mouse position
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
gp.LastMousePos[i] = PixelsToPlot(IO.MousePos, i); gp.LastMousePos[i] = PixelsToPlot(IO.MousePos, i);
} }
@ -1020,7 +1026,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
xt->PixelPos = PlotToPixels(xt->PlotPos, 0, 0).x; xt->PixelPos = PlotToPixels(xt->PlotPos, 0, 0).x;
} }
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.RenderY[i]) { if (gp.RenderY[i]) {
for (int t = 0; t < gp.YTicks[i].Size; t++) { for (int t = 0; t < gp.YTicks[i].Size; t++) {
ImPlotTick *yt = &gp.YTicks[i][t]; ImPlotTick *yt = &gp.YTicks[i][t];
@ -1037,7 +1043,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
} }
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.Y[i].Present && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_GridLines)) { if (gp.Y[i].Present && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_GridLines)) {
for (int t = 0; t < gp.YTicks[i].Size; t++) { for (int t = 0; t < gp.YTicks[i].Size; t++) {
ImPlotTick *yt = &gp.YTicks[i][t]; ImPlotTick *yt = &gp.YTicks[i][t];
@ -1058,8 +1064,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
ImGui::PushClipRect(gp.BB_Frame.Min, gp.BB_Frame.Max, true); ImGui::PushClipRect(gp.BB_Frame.Min, gp.BB_Frame.Max, true);
for (int t = 0; t < gp.XTicks.Size; t++) { for (int t = 0; t < gp.XTicks.Size; t++) {
ImPlotTick *xt = &gp.XTicks[t]; ImPlotTick *xt = &gp.XTicks[t];
if (xt->RenderLabel && xt->PixelPos >= gp.BB_Plot.Min.x - 1 && xt->PixelPos <= gp.BB_Plot.Max.x + 1) if (xt->ShowLabel && xt->PixelPos >= gp.BB_Plot.Min.x - 1 && xt->PixelPos <= gp.BB_Plot.Max.x + 1)
DrawList.AddText(ImVec2(xt->PixelPos - xt->Size.x * 0.5f, gp.BB_Plot.Max.y + txt_off), gp.Col_X.Txt, gp.XTickLabels.Buf.Data + xt->TextOffset); DrawList.AddText(ImVec2(xt->PixelPos - xt->LabelSize.x * 0.5f, gp.BB_Plot.Max.y + IMPLOT_LABEL_PAD), xt->Major ? gp.Col_X.MajTxt : gp.Col_X.MinTxt, gp.XTickLabels.Buf.Data + xt->BufferOffset);
} }
ImGui::PopClipRect(); ImGui::PopClipRect();
} }
@ -1067,17 +1073,17 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
const ImVec2 xLabel_size = ImGui::CalcTextSize(x_label); const ImVec2 xLabel_size = ImGui::CalcTextSize(x_label);
const ImVec2 xLabel_pos(gp.BB_Plot.GetCenter().x - xLabel_size.x * 0.5f, const ImVec2 xLabel_pos(gp.BB_Plot.GetCenter().x - xLabel_size.x * 0.5f,
gp.BB_Canvas.Max.y - txt_height); gp.BB_Canvas.Max.y - txt_height);
DrawList.AddText(xLabel_pos, gp.Col_X.Txt, x_label); DrawList.AddText(xLabel_pos, gp.Col_X.MajTxt, x_label);
} }
ImGui::PushClipRect(gp.BB_Frame.Min, gp.BB_Frame.Max, true); ImGui::PushClipRect(gp.BB_Frame.Min, gp.BB_Frame.Max, true);
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.Y[i].Present && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickLabels)) { if (gp.Y[i].Present && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickLabels)) {
for (int t = 0; t < gp.YTicks[i].Size; t++) { for (int t = 0; t < gp.YTicks[i].Size; t++) {
const float x_start = gp.AxisLabelReference[i] + (i == 0 ? (-txt_off - gp.YTicks[i][t].Size.x) : txt_off); const float x_start = gp.AxisLabelReference[i] + (i == 0 ? (-IMPLOT_LABEL_PAD - gp.YTicks[i][t].LabelSize.x) : IMPLOT_LABEL_PAD);
ImPlotTick *yt = &gp.YTicks[i][t]; ImPlotTick *yt = &gp.YTicks[i][t];
if (yt->RenderLabel && yt->PixelPos >= gp.BB_Plot.Min.y - 1 && yt->PixelPos <= gp.BB_Plot.Max.y + 1) { if (yt->ShowLabel && yt->PixelPos >= gp.BB_Plot.Min.y - 1 && yt->PixelPos <= gp.BB_Plot.Max.y + 1) {
ImVec2 start(x_start, yt->PixelPos - 0.5f * yt->Size.y); ImVec2 start(x_start, yt->PixelPos - 0.5f * yt->LabelSize.y);
DrawList.AddText(start, gp.Col_Y[i].Txt, gp.YTickLabels[i].Buf.Data + yt->TextOffset); DrawList.AddText(start, yt->Major ? gp.Col_Y[i].MajTxt : gp.Col_Y[i].MinTxt, gp.YTickLabels[i].Buf.Data + yt->BufferOffset);
} }
} }
} }
@ -1086,7 +1092,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (y_label) { if (y_label) {
const ImVec2 yLabel_size = CalcTextSizeVertical(y_label); const ImVec2 yLabel_size = CalcTextSizeVertical(y_label);
const ImVec2 yLabel_pos(gp.BB_Canvas.Min.x, gp.BB_Plot.GetCenter().y + yLabel_size.y * 0.5f); const ImVec2 yLabel_pos(gp.BB_Canvas.Min.x, gp.BB_Plot.GetCenter().y + yLabel_size.y * 0.5f);
AddTextVertical(&DrawList, y_label, yLabel_pos, gp.Col_Y[0].Txt); AddTextVertical(&DrawList, y_label, yLabel_pos, gp.Col_Y[0].MajTxt);
} }
// push plot ID into stack // push plot ID into stack
@ -1179,7 +1185,7 @@ void PlotContextMenu(ImPlotState& plot) {
ImGui::PopID(); ImGui::PopID();
ImGui::EndMenu(); ImGui::EndMenu();
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (i == 1 && !ImHasFlag(plot.Flags, ImPlotFlags_YAxis2)) { if (i == 1 && !ImHasFlag(plot.Flags, ImPlotFlags_YAxis2)) {
continue; continue;
} }
@ -1262,14 +1268,14 @@ void EndPlot() {
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks)) { if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks)) {
for (int t = 0; t < gp.XTicks.Size; t++) { for (int t = 0; t < gp.XTicks.Size; t++) {
ImPlotTick *xt = &gp.XTicks[t]; ImPlotTick *xt = &gp.XTicks[t];
DrawList.AddLine(ImVec2(xt->PixelPos, gp.BB_Plot.Max.y),ImVec2(xt->PixelPos, gp.BB_Plot.Max.y - (xt->Major ? 10.0f : 5.0f)), gp.Col_Border, 1); DrawList.AddLine(ImVec2(xt->PixelPos, gp.BB_Plot.Max.y),ImVec2(xt->PixelPos, gp.BB_Plot.Max.y - (xt->Major ? IMPLOT_MAJOR_SIZE : IMPLOT_MINOR_SIZE)), gp.Col_Border, 1);
} }
} }
PopPlotClipRect(); PopPlotClipRect();
ImGui::PushClipRect(gp.BB_Plot.Min, ImVec2(gp.BB_Frame.Max.x, gp.BB_Plot.Max.y), true); ImGui::PushClipRect(gp.BB_Plot.Min, ImVec2(gp.BB_Frame.Max.x, gp.BB_Plot.Max.y), true);
int axis_count = 0; int axis_count = 0;
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (!gp.Y[i].Present) { continue; } if (!gp.Y[i].Present) { continue; }
axis_count++; axis_count++;
@ -1277,14 +1283,13 @@ void EndPlot() {
if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickMarks)) { if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickMarks)) {
float direction = (i == 0) ? 1.0f : -1.0f; float direction = (i == 0) ? 1.0f : -1.0f;
bool no_major = axis_count >= 3; bool no_major = axis_count >= 3;
for (int t = 0; t < gp.YTicks[i].Size; t++) { for (int t = 0; t < gp.YTicks[i].Size; t++) {
ImPlotTick *yt = &gp.YTicks[i][t]; ImPlotTick *yt = &gp.YTicks[i][t];
ImVec2 start = ImVec2(x_start, yt->PixelPos); ImVec2 start = ImVec2(x_start, yt->PixelPos);
DrawList.AddLine( DrawList.AddLine(
start, start,
start + ImVec2(direction * ((!no_major && yt->Major) ? 10.0f : 5.0f), 0), start + ImVec2(direction * ((!no_major && yt->Major) ? IMPLOT_MAJOR_SIZE : IMPLOT_MINOR_SIZE), 0),
gp.Col_Border, 1); gp.Col_Border, 1);
} }
} }
@ -1304,7 +1309,7 @@ void EndPlot() {
ImRect bb_plot_pad = gp.BB_Plot; ImRect bb_plot_pad = gp.BB_Plot;
bb_plot_pad.Min.x += 5; bb_plot_pad.Max.x -= 5; bb_plot_pad.Min.x += 5; bb_plot_pad.Max.x -= 5;
if (!bb_plot_pad.Contains(IO.MousePos)) { if (!bb_plot_pad.Contains(IO.MousePos)) {
for (int i = 0; i < MAX_Y_AXES; ++i) { for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
if (plot.YAxis[i].Hovered) { if (plot.YAxis[i].Hovered) {
float x_loc = gp.AxisLabelReference[i]; float x_loc = gp.AxisLabelReference[i];
ImVec2 p1(x_loc - 5, gp.BB_Plot.Min.y - 5); ImVec2 p1(x_loc - 5, gp.BB_Plot.Min.y - 5);
@ -1315,7 +1320,6 @@ void EndPlot() {
} }
} }
PushPlotClipRect(); PushPlotClipRect();
// render selection/query // render selection/query
if (plot.Selecting) { if (plot.Selecting) {
@ -1472,7 +1476,7 @@ void EndPlot() {
if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMax) && !NanOrInf(gp.ExtentsX.Max)) { if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMax) && !NanOrInf(gp.ExtentsX.Max)) {
plot.XAxis.Range.Max = gp.ExtentsX.Max; plot.XAxis.Range.Max = gp.ExtentsX.Max;
} }
for (int i = 0; i < MAX_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.FitY[i] && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LockMin) && !NanOrInf(gp.ExtentsY[i].Min)) { if (gp.FitY[i] && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LockMin) && !NanOrInf(gp.ExtentsY[i].Min)) {
plot.YAxis[i].Range.Min = gp.ExtentsY[i].Min; plot.YAxis[i].Range.Min = gp.ExtentsY[i].Min;
} }
@ -1530,7 +1534,7 @@ void SetNextPlotLimitsX(double x_min, double x_max, ImGuiCond cond) {
void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond, int y_axis) { void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond, int y_axis) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotLimitsY() needs to be called before BeginPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotLimitsY() needs to be called before BeginPlot()!");
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < MAX_Y_AXES, "y_axis needs to be between 0 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < IMPLOT_Y_AXES, "y_axis needs to be between 0 and IMPLOT_Y_AXES");
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
gp.NextPlotData.HasYRange[y_axis] = true; gp.NextPlotData.HasYRange[y_axis] = true;
gp.NextPlotData.YRangeCond[y_axis] = cond; gp.NextPlotData.YRangeCond[y_axis] = cond;
@ -1555,7 +1559,7 @@ void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char** lab
void SetNextPlotTicksY(const double* values, int n_ticks, const char** labels, bool show_default, int y_axis) { void SetNextPlotTicksY(const double* values, int n_ticks, const char** labels, bool show_default, int y_axis) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksY() needs to be called before BeginPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksY() needs to be called before BeginPlot()!");
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < MAX_Y_AXES, "y_axis needs to be between 0 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < IMPLOT_Y_AXES, "y_axis needs to be between 0 and IMPLOT_Y_AXES");
gp.NextPlotData.ShowDefaultTicksY[y_axis] = show_default; gp.NextPlotData.ShowDefaultTicksY[y_axis] = show_default;
AddCustomTicks(values, labels, n_ticks, gp.YTicks[y_axis], gp.YTickLabels[y_axis]); AddCustomTicks(values, labels, n_ticks, gp.YTicks[y_axis], gp.YTickLabels[y_axis]);
} }
@ -1570,7 +1574,7 @@ void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char** lab
void SetPlotYAxis(int y_axis) { void SetPlotYAxis(int y_axis) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "SetPlotYAxis() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "SetPlotYAxis() needs to be called between BeginPlot() and EndPlot()!");
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < MAX_Y_AXES, "y_axis needs to be between 0 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < IMPLOT_Y_AXES, "y_axis needs to be between 0 and IMPLOT_Y_AXES");
gp.CurrentPlot->CurrentYAxis = y_axis; gp.CurrentPlot->CurrentYAxis = y_axis;
} }
@ -1611,7 +1615,7 @@ bool IsPlotXAxisHovered() {
bool IsPlotYAxisHovered(int y_axis_in) { bool IsPlotYAxisHovered(int y_axis_in) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotYAxisHovered() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotYAxisHovered() needs to be called between BeginPlot() and EndPlot()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
ImRect bb_plot_pad = gp.BB_Plot; ImRect bb_plot_pad = gp.BB_Plot;
@ -1621,7 +1625,7 @@ bool IsPlotYAxisHovered(int y_axis_in) {
ImPlotPoint GetPlotMousePos(int y_axis_in) { ImPlotPoint GetPlotMousePos(int y_axis_in) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotMousePos() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotMousePos() needs to be called between BeginPlot() and EndPlot()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
return gp.LastMousePos[y_axis]; return gp.LastMousePos[y_axis];
@ -1630,7 +1634,7 @@ ImPlotPoint GetPlotMousePos(int y_axis_in) {
ImPlotLimits GetPlotLimits(int y_axis_in) { ImPlotLimits GetPlotLimits(int y_axis_in) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() needs to be called between BeginPlot() and EndPlot()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
@ -1649,7 +1653,7 @@ bool IsPlotQueried() {
ImPlotLimits GetPlotQuery(int y_axis_in) { ImPlotLimits GetPlotQuery(int y_axis_in) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!");
ImPlotState& plot = *gp.CurrentPlot; ImPlotState& plot = *gp.CurrentPlot;
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
@ -1843,7 +1847,7 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
LabelTicks(ticks, false, txt_buff); LabelTicks(ticks, false, txt_buff);
float max_width = 0; float max_width = 0;
for (int i = 0; i < ticks.Size; ++i) for (int i = 0; i < ticks.Size; ++i)
max_width = ticks[i].Size.x > max_width ? ticks[i].Size.x : max_width; max_width = ticks[i].LabelSize.x > max_width ? ticks[i].LabelSize.x : max_width;
ImGuiContext &G = *GImGui; ImGuiContext &G = *GImGui;
ImGuiWindow * Window = G.CurrentWindow; ImGuiWindow * Window = G.CurrentWindow;
@ -1877,7 +1881,7 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
float ypos = ImRemap((float)ticks[i].PlotPos, (float)range.Max, (float)range.Min, bb_grad.Min.y, bb_grad.Max.y); float ypos = ImRemap((float)ticks[i].PlotPos, (float)range.Max, (float)range.Min, bb_grad.Min.y, bb_grad.Max.y);
if (ypos < bb_grad.Max.y - 2 && ypos > bb_grad.Min.y + 2) if (ypos < bb_grad.Max.y - 2 && ypos > bb_grad.Min.y + 2)
DrawList.AddLine(ImVec2(bb_grad.Max.x-1, ypos), ImVec2(bb_grad.Max.x - (ticks[i].Major ? 10.0f : 5.0f), ypos), col_border, 1.0f); DrawList.AddLine(ImVec2(bb_grad.Max.x-1, ypos), ImVec2(bb_grad.Max.x - (ticks[i].Major ? 10.0f : 5.0f), ypos), col_border, 1.0f);
DrawList.AddText(ImVec2(bb_grad.Max.x-1, ypos) + ImVec2(txt_off, -ticks[i].Size.y * 0.5f), ImGui::GetColorU32(ImGuiCol_Text), txt_buff.Buf.Data + ticks[i].TextOffset); DrawList.AddText(ImVec2(bb_grad.Max.x-1, ypos) + ImVec2(txt_off, -ticks[i].LabelSize.y * 0.5f), ImGui::GetColorU32(ImGuiCol_Text), txt_buff.Buf.Data + ticks[i].BufferOffset);
} }
ImGui::PopClipRect(); ImGui::PopClipRect();

View File

@ -151,6 +151,7 @@ struct ImPlotPoint {
struct ImPlotRange { struct ImPlotRange {
double Min, Max; double Min, Max;
ImPlotRange(); ImPlotRange();
ImPlotRange(double _min, double _max) { Min = _min; Max = _max; }
bool Contains(double value) const { return value >= Min && value <= Max; }; bool Contains(double value) const { return value >= Min && value <= Max; };
double Size() const { return Max - Min; }; double Size() const { return Max - Min; };
}; };

View File

@ -762,7 +762,7 @@ void ShowDemoWindow(bool* p_open) {
} }
} }
ImPlot::SetNextPlotLimitsX((double)t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always); ImPlot::SetNextPlotLimitsX((double)t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
if (ImPlot::BeginPlot("##DND", NULL, NULL, ImVec2(-1,0), ImPlotFlags_Legend | ImPlotFlags_Highlight | ImPlotFlags_BoxSelect | ImPlotFlags_ContextMenu | ImPlotFlags_NoChild | ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3)) { if (ImPlot::BeginPlot("##DND", NULL, NULL, ImVec2(-1,0), ImPlotFlags_Legend | ImPlotFlags_Highlight | ImPlotFlags_BoxSelect | ImPlotFlags_ContextMenu | ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3)) {
for (int i = 0; i < K_CHANNELS; ++i) { for (int i = 0; i < K_CHANNELS; ++i) {
if (show[i] && data[i].Data.size() > 0) { if (show[i] && data[i].Data.size() > 0) {
char label[K_CHANNELS]; char label[K_CHANNELS];

View File

@ -26,7 +26,7 @@
// don't provide any guarantee of forward compatibility! // don't provide any guarantee of forward compatibility!
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Header mess // [SECTION] Header Mess
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#pragma once #pragma once
@ -42,7 +42,7 @@
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Forward declarations // [SECTION] Forward Declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
struct ImPlotTick; struct ImPlotTick;
@ -54,20 +54,40 @@ struct ImPlotState;
struct ImPlotNextPlotData; struct ImPlotNextPlotData;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Context pointer // [SECTION] Context Pointer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
extern ImPlotContext* GImPlot; // Current implicit context pointer extern ImPlotContext* GImPlot; // Current implicit context pointer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Macros // [SECTION] Macros and Constants
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Constants can be changed unless stated otherwise
// Default plot frame width when requested width is auto (i.e. 0). This is not the plot area width!
#define IMPLOT_DEFAULT_W 400
// Default plot frame height when requested height is auto (i.e. 0). This is not the plot area height!
#define IMPLOT_DEFAULT_H 300
// Minimum plot frame width when requested width is to edge (i.e. -1). This is not the plot area width!
#define IMPLOT_MIN_W 300
// Minimum plot frame height when requested height is to edge (i.e. -1). This is not the plot area height!
#define IMPLOT_MIN_H 225
// The maximum number of supported y-axes (DO NOT CHANGE THIS) // The maximum number of supported y-axes (DO NOT CHANGE THIS)
#define MAX_Y_AXES 3 #define IMPLOT_Y_AXES 3
// The number of times to subdivided grid divisions (best if a multiple of 1, 2, and 5)
#define IMPLOT_SUB_DIV 10
// Pixel padding used for labels/titles
#define IMPLOT_LABEL_PAD 5
// Major tick size in pixels
#define IMPLOT_MAJOR_SIZE 10
// Minor tick size in pixels
#define IMPLOT_MINOR_SIZE 5
// Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
#define IMPLOT_ZOOM_RATE 0.1f
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Generic helpers // [SECTION] Generic Helpers
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Computes the common (base-10) logarithm // Computes the common (base-10) logarithm
@ -151,16 +171,16 @@ struct ImPlotTick
{ {
double PlotPos; double PlotPos;
float PixelPos; float PixelPos;
ImVec2 Size; ImVec2 LabelSize;
int TextOffset; int BufferOffset;
bool Major; bool Major;
bool RenderLabel; bool ShowLabel;
bool Labeled; bool Labeled;
ImPlotTick(double value, bool major, bool render_label = true) { ImPlotTick(double value, bool major, bool show_label) {
PlotPos = value; PlotPos = value;
Major = major; Major = major;
RenderLabel = render_label; ShowLabel = show_label;
Labeled = false; Labeled = false;
} }
}; };
@ -213,8 +233,8 @@ struct ImPlotAxisState
struct ImPlotAxisColor struct ImPlotAxisColor
{ {
ImU32 Major, Minor, Txt; ImU32 Major, Minor, MajTxt, MinTxt;
ImPlotAxisColor() { Major = Minor = Txt = 0; } ImPlotAxisColor() { Major = Minor = MajTxt = MinTxt = 0; }
}; };
// State information for Plot items // State information for Plot items
@ -245,7 +265,7 @@ struct ImPlotState
ImPlotFlags Flags; ImPlotFlags Flags;
ImPlotFlags PreviousFlags; ImPlotFlags PreviousFlags;
ImPlotAxis XAxis; ImPlotAxis XAxis;
ImPlotAxis YAxis[MAX_Y_AXES]; ImPlotAxis YAxis[IMPLOT_Y_AXES];
ImPool<ImPlotItem> Items; ImPool<ImPlotItem> Items;
ImVec2 SelectStart; ImVec2 SelectStart;
ImVec2 QueryStart; ImVec2 QueryStart;
@ -270,18 +290,18 @@ struct ImPlotState
struct ImPlotNextPlotData struct ImPlotNextPlotData
{ {
ImGuiCond XRangeCond; ImGuiCond XRangeCond;
ImGuiCond YRangeCond[MAX_Y_AXES]; ImGuiCond YRangeCond[IMPLOT_Y_AXES];
ImPlotRange X; ImPlotRange X;
ImPlotRange Y[MAX_Y_AXES]; ImPlotRange Y[IMPLOT_Y_AXES];
bool HasXRange; bool HasXRange;
bool HasYRange[MAX_Y_AXES]; bool HasYRange[IMPLOT_Y_AXES];
bool ShowDefaultTicksX; bool ShowDefaultTicksX;
bool ShowDefaultTicksY[MAX_Y_AXES]; bool ShowDefaultTicksY[IMPLOT_Y_AXES];
ImPlotNextPlotData() { ImPlotNextPlotData() {
HasXRange = false; HasXRange = false;
ShowDefaultTicksX = true; ShowDefaultTicksX = true;
for (int i = 0; i < MAX_Y_AXES; ++i) { for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
HasYRange[i] = false; HasYRange[i] = false;
ShowDefaultTicksY[i] = true; ShowDefaultTicksY[i] = true;
} }
@ -316,30 +336,30 @@ struct ImPlotContext {
// Axis States // Axis States
ImPlotAxisColor Col_X; ImPlotAxisColor Col_X;
ImPlotAxisColor Col_Y[MAX_Y_AXES]; ImPlotAxisColor Col_Y[IMPLOT_Y_AXES];
ImPlotAxisState X; ImPlotAxisState X;
ImPlotAxisState Y[MAX_Y_AXES]; ImPlotAxisState Y[IMPLOT_Y_AXES];
// Tick Marks and Labels // Tick Marks and Labels
ImVector<ImPlotTick> XTicks; ImVector<ImPlotTick> XTicks;
ImVector<ImPlotTick> YTicks[MAX_Y_AXES]; ImVector<ImPlotTick> YTicks[IMPLOT_Y_AXES];
ImGuiTextBuffer XTickLabels; ImGuiTextBuffer XTickLabels;
ImGuiTextBuffer YTickLabels[MAX_Y_AXES]; ImGuiTextBuffer YTickLabels[IMPLOT_Y_AXES];
float AxisLabelReference[MAX_Y_AXES]; float AxisLabelReference[IMPLOT_Y_AXES];
// Transformations and Data Extents // Transformations and Data Extents
ImRect PixelRange[MAX_Y_AXES]; ImRect PixelRange[IMPLOT_Y_AXES];
double Mx; double Mx;
double My[MAX_Y_AXES]; double My[IMPLOT_Y_AXES];
double LogDenX; double LogDenX;
double LogDenY[MAX_Y_AXES]; double LogDenY[IMPLOT_Y_AXES];
ImPlotRange ExtentsX; ImPlotRange ExtentsX;
ImPlotRange ExtentsY[MAX_Y_AXES]; ImPlotRange ExtentsY[IMPLOT_Y_AXES];
// Data Fitting Flags // Data Fitting Flags
bool FitThisFrame; bool FitThisFrame;
bool FitX; bool FitX;
bool FitY[MAX_Y_AXES]; bool FitY[IMPLOT_Y_AXES];
// Hover states // Hover states
bool Hov_Frame; bool Hov_Frame;
@ -347,7 +367,7 @@ struct ImPlotContext {
// Axis Rendering Flags // Axis Rendering Flags
bool RenderX; bool RenderX;
bool RenderY[MAX_Y_AXES]; bool RenderY[IMPLOT_Y_AXES];
// Axis Locking Flags // Axis Locking Flags
bool LockPlot; bool LockPlot;
@ -366,7 +386,7 @@ struct ImPlotContext {
int DigitalPlotOffset; int DigitalPlotOffset;
ImPlotNextPlotData NextPlotData; ImPlotNextPlotData NextPlotData;
ImPlotInputMap InputMap; ImPlotInputMap InputMap;
ImPlotPoint LastMousePos[MAX_Y_AXES]; ImPlotPoint LastMousePos[IMPLOT_Y_AXES];
}; };
struct ImPlotAxisScale struct ImPlotAxisScale
@ -422,8 +442,13 @@ void AddDefaultTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logs
void AddCustomTicks(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer); void AddCustomTicks(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer);
// Creates label information for a list of ImPlotTick // Creates label information for a list of ImPlotTick
void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer); void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer);
// Calculates the maximum width of a list of ImPlotTick // Gets the widest visible (i.e. ShowLabel = true) label size from a list of ticks
float MaxTickLabelWidth(ImVector<ImPlotTick>& ticks); float MaxTickLabelWidth(const ImVector<ImPlotTick>& ticks);
// Sums the widths of visible ticks (i.e. ShowLabel = true) ticks
float SumTickLabelWidth(const ImVector<ImPlotTick>& ticks);
// Sums the heights of visible (i.e. ShowLabel = true) ticks
float SumTickLabelHeight(const ImVector<ImPlotTick>& ticks);
// Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2) // Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2)
double NiceNum(double x, bool round); double NiceNum(double x, bool round);