1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-23 02:38:53 -05:00

tidy up selection/query code, add new methods

This commit is contained in:
epezent 2021-03-23 23:42:26 -06:00
parent 5db2ba3b22
commit ef6c55cd00
4 changed files with 246 additions and 195 deletions

View File

@ -1753,13 +1753,20 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
// BOX-SELECTION AND QUERY ------------------------------------------------ // BOX-SELECTION AND QUERY ------------------------------------------------
// confirm selection // begin selection
if (plot.Selecting && (IO.MouseReleased[gp.InputMap.BoxSelectButton] || !IO.MouseDown[gp.InputMap.BoxSelectButton])) { if (plot.FrameHovered && plot.PlotHovered && IO.MouseClicked[gp.InputMap.BoxSelectButton] && ImHasFlag(IO.KeyMods, gp.InputMap.BoxSelectMod)) {
plot.Selecting = true;
plot.SelectStart = IO.MousePos;
plot.SelectRect = ImRect(0,0,0,0);
}
// update selection
if (plot.Selecting) {
UpdateTransformCache(); UpdateTransformCache();
ImVec2 select_size = plot.SelectStart - IO.MousePos; const ImVec2 d = plot.SelectStart - IO.MousePos;
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect)) { const bool x_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.HorizontalMod) && ImFabs(d.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(d.y) > 2;
const bool y_can_change = !ImHasFlag(IO.KeyMods,gp.InputMap.VerticalMod) && ImFabs(select_size.y) > 2; // confirm
if (IO.MouseReleased[gp.InputMap.BoxSelectButton] || !IO.MouseDown[gp.InputMap.BoxSelectButton]) {
if (!plot.XAxis.IsInputLocked()) { if (!plot.XAxis.IsInputLocked()) {
ImPlotPoint p1 = PixelsToPlot(plot.SelectStart); ImPlotPoint p1 = PixelsToPlot(plot.SelectStart);
ImPlotPoint p2 = PixelsToPlot(IO.MousePos); ImPlotPoint p2 = PixelsToPlot(IO.MousePos);
@ -1769,7 +1776,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
plot.XAxis.SetMax(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++) {
if (!plot.YAxis->IsInputLocked()) { if (!plot.YAxis[i].IsInputLocked()) {
ImPlotPoint p1 = PixelsToPlot(plot.SelectStart, i); ImPlotPoint p1 = PixelsToPlot(plot.SelectStart, i);
ImPlotPoint p2 = PixelsToPlot(IO.MousePos, i); ImPlotPoint p2 = PixelsToPlot(IO.MousePos, i);
if (!plot.YAxis[i].IsLockedMin() && y_can_change) if (!plot.YAxis[i].IsLockedMin() && y_can_change)
@ -1780,37 +1787,48 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
} }
if (x_can_change || y_can_change || (ImHasFlag(IO.KeyMods,gp.InputMap.HorizontalMod) && ImHasFlag(IO.KeyMods,gp.InputMap.VerticalMod))) if (x_can_change || y_can_change || (ImHasFlag(IO.KeyMods,gp.InputMap.HorizontalMod) && ImHasFlag(IO.KeyMods,gp.InputMap.VerticalMod)))
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton; plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
plot.Selected = plot.Selecting = false;
} }
plot.Selecting = false; // cancel
else if (IO.MouseClicked[gp.InputMap.BoxSelectCancelButton] || IO.MouseDown[gp.InputMap.BoxSelectCancelButton]) {
plot.Selected = plot.Selecting = false;
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
} }
else if (ImLengthSqr(d) > 4) {
// bad selection // bad selection
if (plot.Selecting && (ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) || plot.IsInputLocked()) && ImLengthSqr(plot.SelectStart - IO.MousePos) > 4) { if (ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) || plot.IsInputLocked()) {
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton; plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
plot.Selected = false;
} }
// cancel selection else {
if (plot.Selecting && (IO.MouseClicked[gp.InputMap.BoxSelectCancelButton] || IO.MouseDown[gp.InputMap.BoxSelectCancelButton])) { const bool any_y_locked = plot.AnyYLocked();
plot.Selecting = false; // TODO: Handle only min or max locked cases
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton; plot.SelectRect.Min.x = ImHasFlag(IO.KeyMods, gp.InputMap.HorizontalMod) || plot.XAxis.IsInputLocked() ? plot.PlotRect.Min.x : ImMin(plot.SelectStart.x, IO.MousePos.x);
plot.SelectRect.Max.x = ImHasFlag(IO.KeyMods, gp.InputMap.HorizontalMod) || plot.XAxis.IsInputLocked() ? plot.PlotRect.Max.x : ImMax(plot.SelectStart.x, IO.MousePos.x);
plot.SelectRect.Min.y = ImHasFlag(IO.KeyMods, gp.InputMap.VerticalMod) || any_y_locked ? plot.PlotRect.Min.y : ImMin(plot.SelectStart.y, IO.MousePos.y);
plot.SelectRect.Max.y = ImHasFlag(IO.KeyMods, gp.InputMap.VerticalMod) || any_y_locked ? plot.PlotRect.Max.y : ImMax(plot.SelectStart.y, IO.MousePos.y);
plot.SelectRect.Min -= plot.PlotRect.Min;
plot.SelectRect.Max -= plot.PlotRect.Min;
plot.Selected = true;
} }
// begin selection or query }
if (plot.FrameHovered && plot.PlotHovered && IO.MouseClicked[gp.InputMap.BoxSelectButton] && ImHasFlag(IO.KeyMods, gp.InputMap.BoxSelectMod)) { else {
plot.SelectStart = IO.MousePos; plot.Selected = false;
plot.Selecting = true; }
}
// begin query
if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && plot.FrameHovered && plot.PlotHovered && IO.MouseClicked[gp.InputMap.QueryButton] && ImHasFlag(IO.KeyMods, gp.InputMap.QueryMod)) {
plot.Querying = true;
plot.QueryStart = IO.MousePos;
plot.QueryRect = ImRect(0,0,0,0);
} }
// update query // update query
if (plot.Querying) { if (plot.Querying) {
UpdateTransformCache(); UpdateTransformCache();
plot.QueryRect.Min.x = ImHasFlag(IO.KeyMods, gp.InputMap.HorizontalMod) ? plot.PlotRect.Min.x : ImMin(plot.QueryStart.x, IO.MousePos.x); // confirm
plot.QueryRect.Max.x = ImHasFlag(IO.KeyMods, gp.InputMap.HorizontalMod) ? plot.PlotRect.Max.x : ImMax(plot.QueryStart.x, IO.MousePos.x); if (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton]) {
plot.QueryRect.Min.y = ImHasFlag(IO.KeyMods, gp.InputMap.VerticalMod) ? plot.PlotRect.Min.y : ImMin(plot.QueryStart.y, IO.MousePos.y);
plot.QueryRect.Max.y = ImHasFlag(IO.KeyMods, gp.InputMap.VerticalMod) ? plot.PlotRect.Max.y : ImMax(plot.QueryStart.y, IO.MousePos.y);
plot.QueryRect.Min -= plot.PlotRect.Min;
plot.QueryRect.Max -= plot.PlotRect.Min;
}
// end query
if (plot.Querying && (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton])) {
plot.Querying = false; plot.Querying = false;
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) { if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) {
plot.Queried = true; plot.Queried = true;
@ -1819,32 +1837,31 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
else else
plot.Queried = false; plot.Queried = false;
} }
else {
plot.QueryRect.Min.x = ImHasFlag(IO.KeyMods, gp.InputMap.HorizontalMod) ? plot.PlotRect.Min.x : ImMin(plot.QueryStart.x, IO.MousePos.x);
plot.QueryRect.Max.x = ImHasFlag(IO.KeyMods, gp.InputMap.HorizontalMod) ? plot.PlotRect.Max.x : ImMax(plot.QueryStart.x, IO.MousePos.x);
plot.QueryRect.Min.y = ImHasFlag(IO.KeyMods, gp.InputMap.VerticalMod) ? plot.PlotRect.Min.y : ImMin(plot.QueryStart.y, IO.MousePos.y);
plot.QueryRect.Max.y = ImHasFlag(IO.KeyMods, gp.InputMap.VerticalMod) ? plot.PlotRect.Max.y : ImMax(plot.QueryStart.y, IO.MousePos.y);
plot.QueryRect.Min -= plot.PlotRect.Min;
plot.QueryRect.Max -= plot.PlotRect.Min;
plot.Queried = plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2;
}
}
// begin query // switch select to query
if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && plot.FrameHovered && plot.PlotHovered && IO.MouseClicked[gp.InputMap.QueryButton] && ImHasFlag(IO.KeyMods, gp.InputMap.QueryMod)) {
plot.QueryRect = ImRect(0,0,0,0);
plot.Querying = true;
plot.Queried = true;
plot.QueryStart = IO.MousePos;
}
// toggle between select/query
if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && plot.Selecting && ImHasFlag(IO.KeyMods,gp.InputMap.QueryToggleMod)) { if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && plot.Selecting && ImHasFlag(IO.KeyMods,gp.InputMap.QueryToggleMod)) {
plot.Selecting = false; plot.Selecting = plot.Selected = false;
plot.QueryRect = ImRect(0,0,0,0); plot.Querying = plot.Queried = true;
plot.Querying = true;
plot.Queried = true;
plot.QueryStart = plot.SelectStart; plot.QueryStart = plot.SelectStart;
plot.QueryRect = plot.SelectRect;
} }
// switch query to select
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) && plot.Querying && !ImHasFlag(IO.KeyMods, gp.InputMap.QueryToggleMod) && !IO.MouseDown[gp.InputMap.QueryButton]) { if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) && plot.Querying && !ImHasFlag(IO.KeyMods, gp.InputMap.QueryToggleMod) && !IO.MouseDown[gp.InputMap.QueryButton]) {
plot.Selecting = true; plot.Selecting = plot.Selected = true;
plot.Querying = false; plot.Querying = plot.Queried = false;
plot.Queried = false; plot.SelectStart = plot.QueryStart;
plot.QueryRect = ImRect(0,0,0,0); plot.SelectRect = plot.QueryRect;
}
if (!ImHasFlag(plot.Flags, ImPlotFlags_Query)) {
plot.Queried = false;
plot.Querying = false;
plot.QueryRect = ImRect(0,0,0,0);
} }
// FIT ----------------------------------------------------------- // FIT -----------------------------------------------------------
@ -2235,7 +2252,7 @@ void EndPlot() {
// AXIS STATES ------------------------------------------------------------ // AXIS STATES ------------------------------------------------------------
const bool any_y_locked = plot.YAxis[0].IsInputLocked() || plot.YAxis[1].Present ? plot.YAxis[1].IsInputLocked() : false || plot.YAxis[2].Present ? plot.YAxis[2].IsInputLocked() : false; const bool any_y_locked = plot.AnyYLocked();
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;
@ -2324,56 +2341,22 @@ void EndPlot() {
DrawList.AddRectFilled(rect.Min, rect.Max, an.ColorBg); DrawList.AddRectFilled(rect.Min, rect.Max, an.ColorBg);
DrawList.AddText(pos + gp.Style.AnnotationPadding, an.ColorFg, txt); DrawList.AddText(pos + gp.Style.AnnotationPadding, an.ColorFg, txt);
} }
// render selection
// render selection/query if (plot.Selected) {
if (plot.Selecting) {
const ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart));
const bool wide_enough = ImFabs(select_bb.GetWidth()) > 2;
const bool tall_enough = ImFabs(select_bb.GetHeight()) > 2;
const bool big_enough = wide_enough && tall_enough;
if (plot.Selecting && !plot.IsInputLocked() && !ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect)) {
const ImVec4 col = GetStyleColorVec4(ImPlotCol_Selection); const ImVec4 col = GetStyleColorVec4(ImPlotCol_Selection);
const ImU32 col_bg = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f)); const ImU32 col_bg = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f));
const ImU32 col_bd = ImGui::GetColorU32(col); const ImU32 col_bd = ImGui::GetColorU32(col);
if (IO.KeyMods == (gp.InputMap.HorizontalMod | gp.InputMap.VerticalMod) && big_enough) { DrawList.AddRectFilled(plot.SelectRect.Min + plot.PlotRect.Min, plot.SelectRect.Max + plot.PlotRect.Min, col_bg);
DrawList.AddRectFilled(plot.PlotRect.Min, plot.PlotRect.Max, col_bg); DrawList.AddRect( plot.SelectRect.Min + plot.PlotRect.Min, plot.SelectRect.Max + plot.PlotRect.Min, col_bd);
DrawList.AddRect( plot.PlotRect.Min, plot.PlotRect.Max, col_bd);
} }
else if ((plot.XAxis.IsInputLocked() || IO.KeyMods == gp.InputMap.HorizontalMod) && tall_enough) { // render query
DrawList.AddRectFilled(ImVec2(plot.PlotRect.Min.x, select_bb.Min.y), ImVec2(plot.PlotRect.Max.x, select_bb.Max.y), col_bg); if (plot.Queried) {
DrawList.AddRect( ImVec2(plot.PlotRect.Min.x, select_bb.Min.y), ImVec2(plot.PlotRect.Max.x, select_bb.Max.y), col_bd);
}
else if ((any_y_locked || IO.KeyMods == gp.InputMap.VerticalMod) && wide_enough) {
DrawList.AddRectFilled(ImVec2(select_bb.Min.x, plot.PlotRect.Min.y), ImVec2(select_bb.Max.x, plot.PlotRect.Max.y), col_bg);
DrawList.AddRect( ImVec2(select_bb.Min.x, plot.PlotRect.Min.y), ImVec2(select_bb.Max.x, plot.PlotRect.Max.y), col_bd);
}
else if (big_enough) {
DrawList.AddRectFilled(select_bb.Min, select_bb.Max, col_bg);
DrawList.AddRect( select_bb.Min, select_bb.Max, col_bd);
}
}
}
if (ImHasFlag(plot.Flags, ImPlotFlags_Query)) // draw query rect only when query enabled.
{
const ImVec4 col = GetStyleColorVec4(ImPlotCol_Query); const ImVec4 col = GetStyleColorVec4(ImPlotCol_Query);
const ImU32 col_bd = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f)); const ImU32 col_bg = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f));
const ImU32 col_bg = ImGui::GetColorU32(col); const ImU32 col_bd = ImGui::GetColorU32(col);
if (plot.Querying || plot.Queried) { DrawList.AddRectFilled(plot.QueryRect.Min + plot.PlotRect.Min, plot.QueryRect.Max + plot.PlotRect.Min, col_bg);
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) { DrawList.AddRect( plot.QueryRect.Min + plot.PlotRect.Min, plot.QueryRect.Max + plot.PlotRect.Min, col_bd);
DrawList.AddRectFilled(plot.QueryRect.Min + plot.PlotRect.Min, plot.QueryRect.Max + plot.PlotRect.Min, col_bd);
DrawList.AddRect( plot.QueryRect.Min + plot.PlotRect.Min, plot.QueryRect.Max + plot.PlotRect.Min, col_bg);
} }
}
else if (plot.Queried) {
ImRect bb_query = plot.QueryRect;
bb_query.Min += plot.PlotRect.Min;
bb_query.Max += plot.PlotRect.Min;
DrawList.AddRectFilled(bb_query.Min, bb_query.Max, col_bd);
DrawList.AddRect( bb_query.Min, bb_query.Max, col_bg);
}
}
// render crosshairs // render crosshairs
if (ImHasFlag(plot.Flags, ImPlotFlags_Crosshairs) && plot.PlotHovered && plot.FrameHovered && if (ImHasFlag(plot.Flags, ImPlotFlags_Crosshairs) && plot.PlotHovered && plot.FrameHovered &&
!(plot.XAxis.Dragging || any_y_dragging) && !plot.Selecting && !plot.Querying && !plot.LegendHovered) { !(plot.XAxis.Dragging || any_y_dragging) && !plot.Selecting && !plot.Querying && !plot.LegendHovered) {
@ -2754,23 +2737,23 @@ ImPlotLimits GetPlotLimits(ImPlotYAxis y_axis_in) {
return limits; return limits;
} }
bool IsPlotQueried() { bool IsPlotSelected() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotQueried() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotSelected() needs to be called between BeginPlot() and EndPlot()!");
return gp.CurrentPlot->Queried; return gp.CurrentPlot->Selected;
} }
ImPlotLimits GetPlotQuery(ImPlotYAxis y_axis_in) { ImPlotLimits GetPlotSelection(ImPlotYAxis y_axis) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis >= -1 && y_axis < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotSelection() needs to be called between BeginPlot() and EndPlot()!");
ImPlotPlot& plot = *gp.CurrentPlot; ImPlotPlot& plot = *gp.CurrentPlot;
const ImPlotYAxis y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; y_axis = y_axis >= 0 ? y_axis : gp.CurrentPlot->CurrentYAxis;
if (!plot.Selecting)
return ImPlotLimits(0,0,0,0);
UpdateTransformCache(); UpdateTransformCache();
ImPlotPoint p1 = PixelsToPlot(plot.QueryRect.Min + plot.PlotRect.Min, y_axis); ImPlotPoint p1 = PixelsToPlot(plot.SelectRect.Min + plot.PlotRect.Min, y_axis);
ImPlotPoint p2 = PixelsToPlot(plot.QueryRect.Max + plot.PlotRect.Min, y_axis); ImPlotPoint p2 = PixelsToPlot(plot.SelectRect.Max + plot.PlotRect.Min, y_axis);
ImPlotLimits result; ImPlotLimits result;
result.X.Min = ImMin(p1.x, p2.x); result.X.Min = ImMin(p1.x, p2.x);
result.X.Max = ImMax(p1.x, p2.x); result.X.Max = ImMax(p1.x, p2.x);
@ -2779,6 +2762,45 @@ ImPlotLimits GetPlotQuery(ImPlotYAxis y_axis_in) {
return result; return result;
} }
bool IsPlotQueried() {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotQueried() needs to be called between BeginPlot() and EndPlot()!");
return gp.CurrentPlot->Queried;
}
ImPlotLimits GetPlotQuery(ImPlotYAxis y_axis) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis >= -1 && y_axis < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!");
ImPlotPlot& plot = *gp.CurrentPlot;
y_axis = y_axis >= 0 ? y_axis : gp.CurrentPlot->CurrentYAxis;
if (!plot.Queried)
return ImPlotLimits(0,0,0,0);
UpdateTransformCache();
ImPlotPoint p1 = PixelsToPlot(plot.QueryRect.Min + plot.PlotRect.Min, y_axis);
ImPlotPoint p2 = PixelsToPlot(plot.QueryRect.Max + plot.PlotRect.Min, y_axis);
ImPlotLimits result;
result.X.Min = ImMin(p1.x, p2.x);
result.X.Max = ImMax(p1.x, p2.x);
result.Y.Min = ImMin(p1.y, p2.y);
result.Y.Max = ImMax(p1.y, p2.y);
return result;
}
void SetPlotQuery(const ImPlotLimits& query, ImPlotYAxis y_axis) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!");
ImPlotPlot& plot = *gp.CurrentPlot;
y_axis = y_axis >= 0 ? y_axis : gp.CurrentPlot->CurrentYAxis;
UpdateTransformCache();
ImVec2 p1 = PlotToPixels(query.Min(),y_axis);
ImVec2 p2 = PlotToPixels(query.Max(),y_axis);
plot.Queried = true;
plot.Querying = false;
plot.QueryRect = ImRect(ImMin(p1,p2)-plot.PlotRect.Min, ImMax(p1,p2)-plot.PlotRect.Min);
}
void AnnotateEx(double x, double y, bool clamp, const ImVec4& col, const ImVec2& off, const char* fmt, va_list args) { void AnnotateEx(double x, double y, bool clamp, const ImVec4& col, const ImVec2& off, const char* fmt, va_list args) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Annotate() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Annotate() needs to be called between BeginPlot() and EndPlot()!");
@ -3986,6 +4008,7 @@ void ShowMetricsWindow(bool* p_popen) {
ImGui::Bullet(); ImGui::Text("Flags: %d", plot->Flags); ImGui::Bullet(); ImGui::Text("Flags: %d", plot->Flags);
ImGui::Bullet(); ImGui::Text("Initialized: %s", plot->Initialized ? "true" : "false"); ImGui::Bullet(); ImGui::Text("Initialized: %s", plot->Initialized ? "true" : "false");
ImGui::Bullet(); ImGui::Text("Selecting: %s", plot->Selecting ? "true" : "false"); ImGui::Bullet(); ImGui::Text("Selecting: %s", plot->Selecting ? "true" : "false");
ImGui::Bullet(); ImGui::Text("Selected: %s", plot->Selected ? "true" : "false");
ImGui::Bullet(); ImGui::Text("Querying: %s", plot->Querying ? "true" : "false"); ImGui::Bullet(); ImGui::Text("Querying: %s", plot->Querying ? "true" : "false");
ImGui::Bullet(); ImGui::Text("Queried: %s", plot->Queried ? "true" : "false"); ImGui::Bullet(); ImGui::Text("Queried: %s", plot->Queried ? "true" : "false");
ImGui::Bullet(); ImGui::Text("FrameHovered: %s", plot->FrameHovered ? "true" : "false"); ImGui::Bullet(); ImGui::Text("FrameHovered: %s", plot->FrameHovered ? "true" : "false");

View File

@ -341,23 +341,24 @@ IMPLOT_API void SetImGuiContext(ImGuiContext* ctx);
// Begin/End Plot // Begin/End Plot
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Starts a 2D plotting context. If this function returns true, EndPlot() must // Starts a 2D plotting context. If this function returns true, EndPlot() MUST
// be called! You are encouraged to use the following call convention: // be called! You are encouraged to use the following convention:
// //
// if (BeginPlot(...)) { // if (BeginPlot(...)) {
// ImPlot::PlotLine(...); // ImPlot::PlotLine(...);
// ...
// EndPlot(); // EndPlot();
// } // }
// //
// Important notes: // Important notes:
// //
// - #title_id must be unique to the current ImGui window. If you need to avoid ID // - #title_id must be unique to the current ImGui ID scope. If you need to avoid ID
// collisions or don't want to display a title in the plot, use double hashes // collisions or don't want to display a title in the plot, use double hashes
// (e.g. "MyPlot##Hidden" or "##NoTitle"). // (e.g. "MyPlot##HiddenIdText" or "##NoTitle").
// - If #x_label and/or #y_label are provided, axes labels will be displayed. // - If #x_label and/or #y_label are provided, axes labels will be displayed.
// - #size is the **frame** size of the plot widget, not the plot area. The default // - #size is the **frame** size of the plot widget, not the plot area. The default
// size of plots (i.e. when ImVec2(0,0)) can be modified in your ImPlotStyle // size of plots (i.e. when ImVec2(0,0)) can be modified in your ImPlotStyle
// (default is 400x300). // (default is 400x300 px).
// - Auxiliary y-axes must be enabled with ImPlotFlags_YAxis2/3 to be displayed. // - Auxiliary y-axes must be enabled with ImPlotFlags_YAxis2/3 to be displayed.
// - See ImPlotFlags and ImPlotAxisFlags for more available options. // - See ImPlotFlags and ImPlotAxisFlags for more available options.
@ -374,7 +375,7 @@ IMPLOT_API bool BeginPlot(const char* title_id,
const char* y3_label = NULL); const char* y3_label = NULL);
// Only call EndPlot() if BeginPlot() returns true! Typically called at the end // Only call EndPlot() if BeginPlot() returns true! Typically called at the end
// of an if statement conditioned on BeginPlot(). See above. // of an if statement conditioned on BeginPlot(). See example above.
IMPLOT_API void EndPlot(); IMPLOT_API void EndPlot();
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -398,9 +399,9 @@ IMPLOT_API void EndPlot();
// Vector2f data[42]; // Vector2f data[42];
// ImPlot::PlotLine("line", &data[0].x, &data[0].y, 42, 0, sizeof(Vector2f)); // or sizeof(float)*2 // ImPlot::PlotLine("line", &data[0].x, &data[0].y, 42, 0, sizeof(Vector2f)); // or sizeof(float)*2
// //
// 2. Write a custom getter C function or C++ lambda and pass it and your data to // 2. Write a custom getter C function or C++ lambda and pass it and optionally your data to
// an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a // an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a slight performance
// slight performance cost, but probably not enough to worry about. Example: // cost, but probably not enough to worry about unless your data is very large. Examples:
// //
// ImPlotPoint MyDataGetter(void* data, int idx) { // ImPlotPoint MyDataGetter(void* data, int idx) {
// MyData* my_data = (MyData*)data; // MyData* my_data = (MyData*)data;
@ -492,10 +493,10 @@ template <typename T> IMPLOT_API double PlotHistogram2D(const char* label_id, co
template <typename T> IMPLOT_API void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset=0, int stride=sizeof(T)); template <typename T> IMPLOT_API void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset=0, int stride=sizeof(T));
IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset=0); IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset=0);
// Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinatse (y-up) and #uv0/uv1 are in texture coordinates (y-down). // Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down).
IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1)); IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1));
// Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...). // Plots a centered text label at point x,y with an optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...).
IMPLOT_API void PlotText(const char* text, double x, double y, bool vertical=false, const ImVec2& pix_offset=ImVec2(0,0)); IMPLOT_API void PlotText(const char* text, double x, double y, bool vertical=false, const ImVec2& pix_offset=ImVec2(0,0));
// Plots a dummy item (i.e. adds a legend entry colored by ImPlotCol_Line) // Plots a dummy item (i.e. adds a legend entry colored by ImPlotCol_Line)
@ -513,16 +514,16 @@ IMPLOT_API void SetNextPlotLimits(double xmin, double xmax, double ymin, double
IMPLOT_API void SetNextPlotLimitsX(double xmin, double xmax, ImGuiCond cond = ImGuiCond_Once); IMPLOT_API void SetNextPlotLimitsX(double xmin, double xmax, ImGuiCond cond = ImGuiCond_Once);
// 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.
IMPLOT_API void SetNextPlotLimitsY(double ymin, double ymax, ImGuiCond cond = ImGuiCond_Once, ImPlotYAxis y_axis = 0); IMPLOT_API void SetNextPlotLimitsY(double ymin, double ymax, ImGuiCond cond = ImGuiCond_Once, ImPlotYAxis y_axis = 0);
// Links the next plot limits to external values. Set to NULL for no linkage. The pointer data must remain valid until the matching call EndPlot. // Links the next plot limits to external values. Set to NULL for no linkage. The pointer data must remain valid until the matching call to EndPlot.
IMPLOT_API void LinkNextPlotLimits(double* xmin, double* xmax, double* ymin, double* ymax, double* ymin2 = NULL, double* ymax2 = NULL, double* ymin3 = NULL, double* ymax3 = NULL); IMPLOT_API void LinkNextPlotLimits(double* xmin, double* xmax, double* ymin, double* ymax, double* ymin2 = NULL, double* ymax2 = NULL, double* ymin3 = NULL, double* ymax3 = NULL);
// Fits the next plot axes to all plotted data if they are unlocked (equivalent to double-clicks). // Fits the next plot axes to all plotted data if they are unlocked (equivalent to double-clicks).
IMPLOT_API void FitNextPlotAxes(bool x = true, bool y = true, bool y2 = true, bool y3 = true); IMPLOT_API void FitNextPlotAxes(bool x = true, bool y = true, bool y2 = true, bool y3 = true);
// Set the X axis ticks and optionally the labels for the next plot. // Set the X axis ticks and optionally the labels for the next plot. To keep the default ticks, set #show_default=true.
IMPLOT_API void SetNextPlotTicksX(const double* values, int n_ticks, const char* const labels[] = NULL, bool show_default = false); IMPLOT_API void SetNextPlotTicksX(const double* values, int n_ticks, const char* const labels[] = NULL, bool show_default = false);
IMPLOT_API void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char* const labels[] = NULL, bool show_default = false); IMPLOT_API void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char* const labels[] = NULL, bool show_default = false);
// Set the Y axis ticks and optionally the labels for the next plot. // Set the Y axis ticks and optionally the labels for the next plot. To keep the default ticks, set #show_default=true.
IMPLOT_API void SetNextPlotTicksY(const double* values, int n_ticks, const char* const labels[] = NULL, bool show_default = false, ImPlotYAxis y_axis = 0); IMPLOT_API void SetNextPlotTicksY(const double* values, int n_ticks, const char* const labels[] = NULL, bool show_default = false, ImPlotYAxis y_axis = 0);
IMPLOT_API void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* const labels[] = NULL, bool show_default = false, ImPlotYAxis y_axis = 0); IMPLOT_API void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* const labels[] = NULL, bool show_default = false, ImPlotYAxis y_axis = 0);
@ -554,10 +555,17 @@ IMPLOT_API ImPlotPoint GetPlotMousePos(ImPlotYAxis y_axis = IMPLOT_AUTO);
// Returns the current plot axis range. A negative y_axis uses the current value of SetPlotYAxis (ImPlotYAxis_1 initially). // Returns the current plot axis range. A negative y_axis uses the current value of SetPlotYAxis (ImPlotYAxis_1 initially).
IMPLOT_API ImPlotLimits GetPlotLimits(ImPlotYAxis y_axis = IMPLOT_AUTO); IMPLOT_API ImPlotLimits GetPlotLimits(ImPlotYAxis y_axis = IMPLOT_AUTO);
// Returns true if the current plot is being queried. Query must be enabled with ImPlotFlags_Query. // Returns true if the current plot is being box selected.
IMPLOT_API bool IsPlotSelected();
// Returns the current plot box selection bounds.
IMPLOT_API ImPlotLimits GetPlotSelection(ImPlotYAxis y_axis = IMPLOT_AUTO);
// Returns true if the current plot is being queried or has an active query. Query must be enabled with ImPlotFlags_Query.
IMPLOT_API bool IsPlotQueried(); IMPLOT_API bool IsPlotQueried();
// Returns the current plot query bounds. Query must be enabled with ImPlotFlags_Query. // Returns the current plot query bounds. Query must be enabled with ImPlotFlags_Query.
IMPLOT_API ImPlotLimits GetPlotQuery(ImPlotYAxis y_axis = IMPLOT_AUTO); IMPLOT_API ImPlotLimits GetPlotQuery(ImPlotYAxis y_axis = IMPLOT_AUTO);
// Set the current plot query bounds. Query must be enabled with ImPlotFlags_Query.
IMPLOT_API void SetPlotQuery(const ImPlotLimits& query, ImPlotYAxis y_axis = IMPLOT_AUTO);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Plot Tools // Plot Tools
@ -619,7 +627,7 @@ IMPLOT_API bool BeginDragDropTargetLegend();
// Ends a drag and drop target (currently just an alias for ImGui::EndDragDropTarget). // Ends a drag and drop target (currently just an alias for ImGui::EndDragDropTarget).
IMPLOT_API void EndDragDropTarget(); IMPLOT_API void EndDragDropTarget();
// NB: By default, plot and axes drag and drop sources require holding the Ctrl modifier to initiate the drag. // NB: By default, plot and axes drag and drop *sources* require holding the Ctrl modifier to initiate the drag.
// You can change the modifier if desired. If ImGuiKeyModFlags_None is provided, the axes will be locked from panning. // You can change the modifier if desired. If ImGuiKeyModFlags_None is provided, the axes will be locked from panning.
// Turns the current plot's plotting area into a drag and drop source. Don't forget to call EndDragDropSource! // Turns the current plot's plotting area into a drag and drop source. Don't forget to call EndDragDropSource!
@ -650,7 +658,7 @@ IMPLOT_API void EndDragDropSource();
// color in the current colormap. Thus, every item will have a different // color in the current colormap. Thus, every item will have a different
// color up to the number of colors in the colormap, at which point the // color up to the number of colors in the colormap, at which point the
// colormap will roll over. For most use cases, you should not need to // colormap will roll over. For most use cases, you should not need to
// modify these style colors to anything but IMPLOT_COL_AUTO. You are // set these style colors to anything but IMPLOT_COL_AUTO; you are
// probably better off changing the current colormap. However, if you // probably better off changing the current colormap. However, if you
// need to explicitly color a particular item you may either Push/Pop // need to explicitly color a particular item you may either Push/Pop
// the style color around the item in question, or use the SetNextXXXStyle // the style color around the item in question, or use the SetNextXXXStyle
@ -664,7 +672,7 @@ IMPLOT_API void EndDragDropSource();
// detailed above, and in general have been mapped to produce plots visually // detailed above, and in general have been mapped to produce plots visually
// consistent with your current ImGui style. Of course, you are free to // consistent with your current ImGui style. Of course, you are free to
// manually set these colors to whatever you like, and further can Push/Pop // manually set these colors to whatever you like, and further can Push/Pop
// them around individual plots. // them around individual plots for plot-specific styling (e.g. coloring axes).
// Provides access to plot style structure for permanant modifications to colors, sizes, etc. // Provides access to plot style structure for permanant modifications to colors, sizes, etc.
IMPLOT_API ImPlotStyle& GetStyle(); IMPLOT_API ImPlotStyle& GetStyle();
@ -733,15 +741,15 @@ IMPLOT_API const char* GetMarkerName(ImPlotMarker idx);
// 2) Pushed an item style color using PushStyleColor(). // 2) Pushed an item style color using PushStyleColor().
// 3) Set the next item style with a SetNextXXXStyle function. // 3) Set the next item style with a SetNextXXXStyle function.
// Add a new colormap. The colormap can be used by pushing either the returned index or the string name with PushColormap. // Add a new colormap. The color data will be copied. The colormap can be used by pushing either the returned index or the
// The colormap name must be unique and the size must be greater than 1. You will receive an assert otherwise! By default // string name with PushColormap. The colormap name must be unique and the size must be greater than 1. You will receive
// colormaps are considered to be qualitative (i.e. discrete). If you want to create a continuous colormap, set #qual=false. // an assert otherwise! By default colormaps are considered to be qualitative (i.e. discrete). If you want to create a
// This will treat the colors you provide as keys, and ImPlot will build a linearly interpolated lookup table that fills // continuous colormap, set #qual=false. This will treat the colors you provide as keys, and ImPlot will build a linearly
// in the gaps. The memory footprint of this table will be exactly ((size-1)*255+1)*4 bytes. // interpolated lookup table. The memory footprint of this table will be exactly ((size-1)*255+1)*4 bytes.
IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImVec4* cols, int size, bool qual=true); IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImVec4* cols, int size, bool qual=true);
IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int size, bool qual=true); IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int size, bool qual=true);
// Returns the number of available colormaps. // Returns the number of available colormaps (i.e. the built-in + user-added count).
IMPLOT_API int GetColormapCount(); IMPLOT_API int GetColormapCount();
// Returns a null terminated string name for a colormap given an index. Returns NULL if index is invalid. // Returns a null terminated string name for a colormap given an index. Returns NULL if index is invalid.
IMPLOT_API const char* GetColormapName(ImPlotColormap cmap); IMPLOT_API const char* GetColormapName(ImPlotColormap cmap);
@ -750,7 +758,7 @@ IMPLOT_API ImPlotColormap GetColormapIndex(const char* name);
// Temporarily switch to one of the built-in (i.e. ImPlotColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to call PopColormap! // Temporarily switch to one of the built-in (i.e. ImPlotColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to call PopColormap!
IMPLOT_API void PushColormap(ImPlotColormap cmap); IMPLOT_API void PushColormap(ImPlotColormap cmap);
// Push a colormap by string name. Use built-in names such as "Default", "Deep", "Jet", etc or a string you provided to AddColormap. Don't forget to call PopColormap! // Push a colormap by string name. Use built-in names such as "Default", "Deep", "Jet", etc. or a string you provided to AddColormap. Don't forget to call PopColormap!
IMPLOT_API void PushColormap(const char* name); IMPLOT_API void PushColormap(const char* name);
// Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count. // Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count.
IMPLOT_API void PopColormap(int count = 1); IMPLOT_API void PopColormap(int count = 1);
@ -760,7 +768,7 @@ IMPLOT_API void PopColormap(int count = 1);
IMPLOT_API ImVec4 NextColormapColor(); IMPLOT_API ImVec4 NextColormapColor();
// Colormap utils. If cmap = IMPLOT_AUTO (default), the current colormap is assumed. // Colormap utils. If cmap = IMPLOT_AUTO (default), the current colormap is assumed.
// Pass an explicit colormap index (built-in or user added) to specify otherwise. // Pass an explicit colormap index (built-in or user-added) to specify otherwise.
// Returns the size of a colormap. // Returns the size of a colormap.
IMPLOT_API int GetColormapSize(ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API int GetColormapSize(ImPlotColormap cmap = IMPLOT_AUTO);
@ -778,11 +786,11 @@ IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,
// When items in a plot sample their color from a colormap, the color is cached and does not change // When items in a plot sample their color from a colormap, the color is cached and does not change
// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted, // unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted,
// item colors will not update. If you need item colors to resample the new colormap, then use this // item colors will NOT update. If you need item colors to resample the new colormap, then use this
// function to bust the cached colors. If #plot_title_id is NULL, then every item in EVERY existing plot // function to bust the cached colors. If #plot_title_id is NULL, then every item in EVERY existing plot
// will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the // will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the
// latter, this function must be called in the ImGui window that the plot is in. You should rarely if ever // latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever
// need this function, but it is available for applications that require runtime swaps (see Heatmaps demo). // need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo).
IMPLOT_API void BustColorCache(const char* plot_title_id = NULL); IMPLOT_API void BustColorCache(const char* plot_title_id = NULL);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -809,14 +817,14 @@ IMPLOT_API bool ShowColormapSelector(const char* label);
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL); IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL);
// Add basic help/info block for end users (not a window). // Add basic help/info block for end users (not a window).
IMPLOT_API void ShowUserGuide(); IMPLOT_API void ShowUserGuide();
// Shows ImPlot metrics/debug information. // Shows ImPlot metrics/debug information window.
IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL); IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Demo (add implot_demo.cpp to your sources!) // Demo (add implot_demo.cpp to your sources!)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Shows the ImPlot demo. // Shows the ImPlot demo window.
IMPLOT_API void ShowDemoWindow(bool* p_open = NULL); IMPLOT_API void ShowDemoWindow(bool* p_open = NULL);
} // namespace ImPlot } // namespace ImPlot

