mirror of
https://github.com/gwm17/implot.git
synced 2024-11-26 12:18:52 -05:00
Adds PlotHistogram and PlotHistogram2D, Improves Colormaps and Heatmap (#148)
This commit is contained in:
parent
b85a2c0800
commit
1d9381a004
780
implot.cpp
780
implot.cpp
File diff suppressed because it is too large
Load Diff
262
implot.h
262
implot.h
|
@ -1,6 +1,6 @@
|
|||
// MIT License
|
||||
|
||||
// Copyright (c) 2020 Evan Pezent
|
||||
// Copyright (c) 2021 Evan Pezent
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -32,7 +32,7 @@
|
|||
// Define attributes of all API symbols declarations (e.g. for DLL under Windows)
|
||||
// Using ImPlot via a shared library is not recommended, because we don't guarantee
|
||||
// backward nor forward ABI compatibility and also function call overhead. If you
|
||||
// do use ImPlot as a DLL, be sure to call SetImGuiContext (details below).
|
||||
// do use ImPlot as a DLL, be sure to call SetImGuiContext (see Miscellanous section).
|
||||
#ifndef IMPLOT_API
|
||||
#define IMPLOT_API
|
||||
#endif
|
||||
|
@ -61,6 +61,7 @@ typedef int ImPlotColormap; // -> enum ImPlotColormap_
|
|||
typedef int ImPlotLocation; // -> enum ImPlotLocation_
|
||||
typedef int ImPlotOrientation; // -> enum ImPlotOrientation_
|
||||
typedef int ImPlotYAxis; // -> enum ImPlotYAxis_;
|
||||
typedef int ImPlotBin; // -> enum ImPlotBin_
|
||||
|
||||
// Options for plots.
|
||||
enum ImPlotFlags_ {
|
||||
|
@ -85,14 +86,15 @@ enum ImPlotFlags_ {
|
|||
enum ImPlotAxisFlags_ {
|
||||
ImPlotAxisFlags_None = 0, // default
|
||||
ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels also hidden if the supplied string name is NULL)
|
||||
ImPlotAxisFlags_NoGridLines = 1 << 1, // the axis grid lines will not be displayed
|
||||
ImPlotAxisFlags_NoTickMarks = 1 << 2, // the axis tick marks will not be displayed
|
||||
ImPlotAxisFlags_NoTickLabels = 1 << 3, // the axis tick labels will not be displayed
|
||||
ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed
|
||||
ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed
|
||||
ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed
|
||||
ImPlotAxisFlags_LogScale = 1 << 4, // a logartithmic (base 10) axis scale will be used (mutually exclusive with ImPlotAxisFlags_Time)
|
||||
ImPlotAxisFlags_Time = 1 << 5, // axis will display date/time formatted labels (mutually exclusive with ImPlotAxisFlags_LogScale)
|
||||
ImPlotAxisFlags_Invert = 1 << 6, // the axis will be inverted
|
||||
ImPlotAxisFlags_LockMin = 1 << 7, // the axis minimum value will be locked when panning/zooming
|
||||
ImPlotAxisFlags_LockMax = 1 << 8, // the axis maximum value will be locked when panning/zooming
|
||||
ImPlotAxisFlags_AutoFit = 1 << 7, // axis will be auto-fitting to data extents
|
||||
ImPlotAxisFlags_LockMin = 1 << 8, // the axis minimum value will be locked when panning/zooming
|
||||
ImPlotAxisFlags_LockMax = 1 << 9, // the axis maximum value will be locked when panning/zooming
|
||||
ImPlotAxisFlags_Lock = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax,
|
||||
ImPlotAxisFlags_NoDecorations = ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoTickMarks | ImPlotAxisFlags_NoTickLabels
|
||||
};
|
||||
|
@ -180,18 +182,22 @@ enum ImPlotMarker_ {
|
|||
|
||||
// Built-in colormaps
|
||||
enum ImPlotColormap_ {
|
||||
ImPlotColormap_Default = 0, // ImPlot default colormap (n=10)
|
||||
ImPlotColormap_Deep = 1, // a.k.a. seaborn deep (n=10)
|
||||
ImPlotColormap_Dark = 2, // a.k.a. matplotlib "Set1" (n=9)
|
||||
ImPlotColormap_Pastel = 3, // a.k.a. matplotlib "Pastel1" (n=9)
|
||||
ImPlotColormap_Paired = 4, // a.k.a. matplotlib "Paired" (n=12)
|
||||
ImPlotColormap_Viridis = 5, // a.k.a. matplotlib "viridis" (n=11)
|
||||
ImPlotColormap_Plasma = 6, // a.k.a. matplotlib "plasma" (n=11)
|
||||
ImPlotColormap_Hot = 7, // a.k.a. matplotlib/MATLAB "hot" (n=11)
|
||||
ImPlotColormap_Cool = 8, // a.k.a. matplotlib/MATLAB "cool" (n=11)
|
||||
ImPlotColormap_Pink = 9, // a.k.a. matplotlib/MATLAB "pink" (n=11)
|
||||
ImPlotColormap_Jet = 10, // a.k.a. MATLAB "jet" (n=11)
|
||||
ImPlotColormap_COUNT
|
||||
ImPlotColormap_Deep = 0, // a.k.a. seaborn deep (qual=true, n=10) (default)
|
||||
ImPlotColormap_Dark = 1, // a.k.a. matplotlib "Set1" (qual=true, n=9 )
|
||||
ImPlotColormap_Pastel = 2, // a.k.a. matplotlib "Pastel1" (qual=true, n=9 )
|
||||
ImPlotColormap_Paired = 3, // a.k.a. matplotlib "Paired" (qual=true, n=12)
|
||||
ImPlotColormap_Viridis = 4, // a.k.a. matplotlib "viridis" (qual=false, n=11)
|
||||
ImPlotColormap_Plasma = 5, // a.k.a. matplotlib "plasma" (qual=false, n=11)
|
||||
ImPlotColormap_Hot = 6, // a.k.a. matplotlib/MATLAB "hot" (qual=false, n=11)
|
||||
ImPlotColormap_Cool = 7, // a.k.a. matplotlib/MATLAB "cool" (qual=false, n=11)
|
||||
ImPlotColormap_Pink = 8, // a.k.a. matplotlib/MATLAB "pink" (qual=false, n=11)
|
||||
ImPlotColormap_Jet = 9, // a.k.a. MATLAB "jet" (qual=false, n=11)
|
||||
ImPlotColormap_Twilight = 10, // a.k.a. matplotlib "twilight" (qual=false, n=11)
|
||||
ImPlotColormap_RdBu = 11, // red/blue, Color Brewer (qual=false, n=11)
|
||||
ImPlotColormap_BrBG = 12, // brown/blue-green, Color Brewer (qual=false, n=11)
|
||||
ImPlotColormap_PiYG = 13, // pink/yellow-green, Color Brewer (qual=false, n=11)
|
||||
ImPlotColormap_Spectral = 14, // color spectrum, Color Brewer (qual=false, n=11)
|
||||
ImPlotColormap_Greys = 15, // white/black (qual=false, n=2 )
|
||||
};
|
||||
|
||||
// Used to position items on a plot (e.g. legends, labels, etc.)
|
||||
|
@ -220,6 +226,14 @@ enum ImPlotYAxis_ {
|
|||
ImPlotYAxis_3 = 2 // second on right side
|
||||
};
|
||||
|
||||
// Enums for different automatic histogram binning methods (k = bin count or w = bin width)
|
||||
enum ImPlotBin_ {
|
||||
ImPlotBin_Sqrt = -1, // k = sqrt(n)
|
||||
ImPlotBin_Sturges = -2, // k = 1 + log2(n)
|
||||
ImPlotBin_Rice = -3, // k = 2 * cbrt(n)
|
||||
ImPlotBin_Scott = -4, // w = 3.49 * sigma / cbrt(n)
|
||||
};
|
||||
|
||||
// Double precision version of ImVec2 used by ImPlot. Extensible by end users.
|
||||
struct ImPlotPoint {
|
||||
double x, y;
|
||||
|
@ -246,8 +260,12 @@ struct ImPlotRange {
|
|||
// Combination of two ranges for X and Y axes.
|
||||
struct ImPlotLimits {
|
||||
ImPlotRange X, Y;
|
||||
ImPlotLimits() { }
|
||||
ImPlotLimits(double x_min, double x_max, double y_min, double y_max) { X.Min = x_min; X.Max = x_max; Y.Min = y_min; Y.Max = y_max; }
|
||||
bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); }
|
||||
bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); }
|
||||
ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); }
|
||||
ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); }
|
||||
};
|
||||
|
||||
// Plot style structure
|
||||
|
@ -275,14 +293,16 @@ struct ImPlotStyle {
|
|||
ImVec2 LabelPadding; // = 5,5 padding between axes labels, tick labels, and plot edge
|
||||
ImVec2 LegendPadding; // = 10,10 legend padding from plot edges
|
||||
ImVec2 LegendInnerPadding; // = 5,5 legend inner padding from legend edges
|
||||
ImVec2 LegendSpacing; // = 0,0 spacing between legend entries
|
||||
ImVec2 LegendSpacing; // = 5,0 spacing between legend entries
|
||||
ImVec2 MousePosPadding; // = 10,10 padding between plot edge and interior mouse location text
|
||||
ImVec2 AnnotationPadding; // = 2,2 text padding around annotation labels
|
||||
ImVec2 FitPadding; // = 0,0 additional fit padding as a percentage of the fit extents (e.g. ImVec2(0.1f,0.1f) adds 10% to the fit extents of X and Y)
|
||||
ImVec2 PlotDefaultSize; // = 400,300 default size used when ImVec2(0,0) is passed to BeginPlot
|
||||
ImVec2 PlotMinSize; // = 300,225 minimum size plot frame can be when shrunk
|
||||
// colors
|
||||
ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors
|
||||
// style colors
|
||||
ImVec4 Colors[ImPlotCol_COUNT]; // Array of styling colors. Indexable with ImPlotCol_ enums.
|
||||
// colormap
|
||||
ImPlotColormap Colormap; // The current colormap. Set this to either an ImPlotColormap_ enum or an index returned by AddColormap.
|
||||
// settings/flags
|
||||
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
|
||||
bool UseLocalTime; // = false, axis labels will be formatted for your timezone when ImPlotAxisFlag_Time is enabled
|
||||
|
@ -303,22 +323,43 @@ namespace ImPlot {
|
|||
|
||||
// Creates a new ImPlot context. Call this after ImGui::CreateContext.
|
||||
IMPLOT_API ImPlotContext* CreateContext();
|
||||
// Destroys an ImPlot context. Call this before ImGui::DestroyContext. NULL = destroy current context
|
||||
// Destroys an ImPlot context. Call this before ImGui::DestroyContext. NULL = destroy current context.
|
||||
IMPLOT_API void DestroyContext(ImPlotContext* ctx = NULL);
|
||||
// Returns the current ImPlot context. NULL if no context has ben set.
|
||||
IMPLOT_API ImPlotContext* GetCurrentContext();
|
||||
// Sets the current ImPlot context.
|
||||
IMPLOT_API void SetCurrentContext(ImPlotContext* ctx);
|
||||
|
||||
// Sets the current **ImGui** context. This is ONLY necessary if you are compiling
|
||||
// ImPlot as a DLL (not recommended) separate from your ImGui compilation. It
|
||||
// sets the global variable GImGui, which is not shared across DLL boundaries.
|
||||
// See GImGui documentation in imgui.cpp for more details.
|
||||
IMPLOT_API void SetImGuiContext(ImGuiContext* ctx);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Begin/End Plot
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Starts a 2D plotting context. If this function returns true, EndPlot() must
|
||||
// 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" or "##NoTitle").
|
||||
// If #x_label and/or #y_label are provided, axes labels will be displayed.
|
||||
// be called! You are encouraged to use the following call convention:
|
||||
//
|
||||
// if (BeginPlot(...)) {
|
||||
// ImPlot::PlotLine(...);
|
||||
// EndPlot();
|
||||
// }
|
||||
//
|
||||
// Important notes:
|
||||
//
|
||||
// - #title_id must be unique to the current ImGui window. 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" or "##NoTitle").
|
||||
// - If #x_label and/or #y_label are provided, axes labels will be displayed.
|
||||
// - #size is the **frame** size of the plot widget, not the plot area. The default
|
||||
// size of plots (i.e. when ImVec2(0,0)) can be modified in your ImPlotStyle
|
||||
// (default is 400x300).
|
||||
// - Auxiliary y-axes must be enabled with ImPlotFlags_YAxis2/3 to be displayed.
|
||||
// - See ImPlotFlags and ImPlotAxisFlags for more available options.
|
||||
|
||||
IMPLOT_API bool BeginPlot(const char* title_id,
|
||||
const char* x_label = NULL,
|
||||
const char* y_label = NULL,
|
||||
|
@ -332,7 +373,7 @@ IMPLOT_API bool BeginPlot(const char* title_id,
|
|||
const char* y3_label = NULL);
|
||||
|
||||
// Only call EndPlot() if BeginPlot() returns true! Typically called at the end
|
||||
// of an if statement conditioned on BeginPlot().
|
||||
// of an if statement conditioned on BeginPlot(). See above.
|
||||
IMPLOT_API void EndPlot();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -356,9 +397,9 @@ IMPLOT_API void EndPlot();
|
|||
// Vector2f data[42];
|
||||
// ImPlot::PlotLine("line", &data[0].x, &data[0].y, 42, 0, sizeof(Vector2f)); // or sizeof(float)*2
|
||||
//
|
||||
// 2. Write a custom getter function or C++ lambda and pass it and your data to
|
||||
// 2. Write a custom getter C function or C++ lambda and pass it and your data to
|
||||
// an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a
|
||||
// slight performance cost, but probably not enough to worry about.
|
||||
// slight performance cost, but probably not enough to worry about. Example:
|
||||
//
|
||||
// ImPlotPoint MyDataGetter(void* data, int idx) {
|
||||
// MyData* my_data = (MyData*)data;
|
||||
|
@ -368,8 +409,17 @@ IMPLOT_API void EndPlot();
|
|||
// return p
|
||||
// }
|
||||
// ...
|
||||
// auto my_lambda = [](void*, int idx) {
|
||||
// double t = idx / 999.0;
|
||||
// return ImPlotPoint(t, 0.5+0.5*std::sin(2*PI*10*t));
|
||||
// };
|
||||
// ...
|
||||
// if (ImPlot::BeginPlot("MyPlot")) {
|
||||
// MyData my_data;
|
||||
// ImPlot::PlotScatterG("scatter", MyDataGetter, &my_data, my_data.Size());
|
||||
// ImPlot::PlotLineG("line", my_lambda, nullptr, 1000);
|
||||
// ImPlot::EndPlot();
|
||||
// }
|
||||
//
|
||||
// NB: All types are converted to double before plotting. You may lose information
|
||||
// if you try plotting extremely large 64-bit integral types. Proceed with caution!
|
||||
|
@ -427,6 +477,16 @@ template <typename T> IMPLOT_API void PlotPieChart(const char* const label_ids[]
|
|||
// Plots a 2D heatmap chart. Values are expected to be in row-major order. #label_fmt can be set to NULL for no labels.
|
||||
template <typename T> IMPLOT_API void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1));
|
||||
|
||||
// Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #cumulative is true, each bin contains its count plus the counts of all previous bins.
|
||||
// If #density is true, the PDF is visualized. If both are true, the CDF is visualized. If #range is left unspecified, the min/max of #values will be used as the range.
|
||||
// If #range is specified, outlier values outside of the range are not binned. However, outliers still count toward normalizing and cumulative counts unless #outliers is false. The largest bin count or density is returned.
|
||||
template <typename T> IMPLOT_API double PlotHistogram(const char* label_id, const T* values, int count, int bins=ImPlotBin_Sturges, bool cumulative=false, bool density=false, ImPlotRange range=ImPlotRange(), bool outliers=true, double bar_scale=1.0);
|
||||
|
||||
// Plots two dimensional, bivariate histogram as a heatmap. #x_bins and #y_bins can be a positive integer or an ImPlotBin. If #density is true, the PDF is visualized.
|
||||
// If #range is left unspecified, the min/max of #xs an #ys will be used as the ranges. If #range is specified, outlier values outside of range are not binned.
|
||||
// However, outliers still count toward the normalizing count for density plots unless #outliers is false. The largest bin count or density is returned.
|
||||
template <typename T> IMPLOT_API double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins=ImPlotBin_Sturges, int y_bins=ImPlotBin_Sturges, bool density=false, ImPlotLimits range=ImPlotLimits(), bool outliers=true);
|
||||
|
||||
// Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot.
|
||||
template <typename T> IMPLOT_API void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset=0);
|
||||
|
@ -437,7 +497,7 @@ IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, con
|
|||
// Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...).
|
||||
IMPLOT_API void PlotText(const char* text, double x, double y, bool vertical=false, const ImVec2& pix_offset=ImVec2(0,0));
|
||||
|
||||
// Plots an dummy item (i.e. adds a legend entry colored by ImPlotCol_Line)
|
||||
// Plots a dummy item (i.e. adds a legend entry colored by ImPlotCol_Line)
|
||||
IMPLOT_API void PlotDummy(const char* label_id);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -529,7 +589,7 @@ IMPLOT_API bool DragPoint(const char* id, double* x, double* y, bool show_label
|
|||
|
||||
// The following functions MUST be called BETWEEN Begin/EndPlot!
|
||||
|
||||
// Set the location of the current plot's legend.
|
||||
// Set the location of the current plot's legend (default = North|West).
|
||||
IMPLOT_API void SetLegendLocation(ImPlotLocation location, ImPlotOrientation orientation = ImPlotOrientation_Vertical, bool outside = false);
|
||||
// Set the location of the current plot's mouse position text (default = South|East).
|
||||
IMPLOT_API void SetMousePosLocation(ImPlotLocation location);
|
||||
|
@ -576,26 +636,55 @@ IMPLOT_API void EndDragDropSource();
|
|||
// Plot and Item Styling
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Styling colors in ImPlot works similarly to styling colors in ImGui, but
|
||||
// with one important difference. Like ImGui, all style colors are stored in an
|
||||
// indexable array in ImPlotStyle. You can permanently modify these values through
|
||||
// GetStyle().Colors, or temporarily modify them with Push/Pop functions below.
|
||||
// However, by default all style colors in ImPlot default to a special color
|
||||
// IMPLOT_AUTO_COL. The behavior of this color depends upon the style color to
|
||||
// which it as applied:
|
||||
//
|
||||
// 1) For style colors associated with plot items (e.g. ImPlotCol_Line),
|
||||
// IMPLOT_AUTO_COL tells ImPlot to color the item with the next unused
|
||||
// color in the current colormap. Thus, every item will have a different
|
||||
// color up to the number of colors in the colormap, at which point the
|
||||
// colormap will roll over. For most use cases, you should not need to
|
||||
// modify these style colors to anything but IMPLOT_COL_AUTO. You are
|
||||
// probably better off changing the current colormap. However, if you
|
||||
// need to explicitly color a particular item you may either Push/Pop
|
||||
// the style color around the item in question, or use the SetNextXXXStyle
|
||||
// API below. If you permanently set one of these style colors to a specific
|
||||
// color, or forget to call Pop, then all subsequent items will be styled
|
||||
// with the color you set.
|
||||
//
|
||||
// 2) For style colors associated with plot styling (e.g. ImPlotCol_PlotBg),
|
||||
// IMPLOT_AUTO_COL tells ImPlot to set that color from color data in your
|
||||
// **ImGuiStyle**. The ImGuiCol_ that these style colors default to are
|
||||
// detailed above, and in general have been mapped to produce plots visually
|
||||
// consistent with your current ImGui style. Of course, you are free to
|
||||
// manually set these colors to whatever you like, and further can Push/Pop
|
||||
// them around individual plots.
|
||||
|
||||
// Provides access to plot style structure for permanant modifications to colors, sizes, etc.
|
||||
IMPLOT_API ImPlotStyle& GetStyle();
|
||||
|
||||
// Style colors for current ImGui style (default).
|
||||
// Style plot colors for current ImGui style (default).
|
||||
IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = NULL);
|
||||
// Style colors for ImGui "Classic".
|
||||
// Style plot colors for ImGui "Classic".
|
||||
IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = NULL);
|
||||
// Style colors for ImGui "Dark".
|
||||
// Style plot colors for ImGui "Dark".
|
||||
IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = NULL);
|
||||
// Style colors for ImGui "Light".
|
||||
// Style plot colors for ImGui "Light".
|
||||
IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = NULL);
|
||||
|
||||
// Use PushStyleX to temporarily modify your ImPlotStyle. The modification
|
||||
// will last until the matching call to PopStyleX. You MUST call a pop for
|
||||
// every push, otherwise you will leak memory! This behaves just like ImGui.
|
||||
|
||||
// Temporarily modify a plot color. Don't forget to call PopStyleColor!
|
||||
// Temporarily modify a style color. Don't forget to call PopStyleColor!
|
||||
IMPLOT_API void PushStyleColor(ImPlotCol idx, ImU32 col);
|
||||
IMPLOT_API void PushStyleColor(ImPlotCol idx, const ImVec4& col);
|
||||
// Undo temporary color modification. Undo multiple pushes at once by increasing count.
|
||||
// Undo temporary style color modification(s). Undo multiple pushes at once by increasing count.
|
||||
IMPLOT_API void PopStyleColor(int count = 1);
|
||||
|
||||
// Temporarily modify a style variable of float type. Don't forget to call PopStyleVar!
|
||||
|
@ -604,7 +693,7 @@ IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, float val);
|
|||
IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, int val);
|
||||
// Temporarily modify a style variable of ImVec2 type. Don't forget to call PopStyleVar!
|
||||
IMPLOT_API void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val);
|
||||
// Undo temporary style modification. Undo multiple pushes at once by increasing count.
|
||||
// Undo temporary style variable modification(s). Undo multiple pushes at once by increasing count.
|
||||
IMPLOT_API void PopStyleVar(int count = 1);
|
||||
|
||||
// The following can be used to modify the style of the next plot item ONLY. They do
|
||||
|
@ -633,55 +722,82 @@ IMPLOT_API const char* GetMarkerName(ImPlotMarker idx);
|
|||
// Colormaps
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Item styling is based on Colormaps when the relevant ImPlotCol_ is set to
|
||||
// IMPLOT_AUTO_COL (default). Several built in colormaps are available and can be
|
||||
// toggled in the demo. You can push/pop or set your own colormaps as well.
|
||||
// Item styling is based on colormaps when the relevant ImPlotCol_XXX is set to
|
||||
// IMPLOT_AUTO_COL (default). Several built-in colormaps are available. You can
|
||||
// add and then push/pop your own colormaps as well. To permanently set a colormap,
|
||||
// modify the Colormap index member of your ImPlotStyle.
|
||||
|
||||
// The Colormap data will be ignored and a custom color will be used if you have done one of the following:
|
||||
// Colormap data will be ignored and a custom color will be used if you have done one of the following:
|
||||
// 1) Modified an item style color in your ImPlotStyle to anything other than IMPLOT_AUTO_COL.
|
||||
// 2) Pushed an item style color using PushStyleColor().
|
||||
// 3) Set the next item style with a SetNextXStyle function.
|
||||
// 3) Set the next item style with a SetNextXXXStyle function.
|
||||
|
||||
// Temporarily switch to one of the built-in colormaps.
|
||||
IMPLOT_API void PushColormap(ImPlotColormap colormap);
|
||||
// Temporarily switch to your custom colormap. The pointer data must persist until the matching call to PopColormap!
|
||||
IMPLOT_API void PushColormap(const ImVec4* colormap, int size);
|
||||
// Undo temporary colormap modification.
|
||||
// Add a new colormap. The colormap can be used by pushing either the returned index or the string name with PushColormap.
|
||||
// The colormap name must be unique and the size must be greater than 1. You will receive an assert otherwise! By default
|
||||
// colormaps are considered to be qualitative (i.e. discrete). If you want to create a continuous colormap, set #qual=false.
|
||||
// This will treat the colors you provide as keys, and ImPlot will build a linearly interpolated lookup table that fills
|
||||
// in the gaps. The memory footprint of this table will be exactly ((size-1)*255+1)*4 bytes.
|
||||
IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImVec4* cols, int size, bool qual=true);
|
||||
IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int size, bool qual=true);
|
||||
|
||||
// Returns the number of available colormaps.
|
||||
IMPLOT_API int GetColormapCount();
|
||||
// Returns a null terminated string name for a colormap given an index. Returns NULL if index is invalid.
|
||||
IMPLOT_API const char* GetColormapName(ImPlotColormap cmap);
|
||||
// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid.
|
||||
IMPLOT_API ImPlotColormap GetColormapIndex(const char* name);
|
||||
|
||||
// Temporarily switch to one of the built-in (i.e. ImPlotColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to call PopColormap!
|
||||
IMPLOT_API void PushColormap(ImPlotColormap cmap);
|
||||
// Push a colormap by string name. Use built-in names such as "Default", "Deep", "Jet", etc or a string you provided to AddColormap. Don't forget to call PopColormap!
|
||||
IMPLOT_API void PushColormap(const char* name);
|
||||
// Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count.
|
||||
IMPLOT_API void PopColormap(int count = 1);
|
||||
|
||||
// Permanently sets a custom colormap. The colors will be copied to internal memory. Typically used on startup. Prefer PushColormap instead of calling this each frame.
|
||||
IMPLOT_API void SetColormap(const ImVec4* colormap, int size);
|
||||
// Permanently switch to one of the built-in colormaps. If samples is greater than 1, the map will be linearly resampled. Typically used on startup. Don't call this each frame.
|
||||
IMPLOT_API void SetColormap(ImPlotColormap colormap, int samples = 0);
|
||||
|
||||
// Returns the size of the current colormap.
|
||||
IMPLOT_API int GetColormapSize();
|
||||
// Returns a color from the Color map given an index >= 0 (modulo will be performed).
|
||||
IMPLOT_API ImVec4 GetColormapColor(int index);
|
||||
// Linearly interpolates a color from the current colormap given t between 0 and 1.
|
||||
IMPLOT_API ImVec4 LerpColormap(float t);
|
||||
// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.
|
||||
// Returns the next color from the current colormap and advances the colormap for the current plot.
|
||||
// Can also be used with no return value to skip colors if desired. You need to call this between Begin/EndPlot!
|
||||
IMPLOT_API ImVec4 NextColormapColor();
|
||||
|
||||
// Renders a vertical color scale using the current color map. Call this before or after Begin/EndPlot.
|
||||
IMPLOT_API void ShowColormapScale(double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0));
|
||||
// Colormap utils. If cmap = IMPLOT_AUTO (default), the current colormap is assumed.
|
||||
// Pass an explicit colormap index (built-in or user added) to specify otherwise.
|
||||
|
||||
// Returns a null terminated string name for a built-in colormap.
|
||||
IMPLOT_API const char* GetColormapName(ImPlotColormap colormap);
|
||||
// Returns the size of a colormap.
|
||||
IMPLOT_API int GetColormapSize(ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Returns a color from a colormap given an index >= 0 (modulo will be performed).
|
||||
IMPLOT_API ImVec4 GetColormapColor(int idx, ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Sample a color from the current colormap given t between 0 and 1.
|
||||
IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
|
||||
// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel").
|
||||
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
|
||||
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = NULL, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Shows a button with a colormap gradient brackground.
|
||||
IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
|
||||
// When items in a plot sample their color from a colormap, the color is cached and does not change
|
||||
// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted,
|
||||
// item colors will not update. If you need item colors to resample the new colormap, then use this
|
||||
// function to bust the cached colors. If #plot_title_id is NULL, then every item in EVERY existing plot
|
||||
// will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the
|
||||
// latter, this function must be called in the ImGui window that the plot is in. You should rarely if ever
|
||||
// need this function, but it is available for applications that require runtime swaps (see Heatmaps demo).
|
||||
IMPLOT_API void BustColorCache(const char* plot_title_id = NULL);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Miscellaneous
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Render a icon similar to those that appear in legends (nifty for data lists).
|
||||
// Render icons similar to those that appear in legends (nifty for data lists).
|
||||
IMPLOT_API void ItemIcon(const ImVec4& col);
|
||||
IMPLOT_API void ItemIcon(ImU32 col);
|
||||
IMPLOT_API void ColormapIcon(ImPlotColormap cmap);
|
||||
|
||||
// Get the plot draw list for rendering to the current plot area.
|
||||
// Get the plot draw list for custom rendering to the current plot area. Call between Begin/EndPlot.
|
||||
IMPLOT_API ImDrawList* GetPlotDrawList();
|
||||
// Push clip rect for rendering to current plot area.
|
||||
// Push clip rect for rendering to current plot area. Call between Begin/EndPlot.
|
||||
IMPLOT_API void PushPlotClipRect();
|
||||
// Pop plot clip rect.
|
||||
// Pop plot clip rect. Call between Begin/EndPlot.
|
||||
IMPLOT_API void PopPlotClipRect();
|
||||
|
||||
// Shows ImPlot style selector dropdown menu.
|
||||
|
@ -690,17 +806,11 @@ IMPLOT_API bool ShowStyleSelector(const char* label);
|
|||
IMPLOT_API bool ShowColormapSelector(const char* label);
|
||||
// Shows ImPlot style editor block (not a window).
|
||||
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL);
|
||||
// Add basic help/info block (not a window): how to manipulate ImPlot as an end-user.
|
||||
// Add basic help/info block for end users (not a window).
|
||||
IMPLOT_API void ShowUserGuide();
|
||||
// Shows ImPlot metrics/debug information.
|
||||
IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL);
|
||||
|
||||
// Sets the current _ImGui_ context. This is ONLY necessary if you are compiling
|
||||
// ImPlot as a DLL (not recommended) separate from your ImGui compilation. It
|
||||
// sets the global variable GImGui, which is not shared across DLL boundaries.
|
||||
// See GImGui documentation in imgui.cpp for more details.
|
||||
IMPLOT_API void SetImGuiContext(ImGuiContext* ctx);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Demo (add implot_demo.cpp to your sources!)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
274
implot_demo.cpp
274
implot_demo.cpp
|
@ -1,6 +1,6 @@
|
|||
// MIT License
|
||||
|
||||
// Copyright (c) 2020 Evan Pezent
|
||||
// Copyright (c) 2021 Evan Pezent
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -27,7 +27,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define sprintf sprintf_s
|
||||
|
@ -76,6 +75,44 @@ inline T RandomRange(T min, T max) {
|
|||
return min + scale * ( max - min );
|
||||
}
|
||||
|
||||
ImVec4 RandomColor() {
|
||||
ImVec4 col;
|
||||
col.x = RandomRange(0.0f,1.0f);
|
||||
col.y = RandomRange(0.0f,1.0f);
|
||||
col.z = RandomRange(0.0f,1.0f);
|
||||
col.w = 1.0f;
|
||||
return col;
|
||||
}
|
||||
|
||||
double RandomGauss() {
|
||||
static double V1, V2, S;
|
||||
static int phase = 0;
|
||||
double X;
|
||||
if(phase == 0) {
|
||||
do {
|
||||
double U1 = (double)rand() / RAND_MAX;
|
||||
double U2 = (double)rand() / RAND_MAX;
|
||||
V1 = 2 * U1 - 1;
|
||||
V2 = 2 * U2 - 1;
|
||||
S = V1 * V1 + V2 * V2;
|
||||
} while(S >= 1 || S == 0);
|
||||
|
||||
X = V1 * sqrt(-2 * log(S) / S);
|
||||
} else
|
||||
X = V2 * sqrt(-2 * log(S) / S);
|
||||
phase = 1 - phase;
|
||||
return X;
|
||||
}
|
||||
|
||||
template <int N>
|
||||
struct NormalDistribution {
|
||||
NormalDistribution(double mean, double sd) {
|
||||
for (int i = 0; i < N; ++i)
|
||||
Data[i] = RandomGauss()*sd + mean;
|
||||
}
|
||||
double Data[N];
|
||||
};
|
||||
|
||||
// utility structure for realtime plot
|
||||
struct ScrollingBuffer {
|
||||
int MaxSize;
|
||||
|
@ -511,11 +548,17 @@ void ShowDemoWindow(bool* p_open) {
|
|||
static const char* ylabels[] = {"R1","R2","R3","R4","R5","R6","R7"};
|
||||
|
||||
static ImPlotColormap map = ImPlotColormap_Viridis;
|
||||
if (ImGui::Button("Change Colormap",ImVec2(225,0)))
|
||||
map = (map + 1) % ImPlotColormap_COUNT;
|
||||
if (ImPlot::ColormapButton(ImPlot::GetColormapName(map),ImVec2(225,0),map)) {
|
||||
map = (map + 1) % ImPlot::GetColormapCount();
|
||||
// We bust the color cache of our plots so that item colors will
|
||||
// resample the new colormap in the event that they have already
|
||||
// been created. See documentation in implot.h.
|
||||
BustColorCache("##Heatmap1");
|
||||
BustColorCache("##Heatmap2");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::LabelText("##Colormap Index", "%s", ImPlot::GetColormapName(map));
|
||||
ImGui::LabelText("##Colormap Index", "%s", "Change Colormap");
|
||||
ImGui::SetNextItemWidth(225);
|
||||
ImGui::DragFloatRange2("Min / Max",&scale_min, &scale_max, 0.01f, -20, 20);
|
||||
static ImPlotAxisFlags axes_flags = ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoTickMarks;
|
||||
|
@ -528,25 +571,153 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImPlot::EndPlot();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImPlot::ShowColormapScale(scale_min, scale_max, ImVec2(60,225));
|
||||
ImPlot::PopColormap();
|
||||
ImPlot::ColormapScale("##HeatScale",scale_min, scale_max, ImVec2(60,225));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
static double values2[100*100];
|
||||
const int size = 200;
|
||||
static double values2[size*size];
|
||||
srand((unsigned int)(DEMO_TIME*1000000));
|
||||
for (int i = 0; i < 100*100; ++i)
|
||||
for (int i = 0; i < size*size; ++i)
|
||||
values2[i] = RandomRange(0.0,1.0);
|
||||
|
||||
static ImVec4 gray[2] = {ImVec4(0,0,0,1), ImVec4(1,1,1,1)};
|
||||
ImPlot::PushColormap(gray, 2);
|
||||
ImPlot::SetNextPlotLimits(-1,1,-1,1);
|
||||
if (ImPlot::BeginPlot("##Heatmap2",NULL,NULL,ImVec2(225,225),0,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations)) {
|
||||
ImPlot::PlotHeatmap("heat1",values2,100,100,0,1,NULL);
|
||||
ImPlot::PlotHeatmap("heat2",values2,100,100,0,1,NULL, ImPlotPoint(-1,-1), ImPlotPoint(0,0));
|
||||
ImPlot::PlotHeatmap("heat1",values2,size,size,0,1,NULL);
|
||||
ImPlot::PlotHeatmap("heat2",values2,size,size,0,1,NULL, ImPlotPoint(-1,-1), ImPlotPoint(0,0));
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
ImPlot::PopColormap();
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Histograms")) {
|
||||
static int bins = 50;
|
||||
static bool cumulative = false;
|
||||
static bool density = true;
|
||||
static bool outliers = true;
|
||||
static double mu = 5;
|
||||
static double sigma = 2;
|
||||
static NormalDistribution<10000> dist(mu, sigma);
|
||||
static double x[100];
|
||||
static double y[100];
|
||||
if (density) {
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
x[i] = -3 + 16 * (double)i/99.0;
|
||||
y[i] = exp( - (x[i]-mu)*(x[i]-mu) / (2*sigma*sigma)) / (sigma * sqrt(2*3.141592653589793238));
|
||||
}
|
||||
if (cumulative) {
|
||||
for (int i = 1; i < 100; ++i)
|
||||
y[i] += y[i-1];
|
||||
for (int i = 0; i < 100; ++i)
|
||||
y[i] /= y[99];
|
||||
}
|
||||
}
|
||||
ImGui::SetNextItemWidth(200);
|
||||
if (ImGui::RadioButton("Sqrt",bins==ImPlotBin_Sqrt)) { bins = ImPlotBin_Sqrt; } ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Sturges",bins==ImPlotBin_Sturges)) { bins = ImPlotBin_Sturges; } ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Rice",bins==ImPlotBin_Rice)) { bins = ImPlotBin_Rice; } ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Scott",bins==ImPlotBin_Scott)) { bins = ImPlotBin_Scott; } ImGui::SameLine();
|
||||
if (ImGui::RadioButton("N Bins",bins>=0)) bins = 50;
|
||||
if (bins>=0) {
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(200);
|
||||
ImGui::SliderInt("##Bins", &bins, 1, 100);
|
||||
}
|
||||
ImGui::Checkbox("Density", &density);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Cumulative", &cumulative);
|
||||
ImGui::SameLine();
|
||||
static bool range = false;
|
||||
ImGui::Checkbox("Range", &range);
|
||||
static float rmin = -3;
|
||||
static float rmax = 13;
|
||||
if (range) {
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(200);
|
||||
ImGui::DragFloat2("##Range",&rmin,0.1f,-3,13);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Outliers",&outliers);
|
||||
}
|
||||
ImPlot::SetNextPlotLimits(-3, 13, 0, 0.25);
|
||||
if (ImPlot::BeginPlot("##Histograms")) {
|
||||
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL, 0.5f);
|
||||
ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, cumulative, density, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), outliers);
|
||||
if (density && outliers)
|
||||
ImPlot::PlotLine("Theoretical",x,y,100);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
|
||||
static int count = 500000;
|
||||
static int xybins[2] = {200,200};
|
||||
static bool density2 = false;
|
||||
ImGui::SliderInt("Count",&count,100,500000);
|
||||
ImGui::SliderInt2("Bins",xybins,1,500);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Density##2",&density2);
|
||||
static NormalDistribution<500000> dist1(1, 2);
|
||||
static NormalDistribution<500000> dist2(1, 1);
|
||||
double max_count = 0;
|
||||
ImPlot::PushColormap("Twilight");
|
||||
if (ImPlot::BeginPlot("##Hist2D",0,0,ImVec2(ImGui::GetContentRegionAvail().x-100-ImGui::GetStyle().ItemSpacing.x,0),0,ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit)) {
|
||||
max_count = ImPlot::PlotHistogram2D("Hist2D",dist1.Data,dist2.Data,count,xybins[0],xybins[1],density2,ImPlotLimits(-6,6,-6,6));
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImPlot::ColormapScale(density2 ? "Density" : "Count",0,max_count,ImVec2(100,0));
|
||||
ImPlot::PopColormap();
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Digital Plots")) {
|
||||
ImGui::BulletText("Digital plots do not respond to Y drag and zoom, so that");
|
||||
ImGui::Indent();
|
||||
ImGui::Text("you can drag analog plots over the rising/falling digital edge.");
|
||||
ImGui::Unindent();
|
||||
|
||||
static bool paused = false;
|
||||
static ScrollingBuffer dataDigital[2];
|
||||
static ScrollingBuffer dataAnalog[2];
|
||||
static bool showDigital[2] = {true, false};
|
||||
static bool showAnalog[2] = {true, false};
|
||||
|
||||
char label[32];
|
||||
ImGui::Checkbox("digital_0", &showDigital[0]); ImGui::SameLine();
|
||||
ImGui::Checkbox("digital_1", &showDigital[1]); ImGui::SameLine();
|
||||
ImGui::Checkbox("analog_0", &showAnalog[0]); ImGui::SameLine();
|
||||
ImGui::Checkbox("analog_1", &showAnalog[1]);
|
||||
|
||||
static float t = 0;
|
||||
if (!paused) {
|
||||
t += ImGui::GetIO().DeltaTime;
|
||||
//digital signal values
|
||||
if (showDigital[0])
|
||||
dataDigital[0].AddPoint(t, sinf(2*t) > 0.45);
|
||||
if (showDigital[1])
|
||||
dataDigital[1].AddPoint(t, sinf(2*t) < 0.45);
|
||||
//Analog signal values
|
||||
if (showAnalog[0])
|
||||
dataAnalog[0].AddPoint(t, sinf(2*t));
|
||||
if (showAnalog[1])
|
||||
dataAnalog[1].AddPoint(t, cosf(2*t));
|
||||
}
|
||||
ImPlot::SetNextPlotLimitsY(-1, 1);
|
||||
ImPlot::SetNextPlotLimitsX(t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##Digital")) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (showDigital[i] && dataDigital[i].Data.size() > 0) {
|
||||
sprintf(label, "digital_%d", i);
|
||||
ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (showAnalog[i]) {
|
||||
sprintf(label, "analog_%d", i);
|
||||
if (dataAnalog[i].Data.size() > 0)
|
||||
ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Images")) {
|
||||
|
@ -650,7 +821,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ys2[i] = log(xs[i]);
|
||||
ys3[i] = pow(10.0, xs[i]);
|
||||
}
|
||||
ImGui::BulletText("Open the plot context menu (double right click) to change scales.");
|
||||
ImGui::BulletText("Open the plot context menu (right click) to change scales.");
|
||||
|
||||
ImPlot::SetNextPlotLimits(0.1, 100, 0, 10);
|
||||
if (ImPlot::BeginPlot("Log Plot", NULL, NULL, ImVec2(-1,0), 0, ImPlotAxisFlags_LogScale )) {
|
||||
|
@ -826,9 +997,9 @@ void ShowDemoWindow(bool* p_open) {
|
|||
}
|
||||
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")) {
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// mimic's soulthread's imgui_plot demo
|
||||
static float x_data[512];
|
||||
static float y_data1[512];
|
||||
|
@ -847,15 +1018,15 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls).");
|
||||
ImPlot::SetNextPlotLimits(0,0.01,-1,1);
|
||||
ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels;
|
||||
ImPlotLimits query;
|
||||
ImPlotLimits query2;
|
||||
if (ImPlot::BeginPlot("##View1",NULL,NULL,ImVec2(-1,150), ImPlotFlags_Query, flags, flags)) {
|
||||
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
|
||||
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
|
||||
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
|
||||
query = ImPlot::GetPlotQuery();
|
||||
query2 = ImPlot::GetPlotQuery();
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
ImPlot::SetNextPlotLimits(query.X.Min, query.X.Max, query.Y.Min, query.Y.Max, ImGuiCond_Always);
|
||||
ImPlot::SetNextPlotLimits(query2.X.Min, query2.X.Max, query2.Y.Min, query2.Y.Max, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##View2",NULL,NULL,ImVec2(-1,150), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) {
|
||||
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
|
||||
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
|
||||
|
@ -871,7 +1042,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImGui::CheckboxFlags("South", (unsigned int*)&loc, ImPlotLocation_South); ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("West", (unsigned int*)&loc, ImPlotLocation_West); ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("East", (unsigned int*)&loc, ImPlotLocation_East); ImGui::SameLine();
|
||||
ImGui::Checkbox("Horizontal", &h); ImGui::SameLine();
|
||||
ImGui::Checkbox("Horizontal##2", &h); ImGui::SameLine();
|
||||
ImGui::Checkbox("Outside", &o);
|
||||
|
||||
ImGui::SliderFloat2("LegendPadding", (float*)&GetStyle().LegendPadding, 0.0f, 20.0f, "%.0f");
|
||||
|
@ -908,8 +1079,8 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImPlot::DragLineY("y2",&y2,show_labels);
|
||||
double xs[1000], ys[1000];
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
xs[i] = (x2+x1)/2+abs(x2-x1)*(i/1000.0f - 0.5f);
|
||||
ys[i] = (y1+y2)/2+abs(y2-y1)/2*sin(f*i/10);
|
||||
xs[i] = (x2+x1)/2+fabs(x2-x1)*(i/1000.0f - 0.5f);
|
||||
ys[i] = (y1+y2)/2+fabs(y2-y1)/2*sin(f*i/10);
|
||||
}
|
||||
ImPlot::PlotLine("Interactive Data", xs, ys, 1000);
|
||||
ImPlot::SetPlotYAxis(ImPlotYAxis_2);
|
||||
|
@ -992,7 +1163,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
Plt = 0;
|
||||
Yax = ImPlotYAxis_1;
|
||||
sprintf(Label, "%02d Hz", Idx+1);
|
||||
Color = ImPlot::GetColormapColor(Idx);
|
||||
Color = RandomColor();
|
||||
Data.reserve(1001);
|
||||
for (int k = 0; k < 1001; ++k) {
|
||||
float t = k * 1.0f / 999;
|
||||
|
@ -1134,59 +1305,6 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImGui::EndChild();
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Digital and Analog Signals")) {
|
||||
|
||||
ImGui::BulletText("You can plot digital and analog signals on the same plot.");
|
||||
ImGui::BulletText("Digital signals do not respond to Y drag and zoom, so that");
|
||||
ImGui::Indent();
|
||||
ImGui::Text("you can drag analog signals over the rising/falling digital edge.");
|
||||
ImGui::Unindent();
|
||||
|
||||
static bool paused = false;
|
||||
static ScrollingBuffer dataDigital[2];
|
||||
static ScrollingBuffer dataAnalog[2];
|
||||
static bool showDigital[2] = {true, false};
|
||||
static bool showAnalog[2] = {true, false};
|
||||
|
||||
char label[32];
|
||||
ImGui::Checkbox("digital_0", &showDigital[0]); ImGui::SameLine();
|
||||
ImGui::Checkbox("digital_1", &showDigital[1]); ImGui::SameLine();
|
||||
ImGui::Checkbox("analog_0", &showAnalog[0]); ImGui::SameLine();
|
||||
ImGui::Checkbox("analog_1", &showAnalog[1]);
|
||||
|
||||
static float t = 0;
|
||||
if (!paused) {
|
||||
t += ImGui::GetIO().DeltaTime;
|
||||
//digital signal values
|
||||
if (showDigital[0])
|
||||
dataDigital[0].AddPoint(t, sinf(2*t) > 0.45);
|
||||
if (showDigital[1])
|
||||
dataDigital[1].AddPoint(t, sinf(2*t) < 0.45);
|
||||
//Analog signal values
|
||||
if (showAnalog[0])
|
||||
dataAnalog[0].AddPoint(t, sinf(2*t));
|
||||
if (showAnalog[1])
|
||||
dataAnalog[1].AddPoint(t, cosf(2*t));
|
||||
}
|
||||
ImPlot::SetNextPlotLimitsY(-1, 1);
|
||||
ImPlot::SetNextPlotLimitsX(t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##Digital")) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (showDigital[i] && dataDigital[i].Data.size() > 0) {
|
||||
sprintf(label, "digital_%d", i);
|
||||
ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (showAnalog[i]) {
|
||||
sprintf(label, "analog_%d", i);
|
||||
if (dataAnalog[i].Data.size() > 0)
|
||||
ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Tables")) {
|
||||
#ifdef IMGUI_HAS_TABLE
|
||||
static ImGuiTableFlags flags = ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_RowBg;
|
||||
|
@ -1590,7 +1708,7 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens
|
|||
// begin plot item
|
||||
if (ImPlot::BeginItem(label_id)) {
|
||||
// override legend icon color
|
||||
ImPlot::GetCurrentItem()->Color = ImVec4(0.25f,0.25f,0.25f,1);
|
||||
ImPlot::GetCurrentItem()->Color = IM_COL32(64,64,64,255);
|
||||
// fit data if requested
|
||||
if (ImPlot::FitThisFrame()) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIT License
|
||||
|
||||
// Copyright (c) 2020 Evan Pezent
|
||||
// Copyright (c) 2021 Evan Pezent
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -43,26 +43,7 @@
|
|||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Forward Declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ImPlotTick;
|
||||
struct ImPlotAxis;
|
||||
struct ImPlotAxisState;
|
||||
struct ImPlotAxisColor;
|
||||
struct ImPlotItem;
|
||||
struct ImPlotLegendData;
|
||||
struct ImPlotPlot;
|
||||
struct ImPlotNextPlotData;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Context Pointer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Macros and Constants
|
||||
// [SECTION] Constants
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Constants can be changed unless stated otherwise. We may move some of these
|
||||
|
@ -79,6 +60,34 @@ extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
|
|||
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
|
||||
#define IMPLOT_MAX_TIME 32503680000
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Macros
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Split ImU32 color into RGB components [0 255]
|
||||
#define IM_COL32_SPLIT_RGB(col,r,g,b) \
|
||||
ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \
|
||||
ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \
|
||||
ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Forward Declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ImPlotTick;
|
||||
struct ImPlotAxis;
|
||||
struct ImPlotAxisColor;
|
||||
struct ImPlotItem;
|
||||
struct ImPlotLegendData;
|
||||
struct ImPlotPlot;
|
||||
struct ImPlotNextPlotData;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Context Pointer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Generic Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -95,6 +104,9 @@ inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~f
|
|||
// Linearly remaps x from [x0 x1] to [y0 y1].
|
||||
template <typename T>
|
||||
inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
|
||||
// Linear rempas x from [x0 x1] to [0 1]
|
||||
template <typename T>
|
||||
inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }
|
||||
// Returns always positive modulo (assumes r != 0)
|
||||
inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
|
||||
// Returns true if val is NAN or INFINITY
|
||||
|
@ -109,17 +121,80 @@ inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
|
|||
inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
|
||||
// True if two numbers are approximately equal using units in the last place.
|
||||
inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) { return ImAbs(v1-v2) < DBL_EPSILON * ImAbs(v1+v2) * ulp || ImAbs(v1-v2) < DBL_MIN; }
|
||||
|
||||
// Offset calculator helper
|
||||
template <int Count>
|
||||
struct ImOffsetCalculator {
|
||||
ImOffsetCalculator(const int* sizes) {
|
||||
Offsets[0] = 0;
|
||||
for (int i = 1; i < Count; ++i)
|
||||
Offsets[i] = Offsets[i-1] + sizes[i-1];
|
||||
// Finds min value in an unsorted array
|
||||
template <typename T>
|
||||
inline T ImMinArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] < m) { m = values[i]; } } return m; }
|
||||
// Finds the max value in an unsorted array
|
||||
template <typename T>
|
||||
inline T ImMaxArray(const T* values, int count) { T m = values[0]; for (int i = 1; i < count; ++i) { if (values[i] > m) { m = values[i]; } } return m; }
|
||||
// Finds the min and max value in an unsorted array
|
||||
template <typename T>
|
||||
inline void ImMinMaxArray(const T* values, int count, T* min_out, T* max_out) {
|
||||
T Min = values[0]; T Max = values[0];
|
||||
for (int i = 1; i < count; ++i) {
|
||||
if (values[i] < Min) { Min = values[i]; }
|
||||
if (values[i] > Max) { Max = values[i]; }
|
||||
}
|
||||
*min_out = Min; *max_out = Max;
|
||||
}
|
||||
// Finds the mean of an array
|
||||
template <typename T>
|
||||
inline double ImMean(const T* values, int count) {
|
||||
double den = 1.0 / count;
|
||||
double mu = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
mu += values[i] * den;
|
||||
return mu;
|
||||
}
|
||||
// Finds the sample standard deviation of an array
|
||||
template <typename T>
|
||||
inline double ImStdDev(const T* values, int count) {
|
||||
double den = 1.0 / (count - 1.0);
|
||||
double mu = ImMean(values, count);
|
||||
double x = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
x += (values[i] - mu) * (values[i] - mu) * den;
|
||||
return sqrt(x);
|
||||
}
|
||||
// Mix color a and b by factor s in [0 256]
|
||||
inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
|
||||
#ifdef IMPLOT_MIX64
|
||||
const ImU32 af = 256-s;
|
||||
const ImU32 bf = s;
|
||||
const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24);
|
||||
const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24);
|
||||
const ImU64 mix = (al * af + bl * bf);
|
||||
return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8);
|
||||
#else
|
||||
const ImU32 af = 256-s;
|
||||
const ImU32 bf = s;
|
||||
const ImU32 al = (a & 0x00ff00ff);
|
||||
const ImU32 ah = (a & 0xff00ff00) >> 8;
|
||||
const ImU32 bl = (b & 0x00ff00ff);
|
||||
const ImU32 bh = (b & 0xff00ff00) >> 8;
|
||||
const ImU32 ml = (al * af + bl * bf);
|
||||
const ImU32 mh = (ah * af + bh * bf);
|
||||
return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Lerp across an array of 32-bit collors given t in [0.0 1.0]
|
||||
inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) {
|
||||
int i1 = (int)((size - 1 ) * t);
|
||||
int i2 = i1 + 1;
|
||||
if (i2 == size || size == 1)
|
||||
return colors[i1];
|
||||
float den = 1.0f / (size - 1);
|
||||
float t1 = i1 * den;
|
||||
float t2 = i2 * den;
|
||||
float tr = ImRemap01(t, t1, t2);
|
||||
return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));
|
||||
}
|
||||
|
||||
// Set alpha channel of 32-bit color from float in range [0.0 1.0]
|
||||
inline ImU32 ImAlphaU32(ImU32 col, float alpha) {
|
||||
return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
|
||||
}
|
||||
int Offsets[Count];
|
||||
};
|
||||
|
||||
// Character buffer writer helper (FIXME: Can't we replace this with ImGuiTextBuffer?)
|
||||
struct ImBufferWriter
|
||||
|
@ -268,19 +343,111 @@ static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
|||
static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return lhs > rhs || lhs == rhs; }
|
||||
|
||||
// Storage for colormap modifiers
|
||||
struct ImPlotColormapMod {
|
||||
ImPlotColormapMod(const ImVec4* colormap, int colormap_size) {
|
||||
Colormap = colormap;
|
||||
ColormapSize = colormap_size;
|
||||
// Colormap data storage
|
||||
struct ImPlotColormapData {
|
||||
ImVector<ImU32> Keys;
|
||||
ImVector<int> KeyCounts;
|
||||
ImVector<int> KeyOffsets;
|
||||
ImVector<ImU32> Tables;
|
||||
ImVector<int> TableSizes;
|
||||
ImVector<int> TableOffsets;
|
||||
ImGuiTextBuffer Text;
|
||||
ImVector<int> TextOffsets;
|
||||
ImVector<bool> Quals;
|
||||
ImGuiStorage Map;
|
||||
int Count;
|
||||
|
||||
ImPlotColormapData() { Count = 0; }
|
||||
|
||||
int Append(const char* name, const ImU32* keys, int count, bool qual) {
|
||||
if (GetIndex(name) != -1)
|
||||
return -1;
|
||||
KeyOffsets.push_back(Keys.size());
|
||||
KeyCounts.push_back(count);
|
||||
Keys.reserve(Keys.size()+count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
Keys.push_back(keys[i]);
|
||||
TextOffsets.push_back(Text.size());
|
||||
Text.append(name, name + strlen(name) + 1);
|
||||
Quals.push_back(qual);
|
||||
ImGuiID id = ImHashStr(name);
|
||||
int idx = Count++;
|
||||
Map.SetInt(id,idx);
|
||||
_AppendTable(idx);
|
||||
return idx;
|
||||
}
|
||||
const ImVec4* Colormap;
|
||||
int ColormapSize;
|
||||
|
||||
void _AppendTable(ImPlotColormap cmap) {
|
||||
int key_count = GetKeyCount(cmap);
|
||||
const ImU32* keys = GetKeys(cmap);
|
||||
int off = Tables.size();
|
||||
TableOffsets.push_back(off);
|
||||
if (IsQual(cmap)) {
|
||||
Tables.reserve(key_count);
|
||||
for (int i = 0; i < key_count; ++i)
|
||||
Tables.push_back(keys[i]);
|
||||
TableSizes.push_back(key_count);
|
||||
}
|
||||
else {
|
||||
int max_size = 255 * (key_count-1) + 1;
|
||||
Tables.reserve(off + max_size);
|
||||
// ImU32 last = keys[0];
|
||||
// Tables.push_back(last);
|
||||
// int n = 1;
|
||||
for (int i = 0; i < key_count-1; ++i) {
|
||||
for (int s = 0; s < 255; ++s) {
|
||||
ImU32 a = keys[i];
|
||||
ImU32 b = keys[i+1];
|
||||
ImU32 c = ImMixU32(a,b,s);
|
||||
// if (c != last) {
|
||||
Tables.push_back(c);
|
||||
// last = c;
|
||||
// n++;
|
||||
// }
|
||||
}
|
||||
}
|
||||
ImU32 c = keys[key_count-1];
|
||||
// if (c != last) {
|
||||
Tables.push_back(c);
|
||||
// n++;
|
||||
// }
|
||||
// TableSizes.push_back(n);
|
||||
TableSizes.push_back(max_size);
|
||||
}
|
||||
}
|
||||
|
||||
void RebuildTables() {
|
||||
Tables.resize(0);
|
||||
TableSizes.resize(0);
|
||||
TableOffsets.resize(0);
|
||||
for (int i = 0; i < Count; ++i)
|
||||
_AppendTable(i);
|
||||
}
|
||||
|
||||
inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
|
||||
inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : NULL; }
|
||||
inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
|
||||
|
||||
inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
|
||||
inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; }
|
||||
inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; }
|
||||
inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
|
||||
|
||||
inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; }
|
||||
inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; }
|
||||
inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; }
|
||||
|
||||
inline ImU32 LerpTable(ImPlotColormap cmap, float t) const {
|
||||
int off = TableOffsets[cmap];
|
||||
int siz = TableSizes[cmap];
|
||||
int idx = Quals[cmap] ? ImClamp((int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f);
|
||||
return Tables[off + idx];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// ImPlotPoint with positive/negative error values
|
||||
struct ImPlotPointError
|
||||
{
|
||||
struct ImPlotPointError {
|
||||
double X, Y, Neg, Pos;
|
||||
ImPlotPointError(double x, double y, double neg, double pos) {
|
||||
X = x; Y = y; Neg = neg; Pos = pos;
|
||||
|
@ -387,7 +554,7 @@ struct ImPlotTickCollection {
|
|||
Append(tick);
|
||||
}
|
||||
|
||||
const char* GetText(int idx) {
|
||||
const char* GetText(int idx) const {
|
||||
return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
|
||||
}
|
||||
|
||||
|
@ -502,10 +669,12 @@ struct ImPlotAxis
|
|||
|
||||
inline bool IsLabeled() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
|
||||
inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
|
||||
inline bool IsAlwaysLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
|
||||
inline bool IsLockedMin() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMin) || IsAlwaysLocked(); }
|
||||
inline bool IsLockedMax() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMax) || IsAlwaysLocked(); }
|
||||
inline bool IsLocked() const { return !Present || ((IsLockedMin() && IsLockedMax()) || IsAlwaysLocked()); }
|
||||
inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
|
||||
inline bool IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
|
||||
inline bool IsLockedMin() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMin) || IsRangeLocked(); }
|
||||
inline bool IsLockedMax() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMax) || IsRangeLocked(); }
|
||||
inline bool IsLocked() const { return !Present || ((IsLockedMin() && IsLockedMax()) || IsRangeLocked()); }
|
||||
inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
|
||||
inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
|
||||
inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
|
||||
};
|
||||
|
@ -514,7 +683,7 @@ struct ImPlotAxis
|
|||
struct ImPlotItem
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImVec4 Color;
|
||||
ImU32 Color;
|
||||
int NameOffset;
|
||||
bool Show;
|
||||
bool LegendHovered;
|
||||
|
@ -522,7 +691,7 @@ struct ImPlotItem
|
|||
|
||||
ImPlotItem() {
|
||||
ID = 0;
|
||||
Color = ImPlot::NextColormapColor();
|
||||
// Color = ImPlot::NextColormapColor();
|
||||
NameOffset = -1;
|
||||
Show = true;
|
||||
SeenThisFrame = false;
|
||||
|
@ -591,7 +760,7 @@ struct ImPlotPlot
|
|||
ImPlotItem* GetLegendItem(int i);
|
||||
const char* GetLegendLabel(int i);
|
||||
|
||||
inline bool IsLocked() const { return XAxis.IsLocked() && YAxis[0].IsLocked() && YAxis[1].IsLocked() && YAxis[2].IsLocked(); }
|
||||
inline bool IsInputLocked() const { return XAxis.IsInputLocked() && YAxis[0].IsInputLocked() && YAxis[1].IsInputLocked() && YAxis[2].IsInputLocked(); }
|
||||
};
|
||||
|
||||
// Temporary data storage for upcoming plot
|
||||
|
@ -701,13 +870,15 @@ struct ImPlotContext {
|
|||
ImPlotStyle Style;
|
||||
ImVector<ImGuiColorMod> ColorModifiers;
|
||||
ImVector<ImGuiStyleMod> StyleModifiers;
|
||||
const ImVec4* Colormap;
|
||||
int ColormapSize;
|
||||
ImVector<ImPlotColormapMod> ColormapModifiers;
|
||||
ImPlotColormapData ColormapData;
|
||||
ImVector<ImPlotColormap> ColormapModifiers;
|
||||
|
||||
// Time
|
||||
tm Tm;
|
||||
|
||||
// Temp data for general use
|
||||
ImVector<double> Temp1, Temp2;
|
||||
|
||||
// Misc
|
||||
int VisibleItemCount;
|
||||
int DigitalPlotItemCnt;
|
||||
|
@ -862,19 +1033,16 @@ IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
|
|||
inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
|
||||
inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
|
||||
|
||||
// Get built-in colormap data and size
|
||||
IMPLOT_API const ImVec4* GetColormap(ImPlotColormap colormap, int* size_out);
|
||||
// Linearly interpolates a color from the current colormap given t between 0 and 1.
|
||||
IMPLOT_API ImVec4 LerpColormap(const ImVec4* colormap, int size, float t);
|
||||
// Resamples a colormap. #size_out must be greater than 1.
|
||||
IMPLOT_API void ResampleColormap(const ImVec4* colormap_in, int size_in, ImVec4* colormap_out, int size_out);
|
||||
|
||||
// Draws vertical text. The position is the bottom left of the text rect.
|
||||
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
|
||||
// Calculates the size of vertical text
|
||||
inline ImVec2 CalcTextSizeVertical(const char *text) { ImVec2 sz = ImGui::CalcTextSize(text); return ImVec2(sz.y, sz.x); }
|
||||
inline ImVec2 CalcTextSizeVertical(const char *text) {
|
||||
ImVec2 sz = ImGui::CalcTextSize(text);
|
||||
return ImVec2(sz.y, sz.x);
|
||||
}
|
||||
// Returns white or black text given background color
|
||||
inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.5 ? IM_COL32_BLACK : IM_COL32_WHITE; }
|
||||
inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
|
||||
|
||||
// Clamps a label position so that it fits a rect defined by Min/Max
|
||||
inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {
|
||||
|
@ -885,6 +1053,16 @@ inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, c
|
|||
return pos;
|
||||
}
|
||||
|
||||
// Returns a color from the Color map given an index >= 0 (modulo will be performed).
|
||||
IMPLOT_API ImU32 GetColormapColorU32(int idx, ImPlotColormap cmap);
|
||||
// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.
|
||||
IMPLOT_API ImU32 NextColormapColorU32();
|
||||
// Linearly interpolates a color from the current colormap given t between 0 and 1.
|
||||
IMPLOT_API ImU32 SampleColormapU32(float t, ImPlotColormap cmap);
|
||||
|
||||
// Render a colormap bar
|
||||
IMPLOT_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Math and Misc Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -922,6 +1100,27 @@ inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stri
|
|||
return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride);
|
||||
}
|
||||
|
||||
// Calculate histogram bin counts and widths
|
||||
template <typename T>
|
||||
void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
|
||||
switch (meth) {
|
||||
case ImPlotBin_Sqrt:
|
||||
bins_out = (int)ceil(sqrt(count));
|
||||
break;
|
||||
case ImPlotBin_Sturges:
|
||||
bins_out = (int)ceil(1.0 + log2(count));
|
||||
break;
|
||||
case ImPlotBin_Rice:
|
||||
bins_out = (int)ceil(2 * cbrt(count));
|
||||
break;
|
||||
case ImPlotBin_Scott:
|
||||
width_out = 3.49 * ImStdDev(values, count) / cbrt(count);
|
||||
bins_out = (int)round(range.Size() / width_out);
|
||||
break;
|
||||
}
|
||||
width_out = range.Size() / bins_out;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Time Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -982,14 +1181,4 @@ IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const
|
|||
// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
|
||||
IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Internal / Experimental Plotters
|
||||
// No guarantee of forward compatibility here!
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Plots axis-aligned, filled rectangles. Every two consecutive points defines opposite corners of a single rectangle.
|
||||
IMPLOT_API void PlotRects(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float));
|
||||
IMPLOT_API void PlotRects(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double));
|
||||
IMPLOT_API void PlotRects(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0);
|
||||
|
||||
} // namespace ImPlot
|
||||
|
|
448
implot_items.cpp
448
implot_items.cpp
|
@ -119,7 +119,7 @@ void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {
|
|||
ImVec4 GetLastItemColor() {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (gp.PreviousItem)
|
||||
return gp.PreviousItem->Color;
|
||||
return ImGui::ColorConvertU32ToFloat4(gp.PreviousItem->Color);
|
||||
return ImVec4();
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,21 @@ void BustItemCache() {
|
|||
}
|
||||
}
|
||||
|
||||
void BustColorCache(const char* plot_title_id) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (plot_title_id == NULL) {
|
||||
BustItemCache();
|
||||
}
|
||||
else {
|
||||
ImPlotPlot* plot = gp.Plots.GetByKey(ImGui::GetCurrentWindow()->GetID(plot_title_id));
|
||||
if (plot == NULL)
|
||||
return;
|
||||
plot->ColormapIdx = 0;
|
||||
plot->Items.Clear();
|
||||
plot->LegendData.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Begin/EndItem
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -153,12 +168,17 @@ bool BeginItem(const char* label_id, ImPlotCol recolor_from) {
|
|||
// set current item
|
||||
gp.CurrentItem = item;
|
||||
ImPlotNextItemData& s = gp.NextItemData;
|
||||
// override item color
|
||||
// set/override item color
|
||||
if (recolor_from != -1) {
|
||||
if (!IsColorAuto(s.Colors[recolor_from]))
|
||||
item->Color = s.Colors[recolor_from];
|
||||
item->Color = ImGui::ColorConvertFloat4ToU32(s.Colors[recolor_from]);
|
||||
else if (!IsColorAuto(gp.Style.Colors[recolor_from]))
|
||||
item->Color = gp.Style.Colors[recolor_from];
|
||||
item->Color = ImGui::ColorConvertFloat4ToU32(gp.Style.Colors[recolor_from]);
|
||||
else if (just_created)
|
||||
item->Color = NextColormapColorU32();
|
||||
}
|
||||
else if (just_created) {
|
||||
item->Color = NextColormapColorU32();
|
||||
}
|
||||
// hide/show item
|
||||
if (gp.NextItemData.HasHidden) {
|
||||
|
@ -173,9 +193,10 @@ bool BeginItem(const char* label_id, ImPlotCol recolor_from) {
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color);
|
||||
// stage next item colors
|
||||
s.Colors[ImPlotCol_Line] = IsColorAuto(s.Colors[ImPlotCol_Line]) ? ( IsColorAuto(ImPlotCol_Line) ? item->Color : gp.Style.Colors[ImPlotCol_Line] ) : s.Colors[ImPlotCol_Line];
|
||||
s.Colors[ImPlotCol_Fill] = IsColorAuto(s.Colors[ImPlotCol_Fill]) ? ( IsColorAuto(ImPlotCol_Fill) ? item->Color : gp.Style.Colors[ImPlotCol_Fill] ) : s.Colors[ImPlotCol_Fill];
|
||||
s.Colors[ImPlotCol_Line] = IsColorAuto(s.Colors[ImPlotCol_Line]) ? ( IsColorAuto(ImPlotCol_Line) ? item_color : gp.Style.Colors[ImPlotCol_Line] ) : s.Colors[ImPlotCol_Line];
|
||||
s.Colors[ImPlotCol_Fill] = IsColorAuto(s.Colors[ImPlotCol_Fill]) ? ( IsColorAuto(ImPlotCol_Fill) ? item_color : gp.Style.Colors[ImPlotCol_Fill] ) : s.Colors[ImPlotCol_Fill];
|
||||
s.Colors[ImPlotCol_MarkerOutline] = IsColorAuto(s.Colors[ImPlotCol_MarkerOutline]) ? ( IsColorAuto(ImPlotCol_MarkerOutline) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerOutline] ) : s.Colors[ImPlotCol_MarkerOutline];
|
||||
s.Colors[ImPlotCol_MarkerFill] = IsColorAuto(s.Colors[ImPlotCol_MarkerFill]) ? ( IsColorAuto(ImPlotCol_MarkerFill) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerFill] ) : s.Colors[ImPlotCol_MarkerFill];
|
||||
s.Colors[ImPlotCol_ErrorBar] = IsColorAuto(s.Colors[ImPlotCol_ErrorBar]) ? ( GetStyleColorVec4(ImPlotCol_ErrorBar) ) : s.Colors[ImPlotCol_ErrorBar];
|
||||
|
@ -659,51 +680,6 @@ struct ShadedRenderer {
|
|||
static const int VtxConsumed = 5;
|
||||
};
|
||||
|
||||
template <typename TGetter, typename TTransformer>
|
||||
struct RectRenderer {
|
||||
inline RectRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col) :
|
||||
Getter(getter),
|
||||
Transformer(transformer),
|
||||
Prims(Getter.Count / 2),
|
||||
Col(col)
|
||||
{}
|
||||
inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) const {
|
||||
// TODO: Culling
|
||||
ImVec2 P1 = Transformer(Getter(2*prim));
|
||||
ImVec2 P2 = Transformer(Getter(2*prim+1));
|
||||
DrawList._VtxWritePtr[0].pos = P1;
|
||||
DrawList._VtxWritePtr[0].uv = uv;
|
||||
DrawList._VtxWritePtr[0].col = Col;
|
||||
DrawList._VtxWritePtr[1].pos.x = P1.x;
|
||||
DrawList._VtxWritePtr[1].pos.y = P2.y;
|
||||
DrawList._VtxWritePtr[1].uv = uv;
|
||||
DrawList._VtxWritePtr[1].col = Col;
|
||||
DrawList._VtxWritePtr[2].pos = P2;
|
||||
DrawList._VtxWritePtr[2].uv = uv;
|
||||
DrawList._VtxWritePtr[2].col = Col;
|
||||
DrawList._VtxWritePtr[3].pos.x = P2.x;
|
||||
DrawList._VtxWritePtr[3].pos.y = P1.y;
|
||||
DrawList._VtxWritePtr[3].uv = uv;
|
||||
DrawList._VtxWritePtr[3].col = Col;
|
||||
DrawList._VtxWritePtr += 4;
|
||||
DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
|
||||
DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
|
||||
DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
|
||||
DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
|
||||
DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2);
|
||||
DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
|
||||
DrawList._IdxWritePtr += 6;
|
||||
DrawList._VtxCurrentIdx += 4;
|
||||
return true;
|
||||
}
|
||||
const TGetter& Getter;
|
||||
const TTransformer& Transformer;
|
||||
const int Prims;
|
||||
const ImU32 Col;
|
||||
static const int IdxConsumed = 6;
|
||||
static const int VtxConsumed = 4;
|
||||
};
|
||||
|
||||
// Stupid way of calculating maximum index size of ImDrawIdx without integer overflow issues
|
||||
template <typename T>
|
||||
struct MaxIdx { static const unsigned int Value; };
|
||||
|
@ -1462,6 +1438,7 @@ void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg,
|
|||
GetterError<T> getter(xs, ys, neg, pos, count, offset, stride);
|
||||
PlotErrorBarsEx(label_id, getter);
|
||||
}
|
||||
|
||||
template IMPLOT_API void PlotErrorBars<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride);
|
||||
template IMPLOT_API void PlotErrorBars<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride);
|
||||
template IMPLOT_API void PlotErrorBars<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride);
|
||||
|
@ -1729,7 +1706,7 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou
|
|||
double percent = normalize ? (double)values[i] / sum : (double)values[i];
|
||||
a1 = a0 + 2 * IM_PI * percent;
|
||||
if (BeginItem(label_ids[i])) {
|
||||
ImU32 col = ImGui::GetColorU32(GetCurrentItem()->Color);
|
||||
ImU32 col = GetCurrentItem()->Color;
|
||||
if (percent < 0.5) {
|
||||
RenderPieSlice(DrawList, center, radius, a0, a1, col);
|
||||
}
|
||||
|
@ -1754,7 +1731,7 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou
|
|||
ImVec2 size = ImGui::CalcTextSize(buffer);
|
||||
double angle = a0 + (a1 - a0) * 0.5;
|
||||
ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle));
|
||||
ImU32 col = CalcTextColor(item->Color);
|
||||
ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
|
||||
DrawList.AddText(pos - size * 0.5f, col, buffer);
|
||||
}
|
||||
a0 = a1;
|
||||
|
@ -1778,9 +1755,115 @@ template IMPLOT_API void PlotPieChart<double>(const char* const label_ids[], con
|
|||
// PLOT HEATMAP
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct RectInfo {
|
||||
ImPlotPoint Min, Max;
|
||||
ImU32 Color;
|
||||
};
|
||||
|
||||
template <typename TGetter, typename TTransformer>
|
||||
struct RectRenderer {
|
||||
inline RectRenderer(const TGetter& getter, const TTransformer& transformer) :
|
||||
Getter(getter),
|
||||
Transformer(transformer),
|
||||
Prims(Getter.Count)
|
||||
{}
|
||||
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
RectInfo rect = Getter(prim);
|
||||
ImVec2 P1 = Transformer(rect.Min);
|
||||
ImVec2 P2 = Transformer(rect.Max);
|
||||
|
||||
if ((rect.Color & IM_COL32_A_MASK) == 0 || !cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
|
||||
return false;
|
||||
|
||||
DrawList._VtxWritePtr[0].pos = P1;
|
||||
DrawList._VtxWritePtr[0].uv = uv;
|
||||
DrawList._VtxWritePtr[0].col = rect.Color;
|
||||
DrawList._VtxWritePtr[1].pos.x = P1.x;
|
||||
DrawList._VtxWritePtr[1].pos.y = P2.y;
|
||||
DrawList._VtxWritePtr[1].uv = uv;
|
||||
DrawList._VtxWritePtr[1].col = rect.Color;
|
||||
DrawList._VtxWritePtr[2].pos = P2;
|
||||
DrawList._VtxWritePtr[2].uv = uv;
|
||||
DrawList._VtxWritePtr[2].col = rect.Color;
|
||||
DrawList._VtxWritePtr[3].pos.x = P2.x;
|
||||
DrawList._VtxWritePtr[3].pos.y = P1.y;
|
||||
DrawList._VtxWritePtr[3].uv = uv;
|
||||
DrawList._VtxWritePtr[3].col = rect.Color;
|
||||
DrawList._VtxWritePtr += 4;
|
||||
DrawList._IdxWritePtr[0] = (ImDrawIdx)(DrawList._VtxCurrentIdx);
|
||||
DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
|
||||
DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
|
||||
DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
|
||||
DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 2);
|
||||
DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
|
||||
DrawList._IdxWritePtr += 6;
|
||||
DrawList._VtxCurrentIdx += 4;
|
||||
return true;
|
||||
}
|
||||
const TGetter& Getter;
|
||||
const TTransformer& Transformer;
|
||||
const int Prims;
|
||||
static const int IdxConsumed = 6;
|
||||
static const int VtxConsumed = 4;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GetterHeatmap {
|
||||
GetterHeatmap(const T* values, int rows, int cols, double scale_min, double scale_max, double width, double height, double xref, double yref, double ydir) :
|
||||
Values(values),
|
||||
Count(rows*cols),
|
||||
Rows(rows),
|
||||
Cols(cols),
|
||||
ScaleMin(scale_min),
|
||||
ScaleMax(scale_max),
|
||||
Width(width),
|
||||
Height(height),
|
||||
XRef(xref),
|
||||
YRef(yref),
|
||||
YDir(ydir),
|
||||
HalfSize(Width*0.5, Height*0.5)
|
||||
{ }
|
||||
|
||||
inline RectInfo operator()(int idx) const {
|
||||
double val = (double)Values[idx];
|
||||
const int r = idx / Cols;
|
||||
const int c = idx % Cols;
|
||||
const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));
|
||||
RectInfo rect;
|
||||
rect.Min.x = p.x - HalfSize.x;
|
||||
rect.Min.y = p.y - HalfSize.y;
|
||||
rect.Max.x = p.x + HalfSize.x;
|
||||
rect.Max.y = p.y + HalfSize.y;
|
||||
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
|
||||
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t);
|
||||
return rect;
|
||||
}
|
||||
const T* const Values;
|
||||
const int Count, Rows, Cols;
|
||||
const double ScaleMin, ScaleMax, Width, Height, XRef, YRef, YDir;
|
||||
const ImPlotPoint HalfSize;
|
||||
};
|
||||
|
||||
template <typename T, typename Transformer>
|
||||
void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
|
||||
void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, bool reverse_y) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (scale_min == scale_max) {
|
||||
ImVec2 a = transformer(bounds_min);
|
||||
ImVec2 b = transformer(bounds_max);
|
||||
ImU32 col = GetColormapColorU32(0,gp.Style.Colormap);
|
||||
DrawList.AddRectFilled(a, b, col);
|
||||
return;
|
||||
}
|
||||
const double yref = reverse_y ? bounds_max.y : bounds_min.y;
|
||||
const double ydir = reverse_y ? -1 : 1;
|
||||
GetterHeatmap<T> getter(values, rows, cols, scale_min, scale_max, (bounds_max.x - bounds_min.x) / cols, (bounds_max.y - bounds_min.y) / rows, bounds_min.x, yref, ydir);
|
||||
switch (GetCurrentScale()) {
|
||||
case ImPlotScale_LinLin: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLinLin>(getter, TransformerLinLin()), DrawList, gp.CurrentPlot->PlotRect); break;
|
||||
case ImPlotScale_LogLin: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLogLin>(getter, TransformerLogLin()), DrawList, gp.CurrentPlot->PlotRect); break;;
|
||||
case ImPlotScale_LinLog: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLinLog>(getter, TransformerLinLog()), DrawList, gp.CurrentPlot->PlotRect); break;;
|
||||
case ImPlotScale_LogLog: RenderPrimitives(RectRenderer<GetterHeatmap<T>, TransformerLogLog>(getter, TransformerLogLog()), DrawList, gp.CurrentPlot->PlotRect); break;;
|
||||
}
|
||||
if (fmt != NULL) {
|
||||
const double w = (bounds_max.x - bounds_min.x) / cols;
|
||||
const double h = (bounds_max.y - bounds_min.y) / rows;
|
||||
const ImPlotPoint half_size(w*0.5,h*0.5);
|
||||
|
@ -1789,30 +1872,13 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
|
|||
for (int c = 0; c < cols; ++c) {
|
||||
ImPlotPoint p;
|
||||
p.x = bounds_min.x + 0.5*w + c*w;
|
||||
p.y = bounds_max.y - (0.5*h + r*h);
|
||||
ImVec2 a = transformer(ImPlotPoint(p.x - half_size.x, p.y - half_size.y));
|
||||
ImVec2 b = transformer(ImPlotPoint(p.x + half_size.x, p.y + half_size.y));
|
||||
double t = ImRemap((double)values[i], scale_min, scale_max, 0.0, 1.0);
|
||||
ImVec4 color = LerpColormap((float)t);
|
||||
color.w *= gp.Style.FillAlpha;
|
||||
ImU32 col = ImGui::GetColorU32(color);
|
||||
DrawList.AddRectFilled(a, b, col);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (fmt != NULL) {
|
||||
i = 0;
|
||||
for (int r = 0; r < rows; ++r) {
|
||||
for (int c = 0; c < cols; ++c) {
|
||||
ImPlotPoint p;
|
||||
p.x = bounds_min.x + 0.5*w + c*w;
|
||||
p.y = bounds_max.y - (0.5*h + r*h);
|
||||
p.y = yref + ydir * (0.5*h + r*h);
|
||||
ImVec2 px = transformer(p);
|
||||
char buff[32];
|
||||
sprintf(buff, fmt, values[i]);
|
||||
ImVec2 size = ImGui::CalcTextSize(buff);
|
||||
double t = ImRemap((double)values[i], scale_min, scale_max, 0.0, 1.0);
|
||||
ImVec4 color = LerpColormap((float)t);
|
||||
double t = ImClamp(ImRemap01((double)values[i], scale_min, scale_max),0.0,1.0);
|
||||
ImVec4 color = SampleColormap((float)t);
|
||||
ImU32 col = CalcTextColor(color);
|
||||
DrawList.AddText(px - size * 0.5f, col, buff);
|
||||
i++;
|
||||
|
@ -1823,7 +1889,6 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
|
|||
|
||||
template <typename T>
|
||||
void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
|
||||
IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!");
|
||||
if (BeginItem(label_id)) {
|
||||
if (FitThisFrame()) {
|
||||
FitPoint(bounds_min);
|
||||
|
@ -1831,10 +1896,10 @@ void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, doub
|
|||
}
|
||||
ImDrawList& DrawList = *GetPlotDrawList();
|
||||
switch (GetCurrentScale()) {
|
||||
case ImPlotScale_LinLin: RenderHeatmap(TransformerLinLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
|
||||
case ImPlotScale_LogLin: RenderHeatmap(TransformerLogLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
|
||||
case ImPlotScale_LinLog: RenderHeatmap(TransformerLinLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
|
||||
case ImPlotScale_LogLog: RenderHeatmap(TransformerLogLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
|
||||
case ImPlotScale_LinLin: RenderHeatmap(TransformerLinLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
|
||||
case ImPlotScale_LogLin: RenderHeatmap(TransformerLogLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
|
||||
case ImPlotScale_LinLog: RenderHeatmap(TransformerLinLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
|
||||
case ImPlotScale_LogLog: RenderHeatmap(TransformerLogLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true); break;
|
||||
}
|
||||
EndItem();
|
||||
}
|
||||
|
@ -1851,6 +1916,181 @@ template IMPLOT_API void PlotHeatmap<ImU64>(const char* label_id, const ImU64* v
|
|||
template IMPLOT_API void PlotHeatmap<float>(const char* label_id, const float* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
|
||||
template IMPLOT_API void PlotHeatmap<double>(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PLOT HISTOGRAM
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
double PlotHistogram(const char* label_id, const T* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale) {
|
||||
|
||||
if (count <= 0 || bins == 0)
|
||||
return 0;
|
||||
|
||||
if (range.Min == 0 && range.Max == 0) {
|
||||
T Min, Max;
|
||||
ImMinMaxArray(values, count, &Min, &Max);
|
||||
range.Min = (double)Min;
|
||||
range.Max = (double)Max;
|
||||
}
|
||||
|
||||
double width;
|
||||
if (bins < 0)
|
||||
CalculateBins(values, count, bins, range, bins, width);
|
||||
else
|
||||
width = range.Size() / bins;
|
||||
|
||||
ImVector<double>& bin_centers = GImPlot->Temp1;
|
||||
ImVector<double>& bin_counts = GImPlot->Temp2;
|
||||
bin_centers.resize(bins);
|
||||
bin_counts.resize(bins);
|
||||
int below = 0;
|
||||
|
||||
for (int b = 0; b < bins; ++b) {
|
||||
bin_centers[b] = range.Min + b * width + width * 0.5;
|
||||
bin_counts[b] = 0;
|
||||
}
|
||||
int counted = 0;
|
||||
double max_count = 0;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
double val = (double)values[i];
|
||||
if (range.Contains(val)) {
|
||||
const int b = ImClamp((int)((val - range.Min) / width), 0, bins - 1);
|
||||
bin_counts[b] += 1.0;
|
||||
if (bin_counts[b] > max_count)
|
||||
max_count = bin_counts[b];
|
||||
counted++;
|
||||
}
|
||||
else if (val < range.Min) {
|
||||
below++;
|
||||
}
|
||||
}
|
||||
if (cumulative && density) {
|
||||
if (outliers)
|
||||
bin_counts[0] += below;
|
||||
for (int b = 1; b < bins; ++b)
|
||||
bin_counts[b] += bin_counts[b-1];
|
||||
double scale = 1.0 / (outliers ? count : counted);
|
||||
for (int b = 0; b < bins; ++b)
|
||||
bin_counts[b] *= scale;
|
||||
max_count = bin_counts[bins-1];
|
||||
}
|
||||
else if (cumulative) {
|
||||
if (outliers)
|
||||
bin_counts[0] += below;
|
||||
for (int b = 1; b < bins; ++b)
|
||||
bin_counts[b] += bin_counts[b-1];
|
||||
max_count = bin_counts[bins-1];
|
||||
}
|
||||
else if (density) {
|
||||
double scale = 1.0 / ((outliers ? count : counted) * width);
|
||||
for (int b = 0; b < bins; ++b)
|
||||
bin_counts[b] *= scale;
|
||||
max_count *= scale;
|
||||
}
|
||||
PlotBars(label_id, &bin_centers.Data[0], &bin_counts.Data[0], bins, bar_scale*width);
|
||||
return max_count;
|
||||
}
|
||||
|
||||
template IMPLOT_API double PlotHistogram<ImS8>(const char* label_id, const ImS8* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImU8>(const char* label_id, const ImU8* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImS16>(const char* label_id, const ImS16* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImU16>(const char* label_id, const ImU16* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImS32>(const char* label_id, const ImS32* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImU32>(const char* label_id, const ImU32* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImS64>(const char* label_id, const ImS64* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<ImU64>(const char* label_id, const ImU64* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<float>(const char* label_id, const float* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
template IMPLOT_API double PlotHistogram<double>(const char* label_id, const double* values, int count, int bins, bool cumulative, bool density, ImPlotRange range, bool outliers, double bar_scale);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PLOT HISTOGRAM 2D
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers) {
|
||||
|
||||
if (count <= 0 || x_bins == 0 || y_bins == 0)
|
||||
return 0;
|
||||
|
||||
if (range.X.Min == 0 && range.X.Max == 0) {
|
||||
T Min, Max;
|
||||
ImMinMaxArray(xs, count, &Min, &Max);
|
||||
range.X.Min = (double)Min;
|
||||
range.X.Max = (double)Max;
|
||||
}
|
||||
if (range.Y.Min == 0 && range.Y.Max == 0) {
|
||||
T Min, Max;
|
||||
ImMinMaxArray(ys, count, &Min, &Max);
|
||||
range.Y.Min = (double)Min;
|
||||
range.Y.Max = (double)Max;
|
||||
}
|
||||
|
||||
double width, height;
|
||||
if (x_bins < 0)
|
||||
CalculateBins(xs, count, x_bins, range.X, x_bins, width);
|
||||
else
|
||||
width = range.X.Size() / x_bins;
|
||||
if (y_bins < 0)
|
||||
CalculateBins(ys, count, y_bins, range.Y, y_bins, height);
|
||||
else
|
||||
height = range.Y.Size() / y_bins;
|
||||
|
||||
const int bins = x_bins * y_bins;
|
||||
|
||||
ImVector<double>& bin_counts = GImPlot->Temp1;
|
||||
bin_counts.resize(bins);
|
||||
|
||||
for (int b = 0; b < bins; ++b)
|
||||
bin_counts[b] = 0;
|
||||
|
||||
int counted = 0;
|
||||
double max_count = 0;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (range.Contains((double)xs[i], (double)ys[i])) {
|
||||
const int xb = ImClamp( (int)((double)(xs[i] - range.X.Min) / width) , 0, x_bins - 1);
|
||||
const int yb = ImClamp( (int)((double)(ys[i] - range.Y.Min) / height) , 0, y_bins - 1);
|
||||
const int b = yb * x_bins + xb;
|
||||
bin_counts[b] += 1.0;
|
||||
if (bin_counts[b] > max_count)
|
||||
max_count = bin_counts[b];
|
||||
counted++;
|
||||
}
|
||||
}
|
||||
if (density) {
|
||||
double scale = 1.0 / ((outliers ? count : counted) * width * height);
|
||||
for (int b = 0; b < bins; ++b)
|
||||
bin_counts[b] *= scale;
|
||||
max_count *= scale;
|
||||
}
|
||||
|
||||
if (BeginItem(label_id)) {
|
||||
if (FitThisFrame()) {
|
||||
FitPoint(range.Min());
|
||||
FitPoint(range.Max());
|
||||
}
|
||||
ImDrawList& DrawList = *GetPlotDrawList();
|
||||
switch (GetCurrentScale()) {
|
||||
case ImPlotScale_LinLin: RenderHeatmap(TransformerLinLin(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
|
||||
case ImPlotScale_LogLin: RenderHeatmap(TransformerLogLin(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
|
||||
case ImPlotScale_LinLog: RenderHeatmap(TransformerLinLog(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
|
||||
case ImPlotScale_LogLog: RenderHeatmap(TransformerLogLog(), DrawList, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false); break;
|
||||
}
|
||||
EndItem();
|
||||
}
|
||||
return max_count;
|
||||
}
|
||||
|
||||
template IMPLOT_API double PlotHistogram2D<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<float>(const char* label_id, const float* xs, const float* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
template IMPLOT_API double PlotHistogram2D<double>(const char* label_id, const double* xs, const double* ys, int count, int x_bins, int y_bins, bool density, ImPlotLimits range, bool outliers);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PLOT DIGITAL
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1937,51 +2177,6 @@ void PlotDigitalG(const char* label_id, ImPlotPoint (*getter_func)(void* data, i
|
|||
return PlotDigitalEx(label_id, getter);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PLOT RECTS
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename Getter>
|
||||
void PlotRectsEx(const char* label_id, const Getter& getter) {
|
||||
if (BeginItem(label_id, ImPlotCol_Fill)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < getter.Count; ++i) {
|
||||
ImPlotPoint p = getter(i);
|
||||
FitPoint(p);
|
||||
}
|
||||
}
|
||||
const ImPlotNextItemData& s = GetItemData();
|
||||
if (s.RenderFill) {
|
||||
ImDrawList& DrawList = *GetPlotDrawList();
|
||||
ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
|
||||
switch (GetCurrentScale()) {
|
||||
case ImPlotScale_LinLin: RenderPrimitives(RectRenderer<Getter,TransformerLinLin>(getter, TransformerLinLin(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
|
||||
case ImPlotScale_LogLin: RenderPrimitives(RectRenderer<Getter,TransformerLogLin>(getter, TransformerLogLin(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
|
||||
case ImPlotScale_LinLog: RenderPrimitives(RectRenderer<Getter,TransformerLinLog>(getter, TransformerLinLog(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
|
||||
case ImPlotScale_LogLog: RenderPrimitives(RectRenderer<Getter,TransformerLogLog>(getter, TransformerLogLog(), col), DrawList, GImPlot->CurrentPlot->PlotRect); break;
|
||||
}
|
||||
}
|
||||
EndItem();
|
||||
}
|
||||
}
|
||||
|
||||
// float
|
||||
void PlotRects(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) {
|
||||
GetterXsYs<float> getter(xs,ys,count,offset,stride);
|
||||
PlotRectsEx(label_id, getter);
|
||||
}
|
||||
|
||||
// double
|
||||
void PlotRects(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) {
|
||||
GetterXsYs<double> getter(xs,ys,count,offset,stride);
|
||||
PlotRectsEx(label_id, getter);
|
||||
}
|
||||
|
||||
// custom
|
||||
void PlotRects(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
|
||||
GetterFuncPtr getter(getter_func,data,count,offset);
|
||||
return PlotRectsEx(label_id, getter);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PLOT IMAGE
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1992,12 +2187,13 @@ void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPo
|
|||
FitPoint(bmin);
|
||||
FitPoint(bmax);
|
||||
}
|
||||
GetCurrentItem()->Color = tint_col;
|
||||
ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col);
|
||||
GetCurrentItem()->Color = tint_col32;
|
||||
ImDrawList& DrawList = *GetPlotDrawList();
|
||||
ImVec2 p1 = PlotToPixels(bmin.x, bmax.y);
|
||||
ImVec2 p2 = PlotToPixels(bmax.x, bmin.y);
|
||||
PushPlotClipRect();
|
||||
DrawList.AddImage(user_texture_id, p1, p2, uv0, uv1, ImGui::ColorConvertFloat4ToU32(tint_col));
|
||||
DrawList.AddImage(user_texture_id, p1, p2, uv0, uv1, tint_col32);
|
||||
PopPlotClipRect();
|
||||
EndItem();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user