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:
parent
5db2ba3b22
commit
ef6c55cd00
261
implot.cpp
261
implot.cpp
|
@ -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,71 +1787,81 @@ 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]) {
|
||||||
// bad selection
|
plot.Selected = plot.Selecting = false;
|
||||||
if (plot.Selecting && (ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) || plot.IsInputLocked()) && ImLengthSqr(plot.SelectStart - IO.MousePos) > 4) {
|
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
|
|
||||||
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
|
|
||||||
}
|
|
||||||
// cancel selection
|
|
||||||
if (plot.Selecting && (IO.MouseClicked[gp.InputMap.BoxSelectCancelButton] || IO.MouseDown[gp.InputMap.BoxSelectCancelButton])) {
|
|
||||||
plot.Selecting = false;
|
|
||||||
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
|
|
||||||
}
|
|
||||||
// begin selection or query
|
|
||||||
if (plot.FrameHovered && plot.PlotHovered && IO.MouseClicked[gp.InputMap.BoxSelectButton] && ImHasFlag(IO.KeyMods, gp.InputMap.BoxSelectMod)) {
|
|
||||||
plot.SelectStart = IO.MousePos;
|
|
||||||
plot.Selecting = true;
|
|
||||||
}
|
|
||||||
// update query
|
|
||||||
if (plot.Querying) {
|
|
||||||
UpdateTransformCache();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
// end query
|
|
||||||
if (plot.Querying && (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton])) {
|
|
||||||
plot.Querying = false;
|
|
||||||
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) {
|
|
||||||
plot.Queried = true;
|
|
||||||
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
|
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
|
||||||
}
|
}
|
||||||
else
|
else if (ImLengthSqr(d) > 4) {
|
||||||
plot.Queried = false;
|
// bad selection
|
||||||
|
if (ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) || plot.IsInputLocked()) {
|
||||||
|
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
|
||||||
|
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
|
||||||
|
plot.Selected = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const bool any_y_locked = plot.AnyYLocked();
|
||||||
|
// TODO: Handle only min or max locked cases
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
plot.Selected = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// begin query
|
// begin query
|
||||||
if (ImHasFlag(plot.Flags, ImPlotFlags_Query) && plot.FrameHovered && plot.PlotHovered && IO.MouseClicked[gp.InputMap.QueryButton] && ImHasFlag(IO.KeyMods, gp.InputMap.QueryMod)) {
|
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.Querying = true;
|
|
||||||
plot.Queried = true;
|
|
||||||
plot.QueryStart = IO.MousePos;
|
plot.QueryStart = IO.MousePos;
|
||||||
|
plot.QueryRect = ImRect(0,0,0,0);
|
||||||
}
|
}
|
||||||
// toggle between select/query
|
// update query
|
||||||
|
if (plot.Querying) {
|
||||||
|
UpdateTransformCache();
|
||||||
|
// confirm
|
||||||
|
if (IO.MouseReleased[gp.InputMap.QueryButton] || IO.MouseReleased[gp.InputMap.BoxSelectButton]) {
|
||||||
|
plot.Querying = false;
|
||||||
|
if (plot.QueryRect.GetWidth() > 2 && plot.QueryRect.GetHeight() > 2) {
|
||||||
|
plot.Queried = true;
|
||||||
|
plot.ContextLocked = gp.InputMap.BoxSelectButton == gp.InputMap.ContextMenuButton;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch select to 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.QueryStart = plot.SelectStart;
|
||||||
plot.Queried = true;
|
plot.QueryRect = plot.SelectRect;
|
||||||
plot.QueryStart = plot.SelectStart;
|
|
||||||
}
|
}
|
||||||
|
// 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 ImVec4 col = GetStyleColorVec4(ImPlotCol_Selection);
|
||||||
const ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart));
|
const ImU32 col_bg = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f));
|
||||||
const bool wide_enough = ImFabs(select_bb.GetWidth()) > 2;
|
const ImU32 col_bd = ImGui::GetColorU32(col);
|
||||||
const bool tall_enough = ImFabs(select_bb.GetHeight()) > 2;
|
DrawList.AddRectFilled(plot.SelectRect.Min + plot.PlotRect.Min, plot.SelectRect.Max + plot.PlotRect.Min, col_bg);
|
||||||
const bool big_enough = wide_enough && tall_enough;
|
DrawList.AddRect( plot.SelectRect.Min + plot.PlotRect.Min, plot.SelectRect.Max + plot.PlotRect.Min, col_bd);
|
||||||
if (plot.Selecting && !plot.IsInputLocked() && !ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect)) {
|
|
||||||
const ImVec4 col = GetStyleColorVec4(ImPlotCol_Selection);
|
|
||||||
const ImU32 col_bg = ImGui::GetColorU32(col * ImVec4(1,1,1,0.25f));
|
|
||||||
const ImU32 col_bd = ImGui::GetColorU32(col);
|
|
||||||
if (IO.KeyMods == (gp.InputMap.HorizontalMod | gp.InputMap.VerticalMod) && big_enough) {
|
|
||||||
DrawList.AddRectFilled(plot.PlotRect.Min, plot.PlotRect.Max, col_bg);
|
|
||||||
DrawList.AddRect( plot.PlotRect.Min, plot.PlotRect.Max, col_bd);
|
|
||||||
}
|
|
||||||
else if ((plot.XAxis.IsInputLocked() || IO.KeyMods == gp.InputMap.HorizontalMod) && tall_enough) {
|
|
||||||
DrawList.AddRectFilled(ImVec2(plot.PlotRect.Min.x, select_bb.Min.y), ImVec2(plot.PlotRect.Max.x, select_bb.Max.y), col_bg);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// render query
|
||||||
if (ImHasFlag(plot.Flags, ImPlotFlags_Query)) // draw query rect only when query enabled.
|
if (plot.Queried) {
|
||||||
{
|
|
||||||
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");
|
||||||
|
|
70
implot.h
70
implot.h
|
@ -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
|
||||||
|
|
|
@ -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)) {
|
||||||
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
|
if (is_viewed) {
|
||||||
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
|
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
|
||||||
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
|
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
|
||||||
|
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
|
||||||
|
}
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -667,16 +667,22 @@ struct ImPlotAxis
|
||||||
Range.Max = Range.Min + DBL_EPSILON;
|
Range.Max = Range.Min + DBL_EPSILON;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
|
inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
|
||||||
inline bool IsLockedMin() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMin) || IsRangeLocked(); }
|
inline bool IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
|
||||||
inline bool IsLockedMax() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMax) || IsRangeLocked(); }
|
|
||||||
inline bool IsLocked() const { return !Present || ((IsLockedMin() && IsLockedMax()) || IsRangeLocked()); }
|
inline bool IsLockedMin() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
|
||||||
inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
|
inline bool IsLockedMax() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
|
||||||
inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
|
inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); }
|
||||||
inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
|
|
||||||
|
inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); }
|
||||||
|
inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
|
||||||
|
inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
|
||||||
|
|
||||||
|
inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
|
||||||
|
inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// State information for Plot items
|
// State information for Plot items
|
||||||
|
@ -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,7 +769,8 @@ struct ImPlotPlot
|
||||||
ImPlotItem* GetLegendItem(int i);
|
ImPlotItem* GetLegendItem(int i);
|
||||||
const char* GetLegendLabel(int i);
|
const char* GetLegendLabel(int i);
|
||||||
|
|
||||||
inline bool IsInputLocked() const { return XAxis.IsInputLocked() && YAxis[0].IsInputLocked() && YAxis[1].IsInputLocked() && YAxis[2].IsInputLocked(); }
|
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(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Temporary data storage for upcoming plot
|
// Temporary data storage for upcoming plot
|
||||||
|
|
Loading…
Reference in New Issue
Block a user