vsgImGui 0.5.0
VulkanSceneGraph, ImGui and ImPlot integration library
Loading...
Searching...
No Matches
implot_internal.h
1// MIT License
2
3// Copyright (c) 2023 Evan Pezent
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23// ImPlot v0.17
24
25// You may use this file to debug, understand or extend ImPlot features but we
26// don't provide any guarantee of forward compatibility!
27
28//-----------------------------------------------------------------------------
29// [SECTION] Header Mess
30//-----------------------------------------------------------------------------
31
32#pragma once
33
34#include <time.h>
35#include "imgui_internal.h"
36
37#ifndef IMPLOT_VERSION
38#error Must include implot.h before implot_internal.h
39#endif
40
41
42// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize()
43#if (IMGUI_VERSION_NUM < 18303)
44#define GetBufSize GetSize
45#endif
46
47//-----------------------------------------------------------------------------
48// [SECTION] Constants
49//-----------------------------------------------------------------------------
50
51// Constants can be changed unless stated otherwise. We may move some of these
52// to ImPlotStyleVar_ over time.
53
54// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
55#define IMPLOT_MIN_TIME 0
56// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
57#define IMPLOT_MAX_TIME 32503680000
58// Default label format for axis labels
59#define IMPLOT_LABEL_FORMAT "%g"
60// Max character size for tick labels
61#define IMPLOT_LABEL_MAX_SIZE 32
62
63//-----------------------------------------------------------------------------
64// [SECTION] Macros
65//-----------------------------------------------------------------------------
66
67#define IMPLOT_NUM_X_AXES ImAxis_Y1
68#define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES)
69
70// Split ImU32 color into RGB components [0 255]
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);
75
76//-----------------------------------------------------------------------------
77// [SECTION] Forward Declarations
78//-----------------------------------------------------------------------------
79
80struct ImPlotTick;
81struct ImPlotAxis;
82struct ImPlotAxisColor;
83struct ImPlotItem;
84struct ImPlotLegend;
85struct ImPlotPlot;
87struct ImPlotTicker;
88
89//-----------------------------------------------------------------------------
90// [SECTION] Context Pointer
91//-----------------------------------------------------------------------------
92
93#ifndef GImPlot
94extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
95#endif
96
97//-----------------------------------------------------------------------------
98// [SECTION] Generic Helpers
99//-----------------------------------------------------------------------------
100
101// Computes the common (base-10) logarithm
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); }
108// Returns true if a flag is set
109template <typename TSet, typename TFlag>
110static inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
111// Flips a flag in a flagset
112template <typename TSet, typename TFlag>
113static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
114// Linearly remaps x from [x0 x1] to [y0 y1].
115template <typename T>
116static inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
117// Linear rempas x from [x0 x1] to [0 1]
118template <typename T>
119static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }
120// Returns always positive modulo (assumes r != 0)
121static inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
122// Returns true if val is NAN
123static inline bool ImNan(double val) { return isnan(val); }
124// Returns true if val is NAN or INFINITY
125static inline bool ImNanOrInf(double val) { return !(val >= -DBL_MAX && val <= DBL_MAX) || ImNan(val); }
126// Turns NANs to 0s
127static inline double ImConstrainNan(double val) { return ImNan(val) ? 0 : val; }
128// Turns infinity to floating point maximums
129static inline double ImConstrainInf(double val) { return val >= DBL_MAX ? DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; }
130// Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)
131static inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
132// Turns numbers less than 0 to zero
133static inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
134// True if two numbers are approximately equal using units in the last place.
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; }
136// Finds min value in an unsorted array
137template <typename T>
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; }
139// Finds the max value in an unsorted array
140template <typename T>
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; }
142// Finds the min and max value in an unsorted array
143template <typename T>
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]; }
149 }
150 *min_out = Min; *max_out = Max;
151}
152// Finds the sim of an array
153template <typename T>
154static inline T ImSum(const T* values, int count) {
155 T sum = 0;
156 for (int i = 0; i < count; ++i)
157 sum += values[i];
158 return sum;
159}
160// Finds the mean of an array
161template <typename T>
162static inline double ImMean(const T* values, int count) {
163 double den = 1.0 / count;
164 double mu = 0;
165 for (int i = 0; i < count; ++i)
166 mu += (double)values[i] * den;
167 return mu;
168}
169// Finds the sample standard deviation of an array
170template <typename T>
171static inline double ImStdDev(const T* values, int count) {
172 double den = 1.0 / (count - 1.0);
173 double mu = ImMean(values, count);
174 double x = 0;
175 for (int i = 0; i < count; ++i)
176 x += ((double)values[i] - mu) * ((double)values[i] - mu) * den;
177 return sqrt(x);
178}
179// Mix color a and b by factor s in [0 256]
180static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
181#ifdef IMPLOT_MIX64
182 const ImU32 af = 256-s;
183 const ImU32 bf = 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);
188#else
189 const ImU32 af = 256-s;
190 const ImU32 bf = 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);
198#endif
199}
200
201// Lerp across an array of 32-bit collors given t in [0.0 1.0]
202static inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) {
203 int i1 = (int)((size - 1 ) * t);
204 int i2 = i1 + 1;
205 if (i2 == size || size == 1)
206 return colors[i1];
207 float den = 1.0f / (size - 1);
208 float t1 = i1 * den;
209 float t2 = i2 * den;
210 float tr = ImRemap01(t, t1, t2);
211 return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));
212}
213
214// Set alpha channel of 32-bit color from float in range [0.0 1.0]
215static inline ImU32 ImAlphaU32(ImU32 col, float alpha) {
216 return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
217}
218
219// Returns true of two ranges overlap
220template <typename T>
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;
223}
224
225//-----------------------------------------------------------------------------
226// [SECTION] ImPlot Enums
227//-----------------------------------------------------------------------------
228
229typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_
230typedef int ImPlotDateFmt; // -> enum ImPlotDateFmt_
231typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_
232
233enum ImPlotTimeUnit_ {
234 ImPlotTimeUnit_Us, // microsecond
235 ImPlotTimeUnit_Ms, // millisecond
236 ImPlotTimeUnit_S, // second
237 ImPlotTimeUnit_Min, // minute
238 ImPlotTimeUnit_Hr, // hour
239 ImPlotTimeUnit_Day, // day
240 ImPlotTimeUnit_Mo, // month
241 ImPlotTimeUnit_Yr, // year
242 ImPlotTimeUnit_COUNT
243};
244
245enum ImPlotDateFmt_ { // default [ ISO 8601 ]
246 ImPlotDateFmt_None = 0,
247 ImPlotDateFmt_DayMo, // 10/3 [ --10-03 ]
248 ImPlotDateFmt_DayMoYr, // 10/3/91 [ 1991-10-03 ]
249 ImPlotDateFmt_MoYr, // Oct 1991 [ 1991-10 ]
250 ImPlotDateFmt_Mo, // Oct [ --10 ]
251 ImPlotDateFmt_Yr // 1991 [ 1991 ]
252};
253
254enum ImPlotTimeFmt_ { // default [ 24 Hour Clock ]
255 ImPlotTimeFmt_None = 0,
256 ImPlotTimeFmt_Us, // .428 552 [ .428 552 ]
257 ImPlotTimeFmt_SUs, // :29.428 552 [ :29.428 552 ]
258 ImPlotTimeFmt_SMs, // :29.428 [ :29.428 ]
259 ImPlotTimeFmt_S, // :29 [ :29 ]
260 ImPlotTimeFmt_MinSMs, // 21:29.428 [ 21:29.428 ]
261 ImPlotTimeFmt_HrMinSMs, // 7:21:29.428pm [ 19:21:29.428 ]
262 ImPlotTimeFmt_HrMinS, // 7:21:29pm [ 19:21:29 ]
263 ImPlotTimeFmt_HrMin, // 7:21pm [ 19:21 ]
264 ImPlotTimeFmt_Hr // 7pm [ 19:00 ]
265};
266
267//-----------------------------------------------------------------------------
268// [SECTION] Callbacks
269//-----------------------------------------------------------------------------
270
271typedef void (*ImPlotLocator)(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data);
272
273//-----------------------------------------------------------------------------
274// [SECTION] Structs
275//-----------------------------------------------------------------------------
276
277// Combined date/time format spec
280 ImPlotDateTimeSpec(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt, bool use_24_hr_clk = false, bool use_iso_8601 = false) {
281 Date = date_fmt;
282 Time = time_fmt;
283 UseISO8601 = use_iso_8601;
284 Use24HourClock = use_24_hr_clk;
285 }
286 ImPlotDateFmt Date;
287 ImPlotTimeFmt Time;
288 bool UseISO8601;
289 bool Use24HourClock;
290};
291
292// Two part timestamp struct.
294 time_t S; // second part
295 int Us; // microsecond part
296 ImPlotTime() { S = 0; Us = 0; }
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)); }
301};
302
303static inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs)
304{ return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
305static inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs)
306{ return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
307static inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs)
308{ return lhs.S == rhs.S && lhs.Us == rhs.Us; }
309static inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs)
310{ return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
311static inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs)
312{ return rhs < lhs; }
313static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)
314{ return lhs < rhs || lhs == rhs; }
315static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)
316{ return lhs > rhs || lhs == rhs; }
317
318// Colormap data storage
320 ImVector<ImU32> Keys;
321 ImVector<int> KeyCounts;
322 ImVector<int> KeyOffsets;
323 ImVector<ImU32> Tables;
324 ImVector<int> TableSizes;
325 ImVector<int> TableOffsets;
326 ImGuiTextBuffer Text;
327 ImVector<int> TextOffsets;
328 ImVector<bool> Quals;
329 ImGuiStorage Map;
330 int Count;
331
332 ImPlotColormapData() { Count = 0; }
333
334 int Append(const char* name, const ImU32* keys, int count, bool qual) {
335 if (GetIndex(name) != -1)
336 return -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);
346 int idx = Count++;
347 Map.SetInt(id,idx);
348 _AppendTable(idx);
349 return idx;
350 }
351
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);
357 if (IsQual(cmap)) {
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);
362 }
363 else {
364 int max_size = 255 * (key_count-1) + 1;
365 Tables.reserve(off + max_size);
366 // ImU32 last = keys[0];
367 // Tables.push_back(last);
368 // int n = 1;
369 for (int i = 0; i < key_count-1; ++i) {
370 for (int s = 0; s < 255; ++s) {
371 ImU32 a = keys[i];
372 ImU32 b = keys[i+1];
373 ImU32 c = ImMixU32(a,b,s);
374 // if (c != last) {
375 Tables.push_back(c);
376 // last = c;
377 // n++;
378 // }
379 }
380 }
381 ImU32 c = keys[key_count-1];
382 // if (c != last) {
383 Tables.push_back(c);
384 // n++;
385 // }
386 // TableSizes.push_back(n);
387 TableSizes.push_back(max_size);
388 }
389 }
390
391 void RebuildTables() {
392 Tables.resize(0);
393 TableSizes.resize(0);
394 TableOffsets.resize(0);
395 for (int i = 0; i < Count; ++i)
396 _AppendTable(i);
397 }
398
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); }
402
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(); }
407
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]; }
411
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];
417 }
418};
419
420// ImPlotPoint with positive/negative error values
422 double X, Y, Neg, Pos;
423 ImPlotPointError(double x, double y, double neg, double pos) {
424 X = x; Y = y; Neg = neg; Pos = pos;
425 }
426};
427
428// Interior plot label/annotation
430 ImVec2 Pos;
431 ImVec2 Offset;
432 ImU32 ColorBg;
433 ImU32 ColorFg;
434 int TextOffset;
435 bool Clamp;
437 ColorBg = ColorFg = 0;
438 TextOffset = 0;
439 Clamp = false;
440 }
441};
442
443// Collection of plot labels
445
446 ImVector<ImPlotAnnotation> Annotations;
447 ImGuiTextBuffer TextBuffer;
448 int Size;
449
450 ImPlotAnnotationCollection() { Reset(); }
451
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();
457 an.Clamp = clamp;
458 Annotations.push_back(an);
459 TextBuffer.appendfv(fmt, args);
460 const char nul[] = "";
461 TextBuffer.append(nul,nul+1);
462 Size++;
463 }
464
465 void Append(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, ...) IM_FMTARGS(7) {
466 va_list args;
467 va_start(args, fmt);
468 AppendV(pos, off, bg, fg, clamp, fmt, args);
469 va_end(args);
470 }
471
472 const char* GetText(int idx) {
473 return TextBuffer.Buf.Data + Annotations[idx].TextOffset;
474 }
475
476 void Reset() {
477 Annotations.shrink(0);
478 TextBuffer.Buf.shrink(0);
479 Size = 0;
480 }
481};
482
483struct ImPlotTag {
484 ImAxis Axis;
485 double Value;
486 ImU32 ColorBg;
487 ImU32 ColorFg;
488 int TextOffset;
489};
490
492
494 ImGuiTextBuffer TextBuffer;
495 int Size;
496
497 ImPlotTagCollection() { Reset(); }
498
499 void AppendV(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, va_list args) IM_FMTLIST(6) {
500 ImPlotTag tag;
501 tag.Axis = axis;
502 tag.Value = value;
503 tag.ColorBg = bg;
504 tag.ColorFg = fg;
505 tag.TextOffset = TextBuffer.size();
506 Tags.push_back(tag);
507 TextBuffer.appendfv(fmt, args);
508 const char nul[] = "";
509 TextBuffer.append(nul,nul+1);
510 Size++;
511 }
512
513 void Append(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, ...) IM_FMTARGS(6) {
514 va_list args;
515 va_start(args, fmt);
516 AppendV(axis, value, bg, fg, fmt, args);
517 va_end(args);
518 }
519
520 const char* GetText(int idx) {
521 return TextBuffer.Buf.Data + Tags[idx].TextOffset;
522 }
523
524 void Reset() {
525 Tags.shrink(0);
526 TextBuffer.Buf.shrink(0);
527 Size = 0;
528 }
529};
530
531// Tick mark info
533{
534 double PlotPos;
535 float PixelPos;
536 ImVec2 LabelSize;
537 int TextOffset;
538 bool Major;
539 bool ShowLabel;
540 int Level;
541 int Idx;
542
543 ImPlotTick(double value, bool major, int level, bool show_label) {
544 PixelPos = 0;
545 PlotPos = value;
546 Major = major;
547 ShowLabel = show_label;
548 Level = level;
549 TextOffset = -1;
550 }
551};
552
553// Collection of ticks
556 ImGuiTextBuffer TextBuffer;
557 ImVec2 MaxSize;
558 ImVec2 LateSize;
559 int Levels;
560
561 ImPlotTicker() {
562 Reset();
563 }
564
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);
571 }
572 return AddTick(tick);
573 }
574
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);
583 }
584 return AddTick(tick);
585 }
586
587 inline ImPlotTick& AddTick(ImPlotTick 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;
591 }
592 tick.Idx = Ticks.size();
593 Ticks.push_back(tick);
594 return Ticks.back();
595 }
596
597 const char* GetText(int idx) const {
598 return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
599 }
600
601 const char* GetText(const ImPlotTick& tick) {
602 return GetText(tick.Idx);
603 }
604
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;
608 }
609
610 void Reset() {
611 Ticks.shrink(0);
612 TextBuffer.Buf.shrink(0);
613 MaxSize = LateSize;
614 LateSize = ImVec2(0,0);
615 Levels = 1;
616 }
617
618 int TickCount() const {
619 return Ticks.Size;
620 }
621};
622
623// Axis state information that must persist after EndPlot
625{
626 ImGuiID ID;
627 ImPlotAxisFlags Flags;
628 ImPlotAxisFlags PreviousFlags;
629 ImPlotRange Range;
630 ImPlotCond RangeCond;
631 ImPlotScale Scale;
632 ImPlotRange FitExtents;
633 ImPlotAxis* OrthoAxis;
634 ImPlotRange ConstraintRange;
635 ImPlotRange ConstraintZoom;
636
637 ImPlotTicker Ticker;
638 ImPlotFormatter Formatter;
639 void* FormatterData;
640 char FormatSpec[16];
641 ImPlotLocator Locator;
642
643 double* LinkedMin;
644 double* LinkedMax;
645
646 int PickerLevel;
647 ImPlotTime PickerTimeMin, PickerTimeMax;
648
649 ImPlotTransform TransformForward;
650 ImPlotTransform TransformInverse;
651 void* TransformData;
652 float PixelMin, PixelMax;
653 double ScaleMin, ScaleMax;
654 double ScaleToPixel;
655 float Datum1, Datum2;
656
657 ImRect HoverRect;
658 int LabelOffset;
659 ImU32 ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi;
660
661 bool Enabled;
662 bool Vertical;
663 bool FitThisFrame;
664 bool HasRange;
665 bool HasFormatSpec;
666 bool ShowDefaultTicks;
667 bool Hovered;
668 bool Held;
669
670 ImPlotAxis() {
671 ID = 0;
672 Flags = PreviousFlags = ImPlotAxisFlags_None;
673 Range.Min = 0;
674 Range.Max = 1;
675 Scale = ImPlotScale_Linear;
676 TransformForward = TransformInverse = nullptr;
677 TransformData = nullptr;
678 FitExtents.Min = HUGE_VAL;
679 FitExtents.Max = -HUGE_VAL;
680 OrthoAxis = nullptr;
681 ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
682 ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
683 LinkedMin = LinkedMax = nullptr;
684 PickerLevel = 0;
685 Datum1 = Datum2 = 0;
686 PixelMin = PixelMax = 0;
687 LabelOffset = -1;
688 ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
689 ColorHiLi = IM_COL32_BLACK_TRANS;
690 Formatter = nullptr;
691 FormatterData = nullptr;
692 Locator = nullptr;
693 Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;
694 ShowDefaultTicks = true;
695 }
696
697 inline void Reset() {
698 Enabled = false;
699 Scale = ImPlotScale_Linear;
700 TransformForward = TransformInverse = nullptr;
701 TransformData = nullptr;
702 LabelOffset = -1;
703 HasFormatSpec = false;
704 Formatter = nullptr;
705 FormatterData = nullptr;
706 Locator = nullptr;
707 ShowDefaultTicks = true;
708 FitThisFrame = false;
709 FitExtents.Min = HUGE_VAL;
710 FitExtents.Max = -HUGE_VAL;
711 OrthoAxis = nullptr;
712 ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
713 ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
714 Ticker.Reset();
715 }
716
717 inline bool SetMin(double _min, bool force=false) {
718 if (!force && IsLockedMin())
719 return false;
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)
729 return false;
730 Range.Min = _min;
731 PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
732 UpdateTransformCache();
733 return true;
734 };
735
736 inline bool SetMax(double _max, bool force=false) {
737 if (!force && IsLockedMax())
738 return false;
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)
748 return false;
749 Range.Max = _max;
750 PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
751 UpdateTransformCache();
752 return true;
753 };
754
755 inline void SetRange(double v1, double v2) {
756 Range.Min = ImMin(v1,v2);
757 Range.Max = ImMax(v1,v2);
758 Constrain();
759 PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
760 PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
761 UpdateTransformCache();
762 }
763
764 inline void SetRange(const ImPlotRange& range) {
765 SetRange(range.Min, range.Max);
766 }
767
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;
771 if (IsLocked())
772 return;
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);
777 else
778 SetRange(Range.Min - delta, Range.Max + delta);
779 }
780
781 inline float PixelSize() const { return ImAbs(PixelMax - PixelMin); }
782
783 inline double GetAspect() const { return Range.Size() / PixelSize(); }
784
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;
795 Range.Min -= delta;
796 Range.Max += delta;
797 }
798 if (z > ConstraintZoom.Max) {
799 double delta = (z - ConstraintZoom.Max) * 0.5;
800 Range.Min += delta;
801 Range.Max -= delta;
802 }
803 if (Range.Max <= Range.Min)
804 Range.Max = Range.Min + DBL_EPSILON;
805 }
806
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);
812 }
813 else {
814 ScaleMin = Range.Min;
815 ScaleMax = Range.Max;
816 }
817 }
818
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;
824 }
825 return (float)(PixelMin + ScaleToPixel * (plt - Range.Min));
826 }
827
828
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);
835 }
836 return plt;
837 }
838
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;
843 }
844 }
845
846 inline void ExtendFitWith(ImPlotAxis& alt, double v, double v_alt) {
847 if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
848 return;
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;
852 }
853 }
854
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)) {
864 Range.Max += 0.5;
865 Range.Min -= 0.5;
866 }
867 Constrain();
868 UpdateTransformCache();
869 }
870
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); }
889
890 inline bool IsPanLocked(bool increasing) {
891 if (ImHasFlag(Flags, ImPlotAxisFlags_PanStretch)) {
892 return IsInputLocked();
893 }
894 else {
895 if (IsLockedMin() || IsLockedMax() || IsAutoFitting())
896 return false;
897 if (increasing)
898 return Range.Max == ConstraintRange.Max;
899 else
900 return Range.Min == ConstraintRange.Min;
901 }
902 }
903
904 void PushLinks() {
905 if (LinkedMin) { *LinkedMin = Range.Min; }
906 if (LinkedMax) { *LinkedMax = Range.Max; }
907 }
908
909 void PullLinks() {
910 if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); }
911 else if (LinkedMin) { SetMin(*LinkedMin,true); }
912 else if (LinkedMax) { SetMax(*LinkedMax,true); }
913 }
914};
915
916// Align plots group data
918 bool Vertical;
919 float PadA;
920 float PadB;
921 float PadAMax;
922 float PadBMax;
924 Vertical = true;
925 PadA = PadB = PadAMax = PadBMax = 0;
926 }
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; }
934 }
935 void End() { PadA = PadAMax; PadB = PadBMax; }
936 void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }
937};
938
939// State information for Plot items
941{
942 ImGuiID ID;
943 ImU32 Color;
944 ImRect LegendHoverRect;
945 int NameOffset;
946 bool Show;
947 bool LegendHovered;
948 bool SeenThisFrame;
949
950 ImPlotItem() {
951 ID = 0;
952 Color = IM_COL32_WHITE;
953 NameOffset = -1;
954 Show = true;
955 SeenThisFrame = false;
956 LegendHovered = false;
957 }
958
959 ~ImPlotItem() { ID = 0; }
960};
961
962// Holds Legend state
964{
965 ImPlotLegendFlags Flags;
966 ImPlotLegendFlags PreviousFlags;
967 ImPlotLocation Location;
968 ImPlotLocation PreviousLocation;
969 ImVec2 Scroll;
970 ImVector<int> Indices;
971 ImGuiTextBuffer Labels;
972 ImRect Rect;
973 ImRect RectClamped;
974 bool Hovered;
975 bool Held;
976 bool CanGoInside;
977
978 ImPlotLegend() {
979 Flags = PreviousFlags = ImPlotLegendFlags_None;
980 CanGoInside = true;
981 Hovered = Held = false;
982 Location = PreviousLocation = ImPlotLocation_NorthWest;
983 Scroll = ImVec2(0,0);
984 }
985
986 void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
987};
988
989// Holds Items and Legend data
991{
992 ImGuiID ID;
993 ImPlotLegend Legend;
994 ImPool<ImPlotItem> ItemPool;
995 int ColormapIdx;
996
997 ImPlotItemGroup() { ID = 0; ColormapIdx = 0; }
998
999 int GetItemCount() const { return ItemPool.GetBufSize(); }
1000 ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */ }
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; }
1010};
1011
1012// Holds Plot state information that must persist after EndPlot
1014{
1015 ImGuiID ID;
1016 ImPlotFlags Flags;
1017 ImPlotFlags PreviousFlags;
1018 ImPlotLocation MouseTextLocation;
1019 ImPlotMouseTextFlags MouseTextFlags;
1020 ImPlotAxis Axes[ImAxis_COUNT];
1021 ImGuiTextBuffer TextBuffer;
1022 ImPlotItemGroup Items;
1023 ImAxis CurrentX;
1024 ImAxis CurrentY;
1025 ImRect FrameRect;
1026 ImRect CanvasRect;
1027 ImRect PlotRect;
1028 ImRect AxesRect;
1029 ImRect SelectRect;
1030 ImVec2 SelectStart;
1031 int TitleOffset;
1032 bool JustCreated;
1033 bool Initialized;
1034 bool SetupLocked;
1035 bool FitThisFrame;
1036 bool Hovered;
1037 bool Held;
1038 bool Selecting;
1039 bool Selected;
1040 bool ContextLocked;
1041
1042 ImPlotPlot() {
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;
1053 TitleOffset = -1;
1054 JustCreated = true;
1055 Initialized = SetupLocked = FitThisFrame = false;
1056 Hovered = Held = Selected = Selecting = ContextLocked = false;
1057 }
1058
1059 inline bool IsInputLocked() const {
1060 for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {
1061 if (!XAxis(i).IsInputLocked())
1062 return false;
1063 }
1064 for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {
1065 if (!YAxis(i).IsInputLocked())
1066 return false;
1067 }
1068 return true;
1069 }
1070
1071 inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
1072
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);
1077 }
1078 else {
1079 TitleOffset = -1;
1080 }
1081 }
1082 inline bool HasTitle() const { return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); }
1083 inline const char* GetTitle() const { return TextBuffer.Buf.Data + TitleOffset; }
1084
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]; }
1089
1090 inline int EnabledAxesX() {
1091 int cnt = 0;
1092 for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
1093 cnt += XAxis(i).Enabled;
1094 return cnt;
1095 }
1096
1097 inline int EnabledAxesY() {
1098 int cnt = 0;
1099 for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
1100 cnt += YAxis(i).Enabled;
1101 return cnt;
1102 }
1103
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);
1108 }
1109 else {
1110 axis.LabelOffset = -1;
1111 }
1112 }
1113
1114 inline const char* GetAxisLabel(const ImPlotAxis& axis) const { return TextBuffer.Buf.Data + axis.LabelOffset; }
1115};
1116
1117// Holds subplot data that must persist after EndSubplot
1119 ImGuiID ID;
1120 ImPlotSubplotFlags Flags;
1121 ImPlotSubplotFlags PreviousFlags;
1122 ImPlotItemGroup Items;
1123 int Rows;
1124 int Cols;
1125 int CurrentIdx;
1126 ImRect FrameRect;
1127 ImRect GridRect;
1128 ImVec2 CellSize;
1129 ImVector<ImPlotAlignmentData> RowAlignmentData;
1130 ImVector<ImPlotAlignmentData> ColAlignmentData;
1131 ImVector<float> RowRatios;
1132 ImVector<float> ColRatios;
1133 ImVector<ImPlotRange> RowLinkData;
1134 ImVector<ImPlotRange> ColLinkData;
1135 float TempSizes[2];
1136 bool FrameHovered;
1137 bool HasTitle;
1138
1139 ImPlotSubplot() {
1140 ID = 0;
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;
1148 HasTitle = false;
1149 }
1150};
1151
1152// Temporary data storage for upcoming plot
1154{
1155 ImPlotCond RangeCond[ImAxis_COUNT];
1156 ImPlotRange Range[ImAxis_COUNT];
1157 bool HasRange[ImAxis_COUNT];
1158 bool Fit[ImAxis_COUNT];
1159 double* LinkedMin[ImAxis_COUNT];
1160 double* LinkedMax[ImAxis_COUNT];
1161
1162 ImPlotNextPlotData() { Reset(); }
1163
1164 void Reset() {
1165 for (int i = 0; i < ImAxis_COUNT; ++i) {
1166 HasRange[i] = false;
1167 Fit[i] = false;
1168 LinkedMin[i] = LinkedMax[i] = nullptr;
1169 }
1170 }
1171
1172};
1173
1174// Temporary data storage for upcoming item
1176 ImVec4 Colors[5]; // ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar
1177 float LineWeight;
1178 ImPlotMarker Marker;
1179 float MarkerSize;
1180 float MarkerWeight;
1181 float FillAlpha;
1182 float ErrorBarSize;
1183 float ErrorBarWeight;
1184 float DigitalBitHeight;
1185 float DigitalBitGap;
1186 bool RenderLine;
1187 bool RenderFill;
1188 bool RenderMarkerLine;
1189 bool RenderMarkerFill;
1190 bool HasHidden;
1191 bool Hidden;
1192 ImPlotCond HiddenCond;
1193 ImPlotNextItemData() { Reset(); }
1194 void Reset() {
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;
1200 }
1201};
1202
1203// Holds state information that must persist between calls to BeginPlot()/EndPlot()
1205 // Plot States
1206 ImPool<ImPlotPlot> Plots;
1207 ImPool<ImPlotSubplot> Subplots;
1208 ImPlotPlot* CurrentPlot;
1209 ImPlotSubplot* CurrentSubplot;
1210 ImPlotItemGroup* CurrentItems;
1211 ImPlotItem* CurrentItem;
1212 ImPlotItem* PreviousItem;
1213
1214 // Tick Marks and Labels
1215 ImPlotTicker CTicker;
1216
1217 // Annotation and Tabs
1218 ImPlotAnnotationCollection Annotations;
1220
1221 // Style and Colormaps
1222 ImPlotStyle Style;
1223 ImVector<ImGuiColorMod> ColorModifiers;
1224 ImVector<ImGuiStyleMod> StyleModifiers;
1225 ImPlotColormapData ColormapData;
1226 ImVector<ImPlotColormap> ColormapModifiers;
1227
1228 // Time
1229 tm Tm;
1230
1231 // Temp data for general use
1232 ImVector<double> TempDouble1, TempDouble2;
1233 ImVector<int> TempInt1;
1234
1235 // Misc
1236 int DigitalPlotItemCnt;
1237 int DigitalPlotOffset;
1238 ImPlotNextPlotData NextPlotData;
1239 ImPlotNextItemData NextItemData;
1240 ImPlotInputMap InputMap;
1241 bool OpenContextThisFrame;
1242 ImGuiTextBuffer MousePosStringBuilder;
1243 ImPlotItemGroup* SortItems;
1244
1245 // Align plots
1246 ImPool<ImPlotAlignmentData> AlignmentData;
1247 ImPlotAlignmentData* CurrentAlignmentH;
1248 ImPlotAlignmentData* CurrentAlignmentV;
1249};
1250
1251//-----------------------------------------------------------------------------
1252// [SECTION] Internal API
1253// No guarantee of forward compatibility here!
1254//-----------------------------------------------------------------------------
1255
1256namespace ImPlot {
1257
1258//-----------------------------------------------------------------------------
1259// [SECTION] Context Utils
1260//-----------------------------------------------------------------------------
1261
1262// Initializes an ImPlotContext
1263IMPLOT_API void Initialize(ImPlotContext* ctx);
1264// Resets an ImPlot context for the next call to BeginPlot
1265IMPLOT_API void ResetCtxForNextPlot(ImPlotContext* ctx);
1266// Resets an ImPlot context for the next call to BeginAlignedPlots
1267IMPLOT_API void ResetCtxForNextAlignedPlots(ImPlotContext* ctx);
1268// Resets an ImPlot context for the next call to BeginSubplot
1269IMPLOT_API void ResetCtxForNextSubplot(ImPlotContext* ctx);
1270
1271//-----------------------------------------------------------------------------
1272// [SECTION] Plot Utils
1273//-----------------------------------------------------------------------------
1274
1275// Gets a plot from the current ImPlotContext
1276IMPLOT_API ImPlotPlot* GetPlot(const char* title);
1277// Gets the current plot from the current ImPlotContext
1278IMPLOT_API ImPlotPlot* GetCurrentPlot();
1279// Busts the cache for every plot in the current context
1280IMPLOT_API void BustPlotCache();
1281
1282// Shows a plot's context menu.
1283IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
1284
1285//-----------------------------------------------------------------------------
1286// [SECTION] Setup Utils
1287//-----------------------------------------------------------------------------
1288
1289// Lock Setup and call SetupFinish if necessary.
1290static inline void SetupLock() {
1291 ImPlotContext& gp = *GImPlot;
1292 if (!gp.CurrentPlot->SetupLocked)
1293 SetupFinish();
1294 gp.CurrentPlot->SetupLocked = true;
1295}
1296
1297//-----------------------------------------------------------------------------
1298// [SECTION] Subplot Utils
1299//-----------------------------------------------------------------------------
1300
1301// Advances to next subplot
1302IMPLOT_API void SubplotNextCell();
1303
1304// Shows a subplot's context menu.
1305IMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot);
1306
1307//-----------------------------------------------------------------------------
1308// [SECTION] Item Utils
1309//-----------------------------------------------------------------------------
1310
1311// Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect.
1312IMPLOT_API bool BeginItem(const char* label_id, ImPlotItemFlags flags=0, ImPlotCol recolor_from=IMPLOT_AUTO);
1313
1314// Same as above but with fitting functionality.
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)) {
1318 ImPlotPlot& plot = *GetCurrentPlot();
1319 if (plot.FitThisFrame && !ImHasFlag(flags, ImPlotItemFlags_NoFit))
1320 fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]);
1321 return true;
1322 }
1323 return false;
1324}
1325
1326// Ends an item (call only if BeginItem returns true). Pops PlotClipRect.
1327IMPLOT_API void EndItem();
1328
1329// Register or get an existing item from the current plot.
1330IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr);
1331// Get a plot item from the current plot.
1332IMPLOT_API ImPlotItem* GetItem(const char* label_id);
1333// Gets the current item.
1334IMPLOT_API ImPlotItem* GetCurrentItem();
1335// Busts the cache for every item for every plot in the current context.
1336IMPLOT_API void BustItemCache();
1337
1338//-----------------------------------------------------------------------------
1339// [SECTION] Axis Utils
1340//-----------------------------------------------------------------------------
1341
1342// Returns true if any enabled axis is locked from user input.
1343static inline bool AnyAxesInputLocked(ImPlotAxis* axes, int count) {
1344 for (int i = 0; i < count; ++i) {
1345 if (axes[i].Enabled && axes[i].IsInputLocked())
1346 return true;
1347 }
1348 return false;
1349}
1350
1351// Returns true if all enabled axes are locked from user input.
1352static inline bool AllAxesInputLocked(ImPlotAxis* axes, int count) {
1353 for (int i = 0; i < count; ++i) {
1354 if (axes[i].Enabled && !axes[i].IsInputLocked())
1355 return false;
1356 }
1357 return true;
1358}
1359
1360static inline bool AnyAxesHeld(ImPlotAxis* axes, int count) {
1361 for (int i = 0; i < count; ++i) {
1362 if (axes[i].Enabled && axes[i].Held)
1363 return true;
1364 }
1365 return false;
1366}
1367
1368static inline bool AnyAxesHovered(ImPlotAxis* axes, int count) {
1369 for (int i = 0; i < count; ++i) {
1370 if (axes[i].Enabled && axes[i].Hovered)
1371 return true;
1372 }
1373 return false;
1374}
1375
1376// Returns true if the user has requested data to be fit.
1377static inline bool FitThisFrame() {
1378 return GImPlot->CurrentPlot->FitThisFrame;
1379}
1380
1381// Extends the current plot's axes so that it encompasses a vertical line at x
1382static inline void FitPointX(double x) {
1383 ImPlotPlot& plot = *GetCurrentPlot();
1384 ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
1385 x_axis.ExtendFit(x);
1386}
1387
1388// Extends the current plot's axes so that it encompasses a horizontal line at y
1389static inline void FitPointY(double y) {
1390 ImPlotPlot& plot = *GetCurrentPlot();
1391 ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
1392 y_axis.ExtendFit(y);
1393}
1394
1395// Extends the current plot's axes so that it encompasses point p
1396static inline void FitPoint(const ImPlotPoint& p) {
1397 ImPlotPlot& plot = *GetCurrentPlot();
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);
1402}
1403
1404// Returns true if two ranges overlap
1405static inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)
1406{ return r1.Min <= r2.Max && r2.Min <= r1.Max; }
1407
1408// Shows an axis's context menu.
1409IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
1410
1411//-----------------------------------------------------------------------------
1412// [SECTION] Legend Utils
1413//-----------------------------------------------------------------------------
1414
1415// Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
1416IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
1417// Calculates the bounding box size of a legend _before_ clipping.
1418IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);
1419// Clips calculated legend size
1420IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad);
1421// Renders legend entries into a bounding box
1422IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);
1423// Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window! This is not thoroughly tested nor scrollable!).
1424IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true);
1425// Shows a legend's context menu.
1426IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible);
1427
1428//-----------------------------------------------------------------------------
1429// [SECTION] Label Utils
1430//-----------------------------------------------------------------------------
1431
1432// Create a a string label for a an axis value
1433IMPLOT_API void LabelAxisValue(const ImPlotAxis& axis, double value, char* buff, int size, bool round = false);
1434
1435//-----------------------------------------------------------------------------
1436// [SECTION] Styling Utils
1437//-----------------------------------------------------------------------------
1438
1439// Get styling data for next item (call between Begin/EndItem)
1440static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItemData; }
1441
1442// Returns true if a color is set to be automatically determined
1443static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
1444// Returns true if a style color is set to be automatically determined
1445static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
1446// Returns the automatically deduced style color
1447IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
1448
1449// Returns the style color whether it is automatic or custom set
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)); }
1452
1453// Draws vertical text. The position is the bottom left of the text rect.
1454IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr);
1455// Draws multiline horizontal text centered.
1456IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr);
1457// Calculates the size of vertical text
1458static inline ImVec2 CalcTextSizeVertical(const char *text) {
1459 ImVec2 sz = ImGui::CalcTextSize(text);
1460 return ImVec2(sz.y, sz.x);
1461}
1462// Returns white or black text given background color
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)); }
1465// Lightens or darkens a color for hover
1466static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); }
1467
1468// Clamps a label position so that it fits a rect defined by Min/Max
1469static inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {
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;
1474 return pos;
1475}
1476
1477// Returns a color from the Color map given an index >= 0 (modulo will be performed).
1478IMPLOT_API ImU32 GetColormapColorU32(int idx, ImPlotColormap cmap);
1479// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.
1480IMPLOT_API ImU32 NextColormapColorU32();
1481// Linearly interpolates a color from the current colormap given t between 0 and 1.
1482IMPLOT_API ImU32 SampleColormapU32(float t, ImPlotColormap cmap);
1483
1484// Render a colormap bar
1485IMPLOT_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous);
1486
1487//-----------------------------------------------------------------------------
1488// [SECTION] Math and Misc Utils
1489//-----------------------------------------------------------------------------
1490
1491// Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2)
1492IMPLOT_API double NiceNum(double x, bool round);
1493// Computes order of magnitude of double.
1494static inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
1495// Returns the precision required for a order of magnitude.
1496static inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }
1497// Returns a floating point precision to use given a value
1498static inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }
1499// Round a value to a given precision
1500static inline double RoundTo(double val, int prec) { double p = pow(10,(double)prec); return floor(val*p+0.5)/p; }
1501
1502// Returns the intersection point of two lines A and B (assumes they are not parallel!)
1503static inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {
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);
1507}
1508
1509// Fills a buffer with n samples linear interpolated from vmin to vmax
1510template <typename T>
1511void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
1512 buffer.resize(n);
1513 T step = (vmax - vmin) / (n - 1);
1514 for (int i = 0; i < n; ++i) {
1515 buffer[i] = vmin + i * step;
1516 }
1517}
1518
1519// Calculate histogram bin counts and widths
1520template <typename T>
1521static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
1522 switch (meth) {
1523 case ImPlotBin_Sqrt:
1524 bins_out = (int)ceil(sqrt(count));
1525 break;
1526 case ImPlotBin_Sturges:
1527 bins_out = (int)ceil(1.0 + log2(count));
1528 break;
1529 case ImPlotBin_Rice:
1530 bins_out = (int)ceil(2 * cbrt(count));
1531 break;
1532 case ImPlotBin_Scott:
1533 width_out = 3.49 * ImStdDev(values, count) / cbrt(count);
1534 bins_out = (int)round(range.Size() / width_out);
1535 break;
1536 }
1537 width_out = range.Size() / bins_out;
1538}
1539
1540//-----------------------------------------------------------------------------
1541// Time Utils
1542//-----------------------------------------------------------------------------
1543
1544// Returns true if year is leap year (366 days long)
1545static inline bool IsLeapYear(int year) {
1546 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1547}
1548// Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed.
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));
1552}
1553
1554// Make a UNIX timestamp from a tm struct expressed in UTC time (i.e. GMT timezone).
1555IMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm);
1556// Make a tm struct expressed in UTC time (i.e. GMT timezone) from a UNIX timestamp.
1557IMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
1558
1559// Make a UNIX timestamp from a tm struct expressed in local time.
1560IMPLOT_API ImPlotTime MkLocTime(struct tm *ptm);
1561// Make a tm struct expressed in local time from a UNIX timestamp.
1562IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);
1563
1564// NB: The following functions only work if there is a current ImPlotContext because the
1565// internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime.
1566
1567// Make a timestamp from time components.
1568// year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999]
1569IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);
1570// Get year component from timestamp [1970-3000]
1571IMPLOT_API int GetYear(const ImPlotTime& t);
1572
1573// Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract.
1574IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
1575// Rounds a timestamp down to nearest unit.
1576IMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);
1577// Rounds a timestamp up to the nearest unit.
1578IMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);
1579// Rounds a timestamp up or down to the nearest unit.
1580IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
1581// Combines the date of one timestamp with the time-of-day of another timestamp.
1582IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);
1583
1584// Formats the time part of timestamp t into a buffer according to #fmt
1585IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk);
1586// Formats the date part of timestamp t into a buffer according to #fmt
1587IMPLOT_API int FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601);
1588// Formats the time and/or date parts of a timestamp t into a buffer according to #fmt
1589IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeSpec fmt);
1590
1591// Shows a date picker widget block (year/month/day).
1592// #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
1593// #t will be set when a day is clicked and the function will return true.
1594// #t1 and #t2 are optional dates to highlight.
1595IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr);
1596// Shows a time picker widget block (hour/min/sec).
1597// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
1598IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
1599
1600//-----------------------------------------------------------------------------
1601// [SECTION] Transforms
1602//-----------------------------------------------------------------------------
1603
1604static inline double TransformForward_Log10(double v, void*) {
1605 v = v <= 0.0 ? DBL_MIN : v;
1606 return ImLog10(v);
1607}
1608
1609static inline double TransformInverse_Log10(double v, void*) {
1610 return ImPow(10, v);
1611}
1612
1613static inline double TransformForward_SymLog(double v, void*) {
1614 return 2.0 * ImAsinh(v / 2.0);
1615}
1616
1617static inline double TransformInverse_SymLog(double v, void*) {
1618 return 2.0 * ImSinh(v / 2.0);
1619}
1620
1621static inline double TransformForward_Logit(double v, void*) {
1622 v = ImClamp(v, DBL_MIN, 1.0 - DBL_EPSILON);
1623 return ImLog10(v / (1 - v));
1624}
1625
1626static inline double TransformInverse_Logit(double v, void*) {
1627 return 1.0 / (1.0 + ImPow(10,-v));
1628}
1629
1630//-----------------------------------------------------------------------------
1631// [SECTION] Formatters
1632//-----------------------------------------------------------------------------
1633
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);
1637}
1638
1639static inline int Formatter_Logit(double value, char* buff, int size, void*) {
1640 if (value == 0.5)
1641 return ImFormatString(buff,size,"1/2");
1642 else if (value < 0.5)
1643 return ImFormatString(buff,size,"%g", value);
1644 else
1645 return ImFormatString(buff,size,"1 - %g", 1 - value);
1646}
1647
1649 ImPlotTime Time;
1650 ImPlotDateTimeSpec Spec;
1651 ImPlotFormatter UserFormatter;
1652 void* UserFormatterData;
1653};
1654
1655static inline int Formatter_Time(double, char* buff, int size, void* data) {
1657 return FormatDateTime(ftd->Time, buff, size, ftd->Spec);
1658}
1659
1660//------------------------------------------------------------------------------
1661// [SECTION] Locator
1662//------------------------------------------------------------------------------
1663
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);
1668
1669} // namespace ImPlot
Definition imgui.h:2801
Definition imgui.h:2504
Definition imgui.h:2467
Definition implot_internal.h:1648
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.h:564
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.h:468
Definition implot.h:483
Definition implot.h:507
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
Definition imgui.h:275
Definition imgui.h:288
Definition imgui.h:1993