mirror of
https://github.com/gwm17/implot.git
synced 2025-02-16 19:08:50 -05:00
tidy up multi y axis support
This commit is contained in:
parent
bece676929
commit
329ad9dd80
218
implot.cpp
218
implot.cpp
|
@ -20,7 +20,26 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// ImPlot v0.1 WIP
|
||||
// ImPlot v0.2 WIP
|
||||
|
||||
/*
|
||||
|
||||
API BREAKING CHANGES
|
||||
====================
|
||||
Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.
|
||||
Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code.
|
||||
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
|
||||
You can read releases logs https://github.com/epezent/implot/releases for more details.
|
||||
|
||||
- 2020/05/10 (0.2) - The following function/struct names were changes:
|
||||
- ImPlotRange -> ImPlotLimits
|
||||
- GetPlotRange() -> GetPlotLimits()
|
||||
- SetNextPlotRange -> SetNextPlotLimits
|
||||
- SetNextPlotRangeX -> SetNextPlotLimitsX
|
||||
- SetNextPlotRangeY -> SetNextPlotLimitsY
|
||||
- 2020/05/10 (0.2) - Plot queries are pixel based by default. Query rects that maintain relative plot position have been removed. This was done to support multi-y-axis.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
|
@ -30,6 +49,7 @@
|
|||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
|
||||
|
||||
#include <implot.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
|
@ -45,6 +65,8 @@
|
|||
|
||||
// Special Color used to specific that a plot item color should set determined automatically.
|
||||
#define IM_COL_AUTO ImVec4(0,0,0,-1)
|
||||
// The maximum number of support y-axes
|
||||
#define MAX_Y_AXES 3
|
||||
|
||||
ImPlotStyle::ImPlotStyle() {
|
||||
LineWeight = 1;
|
||||
|
@ -65,8 +87,8 @@ ImPlotStyle::ImPlotStyle() {
|
|||
Colors[ImPlotCol_PlotBorder] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_XAxis] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_YAxis] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_Y2Axis] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_Y3Axis] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_YAxis2] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_YAxis3] = IM_COL_AUTO;
|
||||
Colors[ImPlotCol_Selection] = ImVec4(1,1,0,1);
|
||||
Colors[ImPlotCol_Query] = ImVec4(0,1,0,1);
|
||||
}
|
||||
|
@ -81,9 +103,9 @@ float ImPlotRange::Size() const {
|
|||
return Max - Min;
|
||||
}
|
||||
|
||||
ImPlotBounds::ImPlotBounds() {}
|
||||
ImPlotLimits::ImPlotLimits() {}
|
||||
|
||||
bool ImPlotBounds::Contains(const ImVec2& p) const {
|
||||
bool ImPlotLimits::Contains(const ImVec2& p) const {
|
||||
return X.Contains(p.x) && Y.Contains(p.y);
|
||||
}
|
||||
|
||||
|
@ -91,8 +113,6 @@ namespace ImGui {
|
|||
|
||||
namespace {
|
||||
|
||||
#define MAX_Y_AXES 3
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -242,13 +262,13 @@ struct ImPlotAxis {
|
|||
Range.Max = 1;
|
||||
Divisions = 3;
|
||||
Subdivisions = 10;
|
||||
Flags = ImAxisFlags_Default;
|
||||
Flags = PreviousFlags = ImAxisFlags_Default;
|
||||
}
|
||||
bool Dragging;
|
||||
ImPlotRange Range;
|
||||
int Divisions;
|
||||
int Subdivisions;
|
||||
ImAxisFlags Flags;
|
||||
ImAxisFlags Flags, PreviousFlags;
|
||||
};
|
||||
|
||||
/// Holds Plot state information that must persist between frames
|
||||
|
@ -256,7 +276,7 @@ struct ImPlot {
|
|||
ImPlot() {
|
||||
Selecting = Querying = Queried = DraggingQuery = false;
|
||||
SelectStart = QueryStart = ImVec2(0,0);
|
||||
Flags = ImPlotFlags_Default;
|
||||
Flags = PreviousFlags = ImPlotFlags_Default;
|
||||
ColorIdx = 0;
|
||||
CurrentYAxis = 0;
|
||||
}
|
||||
|
@ -274,17 +294,17 @@ struct ImPlot {
|
|||
ImPlotAxis XAxis;
|
||||
ImPlotAxis YAxis[MAX_Y_AXES];
|
||||
|
||||
ImPlotFlags Flags;
|
||||
ImPlotFlags Flags, PreviousFlags;
|
||||
int ColorIdx;
|
||||
int CurrentYAxis;
|
||||
};
|
||||
|
||||
struct ImNextPlotData {
|
||||
ImNextPlotData() : HasXBounds{}, HasYBounds{} {}
|
||||
ImGuiCond XBoundsCond;
|
||||
ImGuiCond YBoundsCond[MAX_Y_AXES];
|
||||
bool HasXBounds;
|
||||
bool HasYBounds[MAX_Y_AXES];
|
||||
ImNextPlotData() : HasXRange{}, HasYRange{} {}
|
||||
ImGuiCond XRangeCond;
|
||||
ImGuiCond YRangeCond[MAX_Y_AXES];
|
||||
bool HasXRange;
|
||||
bool HasYRange[MAX_Y_AXES];
|
||||
ImPlotRange X;
|
||||
ImPlotRange Y[MAX_Y_AXES];
|
||||
};
|
||||
|
@ -642,7 +662,7 @@ ImRect GetAxisScale(int y_axis, float tx, float ty, float zoom_rate) {
|
|||
|
||||
class YPadCalculator {
|
||||
public:
|
||||
YPadCalculator(const AxisState* axis_states, const float* max_label_widths, int txt_off)
|
||||
YPadCalculator(const AxisState* axis_states, const float* max_label_widths, float txt_off)
|
||||
: AxisStates(axis_states), MaxLabelWidths(max_label_widths), TxtOff(txt_off) {}
|
||||
|
||||
float operator()(int y_axis) {
|
||||
|
@ -650,9 +670,9 @@ class YPadCalculator {
|
|||
if (!AxisStates[y_axis].present) { return 0; }
|
||||
// If we have more than 1 axis present before us, then we need
|
||||
// extra space to account for our tick bar.
|
||||
int pad_result = 0;
|
||||
float pad_result = 0;
|
||||
if (AxisStates[y_axis].present_so_far >= 3) {
|
||||
pad_result += 6;
|
||||
pad_result += 6.0f;
|
||||
}
|
||||
if (!HasFlag(plot.YAxis[y_axis].Flags, ImAxisFlags_TickLabels)) {
|
||||
return pad_result;
|
||||
|
@ -664,7 +684,7 @@ class YPadCalculator {
|
|||
private:
|
||||
const AxisState* const AxisStates;
|
||||
const float* const MaxLabelWidths;
|
||||
const int TxtOff;
|
||||
const float TxtOff;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
@ -695,13 +715,31 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
|
||||
plot.CurrentYAxis = 0;
|
||||
|
||||
plot.Flags = flags;
|
||||
if (just_created) {
|
||||
plot.XAxis.Flags = x_flags;
|
||||
plot.Flags = flags;
|
||||
plot.XAxis.Flags = x_flags;
|
||||
plot.YAxis[0].Flags = y_flags;
|
||||
plot.YAxis[1].Flags = y2_flags;
|
||||
plot.YAxis[2].Flags = y3_flags;
|
||||
}
|
||||
else {
|
||||
// TODO: Check which individual flags changed, and only reset those!
|
||||
// There's probably an easy bit mask trick I'm not aware of.
|
||||
if (flags != plot.PreviousFlags)
|
||||
plot.Flags = flags;
|
||||
if (y_flags != plot.YAxis[0].PreviousFlags)
|
||||
plot.YAxis[0].PreviousFlags = y_flags;
|
||||
if (y2_flags != plot.YAxis[1].PreviousFlags)
|
||||
plot.YAxis[1].PreviousFlags = y2_flags;
|
||||
if (y3_flags != plot.YAxis[2].PreviousFlags)
|
||||
plot.YAxis[2].PreviousFlags = y3_flags;
|
||||
}
|
||||
|
||||
plot.PreviousFlags = flags;
|
||||
plot.XAxis.PreviousFlags = x_flags;
|
||||
plot.YAxis[0].PreviousFlags = y_flags;
|
||||
plot.YAxis[1].PreviousFlags = y2_flags;
|
||||
plot.YAxis[2].PreviousFlags = y3_flags;
|
||||
|
||||
// capture scroll with a child region
|
||||
if (!HasFlag(plot.Flags, ImPlotFlags_NoChild)) {
|
||||
|
@ -714,16 +752,16 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
|
||||
// NextPlotData -----------------------------------------------------------
|
||||
|
||||
if (gp.NextPlotData.HasXBounds) {
|
||||
if (just_created || gp.NextPlotData.XBoundsCond == ImGuiCond_Always)
|
||||
if (gp.NextPlotData.HasXRange) {
|
||||
if (just_created || gp.NextPlotData.XRangeCond == ImGuiCond_Always)
|
||||
{
|
||||
plot.XAxis.Range = gp.NextPlotData.X;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||
if (gp.NextPlotData.HasYBounds[i]) {
|
||||
if (just_created || gp.NextPlotData.YBoundsCond[i] == ImGuiCond_Always)
|
||||
if (gp.NextPlotData.HasYRange[i]) {
|
||||
if (just_created || gp.NextPlotData.YRangeCond[i] == ImGuiCond_Always)
|
||||
{
|
||||
plot.YAxis[i].Range = gp.NextPlotData.Y[i];
|
||||
}
|
||||
|
@ -731,13 +769,13 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
}
|
||||
|
||||
// AXIS STATES ------------------------------------------------------------
|
||||
AxisState x(plot.XAxis, gp.NextPlotData.HasXBounds, gp.NextPlotData.XBoundsCond, true, 0);
|
||||
AxisState x(plot.XAxis, gp.NextPlotData.HasXRange, gp.NextPlotData.XRangeCond, true, 0);
|
||||
AxisState y[MAX_Y_AXES];
|
||||
y[0] = AxisState(plot.YAxis[0], gp.NextPlotData.HasYBounds[0], gp.NextPlotData.YBoundsCond[0], true, 0);
|
||||
y[1] = AxisState(plot.YAxis[1], gp.NextPlotData.HasYBounds[1], gp.NextPlotData.YBoundsCond[1],
|
||||
HasFlag(plot.Flags, ImPlotFlags_Y2Axis), y[0].present_so_far);
|
||||
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYBounds[2], gp.NextPlotData.YBoundsCond[2],
|
||||
HasFlag(plot.Flags, ImPlotFlags_Y3Axis), y[1].present_so_far);
|
||||
y[0] = AxisState(plot.YAxis[0], gp.NextPlotData.HasYRange[0], gp.NextPlotData.YRangeCond[0], true, 0);
|
||||
y[1] = AxisState(plot.YAxis[1], gp.NextPlotData.HasYRange[1], gp.NextPlotData.YRangeCond[1],
|
||||
HasFlag(plot.Flags, ImPlotFlags_YAxis2), y[0].present_so_far);
|
||||
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
|
||||
HasFlag(plot.Flags, ImPlotFlags_YAxis3), y[1].present_so_far);
|
||||
|
||||
const bool lock_plot = x.lock && y[0].lock && y[1].lock && y[2].lock;
|
||||
|
||||
|
@ -790,8 +828,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
|
||||
UpdateAxisColor(ImPlotCol_XAxis, &gp.Col_X);
|
||||
UpdateAxisColor(ImPlotCol_YAxis, &gp.Col_Y[0]);
|
||||
UpdateAxisColor(ImPlotCol_Y2Axis, &gp.Col_Y[1]);
|
||||
UpdateAxisColor(ImPlotCol_Y3Axis, &gp.Col_Y[2]);
|
||||
UpdateAxisColor(ImPlotCol_YAxis2, &gp.Col_Y[1]);
|
||||
UpdateAxisColor(ImPlotCol_YAxis3, &gp.Col_Y[2]);
|
||||
|
||||
gp.Col_Txt = GetColorU32(ImGuiCol_Text);
|
||||
gp.Col_TxtDis = GetColorU32(ImGuiCol_TextDisabled);
|
||||
|
@ -866,7 +904,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
gp.Hov_Grid = gp.BB_Grid.Contains(IO.MousePos);
|
||||
|
||||
// axis region bbs
|
||||
const ImRect xAxisRegion_bb(gp.BB_Grid.Min + ImVec2(10, 0), {gp.BB_Grid.Max.x, gp.BB_Frame.Max.y});
|
||||
const ImRect xAxisRegion_bb(gp.BB_Grid.Min + ImVec2(10, 0), ImVec2(gp.BB_Grid.Max.x, gp.BB_Frame.Max.y) - ImVec2(10, 0));
|
||||
const bool hov_x_axis_region = xAxisRegion_bb.Contains(IO.MousePos);
|
||||
|
||||
// The left labels are referenced to the left of the bounding box.
|
||||
|
@ -897,14 +935,13 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
y[1].present && (yAxisRegion_bb[1].Contains(IO.MousePos) || centralRegion.Contains(IO.MousePos)),
|
||||
y[2].present && (yAxisRegion_bb[2].Contains(IO.MousePos) || centralRegion.Contains(IO.MousePos)),
|
||||
};
|
||||
const bool any_hov_y_axis_region =
|
||||
hov_y_axis_region[0] || hov_y_axis_region[1] || hov_y_axis_region[2];
|
||||
const bool any_hov_y_axis_region = hov_y_axis_region[0] || hov_y_axis_region[1] || hov_y_axis_region[2];
|
||||
|
||||
// legend hovered from last frame
|
||||
const bool hov_legend = HasFlag(plot.Flags, ImPlotFlags_Legend) ? gp.Hov_Frame && plot.BB_Legend.Contains(IO.MousePos) : false;
|
||||
|
||||
bool hov_query = false;
|
||||
if (plot.Queried && !plot.Querying) {
|
||||
if (gp.Hov_Frame && gp.Hov_Grid && plot.Queried && !plot.Querying) {
|
||||
ImRect bb_query = plot.QueryRect;
|
||||
|
||||
bb_query.Min += gp.BB_Grid.Min;
|
||||
|
@ -922,10 +959,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
plot.QueryRect.Min += IO.MouseDelta;
|
||||
plot.QueryRect.Max += IO.MouseDelta;
|
||||
}
|
||||
if (gp.Hov_Frame && hov_query && !plot.DraggingQuery && !plot.Selecting && !hov_legend) {
|
||||
if (gp.Hov_Frame && gp.Hov_Grid && hov_query && !plot.DraggingQuery && !plot.Selecting && !hov_legend) {
|
||||
SetMouseCursor(ImGuiMouseCursor_ResizeAll);
|
||||
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;
|
||||
if (IO.MouseDown[0] && !plot.XAxis.Dragging && !any_y_dragging) {
|
||||
plot.DraggingQuery = true;
|
||||
}
|
||||
|
@ -933,6 +969,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
|
||||
// DRAG INPUT -------------------------------------------------------------
|
||||
|
||||
|
||||
// end drags
|
||||
if (plot.XAxis.Dragging && (IO.MouseReleased[0] || !IO.MouseDown[0])) {
|
||||
plot.XAxis.Dragging = false;
|
||||
|
@ -944,11 +981,10 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
G.IO.MouseDragMaxDistanceSqr[0] = 0;
|
||||
}
|
||||
}
|
||||
const bool any_y_dragging = plot.YAxis[0].Dragging || plot.YAxis[1].Dragging || plot.YAxis[2].Dragging;
|
||||
bool drag_in_progress = plot.XAxis.Dragging || any_y_dragging;
|
||||
// do drag
|
||||
const bool any_y_dragging =
|
||||
plot.YAxis[0].Dragging || plot.YAxis[1].Dragging || plot.YAxis[2].Dragging;
|
||||
|
||||
if (plot.XAxis.Dragging || any_y_dragging) {
|
||||
if (drag_in_progress) {
|
||||
UpdateTransformCache();
|
||||
if (!x.lock && plot.XAxis.Dragging) {
|
||||
ImVec2 plot_tl = PixelsToPlot(gp.BB_Grid.Min - IO.MouseDelta, 0);
|
||||
|
@ -993,7 +1029,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
}
|
||||
}
|
||||
// start drag
|
||||
if (gp.Hov_Frame && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) {
|
||||
if (!drag_in_progress && gp.Hov_Frame && IO.MouseDragMaxDistanceSqr[0] > 5 && !plot.Selecting && !hov_legend && !hov_query && !plot.DraggingQuery) {
|
||||
if (hov_x_axis_region) {
|
||||
plot.XAxis.Dragging = true;
|
||||
}
|
||||
|
@ -1051,6 +1087,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
if (!x.lock_max && !IO.KeyAlt)
|
||||
plot.XAxis.Range.Max = ImMax(p1.x, p2.x);
|
||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||
p1 = PixelsToPlot(plot.SelectStart, i);
|
||||
p2 = PixelsToPlot(IO.MousePos, i);
|
||||
if (!y[i].lock_min && !IO.KeyShift)
|
||||
plot.YAxis[i].Range.Min = ImMin(p1.y, p2.y);
|
||||
if (!y[i].lock_max && !IO.KeyShift)
|
||||
|
@ -1094,21 +1132,21 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
}
|
||||
}
|
||||
// begin query
|
||||
if ((gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[2])) {
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_Query) && (gp.Hov_Frame && gp.Hov_Grid && IO.MouseClicked[2])) {
|
||||
plot.QueryRect = ImRect(0,0,0,0);
|
||||
plot.Querying = true;
|
||||
plot.Queried = true;
|
||||
plot.QueryStart = IO.MousePos;
|
||||
}
|
||||
// toggle between select/query
|
||||
if (plot.Selecting && IO.KeyCtrl) {
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_Query) && plot.Selecting && IO.KeyCtrl) {
|
||||
plot.Selecting = false;
|
||||
plot.QueryRect = ImRect(0,0,0,0);
|
||||
plot.Querying = true;
|
||||
plot.Queried = true;
|
||||
plot.QueryStart = plot.SelectStart;
|
||||
}
|
||||
if (plot.Querying && !IO.KeyCtrl && !IO.MouseDown[2]) {
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_Selection) && plot.Querying && !IO.KeyCtrl && !IO.MouseDown[2]) {
|
||||
plot.Selecting = true;
|
||||
plot.Querying = false;
|
||||
plot.Queried = false;
|
||||
|
@ -1203,7 +1241,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
PushClipRect(gp.BB_Frame.Min, gp.BB_Frame.Max, true);
|
||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||
if (y[i].present && HasFlag(plot.YAxis[i].Flags, ImAxisFlags_TickLabels)) {
|
||||
const int x_start =
|
||||
const float x_start =
|
||||
gp.AxisLabelReference[i] +
|
||||
((i == 0) ?
|
||||
(-txt_off - max_label_width[0]) :
|
||||
|
@ -1301,10 +1339,10 @@ void PlotContextMenu(ImPlot& plot) {
|
|||
ImGui::EndMenu();
|
||||
}
|
||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||
if (i == 1 && !HasFlag(plot.Flags, ImPlotFlags_Y2Axis)) {
|
||||
if (i == 1 && !HasFlag(plot.Flags, ImPlotFlags_YAxis2)) {
|
||||
continue;
|
||||
}
|
||||
if (i == 2 && !HasFlag(plot.Flags, ImPlotFlags_Y3Axis)) {
|
||||
if (i == 2 && !HasFlag(plot.Flags, ImPlotFlags_YAxis3)) {
|
||||
continue;
|
||||
}
|
||||
char buf[10] = {};
|
||||
|
@ -1396,13 +1434,13 @@ void EndPlot() {
|
|||
|
||||
// AXIS STATES ------------------------------------------------------------
|
||||
|
||||
AxisState x(plot.XAxis, gp.NextPlotData.HasXBounds, gp.NextPlotData.XBoundsCond, true, 0);
|
||||
AxisState x(plot.XAxis, gp.NextPlotData.HasXRange, gp.NextPlotData.XRangeCond, true, 0);
|
||||
AxisState y[MAX_Y_AXES];
|
||||
y[0] = AxisState(plot.YAxis[0], gp.NextPlotData.HasYBounds[0], gp.NextPlotData.YBoundsCond[0], true, 0);
|
||||
y[1] = AxisState(plot.YAxis[1], gp.NextPlotData.HasYBounds[1], gp.NextPlotData.YBoundsCond[1],
|
||||
HasFlag(plot.Flags, ImPlotFlags_Y2Axis), y[0].present_so_far);
|
||||
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYBounds[2], gp.NextPlotData.YBoundsCond[2],
|
||||
HasFlag(plot.Flags, ImPlotFlags_Y3Axis), y[1].present_so_far);
|
||||
y[0] = AxisState(plot.YAxis[0], gp.NextPlotData.HasYRange[0], gp.NextPlotData.YRangeCond[0], true, 0);
|
||||
y[1] = AxisState(plot.YAxis[1], gp.NextPlotData.HasYRange[1], gp.NextPlotData.YRangeCond[1],
|
||||
HasFlag(plot.Flags, ImPlotFlags_YAxis2), y[0].present_so_far);
|
||||
y[2] = AxisState(plot.YAxis[2], gp.NextPlotData.HasYRange[2], gp.NextPlotData.YRangeCond[2],
|
||||
HasFlag(plot.Flags, ImPlotFlags_YAxis3), y[1].present_so_far);
|
||||
|
||||
const bool lock_plot = x.lock && y[0].lock && y[1].lock && y[2].lock;
|
||||
const bool any_y_locked = y[0].lock || y[1].lock || y[2].lock;
|
||||
|
@ -1413,10 +1451,14 @@ void EndPlot() {
|
|||
PushClipRect(gp.BB_Grid.Min, gp.BB_Frame.Max, true);
|
||||
|
||||
// render ticks
|
||||
PushPlotClipRect();
|
||||
if (HasFlag(plot.XAxis.Flags, ImAxisFlags_TickMarks)) {
|
||||
for (ImTick &xt : gp.XTicks)
|
||||
DrawList.AddLine({xt.PixelPos, gp.BB_Grid.Max.y},{xt.PixelPos, gp.BB_Grid.Max.y - (xt.Major ? 10.0f : 5.0f)}, gp.Col_Border, 1);
|
||||
}
|
||||
PopPlotClipRect();
|
||||
|
||||
PushClipRect(gp.BB_Grid.Min, {gp.BB_Frame.Max.x, gp.BB_Grid.Max.y}, true);
|
||||
int axis_count = 0;
|
||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||
if (!y[i].present) { continue; }
|
||||
|
@ -1425,7 +1467,7 @@ void EndPlot() {
|
|||
if (!HasFlag(plot.YAxis[i].Flags, ImAxisFlags_TickMarks)) { continue; }
|
||||
|
||||
float x_start = gp.AxisLabelReference[i];
|
||||
float direction = (i == 0) ? 1.0 : -1.0;
|
||||
float direction = (i == 0) ? 1.0f : -1.0f;
|
||||
bool no_major = axis_count >= 3;
|
||||
|
||||
for (ImTick &yt : gp.YTicks[i]) {
|
||||
|
@ -1446,6 +1488,9 @@ void EndPlot() {
|
|||
}
|
||||
}
|
||||
|
||||
PopClipRect();
|
||||
|
||||
PushPlotClipRect();
|
||||
// render selection/query
|
||||
if (plot.Selecting) {
|
||||
ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart));
|
||||
|
@ -1568,18 +1613,18 @@ void EndPlot() {
|
|||
BufferWriter writer(buffer, sizeof(buffer));
|
||||
|
||||
writer.Write("%.2f,%.2f", gp.LastMousePos[0].x, gp.LastMousePos[0].y);
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_Y2Axis)) {
|
||||
writer.Write(", (%.2f)", gp.LastMousePos[1].y);
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_YAxis2)) {
|
||||
writer.Write(",(%.2f)", gp.LastMousePos[1].y);
|
||||
}
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_Y3Axis)) {
|
||||
writer.Write(", (%.2f)", gp.LastMousePos[2].y);
|
||||
if (HasFlag(plot.Flags, ImPlotFlags_YAxis3)) {
|
||||
writer.Write(",(%.2f)", gp.LastMousePos[2].y);
|
||||
}
|
||||
ImVec2 size = CalcTextSize(buffer);
|
||||
ImVec2 pos = gp.BB_Grid.Max - size - ImVec2(5, 5);
|
||||
DrawList.AddText(pos, gp.Col_Txt, buffer);
|
||||
}
|
||||
|
||||
PopClipRect();
|
||||
PopPlotClipRect();
|
||||
|
||||
// render border
|
||||
DrawList.AddRect(gp.BB_Grid.Min, gp.BB_Grid.Max, gp.Col_Border);
|
||||
|
@ -1630,24 +1675,24 @@ void EndPlot() {
|
|||
// MISC API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SetNextPlotBounds(float x_min, float x_max, float y_min, float y_max, ImGuiCond cond) {
|
||||
SetNextPlotBoundsX(x_min, x_max, cond);
|
||||
SetNextPlotBoundsY(y_min, y_max, cond);
|
||||
void SetNextPlotLimits(float x_min, float x_max, float y_min, float y_max, ImGuiCond cond) {
|
||||
SetNextPlotLimitsX(x_min, x_max, cond);
|
||||
SetNextPlotLimitsY(y_min, y_max, cond);
|
||||
}
|
||||
|
||||
void SetNextPlotBoundsX(float x_min, float x_max, ImGuiCond cond) {
|
||||
void SetNextPlotLimitsX(float x_min, float x_max, ImGuiCond cond) {
|
||||
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
||||
gp.NextPlotData.HasXBounds = true;
|
||||
gp.NextPlotData.XBoundsCond = cond;
|
||||
gp.NextPlotData.HasXRange = true;
|
||||
gp.NextPlotData.XRangeCond = cond;
|
||||
gp.NextPlotData.X.Min = x_min;
|
||||
gp.NextPlotData.X.Max = x_max;
|
||||
}
|
||||
|
||||
void SetNextPlotBoundsY(float y_min, float y_max, ImGuiCond cond, int y_axis) {
|
||||
void SetNextPlotLimitsY(float y_min, float y_max, ImGuiCond cond, int y_axis) {
|
||||
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < MAX_Y_AXES, "y_axis Needs to be between 0 and MAX_Y_AXES");
|
||||
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
||||
gp.NextPlotData.HasYBounds[y_axis] = true;
|
||||
gp.NextPlotData.YBoundsCond[y_axis] = cond;
|
||||
gp.NextPlotData.HasYRange[y_axis] = true;
|
||||
gp.NextPlotData.YRangeCond[y_axis] = cond;
|
||||
gp.NextPlotData.Y[y_axis].Min = y_min;
|
||||
gp.NextPlotData.Y[y_axis].Max = y_max;
|
||||
}
|
||||
|
@ -1689,16 +1734,16 @@ ImVec2 GetPlotMousePos(int y_axis_in) {
|
|||
}
|
||||
|
||||
|
||||
ImPlotBounds GetPlotBounds(int y_axis_in) {
|
||||
ImPlotLimits GetPlotLimits(int y_axis_in) {
|
||||
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES");
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotBounds() Needs to be called between BeginPlot() and EndPlot()!");
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() Needs to be called between BeginPlot() and EndPlot()!");
|
||||
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||
|
||||
ImPlot& plot = *gp.CurrentPlot;
|
||||
ImPlotBounds bounds;
|
||||
bounds.X = plot.XAxis.Range;
|
||||
bounds.Y = plot.YAxis[y_axis].Range;
|
||||
return bounds;
|
||||
ImPlotLimits limits;
|
||||
limits.X = plot.XAxis.Range;
|
||||
limits.Y = plot.YAxis[y_axis].Range;
|
||||
return limits;
|
||||
}
|
||||
|
||||
bool IsPlotQueried() {
|
||||
|
@ -1706,7 +1751,7 @@ bool IsPlotQueried() {
|
|||
return gp.CurrentPlot->Queried;
|
||||
}
|
||||
|
||||
ImPlotBounds GetPlotQuery(int y_axis_in) {
|
||||
ImPlotLimits GetPlotQuery(int y_axis_in) {
|
||||
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < MAX_Y_AXES, "y_axis needs to between -1 and MAX_Y_AXES");
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() Needs to be called between BeginPlot() and EndPlot()!");
|
||||
ImPlot& plot = *gp.CurrentPlot;
|
||||
|
@ -1716,12 +1761,11 @@ ImPlotBounds GetPlotQuery(int y_axis_in) {
|
|||
ImVec2 p1 = PixelsToPlot(plot.QueryRect.Min + gp.BB_Grid.Min, y_axis);
|
||||
ImVec2 p2 = PixelsToPlot(plot.QueryRect.Max + gp.BB_Grid.Min, y_axis);
|
||||
|
||||
ImPlotBounds result;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2520,10 +2564,10 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of
|
|||
if (count > 1 && rend_line) {
|
||||
//
|
||||
const float mx = (gp.PixelRange[ax].Max.x - gp.PixelRange[ax].Min.x) / gp.CurrentPlot->XAxis.Range.Size();
|
||||
int pixY_0 = line_weight;
|
||||
int pixY_1 = gp.Style.DigitalBitHeight;
|
||||
int pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label
|
||||
int pixY_chOffset = pixY_1 + 3; //3 pixels between channels
|
||||
float pixY_0 = line_weight;
|
||||
float pixY_1 = gp.Style.DigitalBitHeight;
|
||||
float pixY_Offset = 20;//20 pixel from bottom due to mouse cursor label
|
||||
float pixY_chOffset = pixY_1 + 3; //3 pixels between channels
|
||||
ImVec2 pMin, pMax;
|
||||
float y0 = (gp.PixelRange[ax].Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_0 - pixY_Offset);
|
||||
float y1 = (gp.PixelRange[ax].Min.y) + ((-pixY_chOffset * gp.DigitalPlotItemCnt) - pixY_1 - pixY_Offset);
|
||||
|
@ -2554,7 +2598,7 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of
|
|||
//plot a rectangle that extends up to x2 with y1 height
|
||||
if ((pMax.x > pMin.x) && (!cull || gp.BB_Grid.Contains(pMin) || gp.BB_Grid.Contains(pMax))) {
|
||||
ImVec4 colAlpha = item->Color;
|
||||
colAlpha.w = item->Highlight ? 1.0 : 0.9;
|
||||
colAlpha.w = item->Highlight ? 1.0f : 0.9f;
|
||||
DrawList.AddRectFilled(pMin, pMax, GetColorU32(colAlpha));
|
||||
}
|
||||
}
|
||||
|
|
78
implot.h
78
implot.h
|
@ -20,7 +20,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// ImPlot v0.1 WIP
|
||||
// ImPlot v0.2 WIP
|
||||
|
||||
#pragma once
|
||||
#include <imgui.h>
|
||||
|
@ -41,13 +41,14 @@ enum ImPlotFlags_ {
|
|||
ImPlotFlags_Legend = 1 << 1, // a legend will be displayed in the top-left
|
||||
ImPlotFlags_Highlight = 1 << 2, // plot items will be highlighted when their legend entry is hovered
|
||||
ImPlotFlags_Selection = 1 << 3, // the user will be able to box-select with right-mouse
|
||||
ImPlotFlags_ContextMenu = 1 << 4, // the user will be able to open a context menu with double-right click
|
||||
ImPlotFlags_Crosshairs = 1 << 5, // the default mouse cursor will be replaced with a crosshair when hovered
|
||||
ImPlotFlags_CullData = 1 << 6, // plot data outside the plot area will be culled from rendering
|
||||
ImPlotFlags_AntiAliased = 1 << 7, // lines and fills will be anti-aliased (not recommended)
|
||||
ImPlotFlags_NoChild = 1 << 8, // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications)
|
||||
ImPlotFlags_Y2Axis = 1 << 9, // enable a second y axis
|
||||
ImPlotFlags_Y3Axis = 1 << 10, // enable a third y axis
|
||||
ImPlotFlags_Query = 1 << 4, // the user will be able to draw query rects with middle-mouse
|
||||
ImPlotFlags_ContextMenu = 1 << 5, // the user will be able to open a context menu with double-right click
|
||||
ImPlotFlags_Crosshairs = 1 << 6, // the default mouse cursor will be replaced with a crosshair when hovered
|
||||
ImPlotFlags_CullData = 1 << 7, // plot data outside the plot area will be culled from rendering
|
||||
ImPlotFlags_AntiAliased = 1 << 8, // lines and fills will be anti-aliased (not recommended)
|
||||
ImPlotFlags_NoChild = 1 << 9, // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications)
|
||||
ImPlotFlags_YAxis2 = 1 << 10, // enable a 2nd y axis
|
||||
ImPlotFlags_YAxis3 = 1 << 11, // enable a 3rd y axis
|
||||
ImPlotFlags_Default = ImPlotFlags_MousePos | ImPlotFlags_Legend | ImPlotFlags_Highlight | ImPlotFlags_Selection | ImPlotFlags_ContextMenu | ImPlotFlags_CullData
|
||||
};
|
||||
|
||||
|
@ -63,7 +64,7 @@ enum ImAxisFlags_ {
|
|||
ImAxisFlags_LogScale = 1 << 7, // a logartithmic (base 10) axis scale will be used
|
||||
ImAxisFlags_Scientific = 1 << 8, // scientific notation will be used for tick labels if displayed (WIP, not very good yet)
|
||||
ImAxisFlags_Default = ImAxisFlags_GridLines | ImAxisFlags_TickMarks | ImAxisFlags_TickLabels | ImAxisFlags_Adaptive,
|
||||
ImAxisFlags_Auxiliary_Default = ImAxisFlags_Default & ~ImAxisFlags_GridLines,
|
||||
ImAxisFlags_Auxiliary = ImAxisFlags_Default & ~ImAxisFlags_GridLines,
|
||||
};
|
||||
|
||||
// Plot styling colors
|
||||
|
@ -76,15 +77,16 @@ enum ImPlotCol_ {
|
|||
ImPlotCol_FrameBg, // plot frame background color (defaults to ImGuiCol_FrameBg)
|
||||
ImPlotCol_PlotBg, // plot area background color (defaults to ImGuiCol_WindowBg)
|
||||
ImPlotCol_PlotBorder, // plot area border color (defaults to ImGuiCol_Text)
|
||||
ImPlotCol_XAxis, // x-axis grid/label color (defaults to ImGuiCol_Text)
|
||||
ImPlotCol_YAxis, // y-axis grid/label color (defaults to ImGuiCol_Text)
|
||||
ImPlotCol_Y2Axis, // y2-axis grid/label color (defaults to ImGuiCol_Text)
|
||||
ImPlotCol_Y3Axis, // y3-axis grid/label color (defaults to ImGuiCol_Text)
|
||||
ImPlotCol_XAxis, // x-axis grid/label color (defaults to 25% ImGuiCol_Text)
|
||||
ImPlotCol_YAxis, // y-axis grid/label color (defaults to 25% ImGuiCol_Text)
|
||||
ImPlotCol_YAxis2, // 2nd y-axis grid/label color (defaults to 25% ImGuiCol_Text)
|
||||
ImPlotCol_YAxis3, // 3rd y-axis grid/label color (defaults to 25% ImGuiCol_Text)
|
||||
ImPlotCol_Selection, // box-selection color (defaults to yellow)
|
||||
ImPlotCol_Query, // box-query color (defaults to green)
|
||||
ImPlotCol_COUNT
|
||||
};
|
||||
|
||||
// Plot styling variables
|
||||
enum ImPlotStyleVar_ {
|
||||
ImPlotStyleVar_LineWeight, // float, line weight in pixels
|
||||
ImPlotStyleVar_Marker, // int, marker specification
|
||||
|
@ -111,17 +113,18 @@ enum ImMarker_ {
|
|||
ImMarker_Asterisk = 1 << 10, // a asterisk marker will be rendered at each point (not filled)
|
||||
};
|
||||
|
||||
// A range defined by a min/max value. Used for plot axes ranges.
|
||||
struct ImPlotRange {
|
||||
float Min, Max;
|
||||
ImPlotRange();
|
||||
bool Contains(float) const;
|
||||
bool Contains(float value) const;
|
||||
float Size() const;
|
||||
};
|
||||
|
||||
/// Plot range utility struct
|
||||
struct ImPlotBounds {
|
||||
// Combination of two ranges for X and Y axes.
|
||||
struct ImPlotLimits {
|
||||
ImPlotRange X, Y;
|
||||
ImPlotBounds();
|
||||
ImPlotLimits();
|
||||
bool Contains(const ImVec2& p) const;
|
||||
};
|
||||
|
||||
|
@ -148,17 +151,16 @@ namespace ImGui {
|
|||
// be called, e.g. "if (BeginPlot(...)) { ... EndPlot(); }"". #title_id must
|
||||
// be unique. If you need to avoid ID collisions or don't want to display a
|
||||
// title in the plot, use double hashes (e.g. "MyPlot##Hidden"). If #x_label
|
||||
// and/or #y_label are provided, axes labels will be displayed. Axis flags are
|
||||
// only set ONCE during the first call to BeginPlot.
|
||||
// and/or #y_label are provided, axes labels will be displayed.
|
||||
bool BeginPlot(const char* title_id,
|
||||
const char* x_label = NULL,
|
||||
const char* y_label = NULL,
|
||||
const ImVec2& size = ImVec2(-1,-1),
|
||||
ImPlotFlags flags = ImPlotFlags_Default,
|
||||
ImAxisFlags x_flags = ImAxisFlags_Default,
|
||||
ImAxisFlags y_flags = ImAxisFlags_Default,
|
||||
ImAxisFlags y2_flags = ImAxisFlags_Auxiliary_Default,
|
||||
ImAxisFlags y3_flags = ImAxisFlags_Auxiliary_Default);
|
||||
const char* x_label = NULL,
|
||||
const char* y_label = NULL,
|
||||
const ImVec2& size = ImVec2(-1,-1),
|
||||
ImPlotFlags flags = ImPlotFlags_Default,
|
||||
ImAxisFlags x_flags = ImAxisFlags_Default,
|
||||
ImAxisFlags y_flags = ImAxisFlags_Default,
|
||||
ImAxisFlags y2_flags = ImAxisFlags_Auxiliary,
|
||||
ImAxisFlags y3_flags = ImAxisFlags_Auxiliary);
|
||||
// Only call EndPlot() if BeginPlot() returns true! Typically called at the end
|
||||
// of an if statement conditioned on BeginPlot().
|
||||
void EndPlot();
|
||||
|
@ -167,7 +169,7 @@ void EndPlot();
|
|||
// Plot Items
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Plots a standard 2D line and/or scatter plot .
|
||||
// Plots a standard 2D line and/or scatter plot.
|
||||
void Plot(const char* label_id, const float* values, int count, int offset = 0, int stride = sizeof(float));
|
||||
void Plot(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float));
|
||||
void Plot(const char* label_id, const ImVec2* data, int count, int offset = 0);
|
||||
|
@ -201,11 +203,11 @@ bool IsPlotHovered();
|
|||
/// Returns the mouse position in x,y coordinates of the current or most recent plot. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
|
||||
ImVec2 GetPlotMousePos(int y_axis = -1);
|
||||
/// Returns the current or most recent plot axis range. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
|
||||
ImPlotBounds GetPlotBounds(int y_axis = -1);
|
||||
ImPlotLimits GetPlotLimits(int y_axis = -1);
|
||||
/// Returns true if the current or most recent plot is being queried.
|
||||
bool IsPlotQueried();
|
||||
/// Returns the current or most recent plot query bounds.
|
||||
ImPlotBounds GetPlotQuery(int y_axis = -1);
|
||||
ImPlotLimits GetPlotQuery(int y_axis = -1);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plot Styling
|
||||
|
@ -237,15 +239,15 @@ void PopPlotStyleVar(int count = 1);
|
|||
// Plot Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Set the axes ranges of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes will be locked.
|
||||
void SetNextPlotBounds(float x_min, float x_max, float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once);
|
||||
/// Set the X axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked.
|
||||
void SetNextPlotBoundsX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once);
|
||||
/// Set the Y axis range of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis will be locked.
|
||||
void SetNextPlotBoundsY(float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once, int y_axis = 0);
|
||||
/// Set the axes range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes limits will be locked.
|
||||
void SetNextPlotLimits(float x_min, float x_max, float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once);
|
||||
/// Set the X axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis limits will be locked.
|
||||
void SetNextPlotLimitsX(float x_min, float x_max, ImGuiCond cond = ImGuiCond_Once);
|
||||
/// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axis limits will be locked.
|
||||
void SetNextPlotLimitsY(float y_min, float y_max, ImGuiCond cond = ImGuiCond_Once, int y_axis = 0);
|
||||
|
||||
/// Select which Y axis will be used for subsequent plot elements. The default is '0', or the first Y axis.
|
||||
void SetPlotYAxis(int);
|
||||
/// Select which Y axis will be used for subsequent plot elements. The default is '0', or the first Y axis.
|
||||
void SetPlotYAxis(int y_axis);
|
||||
|
||||
// Get the current Plot position (top-left) in pixels.
|
||||
ImVec2 GetPlotPos();
|
||||
|
|
121
implot_demo.cpp
121
implot_demo.cpp
|
@ -20,7 +20,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// ImPlot v0.1 WIP
|
||||
// ImPlot v0.2 WIP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
|
@ -95,7 +95,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ImGui::SetNextWindowPos(ImVec2(50, 50), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(520, 750), ImGuiCond_FirstUseEver);
|
||||
ImGui::Begin("ImPlot Demo", p_open);
|
||||
ImGui::Text("ImPlot says hello. (0.1 WIP)");
|
||||
ImGui::Text("ImPlot says hello. (0.2 WIP)");
|
||||
if (ImGui::CollapsingHeader("Help")) {
|
||||
ImGui::Text("USER GUIDE:");
|
||||
ImGui::BulletText("Left click and drag within the plot area to pan X and Y axes.");
|
||||
|
@ -112,11 +112,6 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ImGui::BulletText("Hold Shift to expand box selection vertically.");
|
||||
ImGui::BulletText("Left click while box selecting to cancel the selection.");
|
||||
ImGui::Unindent();
|
||||
ImGui::BulletText("Middle click (or Ctrl + right click) and drag to create a query range.");
|
||||
ImGui::Indent();
|
||||
ImGui::BulletText("Hold Alt to expand query horizontally.");
|
||||
ImGui::BulletText("Hold Shift to expand query vertically.");
|
||||
ImGui::Unindent();
|
||||
ImGui::BulletText("Double left click to fit all visible data.");
|
||||
ImGui::Indent();
|
||||
ImGui::BulletText("Double left click on an axis to fit the individual axis.");
|
||||
|
@ -176,9 +171,9 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
static bool horz = false;
|
||||
ImGui::Checkbox("Horizontal",&horz);
|
||||
if (horz)
|
||||
ImGui::SetNextPlotBounds(0, 110, -0.5f, 9.5f, ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimits(0, 110, -0.5f, 9.5f, ImGuiCond_Always);
|
||||
else
|
||||
ImGui::SetNextPlotBounds(-0.5f, 9.5f, 0, 110, ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimits(-0.5f, 9.5f, 0, 110, ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("Bar Plot", horz ? "Score": "Student", horz ? "Student" : "Score", {-1, 300})) {
|
||||
static float midtm[10] = {83, 67, 23, 89, 83, 78, 91, 82, 85, 90};
|
||||
static float final[10] = {80, 62, 56, 99, 55, 78, 88, 78, 90, 100};
|
||||
|
@ -203,7 +198,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
float bar[5] = {1,2,5,3,4};
|
||||
float err1[5] = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f};
|
||||
float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f};
|
||||
ImGui::SetNextPlotBounds(0, 6, 0, 10);
|
||||
ImGui::SetNextPlotLimits(0, 6, 0, 10);
|
||||
if (ImGui::BeginPlot("##ErrorBars",NULL,NULL,ImVec2(-1,300))) {
|
||||
|
||||
ImGui::PlotBar("Bar", xs, bar, 5, 0.5f);
|
||||
|
@ -227,7 +222,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ImVec2 center(0.5f,0.5f); // in plot units, not pixels
|
||||
float radius = 0.4f; // in plot units, not pixels
|
||||
|
||||
SetNextPlotBounds(0,1,0,1,ImGuiCond_Always);
|
||||
SetNextPlotLimits(0,1,0,1,ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##Pie1", NULL, NULL, ImVec2(250,250), ImPlotFlags_Legend, 0, 0)) {
|
||||
ImGui::PlotPieChart(labels1, pre_normalized, 4, center, radius);
|
||||
ImGui::EndPlot();
|
||||
|
@ -242,7 +237,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
{0.7412f, 0.0f, 0.1490f, 1.0f},
|
||||
};
|
||||
ImGui::SetPlotPalette(YlOrRd, 5);
|
||||
SetNextPlotBounds(0,1,0,1,ImGuiCond_Always);
|
||||
SetNextPlotLimits(0,1,0,1,ImGuiCond_Always);
|
||||
static const char* labels2[] = {"One","Two","Three","Four","Five"};
|
||||
static float not_normalized[] = {1,2,3,4,5};
|
||||
if (ImGui::BeginPlot("##Pie2", NULL, NULL, ImVec2(250,250), ImPlotFlags_Legend, 0, 0)) {
|
||||
|
@ -268,14 +263,14 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
sdata2.AddPoint(t, mouse.y * 0.0005f);
|
||||
rdata2.AddPoint(t, mouse.y * 0.0005f);
|
||||
}
|
||||
ImGui::SetNextPlotBoundsX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimitsX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
static int rt_axis = ImAxisFlags_Default & ~ImAxisFlags_TickLabels;
|
||||
if (ImGui::BeginPlot("##Scrolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) {
|
||||
ImGui::Plot("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), sdata1.Offset, 2 * sizeof(float));
|
||||
ImGui::Plot("Data 2", &sdata2.Data[0].x, &sdata2.Data[0].y, sdata2.Data.size(), sdata2.Offset, 2 * sizeof(float));
|
||||
ImGui::EndPlot();
|
||||
}
|
||||
ImGui::SetNextPlotBoundsX(0, 10, ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimitsX(0, 10, ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##Rolling", NULL, NULL, {-1,150}, ImPlotFlags_Default, rt_axis, rt_axis)) {
|
||||
ImGui::Plot("Data 1", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 2 * sizeof(float));
|
||||
ImGui::Plot("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float));
|
||||
|
@ -285,7 +280,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Markers and Labels")) {
|
||||
ImGui::SetNextPlotBounds(0, 10, 0, 12);
|
||||
ImGui::SetNextPlotLimits(0, 10, 0, 12);
|
||||
if (ImGui::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,300), 0, 0, 0)) {
|
||||
float xs[2] = {1,4};
|
||||
float ys[2] = {10,11};
|
||||
|
@ -369,7 +364,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ys2[i] = log(xs[i]);
|
||||
ys3[i] = pow(10.0f, xs[i]);
|
||||
}
|
||||
ImGui::SetNextPlotBounds(0.1f, 100, 0, 10);
|
||||
ImGui::SetNextPlotLimits(0.1f, 100, 0, 10);
|
||||
if (ImGui::BeginPlot("Log Plot", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_Default | ImAxisFlags_LogScale )) {
|
||||
ImGui::Plot("f(x) = x", xs, xs, 1001);
|
||||
ImGui::Plot("f(x) = sin(x)+1", xs, ys1, 1001);
|
||||
|
@ -379,25 +374,43 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Multiple Y Axes")) {
|
||||
if (ImGui::CollapsingHeader("Multiple Y-Axes")) {
|
||||
static ImVec4 txt_col = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
||||
txt_col.w = 0.25f;
|
||||
static ImVec4 y1_col = txt_col;
|
||||
static ImVec4 y2_col = txt_col;
|
||||
static ImVec4 y3_col = txt_col;
|
||||
|
||||
static float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001];
|
||||
static bool y2_axis = true;
|
||||
static bool y3_axis = false;
|
||||
|
||||
ImGui::Checkbox("Y-Axis 2", &y2_axis);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Y-Axis 3", &y3_axis);
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit4("##Col1", &y1_col.x, ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit4("##Col2", &y2_col.x, ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit4("##Col3", &y3_col.x, ImGuiColorEditFlags_NoInputs);
|
||||
for (int i = 0; i < 1001; ++i) {
|
||||
xs[i] = (float)(i*0.1f);
|
||||
ys1[i] = sin(xs[i]) * 3 + 1;
|
||||
ys2[i] = cos(xs[i]) * 0.2 + 0.5;
|
||||
ys3[i] = sin(xs[i]+.5) * 100 + 200;
|
||||
xs2[i] = xs[i] + 10.0;
|
||||
ys2[i] = cos(xs[i]) * 0.2f + 0.5f;
|
||||
ys3[i] = sin(xs[i]+0.5f) * 100 + 200;
|
||||
xs2[i] = xs[i] + 10.0f;
|
||||
}
|
||||
ImGui::SetNextPlotBounds(0.1f, 100, 0, 10);
|
||||
ImGui::SetNextPlotBoundsY(0, 1, ImGuiCond_Once, 1);
|
||||
ImGui::SetNextPlotBoundsY(0, 300, ImGuiCond_Once, 2);
|
||||
ImGui::SetNextPlotLimits(0.1f, 100, 0, 10);
|
||||
ImGui::SetNextPlotLimitsY(0, 1, ImGuiCond_Once, 1);
|
||||
ImGui::SetNextPlotLimitsY(0, 300, ImGuiCond_Once, 2);
|
||||
ImGui::PushPlotColor(ImPlotCol_YAxis, y1_col);
|
||||
ImGui::PushPlotColor(ImPlotCol_YAxis2, y2_col);
|
||||
ImGui::PushPlotColor(ImPlotCol_YAxis3, y3_col);
|
||||
|
||||
if (ImGui::BeginPlot("Multi-Axis Plot", NULL, NULL, ImVec2(-1,300),
|
||||
ImPlotFlags_Default |
|
||||
(y2_axis ? ImPlotFlags_Y2Axis : 0) |
|
||||
(y3_axis ? ImPlotFlags_Y3Axis : 0))) {
|
||||
(y2_axis ? ImPlotFlags_YAxis2 : 0) |
|
||||
(y3_axis ? ImPlotFlags_YAxis3 : 0))) {
|
||||
ImGui::Plot("f(x) = x", xs, xs, 1001);
|
||||
ImGui::Plot("f(x) = sin(x)*3+1", xs, ys1, 1001);
|
||||
|
||||
|
@ -413,18 +426,20 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
|
||||
ImGui::EndPlot();
|
||||
}
|
||||
ImGui::Checkbox("Y2 Axis", &y2_axis);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Y3 Axis", &y3_axis);
|
||||
ImGui::PopPlotColor(3);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Querying")) {
|
||||
ImGui::BulletText("Ctrl + click in the plot area to draw points.");
|
||||
ImGui::BulletText("Middle click (or Ctrl + right click) and drag to query points.");
|
||||
ImGui::BulletText("Hold the Alt and/or Shift keys to expand the query range.");
|
||||
ImGui::BulletText("Middle click (or Ctrl + right click) and drag to create a query rect.");
|
||||
ImGui::Indent();
|
||||
ImGui::BulletText("Hold Alt to expand query horizontally.");
|
||||
ImGui::BulletText("Hold Shift to expand query vertically.");
|
||||
ImGui::BulletText("The query rect can be dragged after it's created.");
|
||||
ImGui::Unindent();
|
||||
static ImVector<ImVec2> data;
|
||||
ImPlotBounds range, query;
|
||||
if (ImGui::BeginPlot("##Drawing", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default, ImAxisFlags_GridLines, ImAxisFlags_GridLines)) {
|
||||
ImPlotLimits range, query;
|
||||
if (ImGui::BeginPlot("##Drawing", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default | ImPlotFlags_Query, ImAxisFlags_GridLines, ImAxisFlags_GridLines)) {
|
||||
if (ImGui::IsPlotHovered() && ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyCtrl)
|
||||
data.push_back(ImGui::GetPlotMousePos());
|
||||
ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 0);
|
||||
|
@ -432,7 +447,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
if (data.size() > 0)
|
||||
ImGui::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float));
|
||||
if (ImGui::IsPlotQueried() && data.size() > 0) {
|
||||
ImPlotBounds range = ImGui::GetPlotQuery();
|
||||
ImPlotLimits range = ImGui::GetPlotQuery();
|
||||
int cnt = 0;
|
||||
ImVec2 avg;
|
||||
for (int i = 0; i < data.size(); ++i) {
|
||||
|
@ -449,12 +464,12 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
}
|
||||
}
|
||||
ImGui::PopPlotStyleVar(2);
|
||||
range = ImGui::GetPlotBounds();
|
||||
range = ImGui::GetPlotLimits();
|
||||
query = ImGui::GetPlotQuery();
|
||||
ImGui::EndPlot();
|
||||
}
|
||||
ImGui::Text("The current plot range is: [%g,%g,%g,%g]", range.X.Min, range.X.Max, range.Y.Min, range.Y.Max);
|
||||
ImGui::Text("The current query range is: [%g,%g,%g,%g]", query.X.Min, query.X.Max, query.Y.Min, query.Y.Max);
|
||||
ImGui::Text("The current plot limits are: [%g,%g,%g,%g]", range.X.Min, range.X.Max, range.Y.Min, range.Y.Max);
|
||||
ImGui::Text("The current query limits are: [%g,%g,%g,%g]", query.X.Min, query.X.Max, query.Y.Min, query.Y.Max);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Views")) {
|
||||
|
@ -468,24 +483,23 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
for (size_t i = 0; i < 512; ++i) {
|
||||
const float t = i / sampling_freq;
|
||||
x_data[i] = t;
|
||||
const float arg = 2 * 3.14 * freq * t;
|
||||
const float arg = 2 * 3.14f * freq * t;
|
||||
y_data1[i] = sin(arg);
|
||||
y_data2[i] = y_data1[i] * -0.6 + sin(2 * arg) * 0.4;
|
||||
y_data3[i] = y_data2[i] * -0.6 + sin(3 * arg) * 0.4;
|
||||
y_data2[i] = y_data1[i] * -0.6f + sin(2 * arg) * 0.4f;
|
||||
y_data3[i] = y_data2[i] * -0.6f + sin(3 * arg) * 0.4f;
|
||||
}
|
||||
ImGui::BulletText("Query the first plot to render a subview in the second plot.");
|
||||
ImGui::BulletText("Toggle \"Pixel Query\" in the context menu and then pan the plot.");
|
||||
ImGui::SetNextPlotBounds(0,0.01f,-1,1);
|
||||
ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls).");
|
||||
ImGui::SetNextPlotLimits(0,0.01f,-1,1);
|
||||
ImAxisFlags flgs = ImAxisFlags_Default & ~ImAxisFlags_TickLabels;
|
||||
ImPlotBounds query;
|
||||
if (ImGui::BeginPlot("##View1",NULL,NULL,ImVec2(-1,150), ImPlotFlags_Default, flgs, flgs)) {
|
||||
ImPlotLimits query;
|
||||
if (ImGui::BeginPlot("##View1",NULL,NULL,ImVec2(-1,150), ImPlotFlags_Default | ImPlotFlags_Query, flgs, flgs)) {
|
||||
ImGui::Plot("Signal 1", x_data, y_data1, 512);
|
||||
ImGui::Plot("Signal 2", x_data, y_data2, 512);
|
||||
ImGui::Plot("Signal 3", x_data, y_data3, 512);
|
||||
query = ImGui::GetPlotQuery();
|
||||
ImGui::EndPlot();
|
||||
}
|
||||
ImGui::SetNextPlotBounds(query.X.Min, query.X.Max, query.Y.Min, query.Y.Max, ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimits(query.X.Min, query.X.Max, query.Y.Min, query.Y.Max, ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##View2",NULL,NULL,ImVec2(-1,150), 0, 0, 0)) {
|
||||
ImGui::Plot("Signal 1", x_data, y_data1, 512);
|
||||
ImGui::Plot("Signal 2", x_data, y_data2, 512);
|
||||
|
@ -493,12 +507,9 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ImGui::EndPlot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Drag and Drop")) {
|
||||
srand(10000000 * ImGui::GetTime());
|
||||
srand((int)(10000000 * ImGui::GetTime()));
|
||||
static bool paused = false;
|
||||
static bool init = true;
|
||||
static ScrollingData data[10];
|
||||
|
@ -543,7 +554,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
data[i].Data.back().y + (0.005f + 0.0002f * (float)rand() / float(RAND_MAX)) * (-1 + 2 * (float)rand() / float(RAND_MAX)));
|
||||
}
|
||||
}
|
||||
ImGui::SetNextPlotBoundsX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimitsX(t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##DND", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (show[i]) {
|
||||
|
@ -644,8 +655,8 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sin(2*t) - cos(2*t));
|
||||
}
|
||||
ImGui::SetNextPlotBoundsY(-1, 1);
|
||||
ImGui::SetNextPlotBoundsX(t - 10.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
ImGui::SetNextPlotLimitsY(-1, 1);
|
||||
ImGui::SetNextPlotLimitsX(t - 10.0f, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##Digital", NULL, NULL, ImVec2(-1,300), ImPlotFlags_Default)) {
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) {
|
||||
if (showDigital[i]) {
|
||||
|
@ -692,7 +703,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
ImGui::PushPlotColor(ImPlotCol_XAxis, IM_COL32(192, 192, 192, 192));
|
||||
ImGui::PushPlotColor(ImPlotCol_YAxis, IM_COL32(192, 192, 192, 192));
|
||||
ImGui::PushPlotStyleVar(ImPlotStyleVar_LineWeight, 2);
|
||||
ImGui::SetNextPlotBounds(-0.5f, 9.5f, -0.5f, 9.5f);
|
||||
ImGui::SetNextPlotLimits(-0.5f, 9.5f, -0.5f, 9.5f);
|
||||
if (ImGui::BeginPlot("##Custom", NULL, NULL, {-1,300}, ImPlotFlags_Default & ~ImPlotFlags_Legend, 0)) {
|
||||
float lin[10] = {8,8,9,7,8,8,8,9,7,8};
|
||||
float bar[10] = {1,2,5,3,4,1,2,5,3,4};
|
||||
|
@ -727,7 +738,7 @@ void ShowImPlotDemoWindow(bool* p_open) {
|
|||
static BenchmarkItem items[n_items];
|
||||
ImGui::BulletText("Make sure VSync is disabled.");
|
||||
ImGui::BulletText("%d lines with %d points each @ %.3f FPS.",n_items,1000,ImGui::GetIO().Framerate);
|
||||
SetNextPlotBounds(0,1,0,1, ImGuiCond_Always);
|
||||
SetNextPlotLimits(0,1,0,1, ImGuiCond_Always);
|
||||
if (ImGui::BeginPlot("##Bench",NULL,NULL,{-1,300},ImPlotFlags_Default | ImPlotFlags_NoChild)) {
|
||||
char buff[16];
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user