1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-22 18:28:53 -05:00

rename and refine draglines and dragpoints

This commit is contained in:
epezent 2020-09-19 12:33:33 -05:00
parent 9c4ef16696
commit a7ae1bca53
4 changed files with 137 additions and 123 deletions

View File

@ -2483,68 +2483,9 @@ ImPlotLimits GetPlotQuery(int y_axis_in) {
return result;
}
bool GrabLineH(const char* id, double* value, const ImVec4& col, float thickness) {
bool DragLineX(const char* id, double* value, bool show_label, const ImVec4& col, float thickness) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GrabLineH() needs to be called between BeginPlot() and EndPlot()!");
const float grab_size = ImMax(5.0f, thickness);
float xl = gp.BB_Plot.Min.x;
float xr = gp.BB_Plot.Max.x;
float y = IM_ROUND(PlotToPixels(0, *value).y);
const bool outside = y < (gp.BB_Plot.Min.y - grab_size / 2) || y > (gp.BB_Plot.Max.y + grab_size / 2);
if (outside)
return false;
float len = gp.Style.MajorTickLen.y;
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
ImDrawList& DrawList = *GetPlotDrawList();
PushPlotClipRect();
DrawList.AddLine(ImVec2(xl,y), ImVec2(xr,y), col32, thickness);
DrawList.AddLine(ImVec2(xl,y), ImVec2(xl+len,y), col32, 3*thickness);
DrawList.AddLine(ImVec2(xr,y), ImVec2(xr-len,y), col32, 3*thickness);
PopPlotClipRect();
if (gp.CurrentPlot->Selecting || gp.CurrentPlot->Querying)
return false;
ImVec2 old_cursor_pos = ImGui::GetCursorScreenPos();
ImVec2 new_cursor_pos = ImVec2(xl, y - grab_size / 2.0f);
ImGui::SetItemAllowOverlap();
ImGui::GetCurrentWindow()->DC.CursorPos = new_cursor_pos;
ImGui::InvisibleButton(id, ImVec2(xr - xl, grab_size));
ImGui::GetCurrentWindow()->DC.CursorPos = old_cursor_pos;
int yax = GetCurrentYAxis();
if (ImGui::IsItemHovered() || ImGui::IsItemActive()) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
double range_y = gp.YTicks[yax].Size > 1 ? (gp.YTicks[yax].Ticks[1].PlotPos - gp.YTicks[yax].Ticks[0].PlotPos) : gp.CurrentPlot->YAxis[yax].Range.Size();
char buf[32];
snprintf(buf, 32, "%s = %.*f", id, Precision(range_y), *value);
ImVec2 size = ImGui::CalcTextSize(buf);
const int pad = 2;
PushPlotClipRect();
if (yax == 0) {
DrawList.AddRectFilled(ImVec2(xl,y-pad-size.y/2), ImVec2(xl + size.x + 2 * pad, y+pad+size.y/2), col32);
DrawList.AddText(ImVec2(xl+pad,y-size.y/2),CalcTextColor(color),buf);
}
else {
DrawList.AddRectFilled(ImVec2(xr-size.x-2*pad,y-pad-size.y/2), ImVec2(xr, y+pad+size.y/2), col32);
DrawList.AddText(ImVec2(xr-size.x-pad,y-size.y/2),CalcTextColor(color),buf);
}
PopPlotClipRect();
}
bool dragging = false;
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos().y;
*value = ImClamp(*value, gp.Y[yax].Axis->Range.Min, gp.Y[yax].Axis->Range.Max);
dragging = true;
}
return dragging;
}
bool GrabLineV(const char* id, double* value, const ImVec4& col, float thickness) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GrabLineV() needs to be called between BeginPlot() and EndPlot()!");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "DragLineX() needs to be called between BeginPlot() and EndPlot()!");
const float grab_size = ImMax(5.0f, thickness);
float yt = gp.BB_Plot.Min.y;
float yb = gp.BB_Plot.Max.y;
@ -2556,34 +2497,36 @@ bool GrabLineV(const char* id, double* value, const ImVec4& col, float thickness
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
ImDrawList& DrawList = *GetPlotDrawList();
PushPlotClipRect();
DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yb), col32, thickness);
DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yt+len), col32, 3*thickness);
DrawList.AddLine(ImVec2(x,yb), ImVec2(x,yb-len), col32, 3*thickness);
PopPlotClipRect();
if (gp.CurrentPlot->Selecting || gp.CurrentPlot->Querying)
return false;
ImVec2 old_cursor_pos = ImGui::GetCursorScreenPos();
ImVec2 new_cursor_pos = ImVec2(x - grab_size / 2.0f, yt);
ImGui::GetCurrentWindow()->DC.CursorPos = new_cursor_pos;
ImGui::InvisibleButton(id, ImVec2(grab_size, yb-yt), ImGuiButtonFlags_DontClosePopups);
ImGui::InvisibleButton(id, ImVec2(grab_size, yb-yt));
ImGui::GetCurrentWindow()->DC.CursorPos = old_cursor_pos;
if (ImGui::IsItemHovered() || ImGui::IsItemActive()) {
if (ImGui::IsItemHovered() || ImGui::IsItemActive()) {
gp.Hov_Plot = false;
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : gp.CurrentPlot->XAxis.Range.Size();
char buf[32];
snprintf(buf, 32, "%s = %.*f", id, Precision(range_x), *value);
ImVec2 size = ImGui::CalcTextSize(buf);
const int pad = 2;
PushPlotClipRect();
DrawList.AddRectFilled(ImVec2(x - size.x/2 - pad, yb - size.y - 2*pad), ImVec2(x + pad + size.x/2, yb), col32);
DrawList.AddText(ImVec2(x - size.x/2, yb - size.y - pad), CalcTextColor(color), buf);
PopPlotClipRect();
if (show_label) {
PushPlotClipRect();
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : gp.CurrentPlot->XAxis.Range.Size();
char buf[32];
snprintf(buf, 32, "%s = %.*f", id, Precision(range_x), *value);
ImVec2 size = ImGui::CalcTextSize(buf);
const int pad = 2;
ImVec2 label_pos = ImVec2(x - size.x/2 - pad, yb - size.y - 2*pad);
ImVec2 label_size = size + ImVec2(pad*2,pad*2);
label_pos = ClampLabelPos(label_pos, label_size, gp.BB_Plot.Min, gp.BB_Plot.Max);
DrawList.AddRectFilled(label_pos, label_pos + label_size, col32);
DrawList.AddText(label_pos + ImVec2(pad,pad),CalcTextColor(color),buf);
PopPlotClipRect();
}
}
bool dragging = false;
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos().x;
@ -2593,9 +2536,73 @@ bool GrabLineV(const char* id, double* value, const ImVec4& col, float thickness
return dragging;
}
bool GrabPoint(const char* id, double* x, double* y, const ImVec4& col, float radius) {
bool DragLineY(const char* id, double* value, bool show_label, const ImVec4& col, float thickness) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GrabPoint() needs to be called between BeginPlot() and EndPlot()!");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "DragLineY() needs to be called between BeginPlot() and EndPlot()!");
const float grab_size = ImMax(5.0f, thickness);
float xl = gp.BB_Plot.Min.x;
float xr = gp.BB_Plot.Max.x;
float y = IM_ROUND(PlotToPixels(0, *value).y);
const bool outside = y < (gp.BB_Plot.Min.y - grab_size / 2) || y > (gp.BB_Plot.Max.y + grab_size / 2);
if (outside)
return false;
float len = gp.Style.MajorTickLen.y;
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
ImDrawList& DrawList = *GetPlotDrawList();
PushPlotClipRect();
DrawList.AddLine(ImVec2(xl,y), ImVec2(xr,y), col32, thickness);
DrawList.AddLine(ImVec2(xl,y), ImVec2(xl+len,y), col32, 3*thickness);
DrawList.AddLine(ImVec2(xr,y), ImVec2(xr-len,y), col32, 3*thickness);
PopPlotClipRect();
if (gp.CurrentPlot->Selecting || gp.CurrentPlot->Querying)
return false;
ImVec2 old_cursor_pos = ImGui::GetCursorScreenPos();
ImVec2 new_cursor_pos = ImVec2(xl, y - grab_size / 2.0f);
ImGui::SetItemAllowOverlap();
ImGui::GetCurrentWindow()->DC.CursorPos = new_cursor_pos;
ImGui::InvisibleButton(id, ImVec2(xr - xl, grab_size));
ImGui::GetCurrentWindow()->DC.CursorPos = old_cursor_pos;
int yax = GetCurrentYAxis();
if (ImGui::IsItemHovered() || ImGui::IsItemActive()) {
gp.Hov_Plot = false;
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
if (show_label) {
PushPlotClipRect();
double range_y = gp.YTicks[yax].Size > 1 ? (gp.YTicks[yax].Ticks[1].PlotPos - gp.YTicks[yax].Ticks[0].PlotPos) : gp.CurrentPlot->YAxis[yax].Range.Size();
char buf[32];
snprintf(buf, 32, "%s = %.*f", id, Precision(range_y), *value);
ImVec2 size = ImGui::CalcTextSize(buf);
const int pad = 2;
if (yax == 0) {
ImVec2 label_pos = ImVec2(xl,y-pad-size.y/2);
ImVec2 label_size = size + ImVec2(pad*2,pad*2);
label_pos = ClampLabelPos(label_pos, label_size, gp.BB_Plot.Min, gp.BB_Plot.Max);
DrawList.AddRectFilled(label_pos, label_pos + label_size, col32);
DrawList.AddText(label_pos + ImVec2(pad,pad),CalcTextColor(color),buf);
}
else {
ImVec2 label_pos = ImVec2(xr-size.x-2*pad,y-pad-size.y/2);
ImVec2 label_size = size + ImVec2(pad*2,pad*2);
label_pos = ClampLabelPos(label_pos, label_size, gp.BB_Plot.Min, gp.BB_Plot.Max);
DrawList.AddRectFilled(label_pos, label_pos + label_size, col32);
DrawList.AddText(label_pos + ImVec2(pad,pad),CalcTextColor(color),buf);
}
PopPlotClipRect();
}
}
bool dragging = false;
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos().y;
*value = ImClamp(*value, gp.Y[yax].Axis->Range.Min, gp.Y[yax].Axis->Range.Max);
dragging = true;
}
return dragging;
}
bool DragPoint(const char* id, double* x, double* y, bool show_label, const ImVec4& col, float radius) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "DragPoint() needs to be called between BeginPlot() and EndPlot()!");
const float grab_size = ImMax(5.0f, 2*radius);
const bool outside = !GetPlotLimits().Contains(*x,*y);
if (outside)
@ -2603,13 +2610,10 @@ bool GrabPoint(const char* id, double* x, double* y, const ImVec4& col, float ra
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
ImDrawList& DrawList = *GetPlotDrawList();
ImVec2 pos = PlotToPixels(*x,*y);
PushPlotClipRect();
DrawList.AddCircleFilled(pos, radius, col32);
PopPlotClipRect();
int yax = GetCurrentYAxis();
ImVec2 old_cursor_pos = ImGui::GetCursorScreenPos();
ImVec2 new_cursor_pos = ImVec2(pos - ImVec2(grab_size,grab_size)*0.5f);
@ -2617,18 +2621,23 @@ bool GrabPoint(const char* id, double* x, double* y, const ImVec4& col, float ra
ImGui::InvisibleButton(id, ImVec2(grab_size, grab_size));
ImGui::GetCurrentWindow()->DC.CursorPos = old_cursor_pos;
if (ImGui::IsItemHovered() || ImGui::IsItemActive()) {
gp.Hov_Plot = false;
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
// double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : gp.CurrentPlot->XAxis.Range.Size();
// char buf[32];
// snprintf(buf, 32, "%s = %.*f", id, Precision(range_x), *value);
// ImVec2 size = ImGui::CalcTextSize(buf);
// const int pad = 2;
// PushPlotClipRect();
// DrawList.AddRectFilled(ImVec2(x - size.x/2 - pad, yb - size.y - 2*pad), ImVec2(x + pad + size.x/2, yb), col32);
// DrawList.AddText(ImVec2(x - size.x/2, yb - size.y - pad), CalcTextColor(color), buf);
// PopPlotClipRect();
if (show_label) {
PushPlotClipRect();
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : gp.CurrentPlot->XAxis.Range.Size();
double range_y = gp.YTicks[yax].Size > 1 ? (gp.YTicks[yax].Ticks[1].PlotPos - gp.YTicks[yax].Ticks[0].PlotPos) : gp.CurrentPlot->YAxis[yax].Range.Size();
char buf[64];
const float yb = gp.BB_Plot.Max.y;
snprintf(buf, 64, "%s = %.*f,%.*f", id, Precision(range_x), *x, Precision(range_y), *y);
ImVec2 label_pos = pos + ImVec2(16 * GImGui->Style.MouseCursorScale, 8 * GImGui->Style.MouseCursorScale);
ImVec2 label_size = ImGui::CalcTextSize(buf) + ImVec2(4,4);
label_pos = ClampLabelPos(label_pos, label_size, gp.BB_Plot.Min, gp.BB_Plot.Max);
DrawList.AddRectFilled(label_pos, label_pos + label_size, col32);
DrawList.AddText(label_pos + ImVec2(2,2), CalcTextColor(color), buf);
PopPlotClipRect();
}
}
bool dragging = false;
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
*x = ImPlot::GetPlotMousePos().x;

View File

@ -457,12 +457,12 @@ IMPLOT_API ImPlotLimits GetPlotLimits(int y_axis = IMPLOT_AUTO);
// Plot Tools
//-----------------------------------------------------------------------------
// Shows a draggable horizontal guide line. #col defaults to ImGuiCol_Text.
IMPLOT_API bool GrabLineH(const char* id, double* y_value, const ImVec4& col = IMPLOT_AUTO_COL, float thickness = 1);
// Shows a draggable vertical guide line. #col defaults to ImGuiCol_Text.
IMPLOT_API bool GrabLineV(const char* id, double* x_value, const ImVec4& col = IMPLOT_AUTO_COL, float thickness = 1);
// Shows a draggable anchor point. #col defaults to ImGuiCol_Text.
IMPLOT_API bool GrabPoint(const char* id, double* x, double* y, const ImVec4& col = IMPLOT_AUTO_COL, float radius = 5);
// Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragLineX(const char* id, double* x_value, bool show_label = true, const ImVec4& col = IMPLOT_AUTO_COL, float thickness = 1);
// Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragLineY(const char* id, double* y_value, bool show_label = true, const ImVec4& col = IMPLOT_AUTO_COL, float thickness = 1);
// Shows a draggable point at x,y. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragPoint(const char* id, double* x, double* y, bool show_label = true, const ImVec4& col = IMPLOT_AUTO_COL, float radius = 4);
// Returns true if the current plot is being queried. Query must be enabled with ImPlotFlags_Query.
IMPLOT_API bool IsPlotQueried();

View File

@ -805,36 +805,35 @@ void ShowDemoWindow(bool* p_open) {
}
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Grab Lines and Points")) {
ImGui::BulletText("Click and drag the horizontal and vertical guide lines.");
if (ImGui::CollapsingHeader("Drag Lines and Points")) {
ImGui::BulletText("Click and drag the horizontal and vertical lines.");
static double x1 = 0.2;
static double x2 = 0.8;
static double y1 = 0.25;
static double y2 = 0.75;
static double f = 0.1;
static bool show_labels = true;
ImGui::Checkbox("Show Labels##1",&show_labels);
if (ImPlot::BeginPlot("##guides",0,0,ImVec2(-1,0),ImPlotFlags_YAxis2)) {
ImPlot::GrabLineV("x1",&x1);
ImPlot::GrabLineV("x2",&x2);
ImPlot::GrabLineH("y1",&y1);
ImPlot::GrabLineH("y2",&y2);
ImPlot::SetPlotYAxis(1);
ImPlot::GrabLineH("f",&f, ImVec4(1,0.5f,1,1));
ImPlot::SetPlotYAxis(0);
ImPlot::DragLineX("x1",&x1,show_labels);
ImPlot::DragLineX("x2",&x2,show_labels);
ImPlot::DragLineY("y1",&y1,show_labels);
ImPlot::DragLineY("y2",&y2,show_labels);
double xs[1000], ys[1000];
for (int i = 0; i < 1000; ++i) {
xs[i] = (x2+x1)/2+abs(x2-x1)*(i/1000.0f - 0.5f);
ys[i] = (y1+y2)/2+abs(y2-y1)/2*sin(f*i/10);
}
ImPlot::PlotLine("Why Not?", xs, ys, 1000);
ImPlot::PlotLine("Interactive Data", xs, ys, 1000);
ImPlot::SetPlotYAxis(1);
ImPlot::DragLineY("f",&f,show_labels,ImVec4(1,0.5f,1,1));
ImPlot::EndPlot();
}
ImGui::BulletText("Click and drag the anchor points.");
ImGui::BulletText("Click and drag any point.");
ImGui::Checkbox("Show Labels##2",&show_labels);
ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks;
// ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always);
if (ImPlot::BeginPlot("##Bezier",0,0,ImVec2(-1,0),ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild,flags,flags)) {
static ImPlotPoint P[] = {ImPlotPoint(0,0), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(1,1)};
if (ImPlot::BeginPlot("##Bezier",0,0,ImVec2(-1,0),ImPlotFlags_CanvasOnly,flags,flags)) {
static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)};
static ImPlotPoint B[100];
for (int i = 0; i < 100; ++i) {
double t = i / 99.0;
@ -845,19 +844,16 @@ void ShowDemoWindow(bool* p_open) {
double w4 = t*t*t;
B[i] = ImPlotPoint(w1*P[0].x + w2*P[1].x + w3*P[2].x + w4*P[3].x, w1*P[0].y + w2*P[1].y + w3*P[2].y + w4*P[3].y);
}
static ImVec4 gray = ImVec4(0.5f,0.5f,0.5f,1.0f);
ImPlot::SetNextFillStyle(ImVec4(0,1,0,0.25f));
ImPlot::PlotShaded("##bez",&B[0].x, &B[0].y, 100, 0, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(ImVec4(0,1,0,1), 2);
ImPlot::SetNextLineStyle(ImVec4(0,0.9f,0,1), 2);
ImPlot::PlotLine("##bez",&B[0].x, &B[0].y, 100, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(gray, 2);
ImPlot::SetNextLineStyle(ImVec4(1,0.5f,1,1));
ImPlot::PlotLine("##h1",&P[0].x, &P[0].y, 2, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(gray, 2);
ImPlot::SetNextLineStyle(ImVec4(0,0.5f,1,1));
ImPlot::PlotLine("##h2",&P[2].x, &P[2].y, 2, 0, sizeof(ImPlotPoint));
ImPlot::GrabPoint("P0",&P[0].x,&P[0].y,gray);
ImPlot::GrabPoint("P1",&P[1].x,&P[1].y,gray);
ImPlot::GrabPoint("P2",&P[2].x,&P[2].y,gray);
ImPlot::GrabPoint("P3",&P[3].x,&P[3].y,gray);
ImPlot::DragPoint("P0",&P[0].x,&P[0].y, show_labels, ImVec4(0,0.9f,0,1));
ImPlot::DragPoint("P1",&P[1].x,&P[1].y, show_labels, ImVec4(1,0.5f,1,1));
ImPlot::DragPoint("P2",&P[2].x,&P[2].y, show_labels, ImVec4(0,0.5f,1,1));
ImPlot::DragPoint("P3",&P[3].x,&P[3].y, show_labels, ImVec4(0,0.9f,0,1));
ImPlot::EndPlot();
}
}

View File

@ -768,6 +768,15 @@ inline ImVec2 CalcTextSizeVertical(const char *text) { ImVec2 sz = ImGui::CalcTe
// Returns white or black text given background color
inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.729 ? IM_COL32_BLACK : IM_COL32_WHITE; }
// Clamps a label position so that it fits a rect defined by Min/Max
inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {
if (pos.x < Min.x) pos.x = Min.x;
if (pos.y < Min.y) pos.y = Min.y;
if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x;
if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y;
return pos;
}
//-----------------------------------------------------------------------------
// [SECTION] Math and Misc Utils
//-----------------------------------------------------------------------------