mirror of
https://github.com/gwm17/implot.git
synced 2025-01-30 19:08:51 -05:00
tick abstraction
This commit is contained in:
parent
acb69ab410
commit
cac7a61235
221
implot.cpp
221
implot.cpp
|
@ -338,11 +338,9 @@ void Reset(ImPlotContext* ctx) {
|
|||
ctx->LegendIndices.shrink(0);
|
||||
ctx->LegendLabels.Buf.shrink(0);
|
||||
// reset ticks/labels
|
||||
ctx->XTicks.shrink(0);
|
||||
ctx->XTickLabels.Buf.shrink(0);
|
||||
ctx->XTicks.Reset();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ctx->YTicks[i].shrink(0);
|
||||
ctx->YTickLabels[i].Buf.shrink(0);
|
||||
ctx->YTicks[i].Reset();
|
||||
}
|
||||
// reset extents/fit
|
||||
ctx->FitThisFrame = false;
|
||||
|
@ -539,23 +537,43 @@ const char* GetLegendLabel(int i) {
|
|||
// Tick Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImVector<ImPlotTick> &out) {
|
||||
void LabelTickDefault(ImPlotTick& tick, ImGuiTextBuffer& buffer) {
|
||||
char temp[32];
|
||||
if (tick.ShowLabel) {
|
||||
tick.BufferOffset = buffer.size();
|
||||
sprintf(temp, "%.10g", tick.PlotPos);
|
||||
buffer.append(temp, temp + strlen(temp) + 1);
|
||||
tick.LabelSize = ImGui::CalcTextSize(buffer.Buf.Data + tick.BufferOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelTickScientific(ImPlotTick& tick, ImGuiTextBuffer& buffer) {
|
||||
char temp[32];
|
||||
if (tick.ShowLabel) {
|
||||
tick.BufferOffset = buffer.size();
|
||||
sprintf(temp, "%.0E", tick.PlotPos);
|
||||
buffer.append(temp, temp + strlen(temp) + 1);
|
||||
tick.LabelSize = ImGui::CalcTextSize(buffer.Buf.Data + tick.BufferOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImPlotTickCollection& ticks) {
|
||||
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 (range.Contains(major))
|
||||
out.push_back(ImPlotTick(major, true, true));
|
||||
ticks.AddTick(major, true, true, LabelTickDefault);
|
||||
for (int i = 1; i < nMinor; ++i) {
|
||||
double minor = major + i * interval / nMinor;
|
||||
if (range.Contains(minor))
|
||||
out.push_back(ImPlotTick(minor, false, true));
|
||||
ticks.AddTick(minor, false, true, LabelTickDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImVector<ImPlotTick>& out) {
|
||||
void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollection& ticks) {
|
||||
if (range.Min <= 0 || range.Max <= 0)
|
||||
return;
|
||||
double log_min = ImLog10(range.Min);
|
||||
|
@ -572,7 +590,7 @@ void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImVector<ImPlotTi
|
|||
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, true));
|
||||
ticks.AddTick(major1, true, true, LabelTickScientific);
|
||||
for (int j = 0; j < exp_step; ++j) {
|
||||
major1 = ImPow(10, (double)(e+j));
|
||||
major2 = ImPow(10, (double)(e+j+1));
|
||||
|
@ -580,67 +598,41 @@ void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImVector<ImPlotTi
|
|||
for (int i = 1; i < (9 + (int)(j < (exp_step - 1))); ++i) {
|
||||
double minor = major1 + i * interval;
|
||||
if (minor >= (range.Min - DBL_EPSILON) && minor <= (range.Max + DBL_EPSILON))
|
||||
out.push_back(ImPlotTick(minor, false, false));
|
||||
ticks.AddTick(minor, false, false, LabelTickScientific);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddTicksCustom(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer) {
|
||||
|
||||
void AddTicksCustom(const double* values, const char** labels, int n, ImPlotTickCollection& ticks) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
ImPlotTick tick(values[i],false, true);
|
||||
tick.BufferOffset = buffer.size();
|
||||
ImPlotTick tick(values[i], false, true);
|
||||
tick.BufferOffset = ticks.Labels.size();
|
||||
if (labels != NULL) {
|
||||
buffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
||||
ticks.Labels.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
||||
tick.LabelSize = ImGui::CalcTextSize(labels[i]);
|
||||
tick.Labeled = true;
|
||||
}
|
||||
ticks.push_back(tick);
|
||||
ticks.AddTick(tick);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer) {
|
||||
char temp[32];
|
||||
for (int t = 0; t < ticks.Size; t++) {
|
||||
ImPlotTick *tk = &ticks[t];
|
||||
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->LabelSize = ImGui::CalcTextSize(buffer.Buf.Data + tk->BufferOffset);
|
||||
tk->Labeled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float MaxTickLabelWidth(const ImVector<ImPlotTick>& ticks) {
|
||||
float w = 0;
|
||||
for (int i = 0; i < ticks.Size; ++i)
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Axis Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ConstrainAxis(ImPlotAxis& axis) {
|
||||
axis.Range.Min = ConstrainNan(ConstrainInf(axis.Range.Min));
|
||||
axis.Range.Max = ConstrainNan(ConstrainInf(axis.Range.Max));
|
||||
if (ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale)) {
|
||||
axis.Range.Min = ConstrainLog(axis.Range.Min);
|
||||
axis.Range.Max = ConstrainLog(axis.Range.Max);
|
||||
}
|
||||
if (axis.Range.Max <= axis.Range.Min)
|
||||
axis.Range.Max = axis.Range.Min + DBL_EPSILON;
|
||||
}
|
||||
|
||||
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col) {
|
||||
const ImVec4 col_label = GetStyleColorVec4(axis_flag);
|
||||
const ImVec4 col_grid = GetStyleColorVec4(axis_flag + 1);
|
||||
|
@ -744,30 +736,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
|
||||
// CONSTRAINTS ------------------------------------------------------------
|
||||
|
||||
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 < 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));
|
||||
}
|
||||
|
||||
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale))
|
||||
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 < 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))
|
||||
plot.YAxis[i].Range.Max = ConstrainLog(plot.YAxis[i].Range.Max);
|
||||
}
|
||||
|
||||
if (plot.XAxis.Range.Max <= plot.XAxis.Range.Min)
|
||||
plot.XAxis.Range.Max = plot.XAxis.Range.Min + DBL_EPSILON;
|
||||
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;
|
||||
}
|
||||
ConstrainAxis(plot.XAxis);
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; i++)
|
||||
ConstrainAxis(plot.YAxis[i]);
|
||||
|
||||
// AXIS COLORS -----------------------------------------------------------------
|
||||
|
||||
|
@ -822,31 +793,16 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
}
|
||||
}
|
||||
|
||||
// label ticks
|
||||
if (gp.X.HasLabels)
|
||||
LabelTicks(gp.XTicks, ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_Scientific) || ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTickLabels);
|
||||
|
||||
float max_label_widths[IMPLOT_Y_AXES];
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||
if (gp.Y[i].Present && gp.Y[i].HasLabels) {
|
||||
LabelTicks(gp.YTicks[i], ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_Scientific) || ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale), gp.YTickLabels[i]);
|
||||
max_label_widths[i] = MaxTickLabelWidth(gp.YTicks[i]);
|
||||
}
|
||||
else {
|
||||
max_label_widths[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// plot bb
|
||||
const ImVec2 title_size = ImGui::CalcTextSize(title, NULL, true);
|
||||
const float txt_height = ImGui::GetTextLineHeight();
|
||||
const float pad_top = title_size.x > 0.0f ? txt_height + gp.Style.LabelPadding.y : 0;
|
||||
const float pad_bot = (gp.X.HasLabels ? txt_height + gp.Style.LabelPadding.y : 0) + (x_label ? txt_height + gp.Style.LabelPadding.y : 0);
|
||||
const float pad_left = (y_label ? txt_height + gp.Style.LabelPadding.x : 0)
|
||||
+ (gp.Y[0].HasLabels ? max_label_widths[0] + gp.Style.LabelPadding.x : 0);
|
||||
const float pad_right = ((gp.Y[1].Present && gp.Y[1].HasLabels) ? max_label_widths[1] + gp.Style.LabelPadding.x : 0)
|
||||
+ (gp.Y[0].HasLabels ? gp.YTicks[0].MaxWidth + gp.Style.LabelPadding.x : 0);
|
||||
const float pad_right = ((gp.Y[1].Present && gp.Y[1].HasLabels) ? gp.YTicks[1].MaxWidth + gp.Style.LabelPadding.x : 0)
|
||||
+ ((gp.Y[1].Present && gp.Y[2].Present) ? gp.Style.LabelPadding.x + gp.Style.MinorTickLen.y : 0)
|
||||
+ ((gp.Y[2].Present && gp.Y[2].HasLabels) ? max_label_widths[2] + gp.Style.LabelPadding.x : 0);
|
||||
+ ((gp.Y[2].Present && gp.Y[2].HasLabels) ? gp.YTicks[2].MaxWidth + gp.Style.LabelPadding.x : 0);
|
||||
|
||||
|
||||
gp.BB_Plot = ImRect(gp.BB_Canvas.Min + ImVec2(pad_left, pad_top), gp.BB_Canvas.Max - ImVec2(pad_right, pad_bot));
|
||||
|
@ -860,7 +816,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
// axis label reference
|
||||
gp.YAxisReference[0] = gp.BB_Plot.Min.x;
|
||||
gp.YAxisReference[1] = gp.BB_Plot.Max.x;
|
||||
gp.YAxisReference[2] = !gp.Y[1].Present ? gp.BB_Plot.Max.x : (gp.YAxisReference[1] + (gp.Y[1].HasLabels ? gp.Style.LabelPadding.x + max_label_widths[1] : 0) + gp.Style.LabelPadding.x + gp.Style.MinorTickLen.y);
|
||||
gp.YAxisReference[2] = !gp.Y[1].Present ? gp.BB_Plot.Max.x : (gp.YAxisReference[1] + (gp.Y[1].HasLabels ? gp.Style.LabelPadding.x + gp.YTicks[1].MaxWidth : 0) + gp.Style.LabelPadding.x + gp.Style.MinorTickLen.y);
|
||||
|
||||
// y axis regions bb and hover
|
||||
ImRect yAxisRegion_bb[IMPLOT_Y_AXES];
|
||||
|
@ -1148,17 +1104,17 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
// render axes
|
||||
PushPlotClipRect();
|
||||
|
||||
// transform ticks
|
||||
// transform ticks (TODO: Move this into ImPlotTickCollection)
|
||||
if (gp.RenderX) {
|
||||
for (int t = 0; t < gp.XTicks.Size; t++) {
|
||||
ImPlotTick *xt = &gp.XTicks[t];
|
||||
ImPlotTick *xt = &gp.XTicks.Ticks[t];
|
||||
xt->PixelPos = PlotToPixels(xt->PlotPos, 0, 0).x;
|
||||
}
|
||||
}
|
||||
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];
|
||||
ImPlotTick *yt = &gp.YTicks[i].Ticks[t];
|
||||
yt->PixelPos = PlotToPixels(0, yt->PlotPos, i).y;
|
||||
}
|
||||
}
|
||||
|
@ -1171,7 +1127,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
col_min.w *= ImClamp(ImRemap(density, 0.1f, 0.2f, 1.0f, 0.0f), 0.0f, 1.0f);
|
||||
ImU32 col_min32 = ImGui::ColorConvertFloat4ToU32(col_min);
|
||||
for (int t = 0; t < gp.XTicks.Size; t++) {
|
||||
ImPlotTick& xt = gp.XTicks[t];
|
||||
ImPlotTick& xt = gp.XTicks.Ticks[t];
|
||||
if (xt.Major)
|
||||
DrawList.AddLine(ImVec2(xt.PixelPos, gp.BB_Plot.Min.y), ImVec2(xt.PixelPos, gp.BB_Plot.Max.y), gp.Col_X.Major, gp.Style.MajorGridSize.x);
|
||||
else if (density < 0.2f)
|
||||
|
@ -1186,7 +1142,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
col_min.w *= ImClamp(ImRemap(density, 0.1f, 0.2f, 1.0f, 0.0f), 0.0f, 1.0f);
|
||||
ImU32 col_min32 = ImGui::ColorConvertFloat4ToU32(col_min);
|
||||
for (int t = 0; t < gp.YTicks[i].Size; t++) {
|
||||
ImPlotTick& yt = gp.YTicks[i][t];
|
||||
ImPlotTick& yt = gp.YTicks[i].Ticks[t];
|
||||
if (yt.Major)
|
||||
DrawList.AddLine(ImVec2(gp.BB_Plot.Min.x, yt.PixelPos), ImVec2(gp.BB_Plot.Max.x, yt.PixelPos), gp.Col_Y[i].Major, gp.Style.MajorGridSize.y);
|
||||
else if (density < 0.2f)
|
||||
|
@ -1220,19 +1176,19 @@ 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);
|
||||
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickLabels)) {
|
||||
for (int t = 0; t < gp.XTicks.Size; t++) {
|
||||
ImPlotTick *xt = &gp.XTicks[t];
|
||||
ImPlotTick *xt = &gp.XTicks.Ticks[t];
|
||||
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 + gp.Style.LabelPadding.y), xt->Major ? gp.Col_X.MajTxt : gp.Col_X.MinTxt, gp.XTickLabels.Buf.Data + xt->BufferOffset);
|
||||
DrawList.AddText(ImVec2(xt->PixelPos - xt->LabelSize.x * 0.5f, gp.BB_Plot.Max.y + gp.Style.LabelPadding.y), xt->Major ? gp.Col_X.MajTxt : gp.Col_X.MinTxt, gp.XTicks.GetLabel(t));
|
||||
}
|
||||
}
|
||||
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.YAxisReference[i] + (i == 0 ? (-gp.Style.LabelPadding.x - gp.YTicks[i][t].LabelSize.x) : gp.Style.LabelPadding.x);
|
||||
ImPlotTick *yt = &gp.YTicks[i][t];
|
||||
const float x_start = gp.YAxisReference[i] + (i == 0 ? (-gp.Style.LabelPadding.x - gp.YTicks[i].Ticks[t].LabelSize.x) : gp.Style.LabelPadding.x);
|
||||
ImPlotTick *yt = &gp.YTicks[i].Ticks[t];
|
||||
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);
|
||||
DrawList.AddText(start, yt->Major ? gp.Col_Y[i].MajTxt : gp.Col_Y[i].MinTxt, gp.YTicks[i].GetLabel(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1373,12 +1329,17 @@ void ShowPlotContextMenu(ImPlotState& plot) {
|
|||
if (ImGui::MenuItem("Legend",NULL,ImHasFlag(plot.Flags, ImPlotFlags_Legend))) {
|
||||
ImFlipFlag(plot.Flags, ImPlotFlags_Legend);
|
||||
}
|
||||
#if 0
|
||||
if (ImGui::BeginMenu("Metrics")) {
|
||||
ImGui::PushItemWidth(75);
|
||||
#ifdef IMPLOT_DEBUG
|
||||
if (ImGui::BeginMenu("Debug")) {
|
||||
ImGui::PushItemWidth(50);
|
||||
ImGui::LabelText("Plots", "%d", gp.Plots.GetSize());
|
||||
ImGui::LabelText("Color Modifiers", "%d", gp.ColorModifiers.size());
|
||||
ImGui::LabelText("Style Modifiers", "%d", gp.StyleModifiers.size());
|
||||
ImGui::LabelText("Color Mods", "%d", gp.ColorModifiers.size());
|
||||
ImGui::LabelText("Style Mods", "%d", gp.StyleModifiers.size());
|
||||
ImGui::TextUnformatted(gp.XTicks.Labels.Buf.Data, gp.XTicks.Labels.Buf.Data + gp.XTicks.Labels.size());
|
||||
ImGui::TextUnformatted(gp.YTicks[0].Labels.Buf.Data, gp.YTicks[0].Labels.Buf.Data + gp.YTicks[0].Labels.size());
|
||||
// ImGui::TextUnformatted(gp.YTicks[1].Labels.Buf.Data, gp.YTicks[1].Labels.Buf.Data + gp.YTicks[1].Labels.size());
|
||||
// ImGui::TextUnformatted(gp.YTicks[2].Labels.Buf.Data, gp.YTicks[2].Labels.Buf.Data + gp.YTicks[2].Labels.size());
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
@ -1412,7 +1373,7 @@ void EndPlot() {
|
|||
PushPlotClipRect();
|
||||
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_TickMarks)) {
|
||||
for (int t = 0; t < gp.XTicks.Size; t++) {
|
||||
ImPlotTick *xt = &gp.XTicks[t];
|
||||
ImPlotTick *xt = &gp.XTicks.Ticks[t];
|
||||
DrawList.AddLine(ImVec2(xt->PixelPos, gp.BB_Plot.Max.y),
|
||||
ImVec2(xt->PixelPos, gp.BB_Plot.Max.y - (xt->Major ? gp.Style.MajorTickLen.x : gp.Style.MinorTickLen.x)),
|
||||
gp.Col_X.Major,
|
||||
|
@ -1432,7 +1393,7 @@ void EndPlot() {
|
|||
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];
|
||||
ImPlotTick *yt = &gp.YTicks[i].Ticks[t];
|
||||
ImVec2 start = ImVec2(x_start, yt->PixelPos);
|
||||
DrawList.AddLine(start,
|
||||
start + ImVec2(direction * ((!no_major && yt->Major) ? gp.Style.MajorTickLen.y : gp.Style.MinorTickLen.y), 0),
|
||||
|
@ -1605,7 +1566,7 @@ void EndPlot() {
|
|||
writer.Write("%.3E", gp.MousePos[0].x);
|
||||
}
|
||||
else {
|
||||
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks[1].PlotPos - gp.XTicks[0].PlotPos) : plot.XAxis.Range.Size();
|
||||
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : plot.XAxis.Range.Size();
|
||||
writer.Write("%.*f", Precision(range_x), gp.MousePos[0].x);
|
||||
}
|
||||
// y1
|
||||
|
@ -1613,7 +1574,7 @@ void EndPlot() {
|
|||
writer.Write(",%.3E", gp.MousePos[0].y);
|
||||
}
|
||||
else {
|
||||
double range_y = gp.YTicks[0].Size > 1 ? (gp.YTicks[0][1].PlotPos - gp.YTicks[0][0].PlotPos) : plot.YAxis[0].Range.Size();
|
||||
double range_y = gp.YTicks[0].Size > 1 ? (gp.YTicks[0].Ticks[1].PlotPos - gp.YTicks[0].Ticks[0].PlotPos) : plot.YAxis[0].Range.Size();
|
||||
writer.Write(",%.*f", Precision(range_y), gp.MousePos[0].y);
|
||||
}
|
||||
// y2
|
||||
|
@ -1622,7 +1583,7 @@ void EndPlot() {
|
|||
writer.Write(",(%.3E)", gp.MousePos[1].y);
|
||||
}
|
||||
else {
|
||||
double range_y = gp.YTicks[1].Size > 1 ? (gp.YTicks[1][1].PlotPos - gp.YTicks[1][0].PlotPos) : plot.YAxis[1].Range.Size();
|
||||
double range_y = gp.YTicks[1].Size > 1 ? (gp.YTicks[1].Ticks[1].PlotPos - gp.YTicks[1].Ticks[0].PlotPos) : plot.YAxis[1].Range.Size();
|
||||
writer.Write(",(%.*f)", Precision(range_y), gp.MousePos[1].y);
|
||||
}
|
||||
}
|
||||
|
@ -1632,7 +1593,7 @@ void EndPlot() {
|
|||
writer.Write(",(%.3E)", gp.MousePos[2].y);
|
||||
}
|
||||
else {
|
||||
double range_y = gp.YTicks[2].Size > 1 ? (gp.YTicks[2][1].PlotPos - gp.YTicks[2][0].PlotPos) : plot.YAxis[2].Range.Size();
|
||||
double range_y = gp.YTicks[2].Size > 1 ? (gp.YTicks[2].Ticks[1].PlotPos - gp.YTicks[2].Ticks[0].PlotPos) : plot.YAxis[2].Range.Size();
|
||||
writer.Write(",(%.*f)", Precision(range_y), gp.MousePos[2].y);
|
||||
}
|
||||
}
|
||||
|
@ -1761,7 +1722,7 @@ void SetNextPlotTicksX(const double* values, int n_ticks, const char** labels, b
|
|||
ImPlotContext& gp = *GImPlot;
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksX() needs to be called before BeginPlot()!");
|
||||
gp.NextPlotData.ShowDefaultTicksX = show_default;
|
||||
AddTicksCustom(values, labels, n_ticks, gp.XTicks, gp.XTickLabels);
|
||||
AddTicksCustom(values, labels, n_ticks, gp.XTicks);
|
||||
}
|
||||
|
||||
void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char** labels, bool show_default) {
|
||||
|
@ -1776,7 +1737,7 @@ void SetNextPlotTicksY(const double* values, int n_ticks, const char** labels, b
|
|||
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksY() needs to be called before BeginPlot()!");
|
||||
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;
|
||||
AddTicksCustom(values, labels, n_ticks, gp.YTicks[y_axis], gp.YTickLabels[y_axis]);
|
||||
AddTicksCustom(values, labels, n_ticks, gp.YTicks[y_axis]);
|
||||
}
|
||||
|
||||
void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char** labels, bool show_default, int y_axis) {
|
||||
|
@ -2239,18 +2200,14 @@ ImVec4 NextColormapColor() {
|
|||
|
||||
void ShowColormapScale(double scale_min, double scale_max, float height) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
static ImVector<ImPlotTick> ticks;
|
||||
static ImGuiTextBuffer txt_buff;
|
||||
static ImPlotTickCollection ticks;
|
||||
ticks.Reset();
|
||||
ImPlotRange range;
|
||||
range.Min = scale_min;
|
||||
range.Max = scale_max;
|
||||
ticks.shrink(0);
|
||||
txt_buff.Buf.shrink(0);
|
||||
|
||||
AddTicksDefault(range, 10, 0, ticks);
|
||||
LabelTicks(ticks, false, txt_buff);
|
||||
float max_width = 0;
|
||||
for (int i = 0; i < ticks.Size; ++i)
|
||||
max_width = ticks[i].LabelSize.x > max_width ? ticks[i].LabelSize.x : max_width;
|
||||
|
||||
|
||||
ImGuiContext &G = *GImGui;
|
||||
ImGuiWindow * Window = G.CurrentWindow;
|
||||
|
@ -2260,7 +2217,7 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
|
|||
const float bar_w = 20;
|
||||
|
||||
ImDrawList &DrawList = *Window->DrawList;
|
||||
ImVec2 size(bar_w + txt_off + max_width + 2 * gp.Style.PlotPadding.x, height);
|
||||
ImVec2 size(bar_w + txt_off + ticks.MaxWidth + 2 * gp.Style.PlotPadding.x, height);
|
||||
ImRect bb_frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + size);
|
||||
ImGui::ItemSize(bb_frame);
|
||||
if (!ImGui::ItemAdd(bb_frame, 0, &bb_frame))
|
||||
|
@ -2280,10 +2237,10 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
|
|||
|
||||
ImGui::PushClipRect(bb_frame.Min, bb_frame.Max, true);
|
||||
for (int i = 0; i < ticks.Size; ++i) {
|
||||
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.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].LabelSize.y * 0.5f), ImGui::GetColorU32(ImGuiCol_Text), txt_buff.Buf.Data + ticks[i].BufferOffset);
|
||||
DrawList.AddLine(ImVec2(bb_grad.Max.x-1, ypos), ImVec2(bb_grad.Max.x - (ticks.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.Ticks[i].LabelSize.y * 0.5f), ImGui::GetColorU32(ImGuiCol_Text), ticks.GetLabel(i));
|
||||
}
|
||||
ImGui::PopClipRect();
|
||||
|
||||
|
|
|
@ -176,16 +176,56 @@ struct ImPlotTick
|
|||
int BufferOffset;
|
||||
bool Major;
|
||||
bool ShowLabel;
|
||||
bool Labeled;
|
||||
|
||||
ImPlotTick(double value, bool major, bool show_label) {
|
||||
PlotPos = value;
|
||||
Major = major;
|
||||
ShowLabel = show_label;
|
||||
Labeled = false;
|
||||
BufferOffset = -1;
|
||||
}
|
||||
};
|
||||
|
||||
// Collection of ticks
|
||||
struct ImPlotTickCollection {
|
||||
ImVector<ImPlotTick> Ticks;
|
||||
ImGuiTextBuffer Labels;
|
||||
float TotalWidth;
|
||||
float TotalHeight;
|
||||
float MaxWidth;
|
||||
float MaxHeight;
|
||||
int Size;
|
||||
|
||||
void AddTick(const ImPlotTick& tick) {
|
||||
if (tick.ShowLabel) {
|
||||
TotalWidth += tick.ShowLabel ? tick.LabelSize.x : 0;
|
||||
TotalHeight += tick.ShowLabel ? tick.LabelSize.y : 0;
|
||||
MaxWidth = tick.LabelSize.x > MaxWidth ? tick.LabelSize.x : MaxWidth;
|
||||
MaxHeight = tick.LabelSize.y > MaxHeight ? tick.LabelSize.y : MaxHeight;
|
||||
}
|
||||
Ticks.push_back(tick);
|
||||
Size++;
|
||||
}
|
||||
|
||||
void AddTick(double value, bool major, bool show_label, void (*labeler)(ImPlotTick& tick, ImGuiTextBuffer& buf)) {
|
||||
ImPlotTick tick(value, major, show_label);
|
||||
if (labeler)
|
||||
labeler(tick, Labels);
|
||||
AddTick(tick);
|
||||
}
|
||||
|
||||
const char* GetLabel(int idx) {
|
||||
return Labels.Buf.Data + Ticks[idx].BufferOffset;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
Ticks.shrink(0);
|
||||
Labels.Buf.shrink(0);
|
||||
TotalWidth = TotalHeight = MaxWidth = MaxHeight = 0;
|
||||
Size = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Axis state information that must persist after EndPlot
|
||||
struct ImPlotAxis
|
||||
{
|
||||
|
@ -337,10 +377,8 @@ struct ImPlotContext {
|
|||
ImPlotAxisState Y[IMPLOT_Y_AXES];
|
||||
|
||||
// Tick Marks and Labels
|
||||
ImVector<ImPlotTick> XTicks;
|
||||
ImVector<ImPlotTick> YTicks[IMPLOT_Y_AXES];
|
||||
ImGuiTextBuffer XTickLabels;
|
||||
ImGuiTextBuffer YTickLabels[IMPLOT_Y_AXES];
|
||||
ImPlotTickCollection XTicks;
|
||||
ImPlotTickCollection YTicks[IMPLOT_Y_AXES];
|
||||
float YAxisReference[IMPLOT_Y_AXES];
|
||||
|
||||
// Transformations and Data Extents
|
||||
|
@ -437,25 +475,24 @@ int GetLegendCount();
|
|||
// Gets the ith entry string for the current legend
|
||||
const char* GetLegendLabel(int i);
|
||||
|
||||
// Label a tick with default formatting
|
||||
void LabelTickDefault(ImPlotTick& tick, ImGuiTextBuffer& buffer);
|
||||
// Label a tick with scientific formating
|
||||
void LabelTickScientific(ImPlotTick& tick, ImGuiTextBuffer& buffer);
|
||||
// Populates a list of ImPlotTicks with normal spaced and formatted ticks
|
||||
void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImVector<ImPlotTick> &out);
|
||||
void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImPlotTickCollection& ticks);
|
||||
// Populates a list of ImPlotTicks with logarithmic space and formatted ticks
|
||||
void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImVector<ImPlotTick>& out);
|
||||
void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollection& ticks);
|
||||
// Populates a list of ImPlotTicks with custom spaced and labeled ticks
|
||||
void AddTicksCustom(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);
|
||||
// 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);
|
||||
void AddTicksCustom(const double* values, const char** labels, int n, ImPlotTickCollection& ticks);
|
||||
|
||||
// Constrains an axis range
|
||||
void ConstrainAxis(ImPlotAxis& axis);
|
||||
// Updates axis ticks, lins, and label colors
|
||||
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col);
|
||||
|
||||
// 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);
|
||||
// Updates axis ticks, lins, and label colors
|
||||
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col);
|
||||
// Draws vertical text. The position is the bottom left of the text rect.
|
||||
void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
|
||||
// Calculates the size of vertical text
|
||||
|
|
Loading…
Reference in New Issue
Block a user