#pragma once
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <time.h>
#include "imgui_internal.h"
#ifndef IMPLOT_VERSION
#error Must include implot.h before implot_internal.h
#endif
struct ImPlotTick;
struct ImPlotAxis;
struct ImPlotAxisState;
struct ImPlotAxisColor;
struct ImPlotItem;
struct ImPlotLegendData;
struct ImPlotPlot;
struct ImPlotNextPlotData;
extern IMPLOT_API ImPlotContext* GImPlot;
#define IMPLOT_Y_AXES 3
#define IMPLOT_SUB_DIV 10
#define IMPLOT_ZOOM_RATE 0.1f
#define IMPLOT_MIN_TIME 0
#define IMPLOT_MAX_TIME 32503680000
static inline float ImLog10(float x) { return log10f(x); }
static inline double ImLog10(double x) { return log10(x); }
template <typename TSet, typename TFlag>
inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
template <typename TSet, typename TFlag>
inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
template <typename T>
inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
inline bool ImNanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); }
inline double ImConstrainNan(double val) { return isnan(val) ? 0 : val; }
inline double ImConstrainInf(double val) { return val == HUGE_VAL ? DBL_MAX : val == -HUGE_VAL ? - DBL_MAX : val; }
inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) { return ImAbs(v1-v2) < DBL_EPSILON * ImAbs(v1+v2) * ulp || ImAbs(v1-v2) < DBL_MIN; }
template <int Count>
struct ImOffsetCalculator {
ImOffsetCalculator(const int* sizes) {
Offsets[0] = 0;
for (int i = 1; i < Count; ++i)
Offsets[i] = Offsets[i-1] + sizes[i-1];
}
int Offsets[Count];
};
struct ImBufferWriter
{
char* Buffer;
int Size;
int Pos;
ImBufferWriter(char* buffer, int size) {
Buffer = buffer;
Size = size;
Pos = 0;
}
void Write(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
WriteV(fmt, args);
va_end(args);
}
void WriteV(const char* fmt, va_list args) {
const int written = ::vsnprintf(&Buffer[Pos], Size - Pos - 1, fmt, args);
if (written > 0)
Pos += ImMin(written, Size-Pos-1);
}
};
template <int N>
struct ImPlotPointArray {
inline ImPlotPoint& operator[](int i) { return Data[i]; }
inline const ImPlotPoint& operator[](int i) const { return Data[i]; }
inline int Size() { return N; }
ImPlotPoint Data[N];
};
typedef int ImPlotScale; typedef int ImPlotTimeUnit; typedef int ImPlotDateFmt; typedef int ImPlotTimeFmt;
enum ImPlotScale_ {
ImPlotScale_LinLin, ImPlotScale_LogLin, ImPlotScale_LinLog, ImPlotScale_LogLog };
enum ImPlotTimeUnit_ {
ImPlotTimeUnit_Us, ImPlotTimeUnit_Ms, ImPlotTimeUnit_S, ImPlotTimeUnit_Min, ImPlotTimeUnit_Hr, ImPlotTimeUnit_Day, ImPlotTimeUnit_Mo, ImPlotTimeUnit_Yr, ImPlotTimeUnit_COUNT
};
enum ImPlotDateFmt_ { ImPlotDateFmt_None = 0,
ImPlotDateFmt_DayMo, ImPlotDateFmt_DayMoYr, ImPlotDateFmt_MoYr, ImPlotDateFmt_Mo, ImPlotDateFmt_Yr };
enum ImPlotTimeFmt_ { ImPlotTimeFmt_None = 0,
ImPlotTimeFmt_Us, ImPlotTimeFmt_SUs, ImPlotTimeFmt_SMs, ImPlotTimeFmt_S, ImPlotTimeFmt_HrMinSMs, ImPlotTimeFmt_HrMinS, ImPlotTimeFmt_HrMin, ImPlotTimeFmt_Hr };
struct ImPlotDateTimeFmt {
ImPlotDateTimeFmt(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt, bool use_24_hr_clk = false, bool use_iso_8601 = false) {
Date = date_fmt;
Time = time_fmt;
UseISO8601 = use_iso_8601;
Use24HourClock = use_24_hr_clk;
}
ImPlotDateFmt Date;
ImPlotTimeFmt Time;
bool UseISO8601;
bool Use24HourClock;
};
struct ImPlotTime {
time_t S; int Us; ImPlotTime() { S = 0; Us = 0; }
ImPlotTime(time_t s, int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
double ToDouble() const { return (double)S + (double)Us / 1000000.0; }
static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); }
};
static inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
static inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
static inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return lhs.S == rhs.S && lhs.Us == rhs.Us; }
static inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
static inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return rhs < lhs; }
static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return lhs < rhs || lhs == rhs; }
static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)
{ return lhs > rhs || lhs == rhs; }
struct ImPlotColormapMod {
ImPlotColormapMod(const ImVec4* colormap, int colormap_size) {
Colormap = colormap;
ColormapSize = colormap_size;
}
const ImVec4* Colormap;
int ColormapSize;
};
struct ImPlotPointError
{
double X, Y, Neg, Pos;
ImPlotPointError(double x, double y, double neg, double pos) {
X = x; Y = y; Neg = neg; Pos = pos;
}
};
struct ImPlotAnnotation {
ImVec2 Pos;
ImVec2 Offset;
ImU32 ColorBg;
ImU32 ColorFg;
int TextOffset;
bool Clamp;
};
struct ImPlotAnnotationCollection {
ImVector<ImPlotAnnotation> Annotations;
ImGuiTextBuffer TextBuffer;
int Size;
ImPlotAnnotationCollection() { Reset(); }
void AppendV(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, va_list args) IM_FMTLIST(7) {
ImPlotAnnotation an;
an.Pos = pos; an.Offset = off;
an.ColorBg = bg; an.ColorFg = fg;
an.TextOffset = TextBuffer.size();
an.Clamp = clamp;
Annotations.push_back(an);
TextBuffer.appendfv(fmt, args);
const char nul[] = "";
TextBuffer.append(nul,nul+1);
Size++;
}
void Append(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, ...) IM_FMTARGS(7) {
va_list args;
va_start(args, fmt);
AppendV(pos, off, bg, fg, clamp, fmt, args);
va_end(args);
}
const char* GetText(int idx) {
return TextBuffer.Buf.Data + Annotations[idx].TextOffset;
}
void Reset() {
Annotations.shrink(0);
TextBuffer.Buf.shrink(0);
Size = 0;
}
};
struct ImPlotTick
{
double PlotPos;
float PixelPos;
ImVec2 LabelSize;
int TextOffset;
bool Major;
bool ShowLabel;
int Level;
ImPlotTick(double value, bool major, bool show_label) {
PlotPos = value;
Major = major;
ShowLabel = show_label;
TextOffset = -1;
Level = 0;
}
};
struct ImPlotTickCollection {
ImVector<ImPlotTick> Ticks;
ImGuiTextBuffer TextBuffer;
float TotalWidth;
float TotalHeight;
float MaxWidth;
float MaxHeight;
int Size;
ImPlotTickCollection() { Reset(); }
void Append(const ImPlotTick& tick) {
if (tick.ShowLabel) {
TotalWidth += tick.ShowLabel ? tick.LabelSize.x : 0;
TotalHeight += tick.ShowLabel ? tick.LabelSize.y : 0;
MaxWidth = tick.LabelSize.x > MaxWidth ? tick.LabelSize.x : MaxWidth;
MaxHeight = tick.LabelSize.y > MaxHeight ? tick.LabelSize.y : MaxHeight;
}
Ticks.push_back(tick);
Size++;
}
void Append(double value, bool major, bool show_label, void (*labeler)(ImPlotTick& tick, ImGuiTextBuffer& buf)) {
ImPlotTick tick(value, major, show_label);
if (labeler)
labeler(tick, TextBuffer);
Append(tick);
}
const char* GetText(int idx) {
return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
}
void Reset() {
Ticks.shrink(0);
TextBuffer.Buf.shrink(0);
TotalWidth = TotalHeight = MaxWidth = MaxHeight = 0;
Size = 0;
}
};
struct ImPlotAxis
{
ImPlotAxisFlags Flags;
ImPlotAxisFlags PreviousFlags;
ImPlotRange Range;
float Pixels;
ImPlotOrientation Orientation;
bool Dragging;
bool ExtHovered;
bool AllHovered;
bool Present;
bool HasRange;
double* LinkedMin;
double* LinkedMax;
ImPlotTime PickerTimeMin, PickerTimeMax;
int PickerLevel;
ImU32 ColorMaj, ColorMin, ColorTxt;
ImGuiCond RangeCond;
ImRect HoverRect;
ImPlotAxis() {
Flags = PreviousFlags = ImPlotAxisFlags_None;
Range.Min = 0;
Range.Max = 1;
Dragging = false;
ExtHovered = false;
AllHovered = false;
LinkedMin = LinkedMax = NULL;
PickerLevel = 0;
ColorMaj = ColorMin = ColorTxt = 0;
}
bool SetMin(double _min) {
_min = ImConstrainNan(ImConstrainInf(_min));
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
_min = ImConstrainLog(_min);
if (ImHasFlag(Flags, ImPlotAxisFlags_Time))
_min = ImConstrainTime(_min);
if (_min >= Range.Max)
return false;
Range.Min = _min;
PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
return true;
};
bool SetMax(double _max) {
_max = ImConstrainNan(ImConstrainInf(_max));
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
_max = ImConstrainLog(_max);
if (ImHasFlag(Flags, ImPlotAxisFlags_Time))
_max = ImConstrainTime(_max);
if (_max <= Range.Min)
return false;
Range.Max = _max;
PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
return true;
};
void SetRange(double _min, double _max) {
Range.Min = _min;
Range.Max = _max;
Constrain();
PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
}
void SetRange(const ImPlotRange& range) {
SetRange(range.Min, range.Max);
}
void SetAspect(double unit_per_pix) {
double new_size = unit_per_pix * Pixels;
double delta = (new_size - Range.Size()) * 0.5f;
if (IsLocked())
return;
else if (IsLockedMin() && !IsLockedMax())
SetRange(Range.Min, Range.Max + 2*delta);
else if (!IsLockedMin() && IsLockedMax())
SetRange(Range.Min - 2*delta, Range.Max);
else
SetRange(Range.Min - delta, Range.Max + delta);
}
double GetAspect() const { return Range.Size() / Pixels; }
void Constrain() {
Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale)) {
Range.Min = ImConstrainLog(Range.Min);
Range.Max = ImConstrainLog(Range.Max);
}
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
Range.Min = ImConstrainTime(Range.Min);
Range.Max = ImConstrainTime(Range.Max);
}
if (Range.Max <= Range.Min)
Range.Max = Range.Min + DBL_EPSILON;
}
inline bool IsLabeled() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
inline bool IsAlwaysLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
inline bool IsLockedMin() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMin) || IsAlwaysLocked(); }
inline bool IsLockedMax() const { return ImHasFlag(Flags, ImPlotAxisFlags_LockMax) || IsAlwaysLocked(); }
inline bool IsLocked() const { return !Present || ((IsLockedMin() && IsLockedMax()) || IsAlwaysLocked()); }
inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
};
struct ImPlotItem
{
ImGuiID ID;
ImVec4 Color;
int NameOffset;
bool Show;
bool LegendHovered;
bool SeenThisFrame;
ImPlotItem() {
ID = 0;
Color = ImPlot::NextColormapColor();
NameOffset = -1;
Show = true;
SeenThisFrame = false;
LegendHovered = false;
}
~ImPlotItem() { ID = 0; }
};
struct ImPlotLegendData
{
ImVector<int> Indices;
ImGuiTextBuffer Labels;
void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
};
struct ImPlotPlot
{
ImGuiID ID;
ImPlotFlags Flags;
ImPlotFlags PreviousFlags;
ImPlotAxis XAxis;
ImPlotAxis YAxis[IMPLOT_Y_AXES];
ImPlotLegendData LegendData;
ImPool<ImPlotItem> Items;
ImVec2 SelectStart;
ImVec2 QueryStart;
ImRect QueryRect;
bool Selecting;
bool Querying;
bool Queried;
bool DraggingQuery;
bool LegendHovered;
bool LegendOutside;
bool LegendFlipSideNextFrame;
bool FrameHovered;
bool PlotHovered;
int ColormapIdx;
int CurrentYAxis;
ImPlotLocation MousePosLocation;
ImPlotLocation LegendLocation;
ImPlotOrientation LegendOrientation;
ImRect FrameRect;
ImRect CanvasRect;
ImRect PlotRect;
ImRect AxesRect;
ImPlotPlot() {
Flags = PreviousFlags = ImPlotFlags_None;
XAxis.Orientation = ImPlotOrientation_Horizontal;
for (int i = 0; i < IMPLOT_Y_AXES; ++i)
YAxis[i].Orientation = ImPlotOrientation_Vertical;
SelectStart = QueryStart = ImVec2(0,0);
Selecting = Querying = Queried = DraggingQuery = LegendHovered = LegendOutside = LegendFlipSideNextFrame = false;
ColormapIdx = CurrentYAxis = 0;
LegendLocation = ImPlotLocation_North | ImPlotLocation_West;
LegendOrientation = ImPlotOrientation_Vertical;
MousePosLocation = ImPlotLocation_South | ImPlotLocation_East;
}
int GetLegendCount() const { return LegendData.Indices.size(); }
ImPlotItem* GetLegendItem(int i);
const char* GetLegendLabel(int i);
inline bool IsLocked() const { return XAxis.IsLocked() && YAxis[0].IsLocked() && YAxis[1].IsLocked() && YAxis[2].IsLocked(); }
};
struct ImPlotNextPlotData
{
ImGuiCond XRangeCond;
ImGuiCond YRangeCond[IMPLOT_Y_AXES];
ImPlotRange X;
ImPlotRange Y[IMPLOT_Y_AXES];
bool HasXRange;
bool HasYRange[IMPLOT_Y_AXES];
bool ShowDefaultTicksX;
bool ShowDefaultTicksY[IMPLOT_Y_AXES];
bool FitX;
bool FitY[IMPLOT_Y_AXES];
double* LinkedXmin;
double* LinkedXmax;
double* LinkedYmin[IMPLOT_Y_AXES];
double* LinkedYmax[IMPLOT_Y_AXES];
ImPlotNextPlotData() { Reset(); }
void Reset() {
HasXRange = false;
ShowDefaultTicksX = true;
FitX = false;
LinkedXmin = LinkedXmax = NULL;
for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
HasYRange[i] = false;
ShowDefaultTicksY[i] = true;
FitY[i] = false;
LinkedYmin[i] = LinkedYmax[i] = NULL;
}
}
};
struct ImPlotNextItemData {
ImVec4 Colors[5]; float LineWeight;
ImPlotMarker Marker;
float MarkerSize;
float MarkerWeight;
float FillAlpha;
float ErrorBarSize;
float ErrorBarWeight;
float DigitalBitHeight;
float DigitalBitGap;
bool RenderLine;
bool RenderFill;
bool RenderMarkerLine;
bool RenderMarkerFill;
bool HasHidden;
bool Hidden;
ImGuiCond HiddenCond;
ImPlotNextItemData() { Reset(); }
void Reset() {
for (int i = 0; i < 5; ++i)
Colors[i] = IMPLOT_AUTO_COL;
LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
Marker = IMPLOT_AUTO;
HasHidden = Hidden = false;
}
};
struct ImPlotContext {
ImPool<ImPlotPlot> Plots;
ImPlotPlot* CurrentPlot;
ImPlotItem* CurrentItem;
ImPlotItem* PreviousItem;
ImPlotTickCollection XTicks;
ImPlotTickCollection YTicks[IMPLOT_Y_AXES];
float YAxisReference[IMPLOT_Y_AXES];
ImPlotAnnotationCollection Annotations;
ImPlotScale Scales[IMPLOT_Y_AXES];
ImRect PixelRange[IMPLOT_Y_AXES];
double Mx;
double My[IMPLOT_Y_AXES];
double LogDenX;
double LogDenY[IMPLOT_Y_AXES];
ImPlotRange ExtentsX;
ImPlotRange ExtentsY[IMPLOT_Y_AXES];
bool FitThisFrame;
bool FitX;
bool FitY[IMPLOT_Y_AXES];
bool RenderX;
bool RenderY[IMPLOT_Y_AXES];
bool ChildWindowMade;
ImPlotStyle Style;
ImVector<ImGuiColorMod> ColorModifiers;
ImVector<ImGuiStyleMod> StyleModifiers;
const ImVec4* Colormap;
int ColormapSize;
ImVector<ImPlotColormapMod> ColormapModifiers;
tm Tm;
int VisibleItemCount;
int DigitalPlotItemCnt;
int DigitalPlotOffset;
ImPlotNextPlotData NextPlotData;
ImPlotNextItemData NextItemData;
ImPlotInputMap InputMap;
ImPlotPoint MousePos[IMPLOT_Y_AXES];
};
namespace ImPlot {
IMPLOT_API void Initialize(ImPlotContext* ctx);
IMPLOT_API void Reset(ImPlotContext* ctx);
IMPLOT_API ImPlotPlot* GetPlot(const char* title);
IMPLOT_API ImPlotPlot* GetCurrentPlot();
IMPLOT_API void BustPlotCache();
IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
IMPLOT_API bool BeginItem(const char* label_id, ImPlotCol recolor_from = -1);
IMPLOT_API void EndItem();
IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, bool* just_created = NULL);
IMPLOT_API ImPlotItem* GetItem(const char* label_id);
IMPLOT_API ImPlotItem* GetCurrentItem();
IMPLOT_API void BustItemCache();
inline int GetCurrentYAxis() { return GImPlot->CurrentPlot->CurrentYAxis; }
IMPLOT_API void UpdateAxisColors(int axis_flag, ImPlotAxis* axis);
IMPLOT_API void UpdateTransformCache();
inline ImPlotScale GetCurrentScale() { return GImPlot->Scales[GetCurrentYAxis()]; }
inline bool FitThisFrame() { return GImPlot->FitThisFrame; }
IMPLOT_API void FitPoint(const ImPlotPoint& p);
inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)
{ return r1.Min <= r2.Max && r2.Min <= r1.Max; }
IMPLOT_API void PushLinkedAxis(ImPlotAxis& axis);
IMPLOT_API void PullLinkedAxis(ImPlotAxis& axis);
IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
IMPLOT_API ImVec2 CalcLegendSize(ImPlotPlot& plot, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation);
IMPLOT_API void ShowLegendEntries(ImPlotPlot& plot, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation, ImDrawList& DrawList);
IMPLOT_API void ShowAltLegend(const char* title_id, ImPlotOrientation orientation = ImPlotOrientation_Vertical, const ImVec2 size = ImVec2(0,0), bool interactable = true);
IMPLOT_API void LabelTickDefault(ImPlotTick& tick, ImGuiTextBuffer& buffer);
IMPLOT_API void LabelTickScientific(ImPlotTick& tick, ImGuiTextBuffer& buffer);
IMPLOT_API void LabelTickTime(ImPlotTick& tick, ImGuiTextBuffer& buffer, const ImPlotTime& t, ImPlotDateTimeFmt fmt);
IMPLOT_API void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImPlotTickCollection& ticks);
IMPLOT_API void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollection& ticks);
IMPLOT_API void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollection& ticks);
IMPLOT_API void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks);
IMPLOT_API int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size);
inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItemData; }
inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
IMPLOT_API const ImVec4* GetColormap(ImPlotColormap colormap, int* size_out);
IMPLOT_API ImVec4 LerpColormap(const ImVec4* colormap, int size, float t);
IMPLOT_API void ResampleColormap(const ImVec4* colormap_in, int size_in, ImVec4* colormap_out, int size_out);
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
inline ImVec2 CalcTextSizeVertical(const char *text) { ImVec2 sz = ImGui::CalcTextSize(text); return ImVec2(sz.y, sz.x); }
inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.5 ? IM_COL32_BLACK : IM_COL32_WHITE; }
inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {
if (pos.x < Min.x) pos.x = Min.x;
if (pos.y < Min.y) pos.y = Min.y;
if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x;
if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y;
return pos;
}
IMPLOT_API double NiceNum(double x, bool round);
inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }
inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }
inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {
float v1 = (a1.x * a2.y - a1.y * a2.x); float v2 = (b1.x * b2.y - b1.y * b2.x);
float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x));
return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3);
}
template <typename T>
void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
buffer.resize(n);
T step = (vmax - vmin) / (n - 1);
for (int i = 0; i < n; ++i) {
buffer[i] = vmin + i * step;
}
}
template <typename T>
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);
}
inline bool IsLeapYear(int year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
inline int GetDaysInMonth(int year, int month) {
static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return days[month] + (int)(month == 1 && IsLeapYear(year));
}
IMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm);
IMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
IMPLOT_API ImPlotTime MkLocTime(struct tm *ptm);
IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);
IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);
IMPLOT_API int GetYear(const ImPlotTime& t);
IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
IMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);
IMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);
IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);
IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk);
IMPLOT_API int FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601);
IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeFmt fmt);
IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = NULL, const ImPlotTime* t2 = NULL);
IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
IMPLOT_API void PlotRects(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float));
IMPLOT_API void PlotRects(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double));
IMPLOT_API void PlotRects(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0);
}