35#include "imgui_internal.h"
38#error Must include implot.h before implot_internal.h
43#if (IMGUI_VERSION_NUM < 18303)
44#define GetBufSize GetSize
55#define IMPLOT_MIN_TIME 0
57#define IMPLOT_MAX_TIME 32503680000
59#define IMPLOT_LABEL_FORMAT "%g"
61#define IMPLOT_LABEL_MAX_SIZE 32
67#define IMPLOT_NUM_X_AXES ImAxis_Y1
68#define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES)
71#define IM_COL32_SPLIT_RGB(col,r,g,b) \
72 ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \
73 ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \
74 ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF);
82struct ImPlotAxisColor;
102static inline float ImLog10(
float x) {
return log10f(x); }
103static inline double ImLog10(
double x) {
return log10(x); }
104static inline float ImSinh(
float x) {
return sinhf(x); }
105static inline double ImSinh(
double x) {
return sinh(x); }
106static inline float ImAsinh(
float x) {
return asinhf(x); }
107static inline double ImAsinh(
double x) {
return asinh(x); }
109template <
typename TSet,
typename TFlag>
110static inline bool ImHasFlag(TSet set, TFlag flag) {
return (set & flag) == flag; }
112template <
typename TSet,
typename TFlag>
113static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
116static inline T ImRemap(T x, T x0, T x1, T y0, T y1) {
return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
119static inline T ImRemap01(T x, T x0, T x1) {
return (x - x0) / (x1 - x0); }
121static inline int ImPosMod(
int l,
int r) {
return (l % r + r) % r; }
123static inline bool ImNan(
double val) {
return isnan(val); }
125static inline bool ImNanOrInf(
double val) {
return !(val >= -DBL_MAX && val <= DBL_MAX) || ImNan(val); }
127static inline double ImConstrainNan(
double val) {
return ImNan(val) ? 0 : val; }
129static inline double ImConstrainInf(
double val) {
return val >= DBL_MAX ? DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; }
131static inline double ImConstrainLog(
double val) {
return val <= 0 ? 0.001f : val; }
133static inline double ImConstrainTime(
double val) {
return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
135static 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; }
138static inline T ImMinArray(
const T* values,
int count) { T m = values[0];
for (
int i = 1; i < count; ++i) {
if (values[i] < m) { m = values[i]; } }
return m; }
141static inline T ImMaxArray(
const T* values,
int count) { T m = values[0];
for (
int i = 1; i < count; ++i) {
if (values[i] > m) { m = values[i]; } }
return m; }
144static inline void ImMinMaxArray(
const T* values,
int count, T* min_out, T* max_out) {
145 T Min = values[0]; T Max = values[0];
146 for (
int i = 1; i < count; ++i) {
147 if (values[i] < Min) { Min = values[i]; }
148 if (values[i] > Max) { Max = values[i]; }
150 *min_out = Min; *max_out = Max;
154static inline T ImSum(
const T* values,
int count) {
156 for (
int i = 0; i < count; ++i)
162static inline double ImMean(
const T* values,
int count) {
163 double den = 1.0 / count;
165 for (
int i = 0; i < count; ++i)
166 mu += (
double)values[i] * den;
171static inline double ImStdDev(
const T* values,
int count) {
172 double den = 1.0 / (count - 1.0);
173 double mu = ImMean(values, count);
175 for (
int i = 0; i < count; ++i)
176 x += ((
double)values[i] - mu) * ((double)values[i] - mu) * den;
180static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
182 const ImU32 af = 256-s;
184 const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24);
185 const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24);
186 const ImU64 mix = (al * af + bl * bf);
187 return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8);
189 const ImU32 af = 256-s;
191 const ImU32 al = (a & 0x00ff00ff);
192 const ImU32 ah = (a & 0xff00ff00) >> 8;
193 const ImU32 bl = (b & 0x00ff00ff);
194 const ImU32 bh = (b & 0xff00ff00) >> 8;
195 const ImU32 ml = (al * af + bl * bf);
196 const ImU32 mh = (ah * af + bh * bf);
197 return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8);
202static inline ImU32 ImLerpU32(
const ImU32* colors,
int size,
float t) {
203 int i1 = (int)((size - 1 ) * t);
205 if (i2 == size || size == 1)
207 float den = 1.0f / (size - 1);
210 float tr = ImRemap01(t, t1, t2);
211 return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));
215static inline ImU32 ImAlphaU32(ImU32 col,
float alpha) {
216 return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
221static inline bool ImOverlaps(T min_a, T max_a, T min_b, T max_b) {
222 return min_a <= max_b && min_b <= max_a;
229typedef int ImPlotTimeUnit;
230typedef int ImPlotDateFmt;
231typedef int ImPlotTimeFmt;
233enum ImPlotTimeUnit_ {
246 ImPlotDateFmt_None = 0,
248 ImPlotDateFmt_DayMoYr,
255 ImPlotTimeFmt_None = 0,
260 ImPlotTimeFmt_MinSMs,
261 ImPlotTimeFmt_HrMinSMs,
262 ImPlotTimeFmt_HrMinS,
271typedef void (*ImPlotLocator)(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
280 ImPlotDateTimeSpec(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt,
bool use_24_hr_clk =
false,
bool use_iso_8601 =
false) {
283 UseISO8601 = use_iso_8601;
284 Use24HourClock = use_24_hr_clk;
297 ImPlotTime(time_t s,
int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
298 void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
299 double ToDouble()
const {
return (
double)S + (double)Us / 1000000.0; }
300 static ImPlotTime FromDouble(
double t) {
return ImPlotTime((time_t)t, (
int)(t * 1000000 - floor(t) * 1000000)); }
304{
return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
306{
return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
308{
return lhs.S == rhs.S && lhs.Us == rhs.Us; }
310{
return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
314{
return lhs < rhs || lhs == rhs; }
316{
return lhs > rhs || lhs == rhs; }
334 int Append(
const char* name,
const ImU32* keys,
int count,
bool qual) {
335 if (GetIndex(name) != -1)
337 KeyOffsets.push_back(Keys.size());
338 KeyCounts.push_back(count);
339 Keys.reserve(Keys.size()+count);
340 for (
int i = 0; i < count; ++i)
341 Keys.push_back(keys[i]);
342 TextOffsets.push_back(Text.size());
343 Text.append(name, name + strlen(name) + 1);
344 Quals.push_back(qual);
345 ImGuiID
id = ImHashStr(name);
352 void _AppendTable(ImPlotColormap cmap) {
353 int key_count = GetKeyCount(cmap);
354 const ImU32* keys = GetKeys(cmap);
355 int off = Tables.size();
356 TableOffsets.push_back(off);
358 Tables.reserve(key_count);
359 for (
int i = 0; i < key_count; ++i)
360 Tables.push_back(keys[i]);
361 TableSizes.push_back(key_count);
364 int max_size = 255 * (key_count-1) + 1;
365 Tables.reserve(off + max_size);
369 for (
int i = 0; i < key_count-1; ++i) {
370 for (
int s = 0; s < 255; ++s) {
373 ImU32 c = ImMixU32(a,b,s);
381 ImU32 c = keys[key_count-1];
387 TableSizes.push_back(max_size);
391 void RebuildTables() {
393 TableSizes.resize(0);
394 TableOffsets.resize(0);
395 for (
int i = 0; i < Count; ++i)
399 inline bool IsQual(ImPlotColormap cmap)
const {
return Quals[cmap]; }
400 inline const char* GetName(ImPlotColormap cmap)
const {
return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] :
nullptr; }
401 inline ImPlotColormap GetIndex(
const char* name)
const { ImGuiID key = ImHashStr(name);
return Map.GetInt(key,-1); }
403 inline const ImU32* GetKeys(ImPlotColormap cmap)
const {
return &Keys[KeyOffsets[cmap]]; }
404 inline int GetKeyCount(ImPlotColormap cmap)
const {
return KeyCounts[cmap]; }
405 inline ImU32 GetKeyColor(ImPlotColormap cmap,
int idx)
const {
return Keys[KeyOffsets[cmap]+idx]; }
406 inline void SetKeyColor(ImPlotColormap cmap,
int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
408 inline const ImU32* GetTable(ImPlotColormap cmap)
const {
return &Tables[TableOffsets[cmap]]; }
409 inline int GetTableSize(ImPlotColormap cmap)
const {
return TableSizes[cmap]; }
410 inline ImU32 GetTableColor(ImPlotColormap cmap,
int idx)
const {
return Tables[TableOffsets[cmap]+idx]; }
412 inline ImU32 LerpTable(ImPlotColormap cmap,
float t)
const {
413 int off = TableOffsets[cmap];
414 int siz = TableSizes[cmap];
415 int idx = Quals[cmap] ? ImClamp((
int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f);
416 return Tables[off + idx];
422 double X, Y, Neg, Pos;
424 X = x; Y = y; Neg = neg; Pos = pos;
437 ColorBg = ColorFg = 0;
452 void AppendV(
const ImVec2& pos,
const ImVec2& off, ImU32 bg, ImU32 fg,
bool clamp,
const char* fmt, va_list args) IM_FMTLIST(7) {
454 an.Pos = pos; an.Offset = off;
455 an.ColorBg = bg; an.ColorFg = fg;
456 an.TextOffset = TextBuffer.size();
458 Annotations.push_back(an);
459 TextBuffer.appendfv(fmt, args);
460 const char nul[] =
"";
461 TextBuffer.append(nul,nul+1);
465 void Append(
const ImVec2& pos,
const ImVec2& off, ImU32 bg, ImU32 fg,
bool clamp,
const char* fmt, ...) IM_FMTARGS(7) {
468 AppendV(pos, off, bg, fg, clamp, fmt, args);
472 const char* GetText(
int idx) {
473 return TextBuffer.Buf.Data + Annotations[idx].TextOffset;
477 Annotations.shrink(0);
478 TextBuffer.Buf.shrink(0);
499 void AppendV(ImAxis axis,
double value, ImU32 bg, ImU32 fg,
const char* fmt, va_list args) IM_FMTLIST(6) {
505 tag.TextOffset = TextBuffer.size();
507 TextBuffer.appendfv(fmt, args);
508 const char nul[] =
"";
509 TextBuffer.append(nul,nul+1);
513 void Append(ImAxis axis,
double value, ImU32 bg, ImU32 fg,
const char* fmt, ...) IM_FMTARGS(6) {
516 AppendV(axis, value, bg, fg, fmt, args);
520 const char* GetText(
int idx) {
521 return TextBuffer.Buf.Data + Tags[idx].TextOffset;
526 TextBuffer.Buf.shrink(0);
543 ImPlotTick(
double value,
bool major,
int level,
bool show_label) {
547 ShowLabel = show_label;
565 ImPlotTick& AddTick(
double value,
bool major,
int level,
bool show_label,
const char* label) {
566 ImPlotTick tick(value, major, level, show_label);
567 if (show_label && label !=
nullptr) {
568 tick.TextOffset = TextBuffer.size();
569 TextBuffer.append(label, label + strlen(label) + 1);
570 tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
572 return AddTick(tick);
575 ImPlotTick& AddTick(
double value,
bool major,
int level,
bool show_label, ImPlotFormatter formatter,
void* data) {
576 ImPlotTick tick(value, major, level, show_label);
577 if (show_label && formatter !=
nullptr) {
578 char buff[IMPLOT_LABEL_MAX_SIZE];
579 tick.TextOffset = TextBuffer.size();
580 formatter(tick.PlotPos, buff,
sizeof(buff), data);
581 TextBuffer.append(buff, buff + strlen(buff) + 1);
582 tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
584 return AddTick(tick);
588 if (tick.ShowLabel) {
589 MaxSize.x = tick.LabelSize.x > MaxSize.x ? tick.LabelSize.x : MaxSize.x;
590 MaxSize.y = tick.LabelSize.y > MaxSize.y ? tick.LabelSize.y : MaxSize.y;
592 tick.Idx = Ticks.size();
593 Ticks.push_back(tick);
597 const char* GetText(
int idx)
const {
598 return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
602 return GetText(tick.Idx);
605 void OverrideSizeLate(
const ImVec2& size) {
606 LateSize.x = size.x > LateSize.x ? size.x : LateSize.x;
607 LateSize.y = size.y > LateSize.y ? size.y : LateSize.y;
612 TextBuffer.Buf.shrink(0);
618 int TickCount()
const {
627 ImPlotAxisFlags Flags;
628 ImPlotAxisFlags PreviousFlags;
630 ImPlotCond RangeCond;
638 ImPlotFormatter Formatter;
641 ImPlotLocator Locator;
649 ImPlotTransform TransformForward;
650 ImPlotTransform TransformInverse;
652 float PixelMin, PixelMax;
653 double ScaleMin, ScaleMax;
655 float Datum1, Datum2;
659 ImU32 ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi;
666 bool ShowDefaultTicks;
672 Flags = PreviousFlags = ImPlotAxisFlags_None;
675 Scale = ImPlotScale_Linear;
676 TransformForward = TransformInverse =
nullptr;
677 TransformData =
nullptr;
678 FitExtents.Min = HUGE_VAL;
679 FitExtents.Max = -HUGE_VAL;
683 LinkedMin = LinkedMax =
nullptr;
686 PixelMin = PixelMax = 0;
688 ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
689 ColorHiLi = IM_COL32_BLACK_TRANS;
691 FormatterData =
nullptr;
693 Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec =
false;
694 ShowDefaultTicks =
true;
697 inline void Reset() {
699 Scale = ImPlotScale_Linear;
700 TransformForward = TransformInverse =
nullptr;
701 TransformData =
nullptr;
703 HasFormatSpec =
false;
705 FormatterData =
nullptr;
707 ShowDefaultTicks =
true;
708 FitThisFrame =
false;
709 FitExtents.Min = HUGE_VAL;
710 FitExtents.Max = -HUGE_VAL;
717 inline bool SetMin(
double _min,
bool force=
false) {
718 if (!force && IsLockedMin())
720 _min = ImConstrainNan(ImConstrainInf(_min));
721 if (_min < ConstraintRange.Min)
722 _min = ConstraintRange.Min;
723 double z = Range.Max - _min;
724 if (z < ConstraintZoom.Min)
725 _min = Range.Max - ConstraintZoom.Min;
726 if (z > ConstraintZoom.Max)
727 _min = Range.Max - ConstraintZoom.Max;
728 if (_min >= Range.Max)
731 PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
732 UpdateTransformCache();
736 inline bool SetMax(
double _max,
bool force=
false) {
737 if (!force && IsLockedMax())
739 _max = ImConstrainNan(ImConstrainInf(_max));
740 if (_max > ConstraintRange.Max)
741 _max = ConstraintRange.Max;
742 double z = _max - Range.Min;
743 if (z < ConstraintZoom.Min)
744 _max = Range.Min + ConstraintZoom.Min;
745 if (z > ConstraintZoom.Max)
746 _max = Range.Min + ConstraintZoom.Max;
747 if (_max <= Range.Min)
750 PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
751 UpdateTransformCache();
755 inline void SetRange(
double v1,
double v2) {
756 Range.Min = ImMin(v1,v2);
757 Range.Max = ImMax(v1,v2);
759 PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
760 PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
761 UpdateTransformCache();
765 SetRange(range.Min, range.Max);
768 inline void SetAspect(
double unit_per_pix) {
769 double new_size = unit_per_pix * PixelSize();
770 double delta = (new_size - Range.Size()) * 0.5;
773 else if (IsLockedMin() && !IsLockedMax())
774 SetRange(Range.Min, Range.Max + 2*delta);
775 else if (!IsLockedMin() && IsLockedMax())
776 SetRange(Range.Min - 2*delta, Range.Max);
778 SetRange(Range.Min - delta, Range.Max + delta);
781 inline float PixelSize()
const {
return ImAbs(PixelMax - PixelMin); }
783 inline double GetAspect()
const {
return Range.Size() / PixelSize(); }
785 inline void Constrain() {
786 Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
787 Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
788 if (Range.Min < ConstraintRange.Min)
789 Range.Min = ConstraintRange.Min;
790 if (Range.Max > ConstraintRange.Max)
791 Range.Max = ConstraintRange.Max;
792 double z = Range.Size();
793 if (z < ConstraintZoom.Min) {
794 double delta = (ConstraintZoom.Min - z) * 0.5;
798 if (z > ConstraintZoom.Max) {
799 double delta = (z - ConstraintZoom.Max) * 0.5;
803 if (Range.Max <= Range.Min)
804 Range.Max = Range.Min + DBL_EPSILON;
807 inline void UpdateTransformCache() {
808 ScaleToPixel = (PixelMax - PixelMin) / Range.Size();
809 if (TransformForward !=
nullptr) {
810 ScaleMin = TransformForward(Range.Min, TransformData);
811 ScaleMax = TransformForward(Range.Max, TransformData);
814 ScaleMin = Range.Min;
815 ScaleMax = Range.Max;
819 inline float PlotToPixels(
double plt)
const {
820 if (TransformForward !=
nullptr) {
821 double s = TransformForward(plt, TransformData);
822 double t = (s - ScaleMin) / (ScaleMax - ScaleMin);
823 plt = Range.Min + Range.Size() * t;
825 return (
float)(PixelMin + ScaleToPixel * (plt - Range.Min));
829 inline double PixelsToPlot(
float pix)
const {
830 double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;
831 if (TransformInverse !=
nullptr) {
832 double t = (plt - Range.Min) / Range.Size();
833 double s = t * (ScaleMax - ScaleMin) + ScaleMin;
834 plt = TransformInverse(s, TransformData);
839 inline void ExtendFit(
double v) {
840 if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {
841 FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
842 FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
846 inline void ExtendFitWith(
ImPlotAxis& alt,
double v,
double v_alt) {
847 if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
849 if (!ImNanOrInf(v) && v >= ConstraintRange.Min && v <= ConstraintRange.Max) {
850 FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
851 FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
855 inline void ApplyFit(
float padding) {
856 const double ext_size = FitExtents.Size() * 0.5;
857 FitExtents.Min -= ext_size * padding;
858 FitExtents.Max += ext_size * padding;
859 if (!IsLockedMin() && !ImNanOrInf(FitExtents.Min))
860 Range.Min = FitExtents.Min;
861 if (!IsLockedMax() && !ImNanOrInf(FitExtents.Max))
862 Range.Max = FitExtents.Max;
863 if (ImAlmostEqual(Range.Min, Range.Max)) {
868 UpdateTransformCache();
871 inline bool HasLabel()
const {
return LabelOffset != -1 && !ImHasFlag(Flags, ImPlotAxisFlags_NoLabel); }
872 inline bool HasGridLines()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoGridLines); }
873 inline bool HasTickLabels()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
874 inline bool HasTickMarks()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickMarks); }
875 inline bool WillRender()
const {
return Enabled && (HasGridLines() || HasTickLabels() || HasTickMarks()); }
876 inline bool IsOpposite()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_Opposite); }
877 inline bool IsInverted()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
878 inline bool IsForeground()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_Foreground); }
879 inline bool IsAutoFitting()
const {
return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
880 inline bool CanInitFit()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoInitialFit) && !HasRange && !LinkedMin && !LinkedMax; }
881 inline bool IsRangeLocked()
const {
return HasRange && RangeCond == ImPlotCond_Always; }
882 inline bool IsLockedMin()
const {
return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
883 inline bool IsLockedMax()
const {
return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
884 inline bool IsLocked()
const {
return IsLockedMin() && IsLockedMax(); }
885 inline bool IsInputLockedMin()
const {
return IsLockedMin() || IsAutoFitting(); }
886 inline bool IsInputLockedMax()
const {
return IsLockedMax() || IsAutoFitting(); }
887 inline bool IsInputLocked()
const {
return IsLocked() || IsAutoFitting(); }
888 inline bool HasMenus()
const {
return !ImHasFlag(Flags, ImPlotAxisFlags_NoMenus); }
890 inline bool IsPanLocked(
bool increasing) {
891 if (ImHasFlag(Flags, ImPlotAxisFlags_PanStretch)) {
892 return IsInputLocked();
895 if (IsLockedMin() || IsLockedMax() || IsAutoFitting())
898 return Range.Max == ConstraintRange.Max;
900 return Range.Min == ConstraintRange.Min;
905 if (LinkedMin) { *LinkedMin = Range.Min; }
906 if (LinkedMax) { *LinkedMax = Range.Max; }
910 if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); }
911 else if (LinkedMin) { SetMin(*LinkedMin,
true); }
912 else if (LinkedMax) { SetMax(*LinkedMax,
true); }
925 PadA = PadB = PadAMax = PadBMax = 0;
927 void Begin() { PadAMax = PadBMax = 0; }
928 void Update(
float& pad_a,
float& pad_b,
float& delta_a,
float& delta_b) {
929 float bak_a = pad_a;
float bak_b = pad_b;
930 if (PadAMax < pad_a) { PadAMax = pad_a; }
931 if (PadBMax < pad_b) { PadBMax = pad_b; }
932 if (pad_a < PadA) { pad_a = PadA; delta_a = pad_a - bak_a; }
else { delta_a = 0; }
933 if (pad_b < PadB) { pad_b = PadB; delta_b = pad_b - bak_b; }
else { delta_b = 0; }
935 void End() { PadA = PadAMax; PadB = PadBMax; }
936 void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }
952 Color = IM_COL32_WHITE;
955 SeenThisFrame =
false;
956 LegendHovered =
false;
965 ImPlotLegendFlags Flags;
966 ImPlotLegendFlags PreviousFlags;
967 ImPlotLocation Location;
968 ImPlotLocation PreviousLocation;
979 Flags = PreviousFlags = ImPlotLegendFlags_None;
981 Hovered = Held =
false;
982 Location = PreviousLocation = ImPlotLocation_NorthWest;
986 void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
999 int GetItemCount()
const {
return ItemPool.GetBufSize(); }
1000 ImGuiID GetItemID(
const char* label_id) {
return ImGui::GetID(label_id); }
1001 ImPlotItem* GetItem(ImGuiID
id) {
return ItemPool.GetByKey(
id); }
1002 ImPlotItem* GetItem(
const char* label_id) {
return GetItem(GetItemID(label_id)); }
1003 ImPlotItem* GetOrAddItem(ImGuiID
id) {
return ItemPool.GetOrAddByKey(
id); }
1004 ImPlotItem* GetItemByIndex(
int i) {
return ItemPool.GetByIndex(i); }
1005 int GetItemIndex(
ImPlotItem* item) {
return ItemPool.GetIndex(item); }
1006 int GetLegendCount()
const {
return Legend.Indices.size(); }
1007 ImPlotItem* GetLegendItem(
int i) {
return ItemPool.GetByIndex(Legend.Indices[i]); }
1008 const char* GetLegendLabel(
int i) {
return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; }
1009 void Reset() { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; }
1017 ImPlotFlags PreviousFlags;
1018 ImPlotLocation MouseTextLocation;
1019 ImPlotMouseTextFlags MouseTextFlags;
1043 Flags = PreviousFlags = ImPlotFlags_None;
1044 for (
int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
1045 XAxis(i).Vertical =
false;
1046 for (
int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
1047 YAxis(i).Vertical =
true;
1048 SelectStart =
ImVec2(0,0);
1049 CurrentX = ImAxis_X1;
1050 CurrentY = ImAxis_Y1;
1051 MouseTextLocation = ImPlotLocation_South | ImPlotLocation_East;
1052 MouseTextFlags = ImPlotMouseTextFlags_None;
1055 Initialized = SetupLocked = FitThisFrame =
false;
1056 Hovered = Held = Selected = Selecting = ContextLocked =
false;
1059 inline bool IsInputLocked()
const {
1060 for (
int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {
1061 if (!XAxis(i).IsInputLocked())
1064 for (
int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {
1065 if (!YAxis(i).IsInputLocked())
1071 inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
1073 inline void SetTitle(
const char* title) {
1074 if (title && ImGui::FindRenderedTextEnd(title,
nullptr) != title) {
1075 TitleOffset = TextBuffer.size();
1076 TextBuffer.append(title, title + strlen(title) + 1);
1082 inline bool HasTitle()
const {
return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); }
1083 inline const char* GetTitle()
const {
return TextBuffer.Buf.Data + TitleOffset; }
1085 inline ImPlotAxis& XAxis(
int i) {
return Axes[ImAxis_X1 + i]; }
1086 inline const ImPlotAxis& XAxis(
int i)
const {
return Axes[ImAxis_X1 + i]; }
1087 inline ImPlotAxis& YAxis(
int i) {
return Axes[ImAxis_Y1 + i]; }
1088 inline const ImPlotAxis& YAxis(
int i)
const {
return Axes[ImAxis_Y1 + i]; }
1090 inline int EnabledAxesX() {
1092 for (
int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
1093 cnt += XAxis(i).Enabled;
1097 inline int EnabledAxesY() {
1099 for (
int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
1100 cnt += YAxis(i).Enabled;
1104 inline void SetAxisLabel(
ImPlotAxis& axis,
const char* label) {
1105 if (label && ImGui::FindRenderedTextEnd(label,
nullptr) != label) {
1106 axis.LabelOffset = TextBuffer.size();
1107 TextBuffer.append(label, label + strlen(label) + 1);
1110 axis.LabelOffset = -1;
1114 inline const char* GetAxisLabel(
const ImPlotAxis& axis)
const {
return TextBuffer.Buf.Data + axis.LabelOffset; }
1120 ImPlotSubplotFlags Flags;
1121 ImPlotSubplotFlags PreviousFlags;
1141 Flags = PreviousFlags = ImPlotSubplotFlags_None;
1142 Rows = Cols = CurrentIdx = 0;
1143 Items.Legend.Location = ImPlotLocation_North;
1144 Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
1145 Items.Legend.CanGoInside =
false;
1146 TempSizes[0] = TempSizes[1] = 0;
1147 FrameHovered =
false;
1155 ImPlotCond RangeCond[ImAxis_COUNT];
1157 bool HasRange[ImAxis_COUNT];
1158 bool Fit[ImAxis_COUNT];
1159 double* LinkedMin[ImAxis_COUNT];
1160 double* LinkedMax[ImAxis_COUNT];
1165 for (
int i = 0; i < ImAxis_COUNT; ++i) {
1166 HasRange[i] =
false;
1168 LinkedMin[i] = LinkedMax[i] =
nullptr;
1178 ImPlotMarker Marker;
1183 float ErrorBarWeight;
1184 float DigitalBitHeight;
1185 float DigitalBitGap;
1188 bool RenderMarkerLine;
1189 bool RenderMarkerFill;
1192 ImPlotCond HiddenCond;
1195 for (
int i = 0; i < 5; ++i)
1196 Colors[i] = IMPLOT_AUTO_COL;
1197 LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
1198 Marker = IMPLOT_AUTO;
1199 HasHidden = Hidden =
false;
1236 int DigitalPlotItemCnt;
1237 int DigitalPlotOffset;
1241 bool OpenContextThisFrame;
1267IMPLOT_API
void ResetCtxForNextAlignedPlots(
ImPlotContext* ctx);
1276IMPLOT_API
ImPlotPlot* GetPlot(
const char* title);
1280IMPLOT_API
void BustPlotCache();
1283IMPLOT_API
void ShowPlotContextMenu(
ImPlotPlot& plot);
1290static inline void SetupLock() {
1292 if (!gp.CurrentPlot->SetupLocked)
1294 gp.CurrentPlot->SetupLocked =
true;
1302IMPLOT_API
void SubplotNextCell();
1305IMPLOT_API
void ShowSubplotsContextMenu(
ImPlotSubplot& subplot);
1312IMPLOT_API
bool BeginItem(
const char* label_id, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO);
1315template <
typename _Fitter>
1316bool BeginItemEx(
const char* label_id,
const _Fitter& fitter, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO) {
1317 if (BeginItem(label_id, flags, recolor_from)) {
1319 if (plot.FitThisFrame && !ImHasFlag(flags, ImPlotItemFlags_NoFit))
1320 fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]);
1327IMPLOT_API
void EndItem();
1330IMPLOT_API
ImPlotItem* RegisterOrGetItem(
const char* label_id, ImPlotItemFlags flags,
bool* just_created =
nullptr);
1332IMPLOT_API
ImPlotItem* GetItem(
const char* label_id);
1336IMPLOT_API
void BustItemCache();
1343static inline bool AnyAxesInputLocked(
ImPlotAxis* axes,
int count) {
1344 for (
int i = 0; i < count; ++i) {
1345 if (axes[i].Enabled && axes[i].IsInputLocked())
1352static inline bool AllAxesInputLocked(
ImPlotAxis* axes,
int count) {
1353 for (
int i = 0; i < count; ++i) {
1354 if (axes[i].Enabled && !axes[i].IsInputLocked())
1360static inline bool AnyAxesHeld(
ImPlotAxis* axes,
int count) {
1361 for (
int i = 0; i < count; ++i) {
1362 if (axes[i].Enabled && axes[i].Held)
1368static inline bool AnyAxesHovered(
ImPlotAxis* axes,
int count) {
1369 for (
int i = 0; i < count; ++i) {
1370 if (axes[i].Enabled && axes[i].Hovered)
1377static inline bool FitThisFrame() {
1378 return GImPlot->CurrentPlot->FitThisFrame;
1382static inline void FitPointX(
double x) {
1384 ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
1385 x_axis.ExtendFit(x);
1389static inline void FitPointY(
double y) {
1391 ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
1392 y_axis.ExtendFit(y);
1396static inline void FitPoint(
const ImPlotPoint& p) {
1398 ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
1399 ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
1400 x_axis.ExtendFitWith(y_axis, p.x, p.y);
1401 y_axis.ExtendFitWith(x_axis, p.y, p.x);
1406{
return r1.Min <= r2.Max && r2.Min <= r1.Max; }
1409IMPLOT_API
void ShowAxisContextMenu(
ImPlotAxis& axis,
ImPlotAxis* equal_axis,
bool time_allowed =
false);
1420IMPLOT_API
bool ClampLegendRect(
ImRect& legend_rect,
const ImRect& outer_rect,
const ImVec2& pad);
1424IMPLOT_API
void ShowAltLegend(
const char* title_id,
bool vertical =
true,
const ImVec2 size =
ImVec2(0,0),
bool interactable =
true);
1426IMPLOT_API
bool ShowLegendContextMenu(
ImPlotLegend& legend,
bool visible);
1433IMPLOT_API
void LabelAxisValue(
const ImPlotAxis& axis,
double value,
char* buff,
int size,
bool round =
false);
1440static inline const ImPlotNextItemData& GetItemData() {
return GImPlot->NextItemData; }
1443static inline bool IsColorAuto(
const ImVec4& col) {
return col.w == -1; }
1445static inline bool IsColorAuto(ImPlotCol idx) {
return IsColorAuto(GImPlot->Style.Colors[idx]); }
1447IMPLOT_API
ImVec4 GetAutoColor(ImPlotCol idx);
1450static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) {
return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
1451static inline ImU32 GetStyleColorU32(ImPlotCol idx) {
return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
1454IMPLOT_API
void AddTextVertical(
ImDrawList *DrawList,
ImVec2 pos, ImU32 col,
const char* text_begin,
const char* text_end =
nullptr);
1456IMPLOT_API
void AddTextCentered(
ImDrawList* DrawList,
ImVec2 top_center, ImU32 col,
const char* text_begin,
const char* text_end =
nullptr);
1458static inline ImVec2 CalcTextSizeVertical(
const char *text) {
1459 ImVec2 sz = ImGui::CalcTextSize(text);
1460 return ImVec2(sz.y, sz.x);
1463static inline ImU32 CalcTextColor(
const ImVec4& bg) {
return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE; }
1464static inline ImU32 CalcTextColor(ImU32 bg) {
return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
1466static inline ImU32 CalcHoverColor(ImU32 col) {
return ImMixU32(col, CalcTextColor(col), 32); }
1470 if (pos.x < Min.x) pos.x = Min.x;
1471 if (pos.y < Min.y) pos.y = Min.y;
1472 if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x;
1473 if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y;
1478IMPLOT_API ImU32 GetColormapColorU32(
int idx, ImPlotColormap cmap);
1480IMPLOT_API ImU32 NextColormapColorU32();
1482IMPLOT_API ImU32 SampleColormapU32(
float t, ImPlotColormap cmap);
1485IMPLOT_API
void RenderColorBar(
const ImU32* colors,
int size,
ImDrawList& DrawList,
const ImRect& bounds,
bool vert,
bool reversed,
bool continuous);
1492IMPLOT_API
double NiceNum(
double x,
bool round);
1494static inline int OrderOfMagnitude(
double val) {
return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
1496static inline int OrderToPrecision(
int order) {
return order > 0 ? 0 : 1 - order; }
1498static inline int Precision(
double val) {
return OrderToPrecision(OrderOfMagnitude(val)); }
1500static inline double RoundTo(
double val,
int prec) {
double p = pow(10,(
double)prec);
return floor(val*p+0.5)/p; }
1504 float v1 = (a1.x * a2.y - a1.y * a2.x);
float v2 = (b1.x * b2.y - b1.y * b2.x);
1505 float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x));
1506 return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3);
1510template <
typename T>
1511void FillRange(
ImVector<T>& buffer,
int n, T vmin, T vmax) {
1513 T step = (vmax - vmin) / (n - 1);
1514 for (
int i = 0; i < n; ++i) {
1515 buffer[i] = vmin + i * step;
1520template <
typename T>
1521static inline void CalculateBins(
const T* values,
int count, ImPlotBin meth,
const ImPlotRange& range,
int& bins_out,
double& width_out) {
1523 case ImPlotBin_Sqrt:
1524 bins_out = (int)ceil(sqrt(count));
1526 case ImPlotBin_Sturges:
1527 bins_out = (int)ceil(1.0 + log2(count));
1529 case ImPlotBin_Rice:
1530 bins_out = (int)ceil(2 * cbrt(count));
1532 case ImPlotBin_Scott:
1533 width_out = 3.49 * ImStdDev(values, count) / cbrt(count);
1534 bins_out = (int)round(range.Size() / width_out);
1537 width_out = range.Size() / bins_out;
1545static inline bool IsLeapYear(
int year) {
1546 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1549static inline int GetDaysInMonth(
int year,
int month) {
1550 static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1551 return days[month] + (int)(month == 1 && IsLeapYear(year));
1555IMPLOT_API
ImPlotTime MkGmtTime(
struct tm *ptm);
1557IMPLOT_API tm* GetGmtTime(
const ImPlotTime& t, tm* ptm);
1560IMPLOT_API
ImPlotTime MkLocTime(
struct tm *ptm);
1562IMPLOT_API tm* GetLocTime(
const ImPlotTime& t, tm* ptm);
1569IMPLOT_API
ImPlotTime MakeTime(
int year,
int month = 0,
int day = 1,
int hour = 0,
int min = 0,
int sec = 0,
int us = 0);
1585IMPLOT_API
int FormatTime(
const ImPlotTime& t,
char* buffer,
int size, ImPlotTimeFmt fmt,
bool use_24_hr_clk);
1587IMPLOT_API
int FormatDate(
const ImPlotTime& t,
char* buffer,
int size, ImPlotDateFmt fmt,
bool use_iso_8601);
1598IMPLOT_API
bool ShowTimePicker(
const char*
id,
ImPlotTime* t);
1604static inline double TransformForward_Log10(
double v,
void*) {
1605 v = v <= 0.0 ? DBL_MIN : v;
1609static inline double TransformInverse_Log10(
double v,
void*) {
1610 return ImPow(10, v);
1613static inline double TransformForward_SymLog(
double v,
void*) {
1614 return 2.0 * ImAsinh(v / 2.0);
1617static inline double TransformInverse_SymLog(
double v,
void*) {
1618 return 2.0 * ImSinh(v / 2.0);
1621static inline double TransformForward_Logit(
double v,
void*) {
1622 v = ImClamp(v, DBL_MIN, 1.0 - DBL_EPSILON);
1623 return ImLog10(v / (1 - v));
1626static inline double TransformInverse_Logit(
double v,
void*) {
1627 return 1.0 / (1.0 + ImPow(10,-v));
1634static inline int Formatter_Default(
double value,
char* buff,
int size,
void* data) {
1635 char* fmt = (
char*)data;
1636 return ImFormatString(buff, size, fmt, value);
1639static inline int Formatter_Logit(
double value,
char* buff,
int size,
void*) {
1641 return ImFormatString(buff,size,
"1/2");
1642 else if (value < 0.5)
1643 return ImFormatString(buff,size,
"%g", value);
1645 return ImFormatString(buff,size,
"1 - %g", 1 - value);
1651 ImPlotFormatter UserFormatter;
1652 void* UserFormatterData;
1655static inline int Formatter_Time(
double,
char* buff,
int size,
void* data) {
1657 return FormatDateTime(ftd->Time, buff, size, ftd->Spec);
1664void Locator_Default(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
1665void Locator_Time(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
1666void Locator_Log10(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
1667void Locator_SymLog(
ImPlotTicker& ticker,
const ImPlotRange& range,
float pixels,
bool vertical, ImPlotFormatter formatter,
void* formatter_data);
Definition implot_internal.h:917
Definition implot_internal.h:444
Definition implot_internal.h:429
Definition implot_internal.h:625
Definition implot_internal.h:319
Definition implot_internal.h:1204
Definition implot_internal.h:278
Definition implot_internal.h:991
Definition implot_internal.h:941
Definition implot_internal.h:964
Definition implot_internal.h:1175
Definition implot_internal.h:1154
Definition implot_internal.h:1014
Definition implot_internal.h:421
Definition implot_internal.h:1118
Definition implot_internal.h:491
Definition implot_internal.h:483
Definition implot_internal.h:533
Definition implot_internal.h:554
Definition implot_internal.h:293
Definition imgui_internal.h:676
Definition imgui_internal.h:531