1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-10-09 15:47: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->ExtentsX.Min = 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].Max = -HUGE_VAL;
ctx->FitY[i] = false;
@ -278,7 +278,7 @@ void FitPoint(const ImPlotPoint& p) {
void UpdateTransformCache() {
ImPlotContext& gp = *GImPlot;
// 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,
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,
@ -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.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.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 interval = (major2 - major1) / 9;
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) {
double minor = major1 + i * interval;
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 {
const double nice_range = NiceNum(range.Size() * 0.99, 0);
const double interval = NiceNum(nice_range / (nMajor - 1), 1);
const double nice_range = NiceNum(range.Size() * 0.99, false);
const double interval = NiceNum(nice_range / (nMajor - 1), true);
const double graphmin = floor(range.Min / interval) * interval;
const double graphmax = ceil(range.Max / interval) * interval;
for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) {
if (major >= range.Min && major <= range.Max)
out.push_back(ImPlotTick(major, true));
if (range.Contains(major))
out.push_back(ImPlotTick(major, true, true));
for (int i = 1; i < nMinor; ++i) {
double minor = major + i * interval / nMinor;
if (minor >= range.Min && minor <= range.Max)
out.push_back(ImPlotTick(minor, false));
if (range.Contains(minor))
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) {
for (int i = 0; i < n; ++i) {
ImPlotTick tick(values[i],false);
tick.TextOffset = buffer.size();
ImPlotTick tick(values[i],false, true);
tick.BufferOffset = buffer.size();
if (labels != NULL) {
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;
}
ticks.push_back(tick);
@ -458,26 +458,40 @@ void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& b
char temp[32];
for (int t = 0; t < ticks.Size; t++) {
ImPlotTick *tk = &ticks[t];
if (tk->RenderLabel && !tk->Labeled) {
tk->TextOffset = buffer.size();
if (tk->ShowLabel && !tk->Labeled) {
tk->BufferOffset = buffer.size();
if (scientific)
sprintf(temp, "%.0e", tk->PlotPos);
else
sprintf(temp, "%.10g", tk->PlotPos);
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;
}
}
}
float MaxTickLabelWidth(ImVector<ImPlotTick>& ticks) {
float MaxTickLabelWidth(const ImVector<ImPlotTick>& ticks) {
float w = 0;
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;
}
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 {
public:
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) {
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];
col->Major = ImGui::GetColorU32(col_Axis);
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));
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->Minor = ImGui::GetColorU32(col_axis * ImVec4(1, 1, 1, 0.25f));
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));
}
//-----------------------------------------------------------------------------
@ -541,7 +556,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
const ImGuiIO & IO = ImGui::GetIO();
bool just_created = gp.Plots.GetByKey(ID) == NULL;
gp.CurrentPlot = gp.Plots.GetOrAddByKey(ID);
gp.CurrentPlot = gp.Plots.GetOrAddByKey(ID);
ImPlotState &plot = *gp.CurrentPlot;
plot.CurrentYAxis = 0;
@ -573,10 +588,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.YAxis[2].PreviousFlags = y3_flags;
// capture scroll with a child region
const float default_w = 400;
const float default_h = 300;
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->ScrollMax.y = 1.0f;
gp.ChildWindowMade = true;
@ -590,16 +603,14 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// NextPlotData -----------------------------------------------------------
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;
}
}
for (int i = 0; i < MAX_Y_AXES; i++) {
for (int i = 0; i < IMPLOT_Y_AXES; 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];
}
}
@ -609,9 +620,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
gp.X = ImPlotAxisState(&plot.XAxis, gp.NextPlotData.HasXRange, gp.NextPlotData.XRangeCond, true, 0);
gp.Y[0] = ImPlotAxisState(&plot.YAxis[0], gp.NextPlotData.HasYRange[0], gp.NextPlotData.YRangeCond[0], true, 0);
gp.Y[1] = ImPlotAxisState(&plot.YAxis[1], gp.NextPlotData.HasYRange[1], gp.NextPlotData.YRangeCond[1],
ImHasFlag(plot.Flags, ImPlotFlags_YAxis2), gp.Y[0].PresentSoFar);
ImHasFlag(plot.Flags, ImPlotFlags_YAxis2), gp.Y[0].PresentSoFar);
gp.Y[2] = ImPlotAxisState(&plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
ImHasFlag(plot.Flags, ImPlotFlags_YAxis3), gp.Y[1].PresentSoFar);
ImHasFlag(plot.Flags, ImPlotFlags_YAxis3), gp.Y[1].PresentSoFar);
gp.LockPlot = gp.X.Lock && gp.Y[0].Lock && gp.Y[1].Lock && gp.Y[2].Lock;
@ -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.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.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);
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale))
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))
plot.YAxis[i].Range.Min = ConstrainLog(plot.YAxis[i].Range.Min);
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)
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)
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 -----------------------------------------------------------
// 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);
ImGui::ItemSize(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
int x_divisions = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetWidth()));
int y_divisions[MAX_Y_AXES];
for (int i = 0; i < MAX_Y_AXES; i++) {
int y_divisions[IMPLOT_Y_AXES];
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
y_divisions[i] = ImMax(2, (int)IM_ROUND(0.003 * gp.BB_Canvas.GetHeight()));
}
gp.RenderX = (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_GridLines) ||
ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks) ||
ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels)) && x_divisions > 1;
for (int i = 0; i < MAX_Y_AXES; i++) {
ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks) ||
ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels)) && x_divisions > 1;
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
gp.RenderY[i] =
gp.Y[i].Present &&
(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
if (gp.RenderX && gp.NextPlotData.ShowDefaultTicksX)
AddDefaultTicks(plot.XAxis.Range, x_divisions, 10, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTicks);
for (int i = 0; i < MAX_Y_AXES; i++) {
AddDefaultTicks(plot.XAxis.Range, x_divisions, IMPLOT_SUB_DIV, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTicks);
for (int i = 0; i < IMPLOT_Y_AXES; 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))
LabelTicks(gp.XTicks, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_Scientific), gp.XTickLabels);
float max_label_width[MAX_Y_AXES] = {};
for (int i = 0; i < MAX_Y_AXES; i++) {
float max_label_width[IMPLOT_Y_AXES] = {};
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
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]);
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
const ImVec2 title_size = ImGui::CalcTextSize(title, NULL, true);
const float txt_off = 5;
const float txt_height = ImGui::GetTextLineHeight();
const float pad_top = title_size.x > 0.0f ? txt_height + txt_off : 0;
const float pad_bot = (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels) ? txt_height + txt_off : 0) + (x_label ? txt_height + txt_off : 0);
YPadCalculator y_axis_pad(gp.Y, max_label_width, txt_off);
const float pad_left = y_axis_pad(0) + (y_label ? 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 + IMPLOT_LABEL_PAD : 0) + (x_label ? txt_height + IMPLOT_LABEL_PAD : 0);
YPadCalculator y_axis_pad(gp.Y, max_label_width, IMPLOT_LABEL_PAD);
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);
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);
@ -742,7 +756,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
gp.BB_Plot.Max.x :
(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));
// 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));
@ -793,9 +807,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
plot.XAxis.Dragging = false;
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])) {
plot.YAxis[i].Dragging = false;
plot.YAxis[i].Dragging = false;
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)
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) {
ImPlotPoint plot_tl = PixelsToPlot(gp.BB_Plot.Min - 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) {
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].Lock && plot.YAxis[i].Dragging) {
direction |= (1 << 2);
@ -836,18 +850,14 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
}
}
if (IO.MouseDragMaxDistanceSqr[0] > 5) {
if (direction == 0) {
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
}
else if (direction == (1 << 1)) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
}
else if (direction == (1 << 2)) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
}
else {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
}
if (direction == 0)
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
else if (direction == (1 << 1))
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
else if (direction == (1 << 2))
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
else
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
}
}
// start drag
@ -855,7 +865,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (plot.XAxis.Hovered) {
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) {
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) {
UpdateTransformCache();
float zoom_rate = 0.1f;
float zoom_rate = IMPLOT_ZOOM_RATE;
if (IO.MouseWheel > 0)
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);
@ -881,7 +891,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
if (!gp.X.LockMax)
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) {
ImPlotAxisScale axis_scale(i, tx, ty, zoom_rate);
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);
if (!gp.X.LockMax && IO.KeyMods != gp.InputMap.HorizontalMod)
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);
p2 = PixelsToPlot(IO.MousePos, i);
if (!gp.Y[i].LockMin && IO.KeyMods != gp.InputMap.VerticalMod)
@ -945,12 +955,10 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
// end query
if (plot.Querying && (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton])) {
plot.Querying = false;
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) {
plot.Queried = true;
}
else {
plot.Queried = false;
}
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2)
plot.Queried = true;
else
plot.Queried = false;
}
// begin query
@ -980,16 +988,14 @@ 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) {
gp.FitThisFrame = true;
gp.FitX = plot.XAxis.Hovered;
for (int i = 0; i < MAX_Y_AXES; i++) {
gp.FitY[i] = plot.YAxis[i].Hovered;
}
for (int i = 0; i < IMPLOT_Y_AXES; i++)
gp.FitY[i] = plot.YAxis[i].Hovered;
}
else {
gp.FitThisFrame = false;
gp.FitX = false;
for (int i = 0; i < MAX_Y_AXES; i++) {
gp.FitY[i] = false;
}
for (int i = 0; i < IMPLOT_Y_AXES; i++)
gp.FitY[i] = false;
}
// FOCUS ------------------------------------------------------------------
@ -1001,7 +1007,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
UpdateTransformCache();
// 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);
}
@ -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;
}
}
for (int i = 0; i < MAX_Y_AXES; i++) {
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
if (gp.RenderY[i]) {
for (int t = 0; t < gp.YTicks[i].Size; 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)) {
for (int t = 0; t < gp.YTicks[i].Size; 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);
for (int t = 0; t < gp.XTicks.Size; 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)
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);
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->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();
}
@ -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_pos(gp.BB_Plot.GetCenter().x - xLabel_size.x * 0.5f,
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);
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)) {
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];
if (yt->RenderLabel && 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);
DrawList.AddText(start, gp.Col_Y[i].Txt, gp.YTickLabels[i].Buf.Data + yt->TextOffset);
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->LabelSize.y);
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) {
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);
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
@ -1179,7 +1185,7 @@ void PlotContextMenu(ImPlotState& plot) {
ImGui::PopID();
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)) {
continue;
}
@ -1241,13 +1247,13 @@ void PlotContextMenu(ImPlotState& plot) {
void EndPlot() {
IM_ASSERT_USER_ERROR(GImPlot != NULL, "No current context. Did you call ImPlot::CreateContext() or ImPlot::SetCurrentContext()?");
ImPlotContext& gp = *GImPlot;
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Mismatched BeginPlot()/EndPlot()!");
ImGuiContext &G = *GImGui;
ImPlotState &plot = *gp.CurrentPlot;
ImGuiWindow * Window = G.CurrentWindow;
ImGuiContext &G = *GImGui;
ImPlotState &plot = *gp.CurrentPlot;
ImGuiWindow * Window = G.CurrentWindow;
ImDrawList & DrawList = *Window->DrawList;
const ImGuiIO & IO = ImGui::GetIO();
const ImGuiIO & IO = ImGui::GetIO();
// AXIS STATES ------------------------------------------------------------
@ -1262,14 +1268,14 @@ void EndPlot() {
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks)) {
for (int t = 0; t < gp.XTicks.Size; 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();
ImGui::PushClipRect(gp.BB_Plot.Min, ImVec2(gp.BB_Frame.Max.x, gp.BB_Plot.Max.y), true);
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; }
axis_count++;
@ -1277,14 +1283,13 @@ void EndPlot() {
if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_TickMarks)) {
float direction = (i == 0) ? 1.0f : -1.0f;
bool no_major = axis_count >= 3;
for (int t = 0; t < gp.YTicks[i].Size; t++) {
ImPlotTick *yt = &gp.YTicks[i][t];
ImVec2 start = ImVec2(x_start, yt->PixelPos);
DrawList.AddLine(
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);
}
}
@ -1304,7 +1309,7 @@ void EndPlot() {
ImRect bb_plot_pad = gp.BB_Plot;
bb_plot_pad.Min.x += 5; bb_plot_pad.Max.x -= 5;
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) {
float x_loc = gp.AxisLabelReference[i];
ImVec2 p1(x_loc - 5, gp.BB_Plot.Min.y - 5);
@ -1315,7 +1320,6 @@ void EndPlot() {
}
}
PushPlotClipRect();
// render selection/query
if (plot.Selecting) {
@ -1472,7 +1476,7 @@ void EndPlot() {
if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMax) && !NanOrInf(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)) {
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) {
ImPlotContext& gp = *GImPlot;
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.
gp.NextPlotData.HasYRange[y_axis] = true;
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) {
ImPlotContext& gp = *GImPlot;
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;
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) {
ImPlotContext& gp = *GImPlot;
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;
}
@ -1611,7 +1615,7 @@ bool IsPlotXAxisHovered() {
bool IsPlotYAxisHovered(int y_axis_in) {
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()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
ImRect bb_plot_pad = gp.BB_Plot;
@ -1621,7 +1625,7 @@ bool IsPlotYAxisHovered(int y_axis_in) {
ImPlotPoint GetPlotMousePos(int y_axis_in) {
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()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
return gp.LastMousePos[y_axis];
@ -1630,7 +1634,7 @@ ImPlotPoint GetPlotMousePos(int y_axis_in) {
ImPlotLimits GetPlotLimits(int y_axis_in) {
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()!");
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) {
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()!");
ImPlotState& plot = *gp.CurrentPlot;
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);
float max_width = 0;
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;
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);
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.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();

View File

@ -151,8 +151,9 @@ struct ImPlotPoint {
struct ImPlotRange {
double Min, Max;
ImPlotRange();
bool Contains(double value) const { return value >= Min && value <= Max; };
double Size() const { return Max - Min; };
ImPlotRange(double _min, double _max) { Min = _min; Max = _max; }
bool Contains(double value) const { return value >= Min && value <= Max; };
double Size() const { return Max - Min; };
};
// Combination of two ranges for X and Y axes.

View File

@ -762,7 +762,7 @@ void ShowDemoWindow(bool* p_open) {
}
}
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) {
if (show[i] && data[i].Data.size() > 0) {
char label[K_CHANNELS];

View File

@ -26,7 +26,7 @@
// don't provide any guarantee of forward compatibility!
//-----------------------------------------------------------------------------
// [SECTION] Header mess
// [SECTION] Header Mess
//-----------------------------------------------------------------------------
#pragma once
@ -42,7 +42,7 @@
#endif
//-----------------------------------------------------------------------------
// [SECTION] Forward declarations
// [SECTION] Forward Declarations
//-----------------------------------------------------------------------------
struct ImPlotTick;
@ -54,20 +54,40 @@ struct ImPlotState;
struct ImPlotNextPlotData;
//-----------------------------------------------------------------------------
// [SECTION] Context pointer
// [SECTION] 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)
#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
@ -151,17 +171,17 @@ struct ImPlotTick
{
double PlotPos;
float PixelPos;
ImVec2 Size;
int TextOffset;
ImVec2 LabelSize;
int BufferOffset;
bool Major;
bool RenderLabel;
bool ShowLabel;
bool Labeled;
ImPlotTick(double value, bool major, bool render_label = true) {
PlotPos = value;
Major = major;
RenderLabel = render_label;
Labeled = false;
ImPlotTick(double value, bool major, bool show_label) {
PlotPos = value;
Major = major;
ShowLabel = show_label;
Labeled = false;
}
};
@ -213,8 +233,8 @@ struct ImPlotAxisState
struct ImPlotAxisColor
{
ImU32 Major, Minor, Txt;
ImPlotAxisColor() { Major = Minor = Txt = 0; }
ImU32 Major, Minor, MajTxt, MinTxt;
ImPlotAxisColor() { Major = Minor = MajTxt = MinTxt = 0; }
};
// State information for Plot items
@ -245,7 +265,7 @@ struct ImPlotState
ImPlotFlags Flags;
ImPlotFlags PreviousFlags;
ImPlotAxis XAxis;
ImPlotAxis YAxis[MAX_Y_AXES];
ImPlotAxis YAxis[IMPLOT_Y_AXES];
ImPool<ImPlotItem> Items;
ImVec2 SelectStart;
ImVec2 QueryStart;
@ -270,18 +290,18 @@ struct ImPlotState
struct ImPlotNextPlotData
{
ImGuiCond XRangeCond;
ImGuiCond YRangeCond[MAX_Y_AXES];
ImGuiCond YRangeCond[IMPLOT_Y_AXES];
ImPlotRange X;
ImPlotRange Y[MAX_Y_AXES];
ImPlotRange Y[IMPLOT_Y_AXES];
bool HasXRange;
bool HasYRange[MAX_Y_AXES];
bool HasYRange[IMPLOT_Y_AXES];
bool ShowDefaultTicksX;
bool ShowDefaultTicksY[MAX_Y_AXES];
bool ShowDefaultTicksY[IMPLOT_Y_AXES];
ImPlotNextPlotData() {
HasXRange = false;
ShowDefaultTicksX = true;
for (int i = 0; i < MAX_Y_AXES; ++i) {
for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
HasYRange[i] = false;
ShowDefaultTicksY[i] = true;
}
@ -316,30 +336,30 @@ struct ImPlotContext {
// Axis States
ImPlotAxisColor Col_X;
ImPlotAxisColor Col_Y[MAX_Y_AXES];
ImPlotAxisColor Col_Y[IMPLOT_Y_AXES];
ImPlotAxisState X;
ImPlotAxisState Y[MAX_Y_AXES];
ImPlotAxisState Y[IMPLOT_Y_AXES];
// Tick Marks and Labels
ImVector<ImPlotTick> XTicks;
ImVector<ImPlotTick> YTicks[MAX_Y_AXES];
ImVector<ImPlotTick> YTicks[IMPLOT_Y_AXES];
ImGuiTextBuffer XTickLabels;
ImGuiTextBuffer YTickLabels[MAX_Y_AXES];
float AxisLabelReference[MAX_Y_AXES];
ImGuiTextBuffer YTickLabels[IMPLOT_Y_AXES];
float AxisLabelReference[IMPLOT_Y_AXES];
// Transformations and Data Extents
ImRect PixelRange[MAX_Y_AXES];
ImRect PixelRange[IMPLOT_Y_AXES];
double Mx;
double My[MAX_Y_AXES];
double My[IMPLOT_Y_AXES];
double LogDenX;
double LogDenY[MAX_Y_AXES];
double LogDenY[IMPLOT_Y_AXES];
ImPlotRange ExtentsX;
ImPlotRange ExtentsY[MAX_Y_AXES];
ImPlotRange ExtentsY[IMPLOT_Y_AXES];
// Data Fitting Flags
bool FitThisFrame;
bool FitX;
bool FitY[MAX_Y_AXES];
bool FitY[IMPLOT_Y_AXES];
// Hover states
bool Hov_Frame;
@ -347,7 +367,7 @@ struct ImPlotContext {
// Axis Rendering Flags
bool RenderX;
bool RenderY[MAX_Y_AXES];
bool RenderY[IMPLOT_Y_AXES];
// Axis Locking Flags
bool LockPlot;
@ -366,7 +386,7 @@ struct ImPlotContext {
int DigitalPlotOffset;
ImPlotNextPlotData NextPlotData;
ImPlotInputMap InputMap;
ImPlotPoint LastMousePos[MAX_Y_AXES];
ImPlotPoint LastMousePos[IMPLOT_Y_AXES];
};
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);
// Creates label information for a list of ImPlotTick
void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer);
// Calculates the maximum width of a list of ImPlotTick
float MaxTickLabelWidth(ImVector<ImPlotTick>& ticks);
// Gets the widest visible (i.e. ShowLabel = true) label size from a list of 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)
double NiceNum(double x, bool round);