mirror of
https://github.com/gwm17/implot.git
synced 2025-01-30 19:08:51 -05:00
finish custom ticks
This commit is contained in:
parent
b497e7f72d
commit
f59913b8e0
227
implot.cpp
227
implot.cpp
|
@ -150,6 +150,15 @@ struct OffsetCalculator {
|
||||||
int Offsets[Count];
|
int Offsets[Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
|
||||||
|
buffer.resize(n);
|
||||||
|
T step = (vmax - vmin) / (n - 1);
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
buffer[i] = vmin + i * step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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 HasFlag(TSet set, TFlag flag) {
|
inline bool HasFlag(TSet set, TFlag flag) {
|
||||||
|
@ -234,6 +243,7 @@ struct ImPlotTick {
|
||||||
PlotPos = value;
|
PlotPos = value;
|
||||||
Major = major;
|
Major = major;
|
||||||
RenderLabel = render_label;
|
RenderLabel = render_label;
|
||||||
|
Labeled = false;
|
||||||
}
|
}
|
||||||
double PlotPos;
|
double PlotPos;
|
||||||
float PixelPos;
|
float PixelPos;
|
||||||
|
@ -241,6 +251,7 @@ struct ImPlotTick {
|
||||||
int TextOffset;
|
int TextOffset;
|
||||||
bool Major;
|
bool Major;
|
||||||
bool RenderLabel;
|
bool RenderLabel;
|
||||||
|
bool Labeled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImPlotItem {
|
struct ImPlotItem {
|
||||||
|
@ -307,10 +318,10 @@ struct ImPlotState {
|
||||||
struct ImPlotNextPlotData {
|
struct ImPlotNextPlotData {
|
||||||
ImPlotNextPlotData() {
|
ImPlotNextPlotData() {
|
||||||
HasXRange = false;
|
HasXRange = false;
|
||||||
HasUserXTickLabels = false;
|
ShowDefaultTicksX = true;
|
||||||
for (int i = 0; i < MAX_Y_AXES; ++i) {
|
for (int i = 0; i < MAX_Y_AXES; ++i) {
|
||||||
HasYRange[i] = false;
|
HasYRange[i] = false;
|
||||||
HasUserYTickLabels[i] = false;
|
ShowDefaultTicksY[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGuiCond XRangeCond;
|
ImGuiCond XRangeCond;
|
||||||
|
@ -319,18 +330,53 @@ struct ImPlotNextPlotData {
|
||||||
bool HasYRange[MAX_Y_AXES];
|
bool HasYRange[MAX_Y_AXES];
|
||||||
ImPlotRange X;
|
ImPlotRange X;
|
||||||
ImPlotRange Y[MAX_Y_AXES];
|
ImPlotRange Y[MAX_Y_AXES];
|
||||||
bool HasUserXTickLabels;
|
bool ShowDefaultTicksX;
|
||||||
bool HasUserYTickLabels[MAX_Y_AXES];
|
bool ShowDefaultTicksY[MAX_Y_AXES];
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Holds Plot state information that must persist only between calls to BeginPlot()/EndPlot()
|
/// Holds Plot state information that must persist only between calls to BeginPlot()/EndPlot()
|
||||||
struct ImPlotContext {
|
struct ImPlotContext {
|
||||||
ImPlotContext() : RenderX(), RenderY() {
|
ImPlotContext() : RenderX(), RenderY() {
|
||||||
CurrentPlot = NULL;
|
ChildWindowMade = false;
|
||||||
FitThisFrame = FitX = false;
|
Reset();
|
||||||
SetColormap(ImPlotColormap_Default);
|
SetColormap(ImPlotColormap_Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
// end child window if it was made
|
||||||
|
if (ChildWindowMade)
|
||||||
|
ImGui::EndChild();
|
||||||
|
ChildWindowMade = false;
|
||||||
|
// reset the next plot data
|
||||||
|
NextPlotData = ImPlotNextPlotData();
|
||||||
|
// reset items count
|
||||||
|
VisibleItemCount = 0;
|
||||||
|
// reset legend items
|
||||||
|
LegendIndices.shrink(0);
|
||||||
|
LegendLabels.Buf.shrink(0);
|
||||||
|
// reset ticks/labels
|
||||||
|
XTicks.shrink(0);
|
||||||
|
XTickLabels.Buf.shrink(0);
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
YTicks[i].shrink(0);
|
||||||
|
YTickLabels[i].Buf.shrink(0);
|
||||||
|
}
|
||||||
|
// reset extents
|
||||||
|
FitX = false;
|
||||||
|
ExtentsX.Min = HUGE_VAL;
|
||||||
|
ExtentsX.Max = -HUGE_VAL;
|
||||||
|
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||||
|
ExtentsY[i].Min = HUGE_VAL;
|
||||||
|
ExtentsY[i].Max = -HUGE_VAL;
|
||||||
|
FitY[i] = false;
|
||||||
|
}
|
||||||
|
// reset digital plot items count
|
||||||
|
DigitalPlotItemCnt = 0;
|
||||||
|
DigitalPlotOffset = 0;
|
||||||
|
// nullify plot
|
||||||
|
CurrentPlot = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/// ALl Plots
|
/// ALl Plots
|
||||||
ImPool<ImPlotState> Plots;
|
ImPool<ImPlotState> Plots;
|
||||||
/// Current Plot
|
/// Current Plot
|
||||||
|
@ -370,12 +416,15 @@ struct ImPlotContext {
|
||||||
ImPlotRange ExtentsY[MAX_Y_AXES];
|
ImPlotRange ExtentsY[MAX_Y_AXES];
|
||||||
int VisibleItemCount;
|
int VisibleItemCount;
|
||||||
bool FitThisFrame; bool FitX;
|
bool FitThisFrame; bool FitX;
|
||||||
bool FitY[MAX_Y_AXES] = {};
|
bool FitY[MAX_Y_AXES];
|
||||||
// Hover states
|
// Hover states
|
||||||
bool Hov_Frame;
|
bool Hov_Frame;
|
||||||
bool Hov_Grid;
|
bool Hov_Grid;
|
||||||
// Render flags
|
// Render flags
|
||||||
bool RenderX, RenderY[MAX_Y_AXES];
|
bool RenderX, RenderY[MAX_Y_AXES];
|
||||||
|
// Lock info
|
||||||
|
bool LockPlot;
|
||||||
|
bool ChildWindowMade;
|
||||||
// Mouse pos
|
// Mouse pos
|
||||||
ImPlotPoint LastMousePos[MAX_Y_AXES];
|
ImPlotPoint LastMousePos[MAX_Y_AXES];
|
||||||
// Style
|
// Style
|
||||||
|
@ -394,7 +443,7 @@ struct ImPlotContext {
|
||||||
static ImPlotContext gp;
|
static ImPlotContext gp;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Utils
|
// Context Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Returns the next unused default plot color
|
/// Returns the next unused default plot color
|
||||||
|
@ -440,7 +489,7 @@ inline void UpdateTransformCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ImPlotPoint PixelsToPlot(float x, float y, int y_axis_in = -1) {
|
inline ImPlotPoint PixelsToPlot(float x, float y, int y_axis_in = -1) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PixelsToPlot() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PixelsToPlot() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||||
ImPlotPoint plt;
|
ImPlotPoint plt;
|
||||||
plt.x = (x - gp.PixelRange[y_axis].Min.x) / gp.Mx + gp.CurrentPlot->XAxis.Range.Min;
|
plt.x = (x - gp.PixelRange[y_axis].Min.x) / gp.Mx + gp.CurrentPlot->XAxis.Range.Min;
|
||||||
|
@ -462,7 +511,7 @@ ImPlotPoint PixelsToPlot(const ImVec2& pix, int y_axis) {
|
||||||
|
|
||||||
// This function is convenient but should not be used to process a high volume of points. Use the Transformer structs below instead.
|
// This function is convenient but should not be used to process a high volume of points. Use the Transformer structs below instead.
|
||||||
inline ImVec2 PlotToPixels(double x, double y, int y_axis_in = -1) {
|
inline ImVec2 PlotToPixels(double x, double y, int y_axis_in = -1) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||||
ImVec2 pix;
|
ImVec2 pix;
|
||||||
if (HasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
if (HasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
||||||
|
@ -604,8 +653,7 @@ inline double NiceNum(double x, bool round) {
|
||||||
return nf * ImPow(10.0, expv);
|
return nf * ImPow(10.0, expv);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void GetTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logscale, ImVector<ImPlotTick> &out) {
|
inline void AddDefaultTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logscale, ImVector<ImPlotTick> &out) {
|
||||||
out.shrink(0);
|
|
||||||
if (logscale) {
|
if (logscale) {
|
||||||
if (range.Min <= 0 || range.Max <= 0)
|
if (range.Min <= 0 || range.Max <= 0)
|
||||||
return;
|
return;
|
||||||
|
@ -642,11 +690,10 @@ inline void GetTicks(const ImPlotRange& range, int nMajor, int nMinor, bool logs
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer) {
|
inline void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer) {
|
||||||
buffer.Buf.resize(0);
|
|
||||||
char temp[32];
|
char temp[32];
|
||||||
for (int t = 0; t < ticks.Size; t++) {
|
for (int t = 0; t < ticks.Size; t++) {
|
||||||
ImPlotTick *tk = &ticks[t];
|
ImPlotTick *tk = &ticks[t];
|
||||||
if (tk->RenderLabel) {
|
if (tk->RenderLabel && !tk->Labeled) {
|
||||||
tk->TextOffset = buffer.size();
|
tk->TextOffset = buffer.size();
|
||||||
if (scientific)
|
if (scientific)
|
||||||
sprintf(temp, "%.0e", tk->PlotPos);
|
sprintf(temp, "%.0e", tk->PlotPos);
|
||||||
|
@ -654,10 +701,24 @@ inline void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBu
|
||||||
sprintf(temp, "%g", tk->PlotPos);
|
sprintf(temp, "%g", tk->PlotPos);
|
||||||
buffer.append(temp, temp + strlen(temp) + 1);
|
buffer.append(temp, temp + strlen(temp) + 1);
|
||||||
tk->Size = ImGui::CalcTextSize(buffer.Buf.Data + tk->TextOffset);
|
tk->Size = ImGui::CalcTextSize(buffer.Buf.Data + tk->TextOffset);
|
||||||
|
tk->Labeled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline 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();
|
||||||
|
if (labels != NULL) {
|
||||||
|
buffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
||||||
|
tick.Size = ImGui::CalcTextSize(labels[i]);
|
||||||
|
tick.Labeled = true;
|
||||||
|
}
|
||||||
|
ticks.push_back(tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct AxisState {
|
struct AxisState {
|
||||||
ImPlotAxis* axis;
|
ImPlotAxis* axis;
|
||||||
|
@ -750,7 +811,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
ImGuiContext &G = *GImGui;
|
ImGuiContext &G = *GImGui;
|
||||||
ImGuiWindow * Window = G.CurrentWindow;
|
ImGuiWindow * Window = G.CurrentWindow;
|
||||||
if (Window->SkipItems) {
|
if (Window->SkipItems) {
|
||||||
gp.NextPlotData = ImPlotNextPlotData();
|
gp.Reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,6 +858,10 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
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 ? default_w : size.x, size.y == 0 ? default_h : size.y));
|
||||||
Window = ImGui::GetCurrentWindow();
|
Window = ImGui::GetCurrentWindow();
|
||||||
Window->ScrollMax.y = 1.0f;
|
Window->ScrollMax.y = 1.0f;
|
||||||
|
gp.ChildWindowMade = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gp.ChildWindowMade = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImDrawList &DrawList = *Window->DrawList;
|
ImDrawList &DrawList = *Window->DrawList;
|
||||||
|
@ -828,7 +893,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
|
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
|
||||||
HasFlag(plot.Flags, ImPlotFlags_YAxis3), y[1].present_so_far);
|
HasFlag(plot.Flags, ImPlotFlags_YAxis3), y[1].present_so_far);
|
||||||
|
|
||||||
const bool lock_plot = x.lock && y[0].lock && y[1].lock && y[2].lock;
|
gp.LockPlot = x.lock && y[0].lock &&
|
||||||
|
( HasFlag(plot.Flags, ImPlotFlags_YAxis2) ? y[1].lock : true ) &&
|
||||||
|
( HasFlag(plot.Flags, ImPlotFlags_YAxis3) ? y[2].lock : true );
|
||||||
|
|
||||||
// CONSTRAINTS ------------------------------------------------------------
|
// CONSTRAINTS ------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -896,10 +963,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
gp.BB_Frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);
|
gp.BB_Frame = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);
|
||||||
ImGui::ItemSize(gp.BB_Frame);
|
ImGui::ItemSize(gp.BB_Frame);
|
||||||
if (!ImGui::ItemAdd(gp.BB_Frame, 0, &gp.BB_Frame)) {
|
if (!ImGui::ItemAdd(gp.BB_Frame, 0, &gp.BB_Frame)) {
|
||||||
gp.NextPlotData = ImPlotNextPlotData();
|
gp.Reset();
|
||||||
gp.CurrentPlot = NULL;
|
|
||||||
if (!HasFlag(plot.Flags, ImPlotFlags_NoChild))
|
|
||||||
ImGui::EndChild();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
gp.Hov_Frame = ImGui::ItemHoverable(gp.BB_Frame, ID);
|
gp.Hov_Frame = ImGui::ItemHoverable(gp.BB_Frame, ID);
|
||||||
|
@ -920,11 +984,11 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
// get ticks
|
// get ticks
|
||||||
if (gp.RenderX)
|
if (gp.RenderX && gp.NextPlotData.ShowDefaultTicksX)
|
||||||
GetTicks(plot.XAxis.Range, plot.XAxis.Divisions, plot.XAxis.Subdivisions, HasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTicks);
|
AddDefaultTicks(plot.XAxis.Range, plot.XAxis.Divisions, plot.XAxis.Subdivisions, HasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale), gp.XTicks);
|
||||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||||
if (gp.RenderY[i]) {
|
if (gp.RenderY[i] && gp.NextPlotData.ShowDefaultTicksY[i]) {
|
||||||
GetTicks(plot.YAxis[i].Range, plot.YAxis[i].Divisions, plot.YAxis[i].Subdivisions, HasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale), gp.YTicks[i]);
|
AddDefaultTicks(plot.YAxis[i].Range, plot.YAxis[i].Divisions, plot.YAxis[i].Subdivisions, HasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale), gp.YTicks[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1149,7 +1213,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
plot.Selecting = false;
|
plot.Selecting = false;
|
||||||
}
|
}
|
||||||
// bad selection
|
// bad selection
|
||||||
if (plot.Selecting && (!HasFlag(plot.Flags, ImPlotFlags_BoxSelect) || lock_plot) && ImLengthSqr(plot.SelectStart - IO.MousePos) > 4) {
|
if (plot.Selecting && (!HasFlag(plot.Flags, ImPlotFlags_BoxSelect) || gp.LockPlot) && ImLengthSqr(plot.SelectStart - IO.MousePos) > 4) {
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
|
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
|
||||||
}
|
}
|
||||||
// cancel selection
|
// cancel selection
|
||||||
|
@ -1157,7 +1221,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
plot.Selecting = false;
|
plot.Selecting = false;
|
||||||
}
|
}
|
||||||
// begin selection or query
|
// begin selection or query
|
||||||
if (gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[1]) {
|
if (!gp.LockPlot && gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[1]) {
|
||||||
plot.SelectStart = IO.MousePos;
|
plot.SelectStart = IO.MousePos;
|
||||||
plot.Selecting = true;
|
plot.Selecting = true;
|
||||||
}
|
}
|
||||||
|
@ -1326,20 +1390,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
||||||
|
|
||||||
// push plot ID into stack
|
// push plot ID into stack
|
||||||
ImGui::PushID(ID);
|
ImGui::PushID(ID);
|
||||||
// reset items count
|
|
||||||
gp.VisibleItemCount = 0;
|
|
||||||
// reset extents
|
|
||||||
gp.ExtentsX.Min = HUGE_VAL;
|
|
||||||
gp.ExtentsX.Max = -HUGE_VAL;
|
|
||||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
|
||||||
gp.ExtentsY[i].Min = HUGE_VAL;
|
|
||||||
gp.ExtentsY[i].Max = -HUGE_VAL;
|
|
||||||
}
|
|
||||||
// clear item names
|
|
||||||
gp.LegendLabels.Buf.resize(0);
|
|
||||||
// reset digital plot items count
|
|
||||||
gp.DigitalPlotItemCnt = 0;
|
|
||||||
gp.DigitalPlotOffset = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1515,6 +1565,7 @@ void EndPlot() {
|
||||||
|
|
||||||
// AXIS STATES ------------------------------------------------------------
|
// AXIS STATES ------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO: Move this into gp to avoid repetition
|
||||||
AxisState x(plot.XAxis, gp.NextPlotData.HasXRange, gp.NextPlotData.XRangeCond, true, 0);
|
AxisState x(plot.XAxis, gp.NextPlotData.HasXRange, gp.NextPlotData.XRangeCond, true, 0);
|
||||||
AxisState y[MAX_Y_AXES];
|
AxisState y[MAX_Y_AXES];
|
||||||
y[0] = AxisState(plot.YAxis[0], gp.NextPlotData.HasYRange[0], gp.NextPlotData.YRangeCond[0], true, 0);
|
y[0] = AxisState(plot.YAxis[0], gp.NextPlotData.HasYRange[0], gp.NextPlotData.YRangeCond[0], true, 0);
|
||||||
|
@ -1523,10 +1574,10 @@ void EndPlot() {
|
||||||
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
|
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
|
||||||
HasFlag(plot.Flags, ImPlotFlags_YAxis3), y[1].present_so_far);
|
HasFlag(plot.Flags, ImPlotFlags_YAxis3), y[1].present_so_far);
|
||||||
|
|
||||||
const bool lock_plot = x.lock && y[0].lock && y[1].lock && y[2].lock;
|
|
||||||
const bool any_y_locked = y[0].lock || y[1].lock || y[2].lock;
|
const bool any_y_locked = y[0].lock || y[1].lock || y[2].lock;
|
||||||
const bool any_y_dragging = plot.YAxis[0].Dragging || plot.YAxis[1].Dragging || plot.YAxis[2].Dragging;
|
const bool any_y_dragging = plot.YAxis[0].Dragging || plot.YAxis[1].Dragging || plot.YAxis[2].Dragging;
|
||||||
|
|
||||||
|
|
||||||
// FINAL RENDER -----------------------------------------------------------
|
// FINAL RENDER -----------------------------------------------------------
|
||||||
|
|
||||||
// render ticks
|
// render ticks
|
||||||
|
@ -1575,20 +1626,21 @@ void EndPlot() {
|
||||||
// render selection/query
|
// render selection/query
|
||||||
if (plot.Selecting) {
|
if (plot.Selecting) {
|
||||||
ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart));
|
ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart));
|
||||||
if (plot.Selecting && !lock_plot && HasFlag(plot.Flags, ImPlotFlags_BoxSelect)) {
|
bool select_big_enough = ImLengthSqr(select_bb.GetSize()) > 4;
|
||||||
if (IO.KeyAlt && IO.KeyShift && select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) {
|
if (plot.Selecting && !gp.LockPlot && HasFlag(plot.Flags, ImPlotFlags_BoxSelect) && select_big_enough) {
|
||||||
|
if (IO.KeyAlt && IO.KeyShift) {
|
||||||
DrawList.AddRectFilled(gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBg);
|
DrawList.AddRectFilled(gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBg);
|
||||||
DrawList.AddRect( gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBd);
|
DrawList.AddRect( gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_SlctBd);
|
||||||
}
|
}
|
||||||
else if ((x.lock || IO.KeyAlt) && select_bb.GetHeight() > 2) {
|
else if ((x.lock || IO.KeyAlt)) {
|
||||||
DrawList.AddRectFilled(ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBg);
|
DrawList.AddRectFilled(ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBg);
|
||||||
DrawList.AddRect( ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBd);
|
DrawList.AddRect( ImVec2(gp.BB_Grid.Min.x, select_bb.Min.y), ImVec2(gp.BB_Grid.Max.x, select_bb.Max.y), gp.Col_SlctBd);
|
||||||
}
|
}
|
||||||
else if ((any_y_locked || IO.KeyShift) && select_bb.GetWidth() > 2) {
|
else if ((any_y_locked || IO.KeyShift)) {
|
||||||
DrawList.AddRectFilled(ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBg);
|
DrawList.AddRectFilled(ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBg);
|
||||||
DrawList.AddRect( ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBd);
|
DrawList.AddRect( ImVec2(select_bb.Min.x, gp.BB_Grid.Min.y), ImVec2(select_bb.Max.x, gp.BB_Grid.Max.y), gp.Col_SlctBd);
|
||||||
}
|
}
|
||||||
else if (select_bb.GetWidth() > 2 && select_bb.GetHeight() > 2) {
|
else {
|
||||||
DrawList.AddRectFilled(select_bb.Min, select_bb.Max, gp.Col_SlctBg);
|
DrawList.AddRectFilled(select_bb.Min, select_bb.Max, gp.Col_SlctBg);
|
||||||
DrawList.AddRect( select_bb.Min, select_bb.Max, gp.Col_SlctBd);
|
DrawList.AddRect( select_bb.Min, select_bb.Max, gp.Col_SlctBd);
|
||||||
}
|
}
|
||||||
|
@ -1741,17 +1793,10 @@ void EndPlot() {
|
||||||
}
|
}
|
||||||
// CLEANUP ----------------------------------------------------------------
|
// CLEANUP ----------------------------------------------------------------
|
||||||
|
|
||||||
// Reset legend items
|
|
||||||
gp.LegendIndices.shrink(0);
|
|
||||||
// Null current plot/data
|
|
||||||
gp.CurrentPlot = NULL;
|
|
||||||
// Reset next plot data
|
|
||||||
gp.NextPlotData = ImPlotNextPlotData();
|
|
||||||
// Pop ImGui::PushID at the end of BeginPlot
|
// Pop ImGui::PushID at the end of BeginPlot
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
// End child window
|
// Reset context for next plot
|
||||||
if (!HasFlag(plot.Flags, ImPlotFlags_NoChild))
|
gp.Reset();
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1759,11 +1804,13 @@ void EndPlot() {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void SetNextPlotLimits(double x_min, double x_max, double y_min, double y_max, ImGuiCond cond) {
|
void SetNextPlotLimits(double x_min, double x_max, double y_min, double y_max, ImGuiCond cond) {
|
||||||
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotLimits() needs to be called before BeginPlot()!");
|
||||||
SetNextPlotLimitsX(x_min, x_max, cond);
|
SetNextPlotLimitsX(x_min, x_max, cond);
|
||||||
SetNextPlotLimitsY(y_min, y_max, cond);
|
SetNextPlotLimitsY(y_min, y_max, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNextPlotLimitsX(double x_min, double x_max, ImGuiCond cond) {
|
void SetNextPlotLimitsX(double x_min, double x_max, ImGuiCond cond) {
|
||||||
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotLSetNextPlotLimitsXimitsY() needs to be called before BeginPlot()!");
|
||||||
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
||||||
gp.NextPlotData.HasXRange = true;
|
gp.NextPlotData.HasXRange = true;
|
||||||
gp.NextPlotData.XRangeCond = cond;
|
gp.NextPlotData.XRangeCond = cond;
|
||||||
|
@ -1772,7 +1819,8 @@ void SetNextPlotLimitsX(double x_min, double x_max, ImGuiCond cond) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond, int y_axis) {
|
void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond, int y_axis) {
|
||||||
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(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(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
||||||
gp.NextPlotData.HasYRange[y_axis] = true;
|
gp.NextPlotData.HasYRange[y_axis] = true;
|
||||||
gp.NextPlotData.YRangeCond[y_axis] = cond;
|
gp.NextPlotData.YRangeCond[y_axis] = cond;
|
||||||
|
@ -1780,24 +1828,51 @@ void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond, int y_axis)
|
||||||
gp.NextPlotData.Y[y_axis].Max = y_max;
|
gp.NextPlotData.Y[y_axis].Max = y_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetNextPlotTicksX(const double* values, int n_ticks, const char** labels, bool show_default) {
|
||||||
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksX() needs to be called before BeginPlot()!");
|
||||||
|
gp.NextPlotData.ShowDefaultTicksX = show_default;
|
||||||
|
AddCustomTicks(values, labels, n_ticks, gp.XTicks, gp.XTickLabels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char** labels, bool show_default) {
|
||||||
|
IM_ASSERT_USER_ERROR(n_ticks > 1, "The number of ticks must be greater than 1");
|
||||||
|
static ImVector<double> buffer;
|
||||||
|
FillRange(buffer, n_ticks, x_min, x_max);
|
||||||
|
SetNextPlotTicksX(&buffer[0], n_ticks, labels, show_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNextPlotTicksY(const double* values, int n_ticks, const char** labels, bool show_default, int y_axis) {
|
||||||
|
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");
|
||||||
|
gp.NextPlotData.ShowDefaultTicksY[y_axis] = show_default;
|
||||||
|
AddCustomTicks(values, labels, n_ticks, gp.YTicks[y_axis], gp.YTickLabels[y_axis]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char** labels, bool show_default, int y_axis) {
|
||||||
|
IM_ASSERT_USER_ERROR(n_ticks > 1, "The number of ticks must be greater than 1");
|
||||||
|
static ImVector<double> buffer;
|
||||||
|
FillRange(buffer, n_ticks, y_min, y_max);
|
||||||
|
SetNextPlotTicksY(&buffer[0], n_ticks, labels, show_default,y_axis);
|
||||||
|
}
|
||||||
|
|
||||||
void SetPlotYAxis(int y_axis) {
|
void SetPlotYAxis(int y_axis) {
|
||||||
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(gp.CurrentPlot != NULL, "SetPlotYAxis() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "SetPlotYAxis() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < MAX_Y_AXES, "y_axis needs to be between 0 and MAX_Y_AXES");
|
||||||
gp.CurrentPlot->CurrentYAxis = y_axis;
|
gp.CurrentPlot->CurrentYAxis = y_axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 GetPlotPos() {
|
ImVec2 GetPlotPos() {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotPos() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotPos() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
return gp.BB_Grid.Min;
|
return gp.BB_Grid.Min;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 GetPlotSize() {
|
ImVec2 GetPlotSize() {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotSize() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotSize() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
return gp.BB_Grid.GetSize();
|
return gp.BB_Grid.GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushPlotClipRect() {
|
void PushPlotClipRect() {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PushPlotClipRect() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PushPlotClipRect() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true);
|
ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1806,12 +1881,12 @@ void PopPlotClipRect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPlotHovered() {
|
bool IsPlotHovered() {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotHovered() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotHovered() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
return gp.Hov_Grid;
|
return gp.Hov_Grid;
|
||||||
}
|
}
|
||||||
ImPlotPoint GetPlotMousePos(int y_axis_in) {
|
ImPlotPoint GetPlotMousePos(int y_axis_in) {
|
||||||
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 < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES");
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotMousePos() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotMousePos() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||||
return gp.LastMousePos[y_axis];
|
return gp.LastMousePos[y_axis];
|
||||||
}
|
}
|
||||||
|
@ -1819,7 +1894,7 @@ ImPlotPoint GetPlotMousePos(int y_axis_in) {
|
||||||
|
|
||||||
ImPlotLimits GetPlotLimits(int y_axis_in) {
|
ImPlotLimits GetPlotLimits(int y_axis_in) {
|
||||||
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 < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES");
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||||
|
|
||||||
ImPlotState& plot = *gp.CurrentPlot;
|
ImPlotState& plot = *gp.CurrentPlot;
|
||||||
|
@ -1830,13 +1905,13 @@ ImPlotLimits GetPlotLimits(int y_axis_in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPlotQueried() {
|
bool IsPlotQueried() {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotQueried() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotQueried() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
return gp.CurrentPlot->Queried;
|
return gp.CurrentPlot->Queried;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImPlotLimits GetPlotQuery(int y_axis_in) {
|
ImPlotLimits GetPlotQuery(int y_axis_in) {
|
||||||
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 < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES");
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
ImPlotState& plot = *gp.CurrentPlot;
|
ImPlotState& plot = *gp.CurrentPlot;
|
||||||
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||||
|
|
||||||
|
@ -2301,7 +2376,7 @@ struct GetterFuncPtrImPlotPoint {
|
||||||
template <typename Getter>
|
template <typename Getter>
|
||||||
inline void PlotEx(const char* label_id, Getter getter, int count, int offset)
|
inline void PlotEx(const char* label_id, Getter getter, int count, int offset)
|
||||||
{
|
{
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Plot() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Plot() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
ImPlotState* plot = gp.CurrentPlot;
|
ImPlotState* plot = gp.CurrentPlot;
|
||||||
const int y_axis = plot->CurrentYAxis;
|
const int y_axis = plot->CurrentYAxis;
|
||||||
|
@ -2503,7 +2578,7 @@ struct GetterBarH {
|
||||||
template <typename Getter, typename TWidth>
|
template <typename Getter, typename TWidth>
|
||||||
void PlotBarsEx(const char* label_id, Getter getter, int count, TWidth width, int offset) {
|
void PlotBarsEx(const char* label_id, Getter getter, int count, TWidth width, int offset) {
|
||||||
|
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBars() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBars() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
ImPlotItem* item = RegisterItem(label_id);
|
ImPlotItem* item = RegisterItem(label_id);
|
||||||
if (!item->Show)
|
if (!item->Show)
|
||||||
|
@ -2593,7 +2668,7 @@ void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int i
|
||||||
template <typename Getter, typename THeight>
|
template <typename Getter, typename THeight>
|
||||||
void PlotBarsHEx(const char* label_id, Getter getter, int count, THeight height, int offset) {
|
void PlotBarsHEx(const char* label_id, Getter getter, int count, THeight height, int offset) {
|
||||||
|
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBarsH() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBarsH() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
ImPlotItem* item = RegisterItem(label_id);
|
ImPlotItem* item = RegisterItem(label_id);
|
||||||
if (!item->Show)
|
if (!item->Show)
|
||||||
|
@ -2703,7 +2778,7 @@ struct GetterError {
|
||||||
|
|
||||||
template <typename Getter>
|
template <typename Getter>
|
||||||
void PlotErrorBarsEx(const char* label_id, Getter getter, int count, int offset) {
|
void PlotErrorBarsEx(const char* label_id, Getter getter, int count, int offset) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBars() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBars() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
ImGuiID id = ImGui::GetID(label_id);
|
ImGuiID id = ImGui::GetID(label_id);
|
||||||
ImPlotItem* item = gp.CurrentPlot->Items.GetByKey(id);
|
ImPlotItem* item = gp.CurrentPlot->Items.GetByKey(id);
|
||||||
|
@ -2788,7 +2863,7 @@ inline void DrawPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, double
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void PlotPieChartEx(const char** label_ids, T* values, int count, T x, T y, T radius, bool show_percents, T angle0) {
|
void PlotPieChartEx(const char** label_ids, T* values, int count, T x, T y, T radius, bool show_percents, T angle0) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotPieChart() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
|
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
|
||||||
|
|
||||||
T sum = 0;
|
T sum = 0;
|
||||||
|
@ -2893,7 +2968,7 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T scale_min, T scale_max, bool show_labels, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
|
void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T scale_min, T scale_max, bool show_labels, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotHeatmap() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotHeatmap() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!");
|
IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!");
|
||||||
ImPlotItem* item = RegisterItem(label_id);
|
ImPlotItem* item = RegisterItem(label_id);
|
||||||
if (!item->Show)
|
if (!item->Show)
|
||||||
|
@ -2938,7 +3013,7 @@ void PlotHeatmap(const char* label_id, const double* values, int rows, int cols,
|
||||||
template <typename Getter>
|
template <typename Getter>
|
||||||
inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int offset)
|
inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int offset)
|
||||||
{
|
{
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
ImPlotItem* item = RegisterItem(label_id);
|
ImPlotItem* item = RegisterItem(label_id);
|
||||||
if (!item->Show)
|
if (!item->Show)
|
||||||
|
@ -3044,7 +3119,7 @@ void PlotText(const char* text, float x, float y, bool vertical, const ImVec2& p
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// double
|
// double
|
||||||
void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) {
|
void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotText() Needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
|
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
|
||||||
PushPlotClipRect();
|
PushPlotClipRect();
|
||||||
ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + pixel_offset;
|
ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + pixel_offset;
|
||||||
|
@ -3099,7 +3174,9 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
|
||||||
ImPlotRange range;
|
ImPlotRange range;
|
||||||
range.Min = scale_min;
|
range.Min = scale_min;
|
||||||
range.Max = scale_max;
|
range.Max = scale_max;
|
||||||
GetTicks(range, 10, 0, false, ticks);
|
ticks.shrink(0);
|
||||||
|
txt_buff.Buf.shrink(0);
|
||||||
|
AddDefaultTicks(range, 10, 0, false, ticks);
|
||||||
LabelTicks(ticks, false, txt_buff);
|
LabelTicks(ticks, false, txt_buff);
|
||||||
float max_width = 0;
|
float max_width = 0;
|
||||||
for (int i = 0; i < ticks.Size; ++i)
|
for (int i = 0; i < ticks.Size; ++i)
|
||||||
|
|
7
implot.h
7
implot.h
|
@ -313,6 +313,13 @@ void SetNextPlotLimitsX(double x_min, double x_max, ImGuiCond cond = ImGuiCond_O
|
||||||
// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the Y axis limits will be locked.
|
// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the Y axis limits will be locked.
|
||||||
void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond = ImGuiCond_Once, int y_axis = 0);
|
void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond = ImGuiCond_Once, int y_axis = 0);
|
||||||
|
|
||||||
|
// Set the X axis ticks and optionally the labels for the next plot.
|
||||||
|
void SetNextPlotTicksX(const double* values, int n_ticks, const char** labels = NULL, bool show_default = false);
|
||||||
|
void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char** labels = NULL, bool show_default = false);
|
||||||
|
// Set the Y axis ticks and optionally the labels for the next plot.
|
||||||
|
void SetNextPlotTicksY(const double* values, int n_ticks, const char** labels = NULL, bool show_default = false, int y_axis = 0);
|
||||||
|
void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char** labels = NULL, bool show_default = false, int y_axis = 0);
|
||||||
|
|
||||||
// Select which Y axis will be used for subsequent plot elements. The default is '0', or the first (left) Y axis.
|
// Select which Y axis will be used for subsequent plot elements. The default is '0', or the first (left) Y axis.
|
||||||
void SetPlotYAxis(int y_axis);
|
void SetPlotYAxis(int y_axis);
|
||||||
|
|
||||||
|
|
|
@ -241,12 +241,18 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
if (ImGui::CollapsingHeader("Bar Plots")) {
|
if (ImGui::CollapsingHeader("Bar Plots")) {
|
||||||
|
static const char* labels[] = {"S1","S2","S3","S4","S5","S6","S7","S8","S9","S10"};
|
||||||
|
static const double positions[] = {0,1,2,3,4,5,6,7,8,9};
|
||||||
static bool horz = false;
|
static bool horz = false;
|
||||||
ImGui::Checkbox("Horizontal",&horz);
|
ImGui::Checkbox("Horizontal",&horz);
|
||||||
if (horz)
|
if (horz) {
|
||||||
ImPlot::SetNextPlotLimits(0, 110, -0.5, 9.5, ImGuiCond_Always);
|
ImPlot::SetNextPlotLimits(0, 110, -0.5, 9.5, ImGuiCond_Always);
|
||||||
else
|
ImPlot::SetNextPlotTicksY(positions, 10, labels);
|
||||||
|
}
|
||||||
|
else {
|
||||||
ImPlot::SetNextPlotLimits(-0.5, 9.5, 0, 110, ImGuiCond_Always);
|
ImPlot::SetNextPlotLimits(-0.5, 9.5, 0, 110, ImGuiCond_Always);
|
||||||
|
ImPlot::SetNextPlotTicksX(positions, 10, labels);
|
||||||
|
}
|
||||||
if (ImPlot::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score")) {
|
if (ImPlot::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score")) {
|
||||||
static t_float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90};
|
static t_float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90};
|
||||||
static t_float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100};
|
static t_float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100};
|
||||||
|
@ -331,15 +337,21 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
values2[i] = RandomRange(0,1);
|
values2[i] = RandomRange(0,1);
|
||||||
}
|
}
|
||||||
static ImPlotColormap map = ImPlotColormap_Viridis;
|
static ImPlotColormap map = ImPlotColormap_Viridis;
|
||||||
if (ImGui::Button("Cycle Colormap",ImVec2(225,0)))
|
if (ImGui::Button("Change Colormap",ImVec2(225,0)))
|
||||||
map = (map + 1) % ImPlotColormap_COUNT;
|
map = (map + 1) % ImPlotColormap_COUNT;
|
||||||
ImPlot::SetColormap(map);
|
ImPlot::SetColormap(map);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::LabelText("##Colormap Index", cmap_names[map]);
|
ImGui::LabelText("##Colormap Index", cmap_names[map]);
|
||||||
ImGui::SetNextItemWidth(225);
|
ImGui::SetNextItemWidth(225);
|
||||||
ImGui::DragFloat("Max",&scale_max,0.01f,0.1f,20);
|
ImGui::DragFloat("Max",&scale_max,0.01f,0.1f,20);
|
||||||
static ImPlotAxisFlags axes_flags = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax;
|
static ImPlotAxisFlags axes_flags = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax | ImPlotAxisFlags_TickLabels;
|
||||||
if (ImPlot::BeginPlot("##Heatmap1",NULL,NULL,ImVec2(225,225),ImPlotFlags_ContextMenu,axes_flags,axes_flags)) {
|
static const char* xlabels[] = {"C1","C2","C3","C4","C5","C6","C7"};
|
||||||
|
static const char* ylabels[] = {"R1","R2","R3","R4","R5","R6","R7"};
|
||||||
|
|
||||||
|
SetNextPlotTicksX(0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels);
|
||||||
|
SetNextPlotTicksY(1- 1.0/14.0, 0 + 1.0/14.0, 7, ylabels);
|
||||||
|
|
||||||
|
if (ImPlot::BeginPlot("##Heatmap1",NULL,NULL,ImVec2(225,225),0,axes_flags,axes_flags)) {
|
||||||
ImPlot::PlotHeatmap("heat",values1[0],7,7,scale_min,scale_max);
|
ImPlot::PlotHeatmap("heat",values1[0],7,7,scale_min,scale_max);
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
|
@ -388,11 +400,11 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
if (ImGui::CollapsingHeader("Markers and Text")) {
|
if (ImGui::CollapsingHeader("Markers and Text")) {
|
||||||
static ImPlotColormap map = ImPlotColormap_Default;
|
static ImPlotColormap map = ImPlotColormap_Default;
|
||||||
if (ImGui::Button("Cycle Colormap##2"))
|
if (ImGui::Button("Change Colormap##2"))
|
||||||
map = (map + 1) % ImPlotColormap_COUNT;
|
map = (map + 1) % ImPlotColormap_COUNT;
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::LabelText("##Colormap Index", cmap_names[map]);
|
ImGui::LabelText("##Colormap Index", cmap_names[map]);
|
||||||
ImGui::PushID(map); // NB: The merely a workaround so that the demo can cycle color maps. You wouldn't need to do this in your own code!
|
ImGui::PushID(map); // NB: This is merely a workaround so that the demo can cycle color maps. You wouldn't need to do this in your own code!
|
||||||
ImPlot::SetNextPlotLimits(0, 10, 0, 12);
|
ImPlot::SetNextPlotLimits(0, 10, 0, 12);
|
||||||
if (ImPlot::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,0), 0, 0, 0)) {
|
if (ImPlot::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,0), 0, 0, 0)) {
|
||||||
ImPlot::SetColormap(map);
|
ImPlot::SetColormap(map);
|
||||||
|
@ -830,6 +842,33 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
if (ImGui::CollapsingHeader("Custom Ticks")) {
|
||||||
|
static bool custom_ticks = true;
|
||||||
|
static bool custom_labels = true;
|
||||||
|
ImGui::Checkbox("Show Custom Ticks", &custom_ticks);
|
||||||
|
if (custom_ticks) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("Show Custom Labels", &custom_labels);
|
||||||
|
}
|
||||||
|
double pi = 3.14;
|
||||||
|
const char* pi_str[] = {"PI"};
|
||||||
|
static double yticks[] = {1,3,7,9};
|
||||||
|
static const char* ylabels[] = {"One","Three","Seven","Nine"};
|
||||||
|
static double yticks_aux[] = {0.2,0.4,0.6};
|
||||||
|
static const char* ylabels_aux[] = {"A","B","C","D","E","F"};
|
||||||
|
if (custom_ticks) {
|
||||||
|
ImPlot::SetNextPlotTicksX(&pi,1,custom_labels ? pi_str : NULL, true);
|
||||||
|
ImPlot::SetNextPlotTicksY(yticks, 4, custom_labels ? ylabels : NULL);
|
||||||
|
ImPlot::SetNextPlotTicksY(yticks_aux, 3, custom_labels ? ylabels_aux : NULL, false, 1);
|
||||||
|
ImPlot::SetNextPlotTicksY(0, 1, 6, custom_labels ? ylabels_aux : NULL, false, 2);
|
||||||
|
}
|
||||||
|
ImPlot::SetNextPlotLimits(2.5,5,0,10);
|
||||||
|
if (ImPlot::BeginPlot("Custom Ticks", NULL, NULL, ImVec2(-1,0), ImPlotFlags_Default | ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3)) {
|
||||||
|
|
||||||
|
ImPlot::EndPlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
if (ImGui::CollapsingHeader("Custom Styles")) {
|
if (ImGui::CollapsingHeader("Custom Styles")) {
|
||||||
static ImVec4 my_map[3] = {
|
static ImVec4 my_map[3] = {
|
||||||
ImVec4(0.000f, 0.980f, 0.604f, 1.0f),
|
ImVec4(0.000f, 0.980f, 0.604f, 1.0f),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user