Skip to content

v0.14

Pre-release
Pre-release
Compare
Choose a tag to compare
@epezent epezent released this 17 Sep 20:22
· 46 commits to master since this release

Plot Item Flags

Each of ImPlot's PlotX functions now takes an optional ImPlotXFlags parameter. This decision (1) allows us to easily add more options for plot items and (2) allows us to consolidate and clean up some of the API. Here's what this looks like for PlotLine:

// Flags for ANY PlotX function
enum ImPlotItemFlags_ {
    ImPlotItemFlags_None     = 0,
    ImPlotItemFlags_NoLegend = 1 << 0, // the item won't have a legend entry displayed
    ImPlotItemFlags_NoFit    = 1 << 1, // the item won't be considered for plot fits
};

// Flags for PlotLine
enum ImPlotLineFlags_ {
    ImPlotLineFlags_None        = 0,       // default
    ImPlotLineFlags_Segments    = 1 << 10, // a line segment will be rendered from every two consecutive points
    ImPlotLineFlags_Loop        = 1 << 11, // the last and first point will be connected to form a closed loop
    ImPlotLineFlags_SkipNaN     = 1 << 12, // NaNs values will be skipped instead of rendered as missing data
    ImPlotLineFlags_NoClip      = 1 << 13, // markers (if displayed) on the edge of a plot will not be clipped
};

...

void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T));

As you can see, PlotLine has some new bells and whistles that are enabled with the ImPlotLineFlags_ parameter, like rendering lines as segments or as a closed loop. Several other plotters have also gained new abilities through their respective flags (see the full list below). The special flags in ImPlotItemFlags can be combined with ANY ImPlotXFlags, e.g. ImPlotItemFlags_NoLegend|ImPlotLineFlags_Segments is valid code.

Here's a complete list of flags available for our current plotters:

ImPlotItemFlags_NoLegend         // the item won't have a legend entry displayed
ImPlotItemFlags_NoFit            // the item won't be considered for plot fits

ImPlotLineFlags_Segments         // a line segment will be rendered from every two consecutive points
ImPlotLineFlags_Loop             // the last and first point will be connected to form a closed loop
ImPlotLineFlags_SkipNaN          // NaNs values will be skipped instead of rendered as missing data
ImPlotLineFlags_NoClip           // markers (if displayed) on the edge of a plot will not be clipped

ImPlotScatterFlags_NoClip        // markers on the edge of a plot will not be clipped

ImPlotStairsFlags_PreStep        // the y value is continued constantly to the left from every x position, i.e. the interval (x[i-1], x[i]] has the value y[i]

ImPlotBarsFlags_Horizontal       // bars will be rendered horizontally on the current y-axis

ImPlotBarGroupsFlags_Horizontal  // bar groups will be rendered horizontally on the current y-axis
ImPlotBarGroupsFlags_Stacked     // items in a group will be stacked on top of each other

ImPlotErrorBarsFlags_Horizontal  // error bars will be rendered horizontally on the current y-axis

ImPlotStemsFlags_Horizontal      // stems will be rendered horizontally on the current y-axis

ImPlotInfLinesFlags_Horizontal   // lines will be rendered horizontally on the current y-axis

ImPlotPieChartFlags_Normalize    // force normalization of pie chart values (i.e. always make a full circle if sum < 0)

ImPlotHeatmapFlags_ColMajor      // data will be read in column major order

ImPlotHistogramFlags_Horizontal  // histogram bars will be rendered horizontally (not supported by PlotHistogram2D)
ImPlotHistogramFlags_Cumulative  // each bin will contain its count plus the counts of all previous bins (not supported by PlotHistogram2D)
ImPlotHistogramFlags_Density     // counts will be normalized, i.e. the PDF will be visualized, or the CDF will be visualized if Cumulative is also set
ImPlotHistogramFlags_NoOutliers  // exclude values outside the specifed histogram range from the count toward normalizing and cumulative counts
ImPlotHistogramFlags_ColMajor    // data will be read in column major order (not supported by PlotHistogram)

ImPlotTextFlags_Vertical         // text will be rendered vertically

SUPER IMPORTANT NOTE: Each PlotX function's ImPlotLineFlags flags=0 parameter has been positioned before int offset=0, int stride=sizeof(T) where applicable. This unfortunately means that folks making use of offset and/or stride will need to update their function calls to include a flags parameter, else they will likely see strange results or crashes without any warning. This may rub some users the wrong way, but it was a necessary evil as it stylistically makes the most sense for the flags parameter to take priority over stride and offset in the default argument order for most use cases and users.