View File

@ -595,6 +595,36 @@ void ShowDemoWindow(bool* p_open) {
static bool outliers = true; static bool outliers = true;
static double mu = 5; static double mu = 5;
static double sigma = 2; static double sigma = 2;
ImGui::SetNextItemWidth(200);
if (ImGui::RadioButton("Sqrt",bins==ImPlotBin_Sqrt)) { bins = ImPlotBin_Sqrt; } ImGui::SameLine();
if (ImGui::RadioButton("Sturges",bins==ImPlotBin_Sturges)) { bins = ImPlotBin_Sturges; } ImGui::SameLine();
if (ImGui::RadioButton("Rice",bins==ImPlotBin_Rice)) { bins = ImPlotBin_Rice; } ImGui::SameLine();
if (ImGui::RadioButton("Scott",bins==ImPlotBin_Scott)) { bins = ImPlotBin_Scott; } ImGui::SameLine();
if (ImGui::RadioButton("N Bins",bins>=0)) bins = 50;
if (bins>=0) {
ImGui::SameLine();
ImGui::SetNextItemWidth(200);
ImGui::SliderInt("##Bins", &bins, 1, 100);
}
if (ImGui::Checkbox("Density", &density))
ImPlot::FitNextPlotAxes();
ImGui::SameLine();
if (ImGui::Checkbox("Cumulative", &cumulative))
ImPlot::FitNextPlotAxes();
ImGui::SameLine();
static bool range = false;
ImGui::Checkbox("Range", &range);
static float rmin = -3;
static float rmax = 13;
if (range) {
ImGui::SameLine();
ImGui::SetNextItemWidth(200);
ImGui::DragFloat2("##Range",&rmin,0.1f,-3,13);
ImGui::SameLine();
ImGui::Checkbox("Outliers",&outliers);
}
static NormalDistribution<10000> dist(mu, sigma); static NormalDistribution<10000> dist(mu, sigma);
static double x[100]; static double x[100];
static double y[100]; static double y[100];
@ -610,32 +640,7 @@ void ShowDemoWindow(bool* p_open) {
y[i] /= y[99]; y[i] /= y[99];
} }
} }
ImGui::SetNextItemWidth(200);
if (ImGui::RadioButton("Sqrt",bins==ImPlotBin_Sqrt)) { bins = ImPlotBin_Sqrt; } ImGui::SameLine();
if (ImGui::RadioButton("Sturges",bins==ImPlotBin_Sturges)) { bins = ImPlotBin_Sturges; } ImGui::SameLine();
if (ImGui::RadioButton("Rice",bins==ImPlotBin_Rice)) { bins = ImPlotBin_Rice; } ImGui::SameLine();
if (ImGui::RadioButton("Scott",bins==ImPlotBin_Scott)) { bins = ImPlotBin_Scott; } ImGui::SameLine();
if (ImGui::RadioButton("N Bins",bins>=0)) bins = 50;
if (bins>=0) {
ImGui::SameLine();
ImGui::SetNextItemWidth(200);
ImGui::SliderInt("##Bins", &bins, 1, 100);
}
ImGui::Checkbox("Density", &density);
ImGui::SameLine();
ImGui::Checkbox("Cumulative", &cumulative);
ImGui::SameLine();
static bool range = false;
ImGui::Checkbox("Range", &range);
static float rmin = -3;
static float rmax = 13;
if (range) {
ImGui::SameLine();
ImGui::SetNextItemWidth(200);
ImGui::DragFloat2("##Range",&rmin,0.1f,-3,13);
ImGui::SameLine();
ImGui::Checkbox("Outliers",&outliers);
}
if (ImPlot::BeginPlot("##Histograms")) { if (ImPlot::BeginPlot("##Histograms")) {
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL, 0.5f); ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL, 0.5f);
ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, cumulative, density, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), outliers); ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, cumulative, density, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), outliers);
@ -1013,21 +1018,27 @@ void ShowDemoWindow(bool* p_open) {
y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f; y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f;
} }
ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls)."); ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls).");
ImPlot::SetNextPlotLimits(0,0.01,-1,1);
ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels; ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels;
ImPlotLimits query2; static bool use_selection = false;
ImGui::Checkbox("Use Box Selection",&use_selection);
bool is_viewed = false;
ImPlotLimits view;
ImPlot::SetNextPlotLimits(0,0.01,-1,1);
if (ImPlot::BeginPlot("##View1",NULL,NULL,ImVec2(-1,150), ImPlotFlags_Query, flags, flags)) { if (ImPlot::BeginPlot("##View1",NULL,NULL,ImVec2(-1,150), ImPlotFlags_Query, flags, flags)) {
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512); ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
query2 = ImPlot::GetPlotQuery(); is_viewed = use_selection ? ImPlot::IsPlotSelected() : ImPlot::IsPlotQueried();
view = use_selection ? ImPlot::GetPlotSelection() : ImPlot::GetPlotQuery();
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImPlot::SetNextPlotLimits(query2.X.Min, query2.X.Max, query2.Y.Min, query2.Y.Max, ImGuiCond_Always); ImPlot::SetNextPlotLimits(view.X.Min, view.X.Max, view.Y.Min, view.Y.Max, ImGuiCond_Always);
if (ImPlot::BeginPlot("##View2",NULL,NULL,ImVec2(-1,150), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { if (ImPlot::BeginPlot("##View2",NULL,NULL,ImVec2(-1,150), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) {
if (is_viewed) {
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512); ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
}
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }

View File

@ -669,12 +669,18 @@ struct ImPlotAxis
inline bool IsLabeled() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); } inline bool IsLabeled() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); } inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); } inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
inline bool IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; } inline bool IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
inline bool IsLockedMin() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMin) || IsRangeLocked(); }
inline bool IsLockedMax() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMax) || IsRangeLocked(); } inline bool IsLockedMin() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
inline bool IsLocked() const { return !Present || ((IsLockedMin() && IsLockedMax()) || IsRangeLocked()); } inline bool IsLockedMax() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); }
inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); }
inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); } inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); } inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); } inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
}; };
@ -720,10 +726,12 @@ struct ImPlotPlot
ImPlotLegendData LegendData; ImPlotLegendData LegendData;
ImPool<ImPlotItem> Items; ImPool<ImPlotItem> Items;
ImVec2 SelectStart; ImVec2 SelectStart;
ImRect SelectRect;
ImVec2 QueryStart; ImVec2 QueryStart;
ImRect QueryRect; ImRect QueryRect;
bool Initialized; bool Initialized;
bool Selecting; bool Selecting;
bool Selected;
bool ContextLocked; bool ContextLocked;
bool Querying; bool Querying;
bool Queried; bool Queried;
@ -750,7 +758,7 @@ struct ImPlotPlot
for (int i = 0; i < IMPLOT_Y_AXES; ++i) for (int i = 0; i < IMPLOT_Y_AXES; ++i)
YAxis[i].Orientation = ImPlotOrientation_Vertical; YAxis[i].Orientation = ImPlotOrientation_Vertical;
SelectStart = QueryStart = ImVec2(0,0); SelectStart = QueryStart = ImVec2(0,0);
Initialized = Selecting = ContextLocked = Querying = Queried = DraggingQuery = LegendHovered = LegendOutside = LegendFlipSideNextFrame = false; Initialized = Selecting = Selected = ContextLocked = Querying = Queried = DraggingQuery = LegendHovered = LegendOutside = LegendFlipSideNextFrame = false;
ColormapIdx = CurrentYAxis = 0; ColormapIdx = CurrentYAxis = 0;
LegendLocation = ImPlotLocation_North | ImPlotLocation_West; LegendLocation = ImPlotLocation_North | ImPlotLocation_West;
LegendOrientation = ImPlotOrientation_Vertical; LegendOrientation = ImPlotOrientation_Vertical;
@ -761,6 +769,7 @@ struct ImPlotPlot
ImPlotItem* GetLegendItem(int i); ImPlotItem* GetLegendItem(int i);
const char* GetLegendLabel(int i); const char* GetLegendLabel(int i);
inline bool AnyYLocked() const { return YAxis[0].IsInputLocked() || YAxis[1].Present ? YAxis[1].IsInputLocked() : false || YAxis[2].Present ? YAxis[2].IsInputLocked() : false; }
inline bool IsInputLocked() const { return XAxis.IsInputLocked() && YAxis[0].IsInputLocked() && YAxis[1].IsInputLocked() && YAxis[2].IsInputLocked(); } inline bool IsInputLocked() const { return XAxis.IsInputLocked() && YAxis[0].IsInputLocked() && YAxis[1].IsInputLocked() && YAxis[2].IsInputLocked(); }
}; };