Implot Versions Save

Immediate Mode Plotting

v0.16

8 months ago

This release mostly exists to fix my blunder when releasing v0.15 (forgot to update versioning in headers, oops!) @ocornut kindly attempted to rectify the issue, but this seems to have caused issues for some users (https://github.com/epezent/implot/issues/499). Also included are a few trivial bug fixes and a handful of small PRs.

Full Change Log: https://github.com/epezent/implot/compare/v0.15...v0.16

v0.15

9 months ago

What's Changed

New Contributors

Full Changelog: https://github.com/epezent/implot/compare/v0.14...v0.15

v0.14

1 year ago

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

v0.13

2 years ago

Setup API (see #272)

Previously, setting up a plot and its axes was done by passing several args to BeginPlot and leveraging a handful of preceding SetNextXXX functions. The former was becoming unwieldy with BeginPlot requiring additional args for each newly introduced feature, while the latter was always awkward and a bit of a nightmare to manage under the hood. Neither approach offered room to scale the API gracefully.

Taking a page out of ImGui's Tables API, plots and axes can now be configured by calling a host of optional SetupXXX functions immediately after BeginPlot. With this, the signature of BeginPlot has be greatly simplified. Here's a quick example:

if (BeginPlot("My Plot",ImVec2(-1,-1),ImPlotFlags_Crosshairs) { // 1) begin a new plot
  SetupAxis(ImAxis_X1, "Time", ImPlotAxisFlags_Time);           // 2) make Setup calls
  SetupAxis(ImAxis_Y1, "My Y-Axis");
  SetupAxisLimits(ImAxis_Y1, 0, 1000);
  SetupAxisFormat(ImAxis_Y1, "$%.0f");
  SetupLegend(ImPlotLocation_North);
  ...
  SetupFinish();                                                // 3) [optional] explicitly finish setup
  PlotLine(...);                                                // 4) plot items
  ...
  EndPlot();                                                    // 5) end the plot
}

All of the functionality you previously had with the original signature of BeginPlot and SetNextXXX is now available through the Setup API:

// Begin a new plot. 
bool BeginPlot(const char* title_id, const ImVec2& size = ImVec2(-1,0), ImPlotFlags flags = ImPlotFlags_None);
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = NULL for no label.
void SetupAxis(ImAxis axis, const char* label = NULL, ImPlotAxisFlags flags = ImPlotAxisFlags_None);
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot.
void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);
// Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f).
void SetupAxisFormat(ImAxis axis, const char* fmt);
// Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data.
void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data = NULL);
// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true.
void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[] = NULL, bool keep_default = false);
// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.
void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[] = NULL, bool keep_default = false);

// Sets the label and/or flags for primary X and Y axes (shorthand for two calls to SetupAxis).
void SetupAxes(const char* x_label, const char* y_label, ImPlotAxisFlags x_flags = ImPlotAxisFlags_None, ImPlotAxisFlags y_flags = ImPlotAxisFlags_None);
// Sets the primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits).
void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once);

// Sets up the plot legend.
void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags = ImPlotLegendFlags_None);
// Set the location of the current plot's mouse position text (default = South|East).
void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags = ImPlotMouseTextFlags_None);

// Explicitly finalize plot setup. Once you call this, you cannot make anymore Setup calls for the current plot!
// Note that calling this function is OPTIONAL; it will be called by the first subsequent setup-locking API call.
void SetupFinish();

A few notes:

  • Always call Setup code at the top of your BeginPlot conditional statement.
  • Setup is locked once you start plotting or explicitly call SetupFinish. Do NOT call Setup code after you begin plotting or after you make any non-Setup API calls (e.g. utils like PlotToPixels also lock Setup)
  • Calling SetupFinish is OPTIONAL, but probably good practice. If you do not all it yourself, then the first subsequent plotting or utility function will call it for you.
  • The primary X and Y axis (ImAxis_X1 and ImAxis_Y1) are always enabled. To enable auxiliary axes, you must call, e.g. SetupAxis(ImAxis_Y2,...). This replaces the existing method of enabling auxiliary axes, i.e. passing ImPlotFlags_YAxis2/3.
  • Some SetNextXXX API has been removed or renamed; check the top of implot.cpp for changelogs
  • The original BeginPlot signature has been deprecated, and usage will result in compiler warnings. Please begin transitioning your code before its removal v1.0! You can define IMPLOT_DISABLE_OBSOLETE_FUNCTIONS to remove it now.

New Axes Features

The new Setup API allows us to easily extend and add functionality to axes. Here are a few new features you can start using today, with more expected to come in the near future.

  • support for multiple x-axes (up to 3 x-axes, and 3 y-axes)
    • ImAxis_ enums replace ImPlotYAxis_
    • SetAxis replaces SetPlotYAxis
  • place axes on opposite side with ImPlotAxisFlags_Opposite or simply by dragging the axis to the other side
  • new style colors: ImPlotCol_AxisBgHovered and ImPlotCol_AxisBgActive
  • when multiple x or y axes are enabled, hovering an item legend icon highlights the axes it is plotted on
  • axes use ImGui::ButtonBehavior under the hood for more robust interaction

axes2

  • custom tick label formatting via ImPlotFormatter callbacks passed to SetupAxisFormat
  • formatting is applied to mouse position text
  • context menus now display axis label name, if available

fmt

Improved Tooling

  • Query has been removed and replaced with a more flexible tool, DragRect. Unlike the previous query system, these can be resized and multiple can exist in one plot. An example in the demo shows how you can convert plot selections in to new query rects.