Besides that, items flags brings about a few other API breaking changes users should be aware of:

  • PlotBarsH has been removed; use PlotBars + ImPlotBarsFlags_Horizontal instead
  • PlotErrorBarsH has been removed; use PlotErrorBars + ImPlotErrorBarsFlags_Horizontal
  • PlotVLines and PlotHLines replaced with PlotInfLines (+ ImPlotInfLinesFlags_Horizontal )
  • PlotHistogram/PlotHistogram2D signatures changed; cumulative, density, and outliers options now specified via ImPlotHistogramFlags
  • PlotPieChart signature changed; normalize option now specified via ImPlotPieChartFlags
  • PlotText signature changes; vertical option now specified via ImPlotTextFlags_Vertical

Again, this change will likely cause headaches for some users, but with this new system in place you can expect more plotting options to be added in future updates in a flexible and, importantly, maintainable way. Thanks for understanding.

SetupAxisScale

Previously, users could define time and log scales with ImPlotAxisFlags_Log, and ImPlotAxisFlags_Time. These flags have been replaced with a more general system using a new the setup function SetupAxisScale:

// Axis scale
enum ImPlotScale_ {
    ImPlotScale_Linear = 0, // default linear scale
    ImPlotScale_Time,       // date/time scale
    ImPlotScale_Log10,      // base 10 logartithmic scale
    ImPlotScale_SymLog,     // symmetric log scale
};

// Sets an axis' scale using built-in options.
void SetupAxisScale(ImAxis axis, ImPlotScale scale);

ImPlotScale_SymLog is a new scale that produces a symmertic log scale with a linear region roughly between -1 and 1:

image

More built-in scales may be added in the future. Until then, you can also now define YOUR OWN scales using ImPlotTransform to provide a forward and inverse function:

// Callback signature for axis transform.
typedef double (*ImPlotTransform)(double value, void* user_data);

// Sets an axis' scale using user supplied forward and inverse transfroms.
void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=NULL);

Example:

static inline double TransformForward_Sqrt(double v, void*) {
    return sqrt(v);
}

static inline double TransformInverse_Sqrt(double v, void*) {
    return v*v;
}

...

if (ImPlot::BeginPlot("Sqrt")) {
    ImPlot::SetupAxis(ImAxis_X1, "Linear");
    ImPlot::SetupAxis(ImAxis_Y1, "Sqrt");
    ImPlot::SetupAxisScale(ImAxis_Y1, TransformForward_Sqrt, TransformInverse_Sqrt);
    ImPlot::PlotLine(...);
    ImPlot::EndPlot();
}

image

New Axis Constraints

You can now constrain axes limits so that users can't pan beyond a min or max value, or zoom beyond a min or max width/height. This is nice if you don't want users straying away from displayed data or zooming too far into view. It is demonstrated in the candlestick demo in implot_demo.cpp (see Custom Plotters and Tooltips).

// Sets an axis' limits constraints.
void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max);
// Sets an axis' zoom constraints.
void SetupAxisZoomConstraints(ImAxis axis, double z_min, double z_max);

Customize Supported Types

You can now customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list. As an example, you could use the compile time define given by the line below in order to support only float and double.

-DIMPLOT_CUSTOM_NUMERIC_TYPES="(float)(double)"

In order to support all known C++ types, use:

-DIMPLOT_CUSTOM_NUMERIC_TYPES="(signed char)(unsigned char)(signed short)(unsigned short)(signed int)(unsigned int)(signed long)(unsigned long)(signed long long)(unsigned long long)(float)(double)(long double)"

Special thanks to @pthom for inplementing this feature (#397) and greatly simplifying our plotter insantiation pipeline with some mean macro magic!

Continuous Integration

The ImPlot repository now provides CI through GitHub Actions. The jobs are setup to build ImPlot and a headless example application against the latest ImGui version across several compilers and platforms. Jobs are triggered for all new PRs.

Special thanks to @rokups for setting this up (#395), @ozlb for the initial push (#393), @pthom for further improvements (#397), and @ocornut for his thoughtful comments.

Misc. Improvements

  • Line plots now honor ImGui's AntiAliasedLines and AntiAliasedLinesUseTex. That's right, ImPlot now uses texture based AA! If you weren't using MSAA, you can now expect signficantly smoother lines for very little performance cost.
  • Markers and bar plots now render through ImPlot's custom render pipeline instead of ImGui's drawing API. This should speed up those plotters a good bit.
  • Compile times for implot_items.cpp should now be much quicker now.
  • Legend entries can be sorted using ImPlotLegendFlags_Sort