Skip to content

Commit ebcd473

Browse files
committed
merge: branch 'master' into feat/spec-colors
2 parents f1c318b + 5965089 commit ebcd473

6 files changed

Lines changed: 346 additions & 47 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Of course, there's much more you can do with ImPlot...
7373
7474
A comprehensive example of ImPlot's features can be found in `implot_demo.cpp`. Add this file to your sources and call `ImPlot::ShowDemoWindow()` somewhere in your update loop. You are encouraged to use this file as a reference when needing to implement various plot types. The demo is always updated to show new plot types and features as they are added, so check back with each release!
7575
76-
An online version of the demo is hosted [here](https://traineq.org/implot_demo/src/implot_demo.html). You can view the plots and the source code that generated them. Note that this demo may not always be up to date and is not as performant as a desktop implementation, but it should give you a general taste of what's possible with ImPlot. Special thanks to [pthom](https://github.com/pthom) for creating and hosting this!
76+
An online version of the demo is hosted [here](https://pthom.github.io/imgui_explorer/?lib=implot). You can view the plots and the source code that generated them. Note that this demo may not always be up to date and is not as performant as a desktop implementation, but it should give you a general taste of what's possible with ImPlot. Special thanks to [pthom](https://github.com/pthom) for creating and hosting this!
7777
7878
More sophisticated demos requiring lengthier code and/or third-party libraries can be found in a separate repository: [implot_demos](https://github.com/epezent/implot_demos). Here, you will find advanced signal processing and ImPlot usage in action. Please read the `Contributing` section of that repository if you have an idea for a new demo!
7979

implot.cpp

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ You can read releases logs https://github.com/epezent/implot/releases for more d
215215
// Clang/GCC warnings with -Weverything
216216
#if defined(__clang__)
217217
#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal
218+
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
219+
#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
218220
#elif defined(__GNUC__)
219221
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
220222
#endif
@@ -501,22 +503,22 @@ void Initialize(ImPlotContext* ctx) {
501503
ResetCtxForNextAlignedPlots(ctx);
502504
ResetCtxForNextSubplot(ctx);
503505

504-
const ImU32 Deep[] = {4289753676, 4283598045, 4285048917, 4283584196, 4289950337, 4284512403, 4291005402, 4287401100, 4285839820, 4291671396 };
505-
const ImU32 Dark[] = {4280031972, 4290281015, 4283084621, 4288892568, 4278222847, 4281597951, 4280833702, 4290740727, 4288256409 };
506-
const ImU32 Pastel[] = {4289639675, 4293119411, 4291161036, 4293184478, 4289124862, 4291624959, 4290631909, 4293712637, 4294111986 };
507-
const ImU32 Paired[] = {4293119554, 4290017311, 4287291314, 4281114675, 4288256763, 4280031971, 4285513725, 4278222847, 4292260554, 4288298346, 4288282623, 4280834481};
508-
const ImU32 Viridis[] = {4283695428, 4285867080, 4287054913, 4287455029, 4287526954, 4287402273, 4286883874, 4285579076, 4283552122, 4280737725, 4280674301 };
509-
const ImU32 Plasma[] = {4287039501, 4288480321, 4289200234, 4288941455, 4287638193, 4286072780, 4284638433, 4283139314, 4281771772, 4280667900, 4280416752 };
510-
const ImU32 Hot[] = {4278190144, 4278190208, 4278190271, 4278190335, 4278206719, 4278223103, 4278239231, 4278255615, 4283826175, 4289396735, 4294967295 };
511-
const ImU32 Cool[] = {4294967040, 4294960666, 4294954035, 4294947661, 4294941030, 4294934656, 4294928025, 4294921651, 4294915020, 4294908646, 4294902015 };
512-
const ImU32 Pink[] = {4278190154, 4282532475, 4284308894, 4285690554, 4286879686, 4287870160, 4288794330, 4289651940, 4291685869, 4293392118, 4294967295 };
513-
const ImU32 Jet[] = {4289331200, 4294901760, 4294923520, 4294945280, 4294967040, 4289396565, 4283826090, 4278255615, 4278233855, 4278212095, 4278190335 };
506+
const ImU32 Deep[] = {IM_RGB(76,114,176),IM_RGB(221,132,82),IM_RGB(85,168,104),IM_RGB(196,78,82),IM_RGB(129,114,179),IM_RGB(147,120,96),IM_RGB(218,139,195),IM_RGB(140,140,140),IM_RGB(204,185,116),IM_RGB(100,181,205)};
507+
const ImU32 Dark[] = {IM_RGB(228,26,28),IM_RGB(55,126,184),IM_RGB(77,175,74),IM_RGB(152,78,163),IM_RGB(255,127,0),IM_RGB(255,255,51),IM_RGB(166,86,40),IM_RGB(247,129,191),IM_RGB(153,153,153)};
508+
const ImU32 Pastel[] = {IM_RGB(251,180,174),IM_RGB(179,205,227),IM_RGB(204,235,197),IM_RGB(222,203,228),IM_RGB(254,217,166),IM_RGB(255,255,204),IM_RGB(229,216,189),IM_RGB(253,218,236),IM_RGB(242,242,242)};
509+
const ImU32 Paired[] = {IM_RGB(66,206,227),IM_RGB(31,120,180),IM_RGB(178,223,138),IM_RGB(51,160,44),IM_RGB(251,154,153),IM_RGB(227,26,28),IM_RGB(253,191,111),IM_RGB(255,127,0),IM_RGB(202,178,214),IM_RGB(106,61,154),IM_RGB(255,255,153),IM_RGB(177,89,40)};
510+
const ImU32 Viridis[] = {IM_RGB(68,1,84),IM_RGB(72,36,117),IM_RGB(65,68,135),IM_RGB(53,95,141),IM_RGB(42,120,142),IM_RGB(33,145,140),IM_RGB(34,168,132),IM_RGB(68,191,112),IM_RGB(122,209,81),IM_RGB(189,223,38),IM_RGB(253,231,37)};
511+
const ImU32 Plasma[] = {IM_RGB(13,8,135),IM_RGB(65,4,157),IM_RGB(106,0,168),IM_RGB(143,13,164),IM_RGB(177,42,144),IM_RGB(204,71,120),IM_RGB(225,100,98),IM_RGB(242,132,75),IM_RGB(252,166,54),IM_RGB(252,206,37),IM_RGB(240,249,33)};
512+
const ImU32 Hot[] = {IM_RGB(64,0,0),IM_RGB(128,0,0),IM_RGB(191,0,0),IM_RGB(255,0,0),IM_RGB(255,64,0),IM_RGB(255,128,0),IM_RGB(255,191,0),IM_RGB(255,255,0),IM_RGB(255,255,85),IM_RGB(255,255,170),IM_RGB(255,255,255)};
513+
const ImU32 Cool[] = {IM_RGB(0,255,255),IM_RGB(26,230,255),IM_RGB(51,204,255),IM_RGB(77,179,255),IM_RGB(102,153,255),IM_RGB(128,128,255),IM_RGB(153,102,255),IM_RGB(179,77,255),IM_RGB(204,51,255),IM_RGB(230,26,255),IM_RGB(255,0,255)};
514+
const ImU32 Pink[] = {IM_RGB(74,0,0),IM_RGB(123,66,66),IM_RGB(158,93,93),IM_RGB(186,114,114),IM_RGB(198,151,132),IM_RGB(208,180,147),IM_RGB(218,206,161),IM_RGB(228,228,174),IM_RGB(237,237,205),IM_RGB(246,246,231),IM_RGB(255,255,255)};
515+
const ImU32 Jet[] = {IM_RGB(0,0,170),IM_RGB(0,0,255),IM_RGB(0,85,255),IM_RGB(0,170,255),IM_RGB(0,255,255),IM_RGB(85,255,170),IM_RGB(170,255,85),IM_RGB(255,255,0),IM_RGB(255,170,0),IM_RGB(255,85,0),IM_RGB(255,0,0)};
514516
const ImU32 Twilight[] = {IM_RGB(226,217,226),IM_RGB(166,191,202),IM_RGB(109,144,192),IM_RGB(95,88,176),IM_RGB(83,30,124),IM_RGB(47,20,54),IM_RGB(100,25,75),IM_RGB(159,60,80),IM_RGB(192,117,94),IM_RGB(208,179,158),IM_RGB(226,217,226)};
515517
const ImU32 RdBu[] = {IM_RGB(103,0,31),IM_RGB(178,24,43),IM_RGB(214,96,77),IM_RGB(244,165,130),IM_RGB(253,219,199),IM_RGB(247,247,247),IM_RGB(209,229,240),IM_RGB(146,197,222),IM_RGB(67,147,195),IM_RGB(33,102,172),IM_RGB(5,48,97)};
516518
const ImU32 BrBG[] = {IM_RGB(84,48,5),IM_RGB(140,81,10),IM_RGB(191,129,45),IM_RGB(223,194,125),IM_RGB(246,232,195),IM_RGB(245,245,245),IM_RGB(199,234,229),IM_RGB(128,205,193),IM_RGB(53,151,143),IM_RGB(1,102,94),IM_RGB(0,60,48)};
517519
const ImU32 PiYG[] = {IM_RGB(142,1,82),IM_RGB(197,27,125),IM_RGB(222,119,174),IM_RGB(241,182,218),IM_RGB(253,224,239),IM_RGB(247,247,247),IM_RGB(230,245,208),IM_RGB(184,225,134),IM_RGB(127,188,65),IM_RGB(77,146,33),IM_RGB(39,100,25)};
518520
const ImU32 Spectral[] = {IM_RGB(158,1,66),IM_RGB(213,62,79),IM_RGB(244,109,67),IM_RGB(253,174,97),IM_RGB(254,224,139),IM_RGB(255,255,191),IM_RGB(230,245,152),IM_RGB(171,221,164),IM_RGB(102,194,165),IM_RGB(50,136,189),IM_RGB(94,79,162)};
519-
const ImU32 Greys[] = {IM_COL32_WHITE, IM_COL32_BLACK };
521+
const ImU32 Greys[] = {IM_COL32_WHITE, IM_COL32_BLACK};
520522

521523
IMPLOT_APPEND_CMAP(Deep, true);
522524
IMPLOT_APPEND_CMAP(Dark, true);
@@ -1686,8 +1688,10 @@ void PadAndDatumAxesX(ImPlotPlot& plot, float& pad_T, float& pad_B, ImPlotAlignm
16861688
if (opp) {
16871689
if (count_T++ > 0)
16881690
pad_T += K + P;
1689-
if (label)
1690-
pad_T += T + P;
1691+
if (label) {
1692+
ImVec2 label_size = ImGui::CalcTextSize(plot.GetAxisLabel(axis));
1693+
pad_T += label_size.y + P;
1694+
}
16911695
if (ticks)
16921696
pad_T += ImMax(T, axis.Ticker.MaxSize.y) + P + (time ? T + P : 0);
16931697
axis.Datum1 = plot.CanvasRect.Min.y + pad_T;
@@ -1697,8 +1701,10 @@ void PadAndDatumAxesX(ImPlotPlot& plot, float& pad_T, float& pad_B, ImPlotAlignm
16971701
else {
16981702
if (count_B++ > 0)
16991703
pad_B += K + P;
1700-
if (label)
1701-
pad_B += T + P;
1704+
if (label) {
1705+
ImVec2 label_size = ImGui::CalcTextSize(plot.GetAxisLabel(axis));
1706+
pad_B += label_size.y + P;
1707+
}
17021708
if (ticks)
17031709
pad_B += ImMax(T, axis.Ticker.MaxSize.y) + P + (time ? T + P : 0);
17041710
axis.Datum1 = plot.CanvasRect.Max.y - pad_B;
@@ -2026,20 +2032,22 @@ bool UpdateInput(ImPlotPlot& plot) {
20262032
float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f);
20272033
float ty = ImRemap(IO.MousePos.y, plot.PlotRect.Min.y, plot.PlotRect.Max.y, 0.0f, 1.0f);
20282034

2035+
// Track which axis to use as reference for equal aspect
2036+
ImPlotAxis* equal_ref_axis = nullptr;
2037+
20292038
for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {
20302039
ImPlotAxis& x_axis = plot.XAxis(i);
20312040
const bool equal_zoom = axis_equal && x_axis.OrthoAxis != nullptr;
20322041
const bool equal_locked = (equal_zoom != false) && x_axis.OrthoAxis->IsInputLocked();
20332042
if (x_hov[i] && !x_axis.IsInputLocked() && !equal_locked) {
20342043
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID);
20352044
if (zoom_rate != 0.0f) {
2036-
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
2037-
const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction);
2038-
const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction);
2045+
const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate);
2046+
const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate);
20392047
x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l);
20402048
x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r);
2041-
if (axis_equal && x_axis.OrthoAxis != nullptr)
2042-
x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());
2049+
if (equal_zoom)
2050+
equal_ref_axis = &x_axis;
20432051
changed = true;
20442052
}
20452053
}
@@ -2051,17 +2059,21 @@ bool UpdateInput(ImPlotPlot& plot) {
20512059
if (y_hov[i] && !y_axis.IsInputLocked() && !equal_locked) {
20522060
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID);
20532061
if (zoom_rate != 0.0f) {
2054-
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
2055-
const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction);
2056-
const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction);
2062+
const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate);
2063+
const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate);
20572064
y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b);
20582065
y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t);
2059-
if (axis_equal && y_axis.OrthoAxis != nullptr)
2060-
y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());
2066+
if (equal_zoom)
2067+
equal_ref_axis = &y_axis;
20612068
changed = true;
20622069
}
20632070
}
20642071
}
2072+
2073+
// Apply equal aspect constraint after zooming both axes
2074+
if (equal_ref_axis != nullptr && equal_ref_axis->OrthoAxis != nullptr) {
2075+
equal_ref_axis->OrthoAxis->SetAspect(equal_ref_axis->GetAspect());
2076+
}
20652077
}
20662078

