mirror of
https://github.com/gwm17/implot.git
synced 2024-11-23 02:38:53 -05:00
improve axis constraining
This commit is contained in:
parent
fe552f25f0
commit
e0450d00af
91
implot.cpp
91
implot.cpp
|
@ -401,11 +401,11 @@ void FitPoint(const ImPlotPoint& p) {
|
||||||
ImPlotRange& ex_y = gp.ExtentsY[y_axis];
|
ImPlotRange& ex_y = gp.ExtentsY[y_axis];
|
||||||
const bool log_x = ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale);
|
const bool log_x = ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale);
|
||||||
const bool log_y = ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale);
|
const bool log_y = ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale);
|
||||||
if (!NanOrInf(p.x) && !(log_x && p.x <= 0)) {
|
if (!ImNanOrInf(p.x) && !(log_x && p.x <= 0)) {
|
||||||
ex_x.Min = p.x < ex_x.Min ? p.x : ex_x.Min;
|
ex_x.Min = p.x < ex_x.Min ? p.x : ex_x.Min;
|
||||||
ex_x.Max = p.x > ex_x.Max ? p.x : ex_x.Max;
|
ex_x.Max = p.x > ex_x.Max ? p.x : ex_x.Max;
|
||||||
}
|
}
|
||||||
if (!NanOrInf(p.y) && !(log_y && p.y <= 0)) {
|
if (!ImNanOrInf(p.y) && !(log_y && p.y <= 0)) {
|
||||||
ex_y.Min = p.y < ex_y.Min ? p.y : ex_y.Min;
|
ex_y.Min = p.y < ex_y.Min ? p.y : ex_y.Min;
|
||||||
ex_y.Max = p.y > ex_y.Max ? p.y : ex_y.Max;
|
ex_y.Max = p.y > ex_y.Max ? p.y : ex_y.Max;
|
||||||
}
|
}
|
||||||
|
@ -711,23 +711,6 @@ void AddTicksCustom(const double* values, const char** labels, int n, ImPlotTick
|
||||||
// Axis Utils
|
// 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 (ImHasFlag(axis.Flags, ImPlotAxisFlags_Time)) {
|
|
||||||
axis.Range.Min = ConstrainTime(axis.Range.Min);
|
|
||||||
axis.Range.Max = ConstrainTime(axis.Range.Max);
|
|
||||||
// if (axis.Range.Size() < 0.0001)
|
|
||||||
// axis.Range.Max = axis.Range.Min + 0.0001; // TBD
|
|
||||||
}
|
|
||||||
if (axis.Range.Max <= axis.Range.Min)
|
|
||||||
axis.Range.Max = axis.Range.Min + DBL_EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col) {
|
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col) {
|
||||||
const ImVec4 col_label = GetStyleColorVec4(axis_flag);
|
const ImVec4 col_label = GetStyleColorVec4(axis_flag);
|
||||||
const ImVec4 col_grid = GetStyleColorVec4(axis_flag + 1);
|
const ImVec4 col_grid = GetStyleColorVec4(axis_flag + 1);
|
||||||
|
@ -810,6 +793,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
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;
|
||||||
|
plot.XAxis.Constrain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,6 +801,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
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];
|
||||||
|
plot.YAxis[i].Constrain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -840,12 +825,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
gp.Scales[i] = ImPlotScale_LogLog;
|
gp.Scales[i] = ImPlotScale_LogLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CONSTRAINTS ------------------------------------------------------------
|
|
||||||
|
|
||||||
ConstrainAxis(plot.XAxis);
|
|
||||||
for (int i = 0; i < IMPLOT_Y_AXES; i++)
|
|
||||||
ConstrainAxis(plot.YAxis[i]);
|
|
||||||
|
|
||||||
// AXIS COLORS -----------------------------------------------------------------
|
// AXIS COLORS -----------------------------------------------------------------
|
||||||
|
|
||||||
UpdateAxisColors(ImPlotCol_XAxis, &gp.Col_X);
|
UpdateAxisColors(ImPlotCol_XAxis, &gp.Col_X);
|
||||||
|
@ -1017,19 +996,20 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
ImPlotPoint plot_tl = PixelsToPlot(gp.BB_Plot.Min - IO.MouseDelta, 0);
|
ImPlotPoint plot_tl = PixelsToPlot(gp.BB_Plot.Min - IO.MouseDelta, 0);
|
||||||
ImPlotPoint plot_br = PixelsToPlot(gp.BB_Plot.Max - IO.MouseDelta, 0);
|
ImPlotPoint plot_br = PixelsToPlot(gp.BB_Plot.Max - IO.MouseDelta, 0);
|
||||||
if (!gp.X.LockMin)
|
if (!gp.X.LockMin)
|
||||||
plot.XAxis.Range.Min = gp.X.Invert ? plot_br.x : plot_tl.x;
|
plot.XAxis.SetMin(gp.X.Invert ? plot_br.x : plot_tl.x);
|
||||||
if (!gp.X.LockMax)
|
if (!gp.X.LockMax)
|
||||||
plot.XAxis.Range.Max = gp.X.Invert ? plot_tl.x : plot_br.x;
|
plot.XAxis.SetMax(gp.X.Invert ? plot_tl.x : plot_br.x);
|
||||||
|
// ConstrainAxis(plot.XAxis);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < IMPLOT_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);
|
||||||
|
|
||||||
if (!gp.Y[i].LockMin)
|
if (!gp.Y[i].LockMin)
|
||||||
plot.YAxis[i].Range.Min = gp.Y[i].Invert ? plot_tl.y : plot_br.y;
|
plot.YAxis[i].SetMin(gp.Y[i].Invert ? plot_tl.y : plot_br.y);
|
||||||
if (!gp.Y[i].LockMax)
|
if (!gp.Y[i].LockMax)
|
||||||
plot.YAxis[i].Range.Max = gp.Y[i].Invert ? plot_br.y : plot_tl.y;
|
plot.YAxis[i].SetMax(gp.Y[i].Invert ? plot_br.y : plot_tl.y);
|
||||||
|
// ConstrainAxis(plot.YAxis[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set the mouse cursor based on which axes are moving.
|
// Set the mouse cursor based on which axes are moving.
|
||||||
|
@ -1080,11 +1060,11 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
ImPlotAxisScale axis_scale(0, tx, ty, zoom_rate);
|
ImPlotAxisScale axis_scale(0, tx, ty, zoom_rate);
|
||||||
const ImPlotPoint& plot_tl = axis_scale.Min;
|
const ImPlotPoint& plot_tl = axis_scale.Min;
|
||||||
const ImPlotPoint& plot_br = axis_scale.Max;
|
const ImPlotPoint& plot_br = axis_scale.Max;
|
||||||
|
|
||||||
if (!gp.X.LockMin)
|
if (!gp.X.LockMin)
|
||||||
plot.XAxis.Range.Min = gp.X.Invert ? plot_br.x : plot_tl.x;
|
plot.XAxis.SetMin(gp.X.Invert ? plot_br.x : plot_tl.x);
|
||||||
if (!gp.X.LockMax)
|
if (!gp.X.LockMax)
|
||||||
plot.XAxis.Range.Max = gp.X.Invert ? plot_tl.x : plot_br.x;
|
plot.XAxis.SetMax(gp.X.Invert ? plot_tl.x : plot_br.x);
|
||||||
|
// ConstrainAxis(plot.XAxis);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||||
if (plot.YAxis[i].HoveredTot && !gp.Y[i].Lock) {
|
if (plot.YAxis[i].HoveredTot && !gp.Y[i].Lock) {
|
||||||
|
@ -1092,9 +1072,10 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
const ImPlotPoint& plot_tl = axis_scale.Min;
|
const ImPlotPoint& plot_tl = axis_scale.Min;
|
||||||
const ImPlotPoint& plot_br = axis_scale.Max;
|
const ImPlotPoint& plot_br = axis_scale.Max;
|
||||||
if (!gp.Y[i].LockMin)
|
if (!gp.Y[i].LockMin)
|
||||||
plot.YAxis[i].Range.Min = gp.Y[i].Invert ? plot_tl.y : plot_br.y;
|
plot.YAxis[i].SetMin(gp.Y[i].Invert ? plot_tl.y : plot_br.y);
|
||||||
if (!gp.Y[i].LockMax)
|
if (!gp.Y[i].LockMax)
|
||||||
plot.YAxis[i].Range.Max = gp.Y[i].Invert ? plot_br.y : plot_tl.y;
|
plot.YAxis[i].SetMax(gp.Y[i].Invert ? plot_br.y : plot_tl.y);
|
||||||
|
// ConstrainAxis(plot.YAxis[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1111,16 +1092,16 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
const bool x_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.HorizontalMod) && ImFabs(select_size.x) > 2;
|
const bool x_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.HorizontalMod) && ImFabs(select_size.x) > 2;
|
||||||
const bool y_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.VerticalMod) && ImFabs(select_size.y) > 2;
|
const bool y_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.VerticalMod) && ImFabs(select_size.y) > 2;
|
||||||
if (!gp.X.LockMin && x_can_change)
|
if (!gp.X.LockMin && x_can_change)
|
||||||
plot.XAxis.Range.Min = ImMin(p1.x, p2.x);
|
plot.XAxis.SetMin(ImMin(p1.x, p2.x));
|
||||||
if (!gp.X.LockMax && x_can_change)
|
if (!gp.X.LockMax && x_can_change)
|
||||||
plot.XAxis.Range.Max = ImMax(p1.x, p2.x);
|
plot.XAxis.SetMax(ImMax(p1.x, p2.x));
|
||||||
for (int i = 0; i < IMPLOT_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 && y_can_change)
|
if (!gp.Y[i].LockMin && y_can_change)
|
||||||
plot.YAxis[i].Range.Min = ImMin(p1.y, p2.y);
|
plot.YAxis[i].SetMin(ImMin(p1.y, p2.y));
|
||||||
if (!gp.Y[i].LockMax && y_can_change)
|
if (!gp.Y[i].LockMax && y_can_change)
|
||||||
plot.YAxis[i].Range.Max = ImMax(p1.y, p2.y);
|
plot.YAxis[i].SetMax(ImMax(p1.y, p2.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plot.Selecting = false;
|
plot.Selecting = false;
|
||||||
|
@ -1363,7 +1344,7 @@ inline void ShowAxisContextMenu(ImPlotAxisState& state) {
|
||||||
ImGui::PushItemWidth(75);
|
ImGui::PushItemWidth(75);
|
||||||
bool total_lock = state.HasRange && state.RangeCond == ImGuiCond_Always;
|
bool total_lock = state.HasRange && state.RangeCond == ImGuiCond_Always;
|
||||||
bool logscale = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_LogScale);
|
bool logscale = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_LogScale);
|
||||||
bool timesale = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_Time);
|
// bool timesale = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_Time);
|
||||||
bool grid = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_GridLines);
|
bool grid = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_GridLines);
|
||||||
bool ticks = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_TickMarks);
|
bool ticks = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_TickMarks);
|
||||||
bool labels = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_TickLabels);
|
bool labels = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_TickLabels);
|
||||||
|
@ -1376,7 +1357,9 @@ inline void ShowAxisContextMenu(ImPlotAxisState& state) {
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
BeginDisabledControls(state.LockMin);
|
BeginDisabledControls(state.LockMin);
|
||||||
DragFloat("Min", &state.Axis->Range.Min, (float)drag_speed, -HUGE_VAL, state.Axis->Range.Max - DBL_EPSILON);
|
double temp_min = state.Axis->Range.Min;
|
||||||
|
if (DragFloat("Min", &temp_min, (float)drag_speed, -HUGE_VAL, state.Axis->Range.Max - DBL_EPSILON))
|
||||||
|
state.Axis->SetMin(temp_min);
|
||||||
EndDisabledControls(state.LockMin);
|
EndDisabledControls(state.LockMin);
|
||||||
|
|
||||||
BeginDisabledControls(total_lock);
|
BeginDisabledControls(total_lock);
|
||||||
|
@ -1386,7 +1369,9 @@ inline void ShowAxisContextMenu(ImPlotAxisState& state) {
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
BeginDisabledControls(state.LockMax);
|
BeginDisabledControls(state.LockMax);
|
||||||
DragFloat("Max", &state.Axis->Range.Max, (float)drag_speed, state.Axis->Range.Min + DBL_EPSILON, HUGE_VAL);
|
double temp_max = state.Axis->Range.Max;
|
||||||
|
if (DragFloat("Max", &temp_max, (float)drag_speed, state.Axis->Range.Min + DBL_EPSILON, HUGE_VAL))
|
||||||
|
state.Axis->SetMax(temp_max);
|
||||||
EndDisabledControls(state.LockMax);
|
EndDisabledControls(state.LockMax);
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
@ -1395,8 +1380,8 @@ inline void ShowAxisContextMenu(ImPlotAxisState& state) {
|
||||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_Invert);
|
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_Invert);
|
||||||
if (ImGui::Checkbox("Log Scale", &logscale))
|
if (ImGui::Checkbox("Log Scale", &logscale))
|
||||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_LogScale);
|
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_LogScale);
|
||||||
if (ImGui::Checkbox("Time", ×ale))
|
// if (ImGui::Checkbox("Time", ×ale))
|
||||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_Time);
|
// ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_Time);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::Checkbox("Grid Lines", &grid))
|
if (ImGui::Checkbox("Grid Lines", &grid))
|
||||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_GridLines);
|
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_GridLines);
|
||||||
|
@ -1744,27 +1729,29 @@ void EndPlot() {
|
||||||
// FIT DATA --------------------------------------------------------------
|
// FIT DATA --------------------------------------------------------------
|
||||||
|
|
||||||
if (gp.FitThisFrame && (gp.VisibleItemCount > 0 || plot.Queried)) {
|
if (gp.FitThisFrame && (gp.VisibleItemCount > 0 || plot.Queried)) {
|
||||||
if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMin) && !NanOrInf(gp.ExtentsX.Min)) {
|
if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMin) && !ImNanOrInf(gp.ExtentsX.Min)) {
|
||||||
plot.XAxis.Range.Min = gp.ExtentsX.Min;
|
plot.XAxis.SetMin(gp.ExtentsX.Min);
|
||||||
}
|
}
|
||||||
if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMax) && !NanOrInf(gp.ExtentsX.Max)) {
|
if (gp.FitX && !ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LockMax) && !ImNanOrInf(gp.ExtentsX.Max)) {
|
||||||
plot.XAxis.Range.Max = gp.ExtentsX.Max;
|
plot.XAxis.SetMax(gp.ExtentsX.Max);
|
||||||
}
|
}
|
||||||
if ((plot.XAxis.Range.Max - plot.XAxis.Range.Min) <= (2.0 * FLT_EPSILON)) {
|
if ((plot.XAxis.Range.Max - plot.XAxis.Range.Min) <= (2.0 * FLT_EPSILON)) {
|
||||||
plot.XAxis.Range.Max += FLT_EPSILON;
|
plot.XAxis.Range.Max += FLT_EPSILON;
|
||||||
plot.XAxis.Range.Min -= FLT_EPSILON;
|
plot.XAxis.Range.Min -= FLT_EPSILON;
|
||||||
}
|
}
|
||||||
|
// ConstrainAxis(plot.XAxis);
|
||||||
for (int i = 0; i < IMPLOT_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) && !ImNanOrInf(gp.ExtentsY[i].Min)) {
|
||||||
plot.YAxis[i].Range.Min = gp.ExtentsY[i].Min;
|
plot.YAxis[i].SetMin(gp.ExtentsY[i].Min);
|
||||||
}
|
}
|
||||||
if (gp.FitY[i] && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LockMax) && !NanOrInf(gp.ExtentsY[i].Max)) {
|
if (gp.FitY[i] && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LockMax) && !ImNanOrInf(gp.ExtentsY[i].Max)) {
|
||||||
plot.YAxis[i].Range.Max = gp.ExtentsY[i].Max;
|
plot.YAxis[i].SetMax(gp.ExtentsY[i].Max);
|
||||||
}
|
}
|
||||||
if ((plot.YAxis[i].Range.Max - plot.YAxis[i].Range.Min) <= (2.0 * FLT_EPSILON)) {
|
if ((plot.YAxis[i].Range.Max - plot.YAxis[i].Range.Min) <= (2.0 * FLT_EPSILON)) {
|
||||||
plot.YAxis[i].Range.Max += FLT_EPSILON;
|
plot.YAxis[i].Range.Max += FLT_EPSILON;
|
||||||
plot.YAxis[i].Range.Min -= FLT_EPSILON;
|
plot.YAxis[i].Range.Min -= FLT_EPSILON;
|
||||||
}
|
}
|
||||||
|
// ConstrainAxis(plot.YAxis[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@ extern ImPlotContext* GImPlot; // Current implicit context pointer
|
||||||
// Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
|
// Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
|
||||||
#define IMPLOT_ZOOM_RATE 0.1f
|
#define IMPLOT_ZOOM_RATE 0.1f
|
||||||
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC)
|
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC)
|
||||||
|
#define IMPLOT_MIN_TIME 0
|
||||||
|
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC)
|
||||||
#define IMPLOT_MAX_TIME 32503680000
|
#define IMPLOT_MAX_TIME 32503680000
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -87,21 +89,27 @@ extern ImPlotContext* GImPlot; // Current implicit context pointer
|
||||||
// Computes the common (base-10) logarithm
|
// Computes the common (base-10) logarithm
|
||||||
static inline float ImLog10(float x) { return log10f(x); }
|
static inline float ImLog10(float x) { return log10f(x); }
|
||||||
static inline double ImLog10(double x) { return log10(x); }
|
static inline double ImLog10(double x) { return log10(x); }
|
||||||
|
|
||||||
// Returns true if a flag is set
|
// Returns true if a flag is set
|
||||||
template <typename TSet, typename TFlag>
|
template <typename TSet, typename TFlag>
|
||||||
inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
|
inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
|
||||||
|
|
||||||
// Flips a flag in a flagset
|
// Flips a flag in a flagset
|
||||||
template <typename TSet, typename TFlag>
|
template <typename TSet, typename TFlag>
|
||||||
inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
|
inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
|
||||||
|
|
||||||
// Linearly remaps x from [x0 x1] to [y0 y1].
|
// Linearly remaps x from [x0 x1] to [y0 y1].
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
|
inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
|
||||||
|
|
||||||
// Returns always positive modulo (assumes r != 0)
|
// Returns always positive modulo (assumes r != 0)
|
||||||
inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
|
inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
|
||||||
|
// Returns true if val is NAN or INFINITY
|
||||||
|
inline bool ImNanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); }
|
||||||
|
// Turns NANs to 0s
|
||||||
|
inline double ImConstrainNan(double val) { return isnan(val) ? 0 : val; }
|
||||||
|
// Turns infinity to floating point maximums
|
||||||
|
inline double ImConstrainInf(double val) { return val == HUGE_VAL ? DBL_MAX : val == -HUGE_VAL ? - DBL_MAX : val; }
|
||||||
|
// Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)
|
||||||
|
inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
|
||||||
|
// Turns numbers less than 0 to zero
|
||||||
|
inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
|
||||||
|
|
||||||
// Offset calculator helper
|
// Offset calculator helper
|
||||||
template <int Count>
|
template <int Count>
|
||||||
|
@ -265,6 +273,53 @@ struct ImPlotAxis
|
||||||
HoveredExt = false;
|
HoveredExt = false;
|
||||||
HoveredTot = false;
|
HoveredTot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetMin(double _min) {
|
||||||
|
_min = ImConstrainNan(ImConstrainInf(_min));
|
||||||
|
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
|
||||||
|
_min = ImConstrainLog(_min);
|
||||||
|
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
||||||
|
_min = ImConstrainTime(_min);
|
||||||
|
if ((Range.Max - _min) < 0.0001)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_min >= Range.Max)
|
||||||
|
return false;
|
||||||
|
Range.Min = _min;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool SetMax(double _max) {
|
||||||
|
_max = ImConstrainNan(ImConstrainInf(_max));
|
||||||
|
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
|
||||||
|
_max = ImConstrainLog(_max);
|
||||||
|
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
||||||
|
_max = ImConstrainTime(_max);
|
||||||
|
if ((_max - Range.Min) < 0.0001)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_max <= Range.Min)
|
||||||
|
return false;
|
||||||
|
Range.Max = _max;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Constrain() {
|
||||||
|
Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
|
||||||
|
Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
|
||||||
|
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale)) {
|
||||||
|
Range.Min = ImConstrainLog(Range.Min);
|
||||||
|
Range.Max = ImConstrainLog(Range.Max);
|
||||||
|
}
|
||||||
|
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
||||||
|
Range.Min = ImConstrainTime(Range.Min);
|
||||||
|
Range.Max = ImConstrainTime(Range.Max);
|
||||||
|
if (Range.Size() < 0.0001)
|
||||||
|
Range.Max = Range.Min + 0.0001; // TBD
|
||||||
|
}
|
||||||
|
if (Range.Max <= Range.Min)
|
||||||
|
Range.Max = Range.Min + DBL_EPSILON;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Axis state information only needed between BeginPlot/EndPlot
|
// Axis state information only needed between BeginPlot/EndPlot
|
||||||
|
@ -544,8 +599,6 @@ void BustItemCache();
|
||||||
|
|
||||||
// Gets the current y-axis for the current plot
|
// Gets the current y-axis for the current plot
|
||||||
inline int GetCurrentYAxis() { return GImPlot->CurrentPlot->CurrentYAxis; }
|
inline int GetCurrentYAxis() { return GImPlot->CurrentPlot->CurrentYAxis; }
|
||||||
// Constrains an axis range
|
|
||||||
void ConstrainAxis(ImPlotAxis& axis);
|
|
||||||
// Updates axis ticks, lins, and label colors
|
// Updates axis ticks, lins, and label colors
|
||||||
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col);
|
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col);
|
||||||
|
|
||||||
|
@ -626,16 +679,6 @@ inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.5
|
||||||
|
|
||||||
// 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);
|
||||||
// Returns true if val is NAN or INFINITY
|
|
||||||
inline bool NanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); }
|
|
||||||
// Turns NANs to 0s
|
|
||||||
inline double ConstrainNan(double val) { return isnan(val) ? 0 : val; }
|
|
||||||
// Turns infinity to floating point maximums
|
|
||||||
inline double ConstrainInf(double val) { return val == HUGE_VAL ? DBL_MAX : val == -HUGE_VAL ? - DBL_MAX : val; }
|
|
||||||
// Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)
|
|
||||||
inline double ConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
|
|
||||||
// Turns numbers less than 0 to zero
|
|
||||||
inline double ConstrainTime(double val) { return val < 0 ? 0 : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
|
|
||||||
// Computes order of magnitude of double.
|
// Computes order of magnitude of double.
|
||||||
inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
|
inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
|
||||||
// Returns the precision required for a order of magnitude.
|
// Returns the precision required for a order of magnitude.
|
||||||
|
|
|
@ -1512,11 +1512,11 @@ inline void PlotDigitalEx(const char* label_id, Getter getter) {
|
||||||
ImPlotPoint itemData1 = getter(0);
|
ImPlotPoint itemData1 = getter(0);
|
||||||
for (int i = 0; i < getter.Count; ++i) {
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
ImPlotPoint itemData2 = getter(i);
|
ImPlotPoint itemData2 = getter(i);
|
||||||
if (NanOrInf(itemData1.y)) {
|
if (ImNanOrInf(itemData1.y)) {
|
||||||
itemData1 = itemData2;
|
itemData1 = itemData2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (NanOrInf(itemData2.y)) itemData2.y = ConstrainNan(ConstrainInf(itemData2.y));
|
if (ImNanOrInf(itemData2.y)) itemData2.y = ImConstrainNan(ImConstrainInf(itemData2.y));
|
||||||
int pixY_0 = (int)(s.LineWeight);
|
int pixY_0 = (int)(s.LineWeight);
|
||||||
itemData1.y = ImMax(0.0, itemData1.y);
|
itemData1.y = ImMax(0.0, itemData1.y);
|
||||||
float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y;
|
float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y;
|
||||||
|
@ -1532,7 +1532,7 @@ inline void PlotDigitalEx(const char* label_id, Getter getter) {
|
||||||
while (((i+2) < getter.Count) && (itemData1.y == itemData2.y)) {
|
while (((i+2) < getter.Count) && (itemData1.y == itemData2.y)) {
|
||||||
const int in = (i + 1);
|
const int in = (i + 1);
|
||||||
itemData2 = getter(in);
|
itemData2 = getter(in);
|
||||||
if (NanOrInf(itemData2.y)) break;
|
if (ImNanOrInf(itemData2.y)) break;
|
||||||
pMax.x = PlotToPixels(itemData2).x;
|
pMax.x = PlotToPixels(itemData2).x;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user