github epezent/implot v0.13
v0.13 WIP

latest releases: v0.16, v0.15, v0.14...
pre-release2 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)

Don't miss a new implot release

NewReleases is sending notifications on new releases.