20672079
// BOX-SELECTION ----------------------------------------------------------
@@ -2247,6 +2259,8 @@ void SetupAxisTicks(ImAxis idx, double v_min, double v_max, int n_ticks, const c
22472259
ImPlotContext& gp = *GImPlot;
22482260
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,
22492261
"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!");
2262+
IM_ASSERT_USER_ERROR(labels == nullptr || n_ticks >= 2,
2263+
"When providing custom labels, n_ticks must be at least 2!");
22502264
n_ticks = n_ticks < 2 ? 2 : n_ticks;
22512265
FillRange(gp.TempDouble1, n_ticks, v_min, v_max);
22522266
SetupAxisTicks(idx, gp.TempDouble1.Data, n_ticks, labels, show_default);
@@ -2624,6 +2638,17 @@ void SetupFinish() {
26242638
}
26252639
}
26262640

2641+
// (4.5) recalc padding now that we have actual X-axis tick labels (handles multi-line labels)
2642+
// Save title padding before resetting
2643+
const float title_pad = (title_size.x > 0) ? (title_size.y + gp.Style.LabelPadding.y) : 0.0f;
2644+
pad_top = title_pad;
2645+
pad_bot = 0;
2646+
PadAndDatumAxesX(plot,pad_top,pad_bot,gp.CurrentAlignmentH);
2647+
// Update AxesRect to account for title padding (was done in step 0)
2648+
if (title_size.x > 0) {
2649+
plot.AxesRect.Min.y = plot.FrameRect.Min.y + gp.Style.PlotPadding.y + title_pad;
2650+
}
2651+
26272652
// (5) calc plot bb
26282653
plot.PlotRect = ImRect(plot.CanvasRect.Min + ImVec2(pad_left, pad_top), plot.CanvasRect.Max - ImVec2(pad_right, pad_bot));
26292654