dragect dragect2

  • TagX and TagY have been added and allow you to add custom labels to axes. These use either the axis' formatter, or a custom provided string. You can combine these with other tools like DragLine to create custom interactivity.

tags

  • DragPoint and DragLine no longer take a string ID. Instead they now expect an int ID, and as a result no longer display the optional label. Instead, use TagX/Y and Annotation to add labels too these tools if needed.
  • additional options for drag tools via ImPlotDragToolFlags

PlotBarGroups

  • Bar plots can now be plotted in groups.
  • Bar groups can be stacked
// Flags for ImPlot::PlotBarGroups
enum ImPlotBarGroupsFlags_ {
    ImPlotBarGroupsFlags_None     = 0,      // default
    ImPlotBarGroupsFlags_Stacked  = 1 << 0, // items in a group will be stacked on top of each other
};

// Plots a group of vertical bars. #values is a row-major matrix with #item_count rows and #group_count cols. #label_ids should have #item_count elements.
void PlotBarGroups(const char* const label_ids[], const T* values, int item_count, int group_count, double group_width=0.67, double x0=0, ImPlotBarGroupsFlags flags=ImPlotBarGroupsFlags_None);

// Plots a group of horizontal bars. #values is a row-major matrix with #item_count rows and #group_count cols. #label_ids should have #item_count elements.
void PlotBarGroupsH(const char* const label_ids[], const T* values, int item_count, int group_count, double group_height=0.67, double y0=0, ImPlotBarGroupsFlags flags=ImPlotBarGroupsFlags_None);

image

image

Return of ImPlotInputMap

  • ImPlotInputMap has been revamped and brought back into the public API, and two presets are now provided: Default and Reverse
struct ImPlotInputMap {
    ImGuiMouseButton Pan;           // LMB    enables panning when held,
    ImGuiKeyModFlags PanMod;        // none   optional modifier that must be held for panning/fitting
    ImGuiMouseButton Fit;           // LMB    initiates fit when double clicked
    ImGuiMouseButton Select;        // RMB    begins box selection when pressed and confirms selection when released
    ImGuiMouseButton SelectCancel;  // LMB    cancels active box selection when pressed; cannot be same as Select
    ImGuiKeyModFlags SelectMod;     // none   optional modifier that must be held for box selection
    ImGuiKeyModFlags SelectHorzMod; // Alt    expands active box selection horizontally to plot edge when held
    ImGuiKeyModFlags SelectVertMod; // Shift  expands active box selection vertically to plot edge when held
    ImGuiMouseButton Menu;          // RMB    opens context menus (if enabled) when clicked
    ImGuiKeyModFlags OverrideMod;   // Ctrl   when held, all input is ignored; used to enable axis/plots as DND sources
    ImGuiKeyModFlags ZoomMod;       // none   optional modifier that must be held for scroll wheel zooming
    float            ZoomRate;      // 0.1f   zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click); make negative to invert
    ImPlotInputMap();
};

// Provides access to input mapping structure for permanent modifications to controls for pan, select, etc.
ImPlotInputMap& GetInputMap();

// Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
void MapInputDefault(ImPlotInputMap* dst = NULL);
// Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
void MapInputReverse(ImPlotInputMap* dst = NULL);

Bug Fixes / Improvementss

  • fix Intel compiler warnings (#315)
  • replace sprintf/snprintf calls with ImFormatString for overridability (#310)
  • fix issues with striding when T != float (#303)
  • handle format-nonliteral warnings (#304)
  • fix issue with unitialized variables (#313)
  • make PlotText fitable (#286)

v0.12

2 years ago

Represents a stable release before API breaking changes to be introduced in v0.13.

v0.11

2 years ago

Merely fixes a bug released in v0.10 that caused incompatibility with pre-v1.84 ImGui.

v0.10

2 years ago

New Features

Bug Fixes / Improvements

  • fix y-axis log scale for histograms and bar charts #244
  • fix SampleColormapU32 return value #213
  • fix GetColormapSize return value #241
  • add big warning about 16-bit ImDrawIdx to demo and README #228
  • fix potential division by zero #229
  • fix max inclusivity issue when fitting #236

v0.9

3 years ago

New Features

API Breaking Changes

  • ImPlotInputMap moved to implot_internal.h
  • SetColormap and PushColormap(ImVec4*) have been removed in favor of AddColormap
  • LerpColormap was changed to SampleColormap.
  • ShowColormapScale is now ColormapScale and requires a label and ImVec2 size. The label will be displayed as an axis label (see above).
  • BeginLegendDragDropSource was changed to BeginDragDropSourceItem

Bug Fixes / Improvements

  • single rick-click context menus #170
  • heatmap performance improvements #148
  • date picker disabled color #174
  • fix formatting for axis labels near zero #176
  • improve fit logic for constant or flat data #154

See #168 for more information and screenshots!

v0.8

3 years ago

New Features / Changes

  • support for all typical scalar types
  • configurable legend locations
  • functions for adding annotations
  • tools for draggable reference lines and points
  • ISO 8601 date formatting for time axes
  • date/time pickers for time axes context menus
  • scale and offset args for single array plotting functions
  • PlotImage
  • PlotStairs

See https://github.com/epezent/implot/issues/48 for more details.

Bug Fixes / Improvements

v0.7

3 years ago

New Features / Changes

Bug Fixes / Improvements

  • improved axis constraints
  • updated README images