1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-22 18:28:53 -05:00

Merge branch 'master' into backends

This commit is contained in:
Evan Pezent 2021-07-30 20:34:11 -07:00
commit 621d56b379
6 changed files with 271 additions and 194 deletions

46
TODO.md Normal file
View 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

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.11 WIP
// ImPlot v0.12 WIP
/*
@ -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.
@ -2817,7 +2818,6 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
// calc plot frame sizes
ImVec2 title_size(0.0f, 0.0f);
const float txt_height = ImGui::GetTextLineHeight();
if (!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoTitle))
title_size = ImGui::CalcTextSize(title, NULL, true);
const float pad_top = title_size.x > 0.0f ? title_size.y + gp.Style.LabelPadding.y : 0;
@ -2860,12 +2860,10 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
// render splitters
if (!ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoResize)) {
ImDrawList& DrawList = *ImGui::GetWindowDrawList();
const ImU32 nrm_col = ImGui::ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_Separator]);
const ImU32 hov_col = ImGui::ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_SeparatorHovered]);
const ImU32 act_col = ImGui::ColorConvertFloat4ToU32(GImGui->Style.Colors[ImGuiCol_SeparatorActive]);
float xpos = subplot.GridRect.Min.x;
float ypos = subplot.GridRect.Min.y;
const ImVec2 mouse = ImGui::GetIO().MousePos;
int separator = 1;
// bool pass = false;
for (int r = 0; r < subplot.Rows-1; ++r) {
@ -3188,6 +3186,12 @@ void PopPlotClipRect() {
ImGui::PopClipRect();
}
bool IsSubplotsHovered() {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentSubplot != NULL, "IsSubplotsHovered() needs to be called between BeginSubplots() and EndSubplots()!");
return gp.CurrentSubplot->FrameHovered;
}
bool IsPlotHovered() {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "IsPlotHovered() needs to be called between BeginPlot() and EndPlot()!");
@ -4924,7 +4928,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;
}

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.11 WIP
// ImPlot v0.12 WIP
#pragma once
#include "imgui.h"
@ -38,7 +38,7 @@
#endif
// ImPlot version string
#define IMPLOT_VERSION "0.11 WIP"
#define IMPLOT_VERSION "0.12 WIP"
// Indicates variable should deduced automatically.
#define IMPLOT_AUTO -1
// Special color used to indicate that a color should be deduced automatically.
@ -420,7 +420,7 @@ IMPLOT_API void EndPlot();
// EndSubplots();
// }
//
// Procudes:
// Produces:
//
// [0][1][2]
// [3][4][5]
@ -510,33 +510,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));
@ -572,7 +572,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));
@ -652,8 +652,11 @@ IMPLOT_API ImPlotLimits GetPlotQuery(ImPlotYAxis y_axis = IMPLOT_AUTO);
// Set the current plot query bounds. Query must be enabled with ImPlotFlags_Query.
IMPLOT_API void SetPlotQuery(const ImPlotLimits& query, ImPlotYAxis y_axis = IMPLOT_AUTO);
// Returns true if the bounding frame of a subplot is hovered/
IMPLOT_API bool IsSubplotsHovered();
//-----------------------------------------------------------------------------
// Algined Plots
// Aligned Plots
//-----------------------------------------------------------------------------
// Consider using Begin/EndSubplots first. They are more feature rich and

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.11 WIP
// ImPlot v0.12 WIP
#include "implot.h"
#include <math.h>
@ -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();
}

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.11 WIP
// ImPlot v0.12 WIP
// You may use this file to debug, understand or extend ImPlot features but we
// don't provide any guarantee of forward compatibility!
@ -1271,12 +1271,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) {

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.11 WIP
// ImPlot v0.12 WIP
#include "implot.h"
#include "implot_internal.h"
@ -33,15 +33,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)
@ -70,6 +86,16 @@ template <> const ImGuiDataType ImGuiDataTypeGetter<ImS32>::Value = ImGuiDataTy
template <> const ImGuiDataType ImGuiDataTypeGetter<ImU64>::Value = ImGuiDataType_U64;
template <> const ImGuiDataType ImGuiDataTypeGetter<ImS64>::Value = ImGuiDataType_S64;
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
@ -267,6 +293,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
//-----------------------------------------------------------------------------
@ -285,8 +328,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;
@ -306,8 +349,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;
@ -324,7 +367,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;
@ -343,8 +386,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;
@ -363,8 +406,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;
@ -375,34 +418,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>
@ -416,11 +456,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;
@ -437,73 +477,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;
@ -531,7 +554,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;
@ -559,22 +582,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;
}
@ -582,15 +605,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),
@ -599,17 +650,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;
}
@ -623,37 +671,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),
@ -664,7 +686,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));
@ -695,8 +717,8 @@ struct ShadedRenderer {
DrawList._IdxWritePtr[1] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1 + intersect);
DrawList._IdxWritePtr[2] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3);
DrawList._IdxWritePtr[3] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 1);
DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - intersect);
DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4);
DrawList._IdxWritePtr[4] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 4);
DrawList._IdxWritePtr[5] = (ImDrawIdx)(DrawList._VtxCurrentIdx + 3 - intersect);
DrawList._IdxWritePtr += 6;
DrawList._VtxCurrentIdx += 5;
P11 = P21;
@ -716,7 +738,7 @@ struct ShadedRenderer {
/// 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;
@ -753,7 +775,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));
@ -770,7 +792,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);
@ -787,7 +809,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));
@ -810,14 +832,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);
@ -827,7 +849,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),
@ -841,37 +863,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);
@ -879,14 +901,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);
@ -894,7 +916,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,
@ -921,7 +943,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) {
@ -957,6 +979,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);
@ -992,8 +1015,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);
}
@ -1002,7 +1025,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) {
@ -1065,8 +1088,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);
}
@ -1075,7 +1098,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) {
@ -1146,8 +1169,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);
}
@ -1156,7 +1179,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)
@ -1254,9 +1277,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);
}
@ -1290,6 +1313,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)
@ -1334,8 +1364,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);
}
@ -1413,8 +1443,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);
}
@ -1557,7 +1587,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) {
@ -1714,7 +1744,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);
@ -1803,12 +1833,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);
@ -1865,7 +1895,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;
@ -2154,7 +2184,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();
@ -2228,8 +2258,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);
}