implot.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ typedef int ImPlotItemFlags; // -> ImPlotItemFlags_
9595
typedef int ImPlotLineFlags; // -> ImPlotLineFlags_
9696
typedef int ImPlotScatterFlags; // -> ImPlotScatterFlags
9797
typedef int ImPlotBubblesFlags; // -> ImPlotBubblesFlags
98+
typedef int ImPlotPolygonFlags; // -> ImPlotPolygonFlags_
9899
typedef int ImPlotStairsFlags; // -> ImPlotStairsFlags_
99100
typedef int ImPlotShadedFlags; // -> ImPlotShadedFlags_
100101
typedef int ImPlotBarsFlags; // -> ImPlotBarsFlags_
@@ -276,6 +277,12 @@ enum ImPlotBubblesFlags_ {
276277
ImPlotBubblesFlags_None = 0, // default
277278
};
278279

280+
// Flags for PlotPolygon. Used by setting ImPlotSpec::Flags.
281+
enum ImPlotPolygonFlags_ {
282+
ImPlotPolygonFlags_None = 0, // default (closed, convex polygon)
283+
ImPlotPolygonFlags_Concave = 1 << 10, // use concave polygon filling (slower but supports concave shapes)
284+
};
285+
279286
// Flags for PlotStairs. Used by setting ImPlotSpec::Flags.
280287
enum ImPlotStairsFlags_ {
281288
ImPlotStairsFlags_None = 0, // default
@@ -321,10 +328,11 @@ enum ImPlotInfLinesFlags_ {
321328

322329
// Flags for PlotPieChart. Used by setting ImPlotSpec::Flags.
323330
enum ImPlotPieChartFlags_ {
324-
ImPlotPieChartFlags_None = 0, // default
325-
ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
326-
ImPlotPieChartFlags_IgnoreHidden = 1 << 11, // ignore hidden slices when drawing the pie chart (as if they were not there)
327-
ImPlotPieChartFlags_Exploding = 1 << 12 // Explode legend-hovered slice
331+
ImPlotPieChartFlags_None = 0, // default
332+
ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
333+
ImPlotPieChartFlags_IgnoreHidden = 1 << 11, // ignore hidden slices when drawing the pie chart (as if they were not there)
334+
ImPlotPieChartFlags_Exploding = 1 << 12, // explode legend-hovered slice
335+
ImPlotPieChartFlags_NoSliceBorder = 1 << 13 // do not draw slice borders
328336
};
329337

330338
// Flags for PlotHeatmap. Used by setting ImPlotSpec::Flags.
@@ -991,6 +999,9 @@ IMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* da
991999
IMPLOT_TMP void PlotBubbles(const char* label_id, const T* values, const T* szs, int count, double xscale=1, double xstart=0, const ImPlotSpec& spec=ImPlotSpec());
9921000
IMPLOT_TMP void PlotBubbles(const char* label_id, const T* xs, const T* ys, const T* szs, int count, const ImPlotSpec& spec=ImPlotSpec());
9931001

1002+
// Plots a polygon. Points are specified in counter-clockwise order. If concave, make sure to set the Concave flag.
1003+
IMPLOT_TMP void PlotPolygon(const char* label_id, const T* xs, const T* ys, int count, const ImPlotSpec& spec=ImPlotSpec());
1004+
9941005
// Plots a a stairstep graph. The y value is continued constantly to the right from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i]
9951006
IMPLOT_TMP void PlotStairs(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, const ImPlotSpec& spec=ImPlotSpec());
9961007
IMPLOT_TMP void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, const ImPlotSpec& spec=ImPlotSpec());
@@ -1224,18 +1235,18 @@ IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, int val);
12241235
IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val);
12251236
// Undo temporary style variable modification(s). Undo multiple pushes at once by increasing count.
12261237
IMPLOT_API void PopStyleVar(int count = 1);
1227-
1238+
12281239
// Gets the last item primary color (i.e. its legend icon color)
12291240
IMPLOT_API ImVec4 GetLastItemColor();
12301241

12311242
// Returns the null terminated string name for an ImPlotCol.
12321243
IMPLOT_API const char* GetStyleColorName(ImPlotCol idx);
12331244
// Returns the null terminated string name for an ImPlotMarker.
12341245
IMPLOT_API const char* GetMarkerName(ImPlotMarker idx);
1235-
1246+
12361247
// Returns the next marker and advances the marker for the current plot. You need to call this between Begin/EndPlot!
12371248
IMPLOT_API ImPlotMarker NextMarker();
1238-
1249+
12391250
//-----------------------------------------------------------------------------
12401251
// [SECTION] Colormaps
12411252
//-----------------------------------------------------------------------------
@@ -1305,7 +1316,7 @@ IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr);
13051316
//-----------------------------------------------------------------------------
13061317
// [SECTION] Input Mapping
13071318
//-----------------------------------------------------------------------------
1308-
1319+
13091320
// Provides access to input mapping structure for permanent modifications to controls for pan, select, etc.
13101321
IMPLOT_API ImPlotInputMap& GetInputMap();
13111322

0 commit comments

Comments
 (0)