mirror of
https://github.com/gwm17/implot.git
synced 2024-11-22 18:28:53 -05:00
improve indexing, line rendering performance by 45% (#270)
* add IndexData and Indexers * simplify transformers * 30% improvement * moving around * add TODO.md * fix bar plot aliasing * finishup indexing * remove debug bools
This commit is contained in:
parent
c8601ac0d5
commit
3e96fd7c02
46
TODO.md
Normal file
46
TODO.md
Normal file
|
@ -0,0 +1,46 @@
|
|||
The list below represents a combination of high-priority work, nice-to-have features, and random ideas. We make no guarantees that all of this work will be completed or even started. If you see something that you need or would like to have, let us know, or better yet consider submitting a PR for the feature.
|
||||
|
||||
## Plots
|
||||
|
||||
- remove axis-related args from signature of `BeginPlot` and add `SetupNextAxis` API
|
||||
- add a few overloads of `BeginPlot` that bypass `SetupNextAxis` for common scenarios
|
||||
- make current `BeginPlot` a wrapper to this API
|
||||
|
||||
## Axes
|
||||
|
||||
- add support for multiple x-axes and don't limit count to 3
|
||||
- will require `SetupNextAxis` API
|
||||
- make axis side configurable (top/left, right/bottom) via new flag `ImPlotAxisFlags_Opposite`
|
||||
- add support for setting tick label strings via callback
|
||||
- add flag to remove weekends on Time axis
|
||||
|
||||
## Plot Items
|
||||
|
||||
- add `ImPlotLineFlags`, `ImPlotBarsFlags`, etc. for each plot type
|
||||
- add `PlotBarGroups` wrapper that makes rendering groups of bars easier
|
||||
- add non-zero references for `PlotBars` etc.
|
||||
|
||||
|
||||
## Styling
|
||||
|
||||
- support gradient and/or colormap sampled fills (e.g. ImPlotFillStyle_)
|
||||
- add hover/active color for plot
|
||||
|
||||
## Legend
|
||||
|
||||
- change `SetLegendLocation` API to be more consistent, i.e. `SetNextLegendLocation`
|
||||
- add legend scroll
|
||||
- improve legend icons (e.g. adopt markers, gradients, etc)
|
||||
- `ImPlotLegendFlags`
|
||||
|
||||
## Tools / Misc.
|
||||
|
||||
- add `IsPlotChanging` to detect change in limits
|
||||
- add ability to extend plot/axis context menus
|
||||
- add LTTB downsampling for lines
|
||||
|
||||
## Optimizations
|
||||
|
||||
- find faster way to buffer data into ImDrawList (very slow)
|
||||
- reduce number of calls to `PushClipRect`
|
||||
- explore SIMD operations for high density plot items
|
|
@ -31,6 +31,7 @@ Below is a change-log of API breaking changes only. If you are using one of the
|
|||
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
|
||||
You can read releases logs https://github.com/epezent/implot/releases for more details.
|
||||
|
||||
- 2021/07/30 (0.12) - The offset argument of `PlotXG` functions was been removed. Implement offsetting in your getter callback instead.
|
||||
- 2021/03/08 (0.9) - SetColormap and PushColormap(ImVec4*) were removed. Use AddColormap for custom colormap support. LerpColormap was changed to SampleColormap.
|
||||
ShowColormapScale was changed to ColormapScale and requires additional arguments.
|
||||
- 2021/03/07 (0.9) - The signature of ShowColormapScale was modified to accept a ImVec2 size.
|
||||
|
@ -436,7 +437,6 @@ void Initialize(ImPlotContext* ctx) {
|
|||
IMPLOT_APPEND_CMAP(PiYG, false);
|
||||
IMPLOT_APPEND_CMAP(Spectral, false);
|
||||
IMPLOT_APPEND_CMAP(Greys, false);
|
||||
|
||||
}
|
||||
|
||||
void ResetCtxForNextPlot(ImPlotContext* ctx) {
|
||||
|
@ -4910,7 +4910,7 @@ bool ShowTimePicker(const char* id, ImPlotTime* t) {
|
|||
}
|
||||
if (!hour24) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(am_pm[ap],ImVec2(height,height))) {
|
||||
if (ImGui::Button(am_pm[ap],ImVec2(0,height))) {
|
||||
ap = 1 - ap;
|
||||
changed = true;
|
||||
}
|
||||
|
|
14
implot.h
14
implot.h
|
@ -509,33 +509,33 @@ IMPLOT_API void EndSubplots();
|
|||
// Plots a standard 2D line plot.
|
||||
template <typename T> IMPLOT_API void PlotLine(const char* label_id, const T* values, int count, double xscale=1, double x0=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotLine(const char* label_id, const T* xs, const T* ys, int count, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotLineG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset=0);
|
||||
IMPLOT_API void PlotLineG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count);
|
||||
|
||||
// Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle.
|
||||
template <typename T> IMPLOT_API void PlotScatter(const char* label_id, const T* values, int count, double xscale=1, double x0=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotScatterG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset=0);
|
||||
IMPLOT_API void PlotScatterG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count);
|
||||
|
||||
// Plots a a stairstep graph. The y value is continued constantly from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i].
|
||||
template <typename T> IMPLOT_API void PlotStairs(const char* label_id, const T* values, int count, double xscale=1, double x0=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotStairsG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset=0);
|
||||
IMPLOT_API void PlotStairsG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count);
|
||||
|
||||
// Plots a shaded (filled) region between two lines, or a line and a horizontal reference. Set y_ref to +/-INFINITY for infinite fill extents.
|
||||
template <typename T> IMPLOT_API void PlotShaded(const char* label_id, const T* values, int count, double y_ref=0, double xscale=1, double x0=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double y_ref=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotShadedG(const char* label_id, ImPlotPoint (*getter1)(void* data, int idx), void* data1, ImPlotPoint (*getter2)(void* data, int idx), void* data2, int count, int offset=0);
|
||||
IMPLOT_API void PlotShadedG(const char* label_id, ImPlotPoint (*getter1)(void* data, int idx), void* data1, ImPlotPoint (*getter2)(void* data, int idx), void* data2, int count);
|
||||
|
||||
// Plots a vertical bar graph. #width and #shift are in X units.
|
||||
template <typename T> IMPLOT_API void PlotBars(const char* label_id, const T* values, int count, double width=0.67, double shift=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double width, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotBarsG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double width, int offset=0);
|
||||
IMPLOT_API void PlotBarsG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double width);
|
||||
|
||||
// Plots a horizontal bar graph. #height and #shift are in Y units.
|
||||
template <typename T> IMPLOT_API void PlotBarsH(const char* label_id, const T* values, int count, double height=0.67, double shift=0, int offset=0, int stride=sizeof(T));
|
||||
template <typename T> IMPLOT_API void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset=0, int stride=sizeof(T));
|
||||
IMPLOT_API void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset=0);
|
||||
IMPLOT_API void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height);
|
||||
|
||||
// Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot.
|
||||
template <typename T> IMPLOT_API void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset=0, int stride=sizeof(T));
|
||||
|
@ -571,7 +571,7 @@ template <typename T> IMPLOT_API double PlotHistogram2D(const char* label_id, co
|
|||
|
||||
// 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);
|
||||
IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count);
|
||||
|
||||
// Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down).
|
||||
IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1));
|
||||
|
|
|
@ -1025,7 +1025,7 @@ void ShowDemo_SubplotItemSharing() {
|
|||
}
|
||||
}
|
||||
if (ImPlot::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND"))
|
||||
if (ImGui::AcceptDragDropPayload("MY_DND"))
|
||||
id[curj] = i;
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
|
|
|
@ -1267,12 +1267,6 @@ void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
|
|||
}
|
||||
}
|
||||
|
||||
// Offsets and strides a data buffer
|
||||
template <typename T>
|
||||
static inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) {
|
||||
idx = ImPosMod(offset + idx, count);
|
||||
return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride);
|
||||
}
|
||||
// Calculate histogram bin counts and widths
|
||||
template <typename T>
|
||||
static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
|
||||
|
|
368
implot_items.cpp
368
implot_items.cpp
|
@ -32,15 +32,31 @@
|
|||
#define SQRT_1_2 0.70710678118f
|
||||
#define SQRT_3_2 0.86602540378f
|
||||
|
||||
#define IMPLOT_NORMALIZE2F_OVER_ZERO(VX, VY) \
|
||||
{ \
|
||||
float d2 = VX * VX + VY * VY; \
|
||||
if (d2 > 0.0f) { \
|
||||
float inv_len = 1.0f / ImSqrt(d2); \
|
||||
VX *= inv_len; \
|
||||
VY *= inv_len; \
|
||||
} \
|
||||
}
|
||||
#ifndef IMPLOT_NO_FORCE_INLINE
|
||||
#ifdef _MSC_VER
|
||||
#define IMPLOT_INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
#define IMPLOT_INLINE inline __attribute__((__always_inline__))
|
||||
#elif defined(__CLANG__)
|
||||
#if __has_attribute(__always_inline__)
|
||||
#define IMPLOT_INLINE inline __attribute__((__always_inline__))
|
||||
#else
|
||||
#define IMPLOT_INLINE inline
|
||||
#endif
|
||||
#else
|
||||
#define IMPLOT_INLINE inline
|
||||
#endif
|
||||
#else
|
||||
#define IMPLOT_INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined __SSE__ || defined __x86_64__ || defined _M_X64
|
||||
static IMPLOT_INLINE float ImInvSqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }
|
||||
#else
|
||||
static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); }
|
||||
#endif
|
||||
|
||||
#define IMPLOT_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImInvSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)
|
||||
|
||||
// Support for pre-1.82 versions. Users on 1.82+ can use 0 (default) flags to mean "all corners" but in order to support older versions we are more explicit.
|
||||
#if (IMGUI_VERSION_NUM < 18102) && !defined(ImDrawFlags_RoundCornersAll)
|
||||
|
@ -49,6 +65,16 @@
|
|||
|
||||
namespace ImPlot {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Calc maximum index size of ImDrawIdx
|
||||
template <typename T>
|
||||
struct MaxIdx { static const unsigned int Value; };
|
||||
template <> const unsigned int MaxIdx<unsigned short>::Value = 65535;
|
||||
template <> const unsigned int MaxIdx<unsigned int>::Value = 4294967295;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Item Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -245,6 +271,23 @@ void EndItem() {
|
|||
gp.CurrentItem = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// INDEXERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Offsets and strides a data buffer
|
||||
template <typename T>
|
||||
IMPLOT_INLINE T IndexData(const T* data, int idx, int count, int offset, int stride) {
|
||||
const int s = ((offset == 0) << 0) | ((stride == sizeof(float)) << 1);
|
||||
switch (s) {
|
||||
case 3 : return data[idx];
|
||||
case 2 : return data[(offset + idx) % count];
|
||||
case 1 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx) ) * stride);
|
||||
case 0 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((offset + idx) % count) * stride);
|
||||
default: return T(0);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GETTERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -263,8 +306,8 @@ struct GetterYs {
|
|||
Offset(count ? ImPosMod(offset, count) : 0),
|
||||
Stride(stride)
|
||||
{ }
|
||||
inline ImPlotPoint operator()(int idx) const {
|
||||
return ImPlotPoint(X0 + XScale * idx, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {
|
||||
return ImPlotPoint(X0 + XScale * idx, (double)IndexData(Ys, idx, Count, Offset, Stride));
|
||||
}
|
||||
const T* const Ys;
|
||||
const int Count;
|
||||
|
@ -284,8 +327,8 @@ struct GetterXsYs {
|
|||
Offset(count ? ImPosMod(offset, count) : 0),
|
||||
Stride(stride)
|
||||
{ }
|
||||
inline ImPlotPoint operator()(int idx) const {
|
||||
return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {
|
||||
return ImPlotPoint((double)IndexData(Xs, idx, Count, Offset, Stride), (double)IndexData(Ys, idx, Count, Offset, Stride));
|
||||
}
|
||||
const T* const Xs;
|
||||
const T* const Ys;
|
||||
|
@ -302,7 +345,7 @@ struct GetterYRef {
|
|||
XScale(xscale),
|
||||
X0(x0)
|
||||
{ }
|
||||
inline ImPlotPoint operator()(int idx) const {
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {
|
||||
return ImPlotPoint(X0 + XScale*idx, YRef);
|
||||
}
|
||||
const double YRef;
|
||||
|
@ -321,8 +364,8 @@ struct GetterXsYRef {
|
|||
Offset(count ? ImPosMod(offset, count) : 0),
|
||||
Stride(stride)
|
||||
{ }
|
||||
inline ImPlotPoint operator()(int idx) const {
|
||||
return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), YRef);
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {
|
||||
return ImPlotPoint((double)IndexData(Xs, idx, Count, Offset, Stride), YRef);
|
||||
}
|
||||
const T* const Xs;
|
||||
const double YRef;
|
||||
|
@ -341,8 +384,8 @@ struct GetterXRefYs {
|
|||
Offset(count ? ImPosMod(offset, count) : 0),
|
||||
Stride(stride)
|
||||
{ }
|
||||
inline ImPlotPoint operator()(int idx) const {
|
||||
return ImPlotPoint(XRef, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {
|
||||
return ImPlotPoint(XRef, (double)IndexData(Ys, idx, Count, Offset, Stride));
|
||||
}
|
||||
const double XRef;
|
||||
const T* const Ys;
|
||||
|
@ -353,34 +396,31 @@ struct GetterXRefYs {
|
|||
|
||||
/// Interprets a user's function pointer as ImPlotPoints
|
||||
struct GetterFuncPtr {
|
||||
GetterFuncPtr(ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset) :
|
||||
GetterFuncPtr(ImPlotPoint (*getter)(void* data, int idx), void* data, int count) :
|
||||
Getter(getter),
|
||||
Data(data),
|
||||
Count(count),
|
||||
Offset(count ? ImPosMod(offset, count) : 0)
|
||||
Count(count)
|
||||
{ }
|
||||
inline ImPlotPoint operator()(int idx) const {
|
||||
idx = ImPosMod(Offset + idx, Count);
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const {
|
||||
return Getter(Data, idx);
|
||||
}
|
||||
ImPlotPoint (* const Getter)(void* data, int idx);
|
||||
void* const Data;
|
||||
const int Count;
|
||||
const int Offset;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GetterBarV {
|
||||
const T* Ys; double XShift; int Count; int Offset; int Stride;
|
||||
GetterBarV(const T* ys, double xshift, int count, int offset, int stride) { Ys = ys; XShift = xshift; Count = count; Offset = offset; Stride = stride; }
|
||||
inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)idx + (double)XShift, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); }
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { return ImPlotPoint((double)idx + (double)XShift, (double)IndexData(Ys, idx, Count, Offset, Stride)); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GetterBarH {
|
||||
const T* Xs; double YShift; int Count; int Offset; int Stride;
|
||||
GetterBarH(const T* xs, double yshift, int count, int offset, int stride) { Xs = xs; YShift = yshift; Count = count; Offset = offset; Stride = stride; }
|
||||
inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); }
|
||||
template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { return ImPlotPoint((double)IndexData(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -394,11 +434,11 @@ struct GetterError {
|
|||
Offset(count ? ImPosMod(offset, count) : 0),
|
||||
Stride(stride)
|
||||
{ }
|
||||
inline ImPlotPointError operator()(int idx) const {
|
||||
return ImPlotPointError((double)OffsetAndStride(Xs, idx, Count, Offset, Stride),
|
||||
(double)OffsetAndStride(Ys, idx, Count, Offset, Stride),
|
||||
(double)OffsetAndStride(Neg, idx, Count, Offset, Stride),
|
||||
(double)OffsetAndStride(Pos, idx, Count, Offset, Stride));
|
||||
template <typename I> IMPLOT_INLINE ImPlotPointError operator()(I idx) const {
|
||||
return ImPlotPointError((double)IndexData(Xs, idx, Count, Offset, Stride),
|
||||
(double)IndexData(Ys, idx, Count, Offset, Stride),
|
||||
(double)IndexData(Neg, idx, Count, Offset, Stride),
|
||||
(double)IndexData(Pos, idx, Count, Offset, Stride));
|
||||
}
|
||||
const T* const Xs;
|
||||
const T* const Ys;
|
||||
|
@ -415,73 +455,56 @@ struct GetterError {
|
|||
|
||||
// Transforms convert points in plot space (i.e. ImPlotPoint) to pixel space (i.e. ImVec2)
|
||||
|
||||
// Transforms points for linear x and linear y space
|
||||
struct TransformerLinLin {
|
||||
TransformerLinLin() : YAxis(GetCurrentYAxis()) {}
|
||||
// inline ImVec2 operator()(const ImPlotPoint& plt) const { return (*this)(plt.x, plt.y); }
|
||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||
}
|
||||
const int YAxis;
|
||||
struct TransformerLin {
|
||||
TransformerLin(double pixMin, double pltMin, double, double m, double ) : PixMin(pixMin), PltMin(pltMin), M(m) { }
|
||||
template <typename T> IMPLOT_INLINE float operator()(T p) const { return (float)(PixMin + M * (p - PltMin)); }
|
||||
double PixMin, PltMin, M;
|
||||
};
|
||||
|
||||
// Transforms points for log x and linear y space
|
||||
struct TransformerLogLin {
|
||||
TransformerLogLin() : YAxis(GetCurrentYAxis()) {}
|
||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
double x = plt.x <= 0.0 ? IMPLOT_LOG_ZERO : plt.x;
|
||||
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||
struct TransformerLog {
|
||||
TransformerLog(double pixMin, double pltMin, double pltMax, double m, double den) : Den(den), PltMin(pltMin), PltMax(pltMax), PixMin(pixMin), M(m) { }
|
||||
template <typename T> IMPLOT_INLINE float operator()(T p) const {
|
||||
p = p <= 0.0 ? IMPLOT_LOG_ZERO : p;
|
||||
double t = ImLog10(p / PltMin) / Den;
|
||||
p = ImLerp(PltMin, PltMax, (float)t);
|
||||
return (float)(PixMin + M * (p - PltMin));
|
||||
}
|
||||
const int YAxis;
|
||||
double Den, PltMin, PltMax, PixMin, M;
|
||||
};
|
||||
|
||||
// Transforms points for linear x and log y space
|
||||
struct TransformerLinLog {
|
||||
TransformerLinLog() : YAxis(GetCurrentYAxis()) {}
|
||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
double y = plt.y <= 0.0 ? IMPLOT_LOG_ZERO : plt.y;
|
||||
double t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
||||
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||
template <typename TransformerX, typename TransformerY>
|
||||
struct TransformerXY {
|
||||
TransformerXY() :
|
||||
YAxis(GetCurrentYAxis()),
|
||||
Tx(GImPlot->PixelRange[YAxis].Min.x, GImPlot->CurrentPlot->XAxis.Range.Min, GImPlot->CurrentPlot->XAxis.Range.Max, GImPlot->Mx, GImPlot->LogDenX),
|
||||
Ty(GImPlot->PixelRange[YAxis].Min.y, GImPlot->CurrentPlot->YAxis[YAxis].Range.Min, GImPlot->CurrentPlot->YAxis[YAxis].Range.Max, GImPlot->My[YAxis], GImPlot->LogDenY[YAxis])
|
||||
{ }
|
||||
template <typename P> IMPLOT_INLINE ImVec2 operator()(const P& plt) const {
|
||||
ImVec2 out;
|
||||
out.x = Tx(plt.x);
|
||||
out.y = Ty(plt.y);
|
||||
return out;
|
||||
}
|
||||
const int YAxis;
|
||||
int YAxis;
|
||||
TransformerX Tx;
|
||||
TransformerY Ty;
|
||||
};
|
||||
|
||||
// Transforms points for log x and log y space
|
||||
struct TransformerLogLog {
|
||||
TransformerLogLog() : YAxis(GetCurrentYAxis()) {}
|
||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
double x = plt.x <= 0.0 ? IMPLOT_LOG_ZERO : plt.x;
|
||||
double y = plt.y <= 0.0 ? IMPLOT_LOG_ZERO : plt.y;
|
||||
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||
t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
||||
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||
}
|
||||
const int YAxis;
|
||||
};
|
||||
typedef TransformerXY<TransformerLin,TransformerLin> TransformerLinLin;
|
||||
typedef TransformerXY<TransformerLin,TransformerLog> TransformerLinLog;
|
||||
typedef TransformerXY<TransformerLog,TransformerLin> TransformerLogLin;
|
||||
typedef TransformerXY<TransformerLog,TransformerLog> TransformerLogLog;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIMITIVE RENDERERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void AddLine(const ImVec2& P1, const ImVec2& P2, float weight, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
|
||||
IMPLOT_INLINE void PrimLine(const ImVec2& P1, const ImVec2& P2, float half_weight, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
|
||||
float dx = P2.x - P1.x;
|
||||
float dy = P2.y - P1.y;
|
||||
IMPLOT_NORMALIZE2F_OVER_ZERO(dx, dy);
|
||||
dx *= (weight * 0.5f);
|
||||
dy *= (weight * 0.5f);
|
||||
dx *= half_weight;
|
||||
dy *= half_weight;
|
||||
DrawList._VtxWritePtr[0].pos.x = P1.x + dy;
|
||||
DrawList._VtxWritePtr[0].pos.y = P1.y - dx;
|
||||
DrawList._VtxWritePtr[0].uv = uv;
|
||||
|
@ -509,7 +532,7 @@ inline void AddLine(const ImVec2& P1, const ImVec2& P2, float weight, ImU32 col,
|
|||
DrawList._VtxCurrentIdx += 4;
|
||||
}
|
||||
|
||||
inline void AddRectFilled(const ImVec2& Pmin, const ImVec2& Pmax, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
|
||||
IMPLOT_INLINE void PrimRectFilled(const ImVec2& Pmin, const ImVec2& Pmax, ImU32 col, ImDrawList& DrawList, ImVec2 uv) {
|
||||
DrawList._VtxWritePtr[0].pos = Pmin;
|
||||
DrawList._VtxWritePtr[0].uv = uv;
|
||||
DrawList._VtxWritePtr[0].col = col;
|
||||
|
@ -537,22 +560,22 @@ inline void AddRectFilled(const ImVec2& Pmin, const ImVec2& Pmax, ImU32 col, ImD
|
|||
|
||||
template <typename TGetter, typename TTransformer>
|
||||
struct LineStripRenderer {
|
||||
inline LineStripRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
|
||||
IMPLOT_INLINE LineStripRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
|
||||
Getter(getter),
|
||||
Transformer(transformer),
|
||||
Prims(Getter.Count - 1),
|
||||
Col(col),
|
||||
Weight(weight)
|
||||
HalfWeight(weight/2)
|
||||
{
|
||||
P1 = Transformer(Getter(0));
|
||||
}
|
||||
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
IMPLOT_INLINE bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
ImVec2 P2 = Transformer(Getter(prim + 1));
|
||||
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
|
||||
P1 = P2;
|
||||
return false;
|
||||
}
|
||||
AddLine(P1,P2,Weight,Col,DrawList,uv);
|
||||
PrimLine(P1,P2,HalfWeight,Col,DrawList,uv);
|
||||
P1 = P2;
|
||||
return true;
|
||||
}
|
||||
|
@ -560,15 +583,43 @@ struct LineStripRenderer {
|
|||
const TTransformer& Transformer;
|
||||
const int Prims;
|
||||
const ImU32 Col;
|
||||
const float Weight;
|
||||
const float HalfWeight;
|
||||
mutable ImVec2 P1;
|
||||
static const int IdxConsumed = 6;
|
||||
static const int VtxConsumed = 4;
|
||||
};
|
||||
|
||||
template <typename TGetter1, typename TGetter2, typename TTransformer>
|
||||
struct LineSegmentsRenderer {
|
||||
IMPLOT_INLINE LineSegmentsRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col, float weight) :
|
||||
Getter1(getter1),
|
||||
Getter2(getter2),
|
||||
Transformer(transformer),
|
||||
Prims(ImMin(Getter1.Count, Getter2.Count)),
|
||||
Col(col),
|
||||
HalfWeight(weight/2)
|
||||
{}
|
||||
IMPLOT_INLINE bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
ImVec2 P1 = Transformer(Getter1(prim));
|
||||
ImVec2 P2 = Transformer(Getter2(prim));
|
||||
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
|
||||
return false;
|
||||
PrimLine(P1,P2,HalfWeight,Col,DrawList,uv);
|
||||
return true;
|
||||
}
|
||||
const TGetter1& Getter1;
|
||||
const TGetter2& Getter2;
|
||||
const TTransformer& Transformer;
|
||||
const int Prims;
|
||||
const ImU32 Col;
|
||||
const float HalfWeight;
|
||||
static const int IdxConsumed = 6;
|
||||
static const int VtxConsumed = 4;
|
||||
};
|
||||
|
||||
template <typename TGetter, typename TTransformer>
|
||||
struct StairsRenderer {
|
||||
inline StairsRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
|
||||
IMPLOT_INLINE StairsRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
|
||||
Getter(getter),
|
||||
Transformer(transformer),
|
||||
Prims(Getter.Count - 1),
|
||||
|
@ -577,17 +628,14 @@ struct StairsRenderer {
|
|||
{
|
||||
P1 = Transformer(Getter(0));
|
||||
}
|
||||
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
IMPLOT_INLINE bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
ImVec2 P2 = Transformer(Getter(prim + 1));
|
||||
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
|
||||
P1 = P2;
|
||||
return false;
|
||||
}
|
||||
AddRectFilled(ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, DrawList, uv);
|
||||
AddRectFilled(ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, DrawList, uv);
|
||||
|
||||
// AddLine(P1, P12, Weight, Col, DrawList, uv);
|
||||
// AddLine(P12, P2, Weight, Col, DrawList, uv);
|
||||
PrimRectFilled(ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, DrawList, uv);
|
||||
PrimRectFilled(ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, DrawList, uv);
|
||||
P1 = P2;
|
||||
return true;
|
||||
}
|
||||
|
@ -601,37 +649,11 @@ struct StairsRenderer {
|
|||
static const int VtxConsumed = 8;
|
||||
};
|
||||
|
||||
template <typename TGetter1, typename TGetter2, typename TTransformer>
|
||||
struct LineSegmentsRenderer {
|
||||
inline LineSegmentsRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col, float weight) :
|
||||
Getter1(getter1),
|
||||
Getter2(getter2),
|
||||
Transformer(transformer),
|
||||
Prims(ImMin(Getter1.Count, Getter2.Count)),
|
||||
Col(col),
|
||||
Weight(weight)
|
||||
{}
|
||||
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
ImVec2 P1 = Transformer(Getter1(prim));
|
||||
ImVec2 P2 = Transformer(Getter2(prim));
|
||||
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
|
||||
return false;
|
||||
AddLine(P1,P2,Weight,Col,DrawList,uv);
|
||||
return true;
|
||||
}
|
||||
const TGetter1& Getter1;
|
||||
const TGetter2& Getter2;
|
||||
const TTransformer& Transformer;
|
||||
const int Prims;
|
||||
const ImU32 Col;
|
||||
const float Weight;
|
||||
static const int IdxConsumed = 6;
|
||||
static const int VtxConsumed = 4;
|
||||
};
|
||||
|
||||
|
||||
template <typename TGetter1, typename TGetter2, typename TTransformer>
|
||||
struct ShadedRenderer {
|
||||
ShadedRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col) :
|
||||
IMPLOT_INLINE ShadedRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col) :
|
||||
Getter1(getter1),
|
||||
Getter2(getter2),
|
||||
Transformer(transformer),
|
||||
|
@ -642,7 +664,7 @@ struct ShadedRenderer {
|
|||
P12 = Transformer(Getter2(0));
|
||||
}
|
||||
|
||||
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
IMPLOT_INLINE bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
|
||||
ImVec2 P21 = Transformer(Getter1(prim+1));
|
||||
ImVec2 P22 = Transformer(Getter2(prim+1));
|
||||
ImRect rect(ImMin(ImMin(ImMin(P11,P12),P21),P22), ImMax(ImMax(ImMax(P11,P12),P21),P22));
|
||||
|
@ -692,15 +714,9 @@ struct ShadedRenderer {
|
|||
static const int VtxConsumed = 5;
|
||||
};
|
||||
|
||||
// Stupid way of calculating maximum index size of ImDrawIdx without integer overflow issues
|
||||
template <typename T>
|
||||
struct MaxIdx { static const unsigned int Value; };
|
||||
template <> const unsigned int MaxIdx<unsigned short>::Value = 65535;
|
||||
template <> const unsigned int MaxIdx<unsigned int>::Value = 4294967295;
|
||||
|
||||
/// Renders primitive shapes in bulk as efficiently as possible.
|
||||
template <typename Renderer>
|
||||
inline void RenderPrimitives(const Renderer& renderer, ImDrawList& DrawList, const ImRect& cull_rect) {
|
||||
IMPLOT_INLINE void RenderPrimitives(const Renderer& renderer, ImDrawList& DrawList, const ImRect& cull_rect) {
|
||||
unsigned int prims = renderer.Prims;
|
||||
unsigned int prims_culled = 0;
|
||||
unsigned int idx = 0;
|
||||
|
@ -737,7 +753,7 @@ inline void RenderPrimitives(const Renderer& renderer, ImDrawList& DrawList, con
|
|||
}
|
||||
|
||||
template <typename Getter, typename Transformer>
|
||||
inline void RenderLineStrip(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
|
||||
IMPLOT_INLINE void RenderLineStrip(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
|
||||
ImVec2 p1 = transformer(getter(0));
|
||||
|
@ -754,7 +770,7 @@ inline void RenderLineStrip(const Getter& getter, const Transformer& transformer
|
|||
}
|
||||
|
||||
template <typename Getter1, typename Getter2, typename Transformer>
|
||||
inline void RenderLineSegments(const Getter1& getter1, const Getter2& getter2, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
|
||||
IMPLOT_INLINE void RenderLineSegments(const Getter1& getter1, const Getter2& getter2, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
|
||||
int I = ImMin(getter1.Count, getter2.Count);
|
||||
|
@ -771,7 +787,7 @@ inline void RenderLineSegments(const Getter1& getter1, const Getter2& getter2, c
|
|||
}
|
||||
|
||||
template <typename Getter, typename Transformer>
|
||||
inline void RenderStairs(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
|
||||
IMPLOT_INLINE void RenderStairs(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
|
||||
ImVec2 p1 = transformer(getter(0));
|
||||
|
@ -794,14 +810,14 @@ inline void RenderStairs(const Getter& getter, const Transformer& transformer, I
|
|||
// MARKER RENDERERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void TransformMarker(ImVec2* points, int n, const ImVec2& c, float s) {
|
||||
IMPLOT_INLINE void TransformMarker(ImVec2* points, int n, const ImVec2& c, float s) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
points[i].x = c.x + points[i].x * s;
|
||||
points[i].y = c.y + points[i].y * s;
|
||||
}
|
||||
}
|
||||
|
||||
inline void RenderMarkerGeneral(ImDrawList& DrawList, ImVec2* points, int n, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerGeneral(ImDrawList& DrawList, ImVec2* points, int n, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
TransformMarker(points, n, c, s);
|
||||
if (fill)
|
||||
DrawList.AddConvexPolyFilled(points, n, col_fill);
|
||||
|
@ -811,7 +827,7 @@ inline void RenderMarkerGeneral(ImDrawList& DrawList, ImVec2* points, int n, con
|
|||
}
|
||||
}
|
||||
|
||||
inline void RenderMarkerCircle(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerCircle(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[10] = {ImVec2(1.0f, 0.0f),
|
||||
ImVec2(0.809017f, 0.58778524f),
|
||||
ImVec2(0.30901697f, 0.95105654f),
|
||||
|
@ -825,37 +841,37 @@ inline void RenderMarkerCircle(ImDrawList& DrawList, const ImVec2& c, float s, b
|
|||
RenderMarkerGeneral(DrawList, marker, 10, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerDiamond(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerDiamond(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};
|
||||
RenderMarkerGeneral(DrawList, marker, 4, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerSquare(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerSquare(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[4] = {ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)};
|
||||
RenderMarkerGeneral(DrawList, marker, 4, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerUp(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerUp(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[3] = {ImVec2(SQRT_3_2,0.5f),ImVec2(0,-1),ImVec2(-SQRT_3_2,0.5f)};
|
||||
RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerDown(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerDown(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[3] = {ImVec2(SQRT_3_2,-0.5f),ImVec2(0,1),ImVec2(-SQRT_3_2,-0.5f)};
|
||||
RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerLeft(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerLeft(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[3] = {ImVec2(-1,0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2)};
|
||||
RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerRight(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerRight(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) {
|
||||
ImVec2 marker[3] = {ImVec2(1,0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2)};
|
||||
RenderMarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerAsterisk(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerAsterisk(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
|
||||
ImVec2 marker[6] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f)};
|
||||
TransformMarker(marker, 6, c, s);
|
||||
DrawList.AddLine(marker[0], marker[5], col_outline, weight);
|
||||
|
@ -863,14 +879,14 @@ inline void RenderMarkerAsterisk(ImDrawList& DrawList, const ImVec2& c, float s,
|
|||
DrawList.AddLine(marker[2], marker[3], col_outline, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerPlus(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerPlus(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
|
||||
ImVec2 marker[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};
|
||||
TransformMarker(marker, 4, c, s);
|
||||
DrawList.AddLine(marker[0], marker[2], col_outline, weight);
|
||||
DrawList.AddLine(marker[1], marker[3], col_outline, weight);
|
||||
}
|
||||
|
||||
inline void RenderMarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
|
||||
IMPLOT_INLINE void RenderMarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
|
||||
ImVec2 marker[4] = {ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)};
|
||||
TransformMarker(marker, 4, c, s);
|
||||
DrawList.AddLine(marker[0], marker[2], col_outline, weight);
|
||||
|
@ -878,7 +894,7 @@ inline void RenderMarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bo
|
|||
}
|
||||
|
||||
template <typename Transformer, typename Getter>
|
||||
inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& DrawList, ImPlotMarker marker, float size, bool rend_mk_line, ImU32 col_mk_line, float weight, bool rend_mk_fill, ImU32 col_mk_fill) {
|
||||
IMPLOT_INLINE void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& DrawList, ImPlotMarker marker, float size, bool rend_mk_line, ImU32 col_mk_line, float weight, bool rend_mk_fill, ImU32 col_mk_fill) {
|
||||
static void (*marker_table[ImPlotMarker_COUNT])(ImDrawList&, const ImVec2&, float s, bool, ImU32, bool, ImU32, float) = {
|
||||
RenderMarkerCircle,
|
||||
RenderMarkerSquare,
|
||||
|
@ -905,7 +921,7 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename Getter>
|
||||
inline void PlotLineEx(const char* label_id, const Getter& getter) {
|
||||
IMPLOT_INLINE void PlotLineEx(const char* label_id, const Getter& getter) {
|
||||
if (BeginItem(label_id, ImPlotCol_Line)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < getter.Count; ++i) {
|
||||
|
@ -941,6 +957,7 @@ inline void PlotLineEx(const char* label_id, const Getter& getter) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void PlotLine(const char* label_id, const T* values, int count, double xscale, double x0, int offset, int stride) {
|
||||
GetterYs<T> getter(values,count,xscale,x0,offset,stride);
|
||||
|
@ -976,8 +993,8 @@ template IMPLOT_API void PlotLine<float>(const char* label_id, const float* xs,
|
|||
template IMPLOT_API void PlotLine<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotLineG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
|
||||
GetterFuncPtr getter(getter_func,data, count, offset);
|
||||
void PlotLineG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count) {
|
||||
GetterFuncPtr getter(getter_func,data, count);
|
||||
return PlotLineEx(label_id, getter);
|
||||
}
|
||||
|
||||
|
@ -986,7 +1003,7 @@ void PlotLineG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename Getter>
|
||||
inline void PlotScatterEx(const char* label_id, const Getter& getter) {
|
||||
IMPLOT_INLINE void PlotScatterEx(const char* label_id, const Getter& getter) {
|
||||
if (BeginItem(label_id, ImPlotCol_MarkerOutline)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < getter.Count; ++i) {
|
||||
|
@ -1049,8 +1066,8 @@ template IMPLOT_API void PlotScatter<float>(const char* label_id, const float* x
|
|||
template IMPLOT_API void PlotScatter<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotScatterG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
|
||||
GetterFuncPtr getter(getter_func,data, count, offset);
|
||||
void PlotScatterG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count) {
|
||||
GetterFuncPtr getter(getter_func,data, count);
|
||||
return PlotScatterEx(label_id, getter);
|
||||
}
|
||||
|
||||
|
@ -1059,7 +1076,7 @@ void PlotScatterG(const char* label_id, ImPlotPoint (*getter_func)(void* data, i
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename Getter>
|
||||
inline void PlotStairsEx(const char* label_id, const Getter& getter) {
|
||||
IMPLOT_INLINE void PlotStairsEx(const char* label_id, const Getter& getter) {
|
||||
if (BeginItem(label_id, ImPlotCol_Line)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < getter.Count; ++i) {
|
||||
|
@ -1130,8 +1147,8 @@ template IMPLOT_API void PlotStairs<float>(const char* label_id, const float* xs
|
|||
template IMPLOT_API void PlotStairs<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotStairsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
|
||||
GetterFuncPtr getter(getter_func,data, count, offset);
|
||||
void PlotStairsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count) {
|
||||
GetterFuncPtr getter(getter_func,data, count);
|
||||
return PlotStairsEx(label_id, getter);
|
||||
}
|
||||
|
||||
|
@ -1140,7 +1157,7 @@ void PlotStairsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, in
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename Getter1, typename Getter2>
|
||||
inline void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, bool fit2) {
|
||||
IMPLOT_INLINE void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, bool fit2) {
|
||||
if (BeginItem(label_id, ImPlotCol_Fill)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < getter1.Count; ++i)
|
||||
|
@ -1238,9 +1255,9 @@ template IMPLOT_API void PlotShaded<float>(const char* label_id, const float* xs
|
|||
template IMPLOT_API void PlotShaded<double>(const char* label_id, const double* xs, const double* ys1, const double* ys2, int count, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotShadedG(const char* label_id, ImPlotPoint (*g1)(void* data, int idx), void* data1, ImPlotPoint (*g2)(void* data, int idx), void* data2, int count, int offset) {
|
||||
GetterFuncPtr getter1(g1, data1, count, offset);
|
||||
GetterFuncPtr getter2(g2, data2, count, offset);
|
||||
void PlotShadedG(const char* label_id, ImPlotPoint (*g1)(void* data, int idx), void* data1, ImPlotPoint (*g2)(void* data, int idx), void* data2, int count) {
|
||||
GetterFuncPtr getter1(g1, data1, count);
|
||||
GetterFuncPtr getter2(g2, data2, count);
|
||||
PlotShadedEx(label_id, getter1, getter2, true);
|
||||
}
|
||||
|
||||
|
@ -1274,6 +1291,13 @@ void PlotBarsEx(const char* label_id, const Getter& getter, double width) {
|
|||
continue;
|
||||
ImVec2 a = PlotToPixels(p.x - half_width, p.y);
|
||||
ImVec2 b = PlotToPixels(p.x + half_width, 0);
|
||||
float width_px = ImAbs(a.x-b.x);
|
||||
if (width_px < 1.0f) {
|
||||
a.x += a.x > b.x ? (1-width_px) / 2 : (width_px-1) / 2;
|
||||
b.x += b.x > a.x ? (1-width_px) / 2 : (width_px-1) / 2;
|
||||
}
|
||||
// a.x = IM_ROUND(a.x);
|
||||
// b.x = IM_ROUND(b.x);
|
||||
if (s.RenderFill)
|
||||
DrawList.AddRectFilled(a, b, col_fill);
|
||||
if (rend_line)
|
||||
|
@ -1318,8 +1342,8 @@ template IMPLOT_API void PlotBars<float>(const char* label_id, const float* xs,
|
|||
template IMPLOT_API void PlotBars<double>(const char* label_id, const double* xs, const double* ys, int count, double width, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotBarsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width, int offset) {
|
||||
GetterFuncPtr getter(getter_func, data, count, offset);
|
||||
void PlotBarsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width) {
|
||||
GetterFuncPtr getter(getter_func, data, count);
|
||||
PlotBarsEx(label_id, getter, width);
|
||||
}
|
||||
|
||||
|
@ -1397,8 +1421,8 @@ template IMPLOT_API void PlotBarsH<float>(const char* label_id, const float* xs,
|
|||
template IMPLOT_API void PlotBarsH<double>(const char* label_id, const double* xs, const double* ys, int count, double height, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotBarsHG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height, int offset) {
|
||||
GetterFuncPtr getter(getter_func, data, count, offset);
|
||||
void PlotBarsHG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height) {
|
||||
GetterFuncPtr getter(getter_func, data, count);
|
||||
PlotBarsHEx(label_id, getter, height);
|
||||
}
|
||||
|
||||
|
@ -1541,7 +1565,7 @@ template IMPLOT_API void PlotErrorBarsH<double>(const char* label_id, const doub
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename GetterM, typename GetterB>
|
||||
inline void PlotStemsEx(const char* label_id, const GetterM& get_mark, const GetterB& get_base) {
|
||||
IMPLOT_INLINE void PlotStemsEx(const char* label_id, const GetterM& get_mark, const GetterB& get_base) {
|
||||
if (BeginItem(label_id, ImPlotCol_Line)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < get_base.Count; ++i) {
|
||||
|
@ -1698,7 +1722,7 @@ template IMPLOT_API void PlotHLines<double>(const char* label_id, const double*
|
|||
// PLOT PIE CHART
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void RenderPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) {
|
||||
IMPLOT_INLINE void RenderPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) {
|
||||
static const float resolution = 50 / (2 * IM_PI);
|
||||
static ImVec2 buffer[50];
|
||||
buffer[0] = PlotToPixels(center);
|
||||
|
@ -1787,12 +1811,12 @@ struct RectInfo {
|
|||
|
||||
template <typename TGetter, typename TTransformer>
|
||||
struct RectRenderer {
|
||||
inline RectRenderer(const TGetter& getter, const TTransformer& transformer) :
|
||||
IMPLOT_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 {
|
||||
IMPLOT_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);
|
||||
|
@ -1849,7 +1873,7 @@ struct GetterHeatmap {
|
|||
HalfSize(Width*0.5, Height*0.5)
|
||||
{ }
|
||||
|
||||
inline RectInfo operator()(int idx) const {
|
||||
template <typename I> IMPLOT_INLINE RectInfo operator()(I idx) const {
|
||||
double val = (double)Values[idx];
|
||||
const int r = idx / Cols;
|
||||
const int c = idx % Cols;
|
||||
|
@ -2129,7 +2153,7 @@ template IMPLOT_API double PlotHistogram2D<double>(const char* label_id, const d
|
|||
// TODO: Make this behave like all the other plot types (.e. not fixed in y axis)
|
||||
|
||||
template <typename Getter>
|
||||
inline void PlotDigitalEx(const char* label_id, Getter getter) {
|
||||
IMPLOT_INLINE void PlotDigitalEx(const char* label_id, Getter getter) {
|
||||
if (BeginItem(label_id, ImPlotCol_Fill)) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
ImDrawList& DrawList = *GetPlotDrawList();
|
||||
|
@ -2203,8 +2227,8 @@ template IMPLOT_API void PlotDigital<float>(const char* label_id, const float* x
|
|||
template IMPLOT_API void PlotDigital<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
|
||||
|
||||
// custom
|
||||
void PlotDigitalG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
|
||||
GetterFuncPtr getter(getter_func,data,count,offset);
|
||||
void PlotDigitalG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count) {
|
||||
GetterFuncPtr getter(getter_func,data,count);
|
||||
return PlotDigitalEx(label_id, getter);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user