implot_internal.h 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. // MIT License
  2. // Copyright (c) 2021 Evan Pezent
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. // The above copyright notice and this permission notice shall be included in all
  10. // copies or substantial portions of the Software.
  11. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. // SOFTWARE.
  18. // ImPlot v0.11 WIP
  19. // You may use this file to debug, understand or extend ImPlot features but we
  20. // don't provide any guarantee of forward compatibility!
  21. //-----------------------------------------------------------------------------
  22. // [SECTION] Header Mess
  23. //-----------------------------------------------------------------------------
  24. #pragma once
  25. #ifndef IMGUI_DEFINE_MATH_OPERATORS
  26. #define IMGUI_DEFINE_MATH_OPERATORS
  27. #endif
  28. #include <time.h>
  29. #include "imgui_internal.h"
  30. #ifndef IMPLOT_VERSION
  31. #error Must include implot.h before implot_internal.h
  32. #endif
  33. // Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize()
  34. #if (IMGUI_VERSION_NUM < 18303)
  35. #define GetBufSize GetSize
  36. #endif
  37. //-----------------------------------------------------------------------------
  38. // [SECTION] Constants
  39. //-----------------------------------------------------------------------------
  40. // Constants can be changed unless stated otherwise. We may move some of these
  41. // to ImPlotStyleVar_ over time.
  42. // The maximum number of supported y-axes (DO NOT CHANGE THIS)
  43. #define IMPLOT_Y_AXES 3
  44. // Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
  45. #define IMPLOT_ZOOM_RATE 0.1f
  46. // Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
  47. #define IMPLOT_MIN_TIME 0
  48. // Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
  49. #define IMPLOT_MAX_TIME 32503680000
  50. // Default label format for axis labels
  51. #define IMPLOT_LABEL_FMT "%g"
  52. // Plot values less than or equal to 0 will be replaced with this on log scale axes
  53. #define IMPLOT_LOG_ZERO DBL_MIN
  54. //-----------------------------------------------------------------------------
  55. // [SECTION] Macros
  56. //-----------------------------------------------------------------------------
  57. // Split ImU32 color into RGB components [0 255]
  58. #define IM_COL32_SPLIT_RGB(col,r,g,b) \
  59. ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \
  60. ImU32 g = ((col >> IM_COL32_G_SHIFT) & 0xFF); \
  61. ImU32 b = ((col >> IM_COL32_B_SHIFT) & 0xFF);
  62. //-----------------------------------------------------------------------------
  63. // [SECTION] Forward Declarations
  64. //-----------------------------------------------------------------------------
  65. struct ImPlotTick;
  66. struct ImPlotAxis;
  67. struct ImPlotAxisColor;
  68. struct ImPlotItem;
  69. struct ImPlotLegendData;
  70. struct ImPlotPlot;
  71. struct ImPlotNextPlotData;
  72. //-----------------------------------------------------------------------------
  73. // [SECTION] Context Pointer
  74. //-----------------------------------------------------------------------------
  75. extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
  76. //-----------------------------------------------------------------------------
  77. // [SECTION] Generic Helpers
  78. //-----------------------------------------------------------------------------
  79. // Computes the common (base-10) logarithm
  80. static inline float ImLog10(float x) { return log10f(x); }
  81. static inline double ImLog10(double x) { return log10(x); }
  82. // Returns true if a flag is set
  83. template <typename TSet, typename TFlag>
  84. static inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
  85. // Flips a flag in a flagset
  86. template <typename TSet, typename TFlag>
  87. static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
  88. // Linearly remaps x from [x0 x1] to [y0 y1].
  89. template <typename T>
  90. static inline T ImRemap(T x, T x0, T x1, T y0, T y1) { return y0 + (x - x0) * (y1 - y0) / (x1 - x0); }
  91. // Linear rempas x from [x0 x1] to [0 1]
  92. template <typename T>
  93. static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }
  94. // Returns always positive modulo (assumes r != 0)
  95. static inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
  96. // Returns true if val is NAN or INFINITY
  97. static inline bool ImNanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); }
  98. // Turns NANs to 0s
  99. static inline double ImConstrainNan(double val) { return isnan(val) ? 0 : val; }
  100. // Turns infinity to floating point maximums
  101. static inline double ImConstrainInf(double val) { return val == HUGE_VAL ? DBL_MAX : val == -HUGE_VAL ? - DBL_MAX : val; }
  102. // Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)
  103. static inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
  104. // Turns numbers less than 0 to zero
  105. static inline double ImConstrainTime(double val) { return val < IMPLOT_MIN_TIME ? IMPLOT_MIN_TIME : (val > IMPLOT_MAX_TIME ? IMPLOT_MAX_TIME : val); }
  106. // True if two numbers are approximately equal using units in the last place.
  107. static 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; }
  108. // Finds min value in an unsorted array
  109. template <typename T>
  110. static 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; }
  111. // Finds the max value in an unsorted array
  112. template <typename T>
  113. static 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; }
  114. // Finds the min and max value in an unsorted array
  115. template <typename T>
  116. static inline void ImMinMaxArray(const T* values, int count, T* min_out, T* max_out) {
  117. T Min = values[0]; T Max = values[0];
  118. for (int i = 1; i < count; ++i) {
  119. if (values[i] < Min) { Min = values[i]; }
  120. if (values[i] > Max) { Max = values[i]; }
  121. }
  122. *min_out = Min; *max_out = Max;
  123. }
  124. // Finds the sim of an array
  125. template <typename T>
  126. static inline T ImSum(const T* values, int count) {
  127. T sum = 0;
  128. for (int i = 0; i < count; ++i)
  129. sum += values[i];
  130. return sum;
  131. }
  132. // Finds the mean of an array
  133. template <typename T>
  134. static inline double ImMean(const T* values, int count) {
  135. double den = 1.0 / count;
  136. double mu = 0;
  137. for (int i = 0; i < count; ++i)
  138. mu += values[i] * den;
  139. return mu;
  140. }
  141. // Finds the sample standard deviation of an array
  142. template <typename T>
  143. static inline double ImStdDev(const T* values, int count) {
  144. double den = 1.0 / (count - 1.0);
  145. double mu = ImMean(values, count);
  146. double x = 0;
  147. for (int i = 0; i < count; ++i)
  148. x += (values[i] - mu) * (values[i] - mu) * den;
  149. return sqrt(x);
  150. }
  151. // Mix color a and b by factor s in [0 256]
  152. static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
  153. #ifdef IMPLOT_MIX64
  154. const ImU32 af = 256-s;
  155. const ImU32 bf = s;
  156. const ImU64 al = (a & 0x00ff00ff) | (((ImU64)(a & 0xff00ff00)) << 24);
  157. const ImU64 bl = (b & 0x00ff00ff) | (((ImU64)(b & 0xff00ff00)) << 24);
  158. const ImU64 mix = (al * af + bl * bf);
  159. return ((mix >> 32) & 0xff00ff00) | ((mix & 0xff00ff00) >> 8);
  160. #else
  161. const ImU32 af = 256-s;
  162. const ImU32 bf = s;
  163. const ImU32 al = (a & 0x00ff00ff);
  164. const ImU32 ah = (a & 0xff00ff00) >> 8;
  165. const ImU32 bl = (b & 0x00ff00ff);
  166. const ImU32 bh = (b & 0xff00ff00) >> 8;
  167. const ImU32 ml = (al * af + bl * bf);
  168. const ImU32 mh = (ah * af + bh * bf);
  169. return (mh & 0xff00ff00) | ((ml & 0xff00ff00) >> 8);
  170. #endif
  171. }
  172. // Lerp across an array of 32-bit collors given t in [0.0 1.0]
  173. static inline ImU32 ImLerpU32(const ImU32* colors, int size, float t) {
  174. int i1 = (int)((size - 1 ) * t);
  175. int i2 = i1 + 1;
  176. if (i2 == size || size == 1)
  177. return colors[i1];
  178. float den = 1.0f / (size - 1);
  179. float t1 = i1 * den;
  180. float t2 = i2 * den;
  181. float tr = ImRemap01(t, t1, t2);
  182. return ImMixU32(colors[i1], colors[i2], (ImU32)(tr*256));
  183. }
  184. // Set alpha channel of 32-bit color from float in range [0.0 1.0]
  185. static inline ImU32 ImAlphaU32(ImU32 col, float alpha) {
  186. return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
  187. }
  188. // Character buffer writer helper (FIXME: Can't we replace this with ImGuiTextBuffer?)
  189. struct ImBufferWriter
  190. {
  191. char* Buffer;
  192. int Size;
  193. int Pos;
  194. ImBufferWriter(char* buffer, int size) {
  195. Buffer = buffer;
  196. Size = size;
  197. Pos = 0;
  198. }
  199. void Write(const char* fmt, ...) {
  200. va_list args;
  201. va_start(args, fmt);
  202. WriteV(fmt, args);
  203. va_end(args);
  204. }
  205. void WriteV(const char* fmt, va_list args) {
  206. const int written = ::vsnprintf(&Buffer[Pos], Size - Pos - 1, fmt, args);
  207. if (written > 0)
  208. Pos += ImMin(written, Size-Pos-1);
  209. }
  210. };
  211. // Fixed size point array
  212. template <int N>
  213. struct ImPlotPointArray {
  214. inline ImPlotPoint& operator[](int i) { return Data[i]; }
  215. inline const ImPlotPoint& operator[](int i) const { return Data[i]; }
  216. inline int Size() { return N; }
  217. ImPlotPoint Data[N];
  218. };
  219. //-----------------------------------------------------------------------------
  220. // [SECTION] ImPlot Enums
  221. //-----------------------------------------------------------------------------
  222. typedef int ImPlotScale; // -> enum ImPlotScale_
  223. typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_
  224. typedef int ImPlotDateFmt; // -> enum ImPlotDateFmt_
  225. typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_
  226. // XY axes scaling combinations
  227. enum ImPlotScale_ {
  228. ImPlotScale_LinLin, // linear x, linear y
  229. ImPlotScale_LogLin, // log x, linear y
  230. ImPlotScale_LinLog, // linear x, log y
  231. ImPlotScale_LogLog // log x, log y
  232. };
  233. enum 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. enum ImPlotDateFmt_ { // default [ ISO 8601 ]
  245. ImPlotDateFmt_None = 0,
  246. ImPlotDateFmt_DayMo, // 10/3 [ --10-03 ]
  247. ImPlotDateFmt_DayMoYr, // 10/3/91 [ 1991-10-03 ]
  248. ImPlotDateFmt_MoYr, // Oct 1991 [ 1991-10 ]
  249. ImPlotDateFmt_Mo, // Oct [ --10 ]
  250. ImPlotDateFmt_Yr // 1991 [ 1991 ]
  251. };
  252. enum ImPlotTimeFmt_ { // default [ 24 Hour Clock ]
  253. ImPlotTimeFmt_None = 0,
  254. ImPlotTimeFmt_Us, // .428 552 [ .428 552 ]
  255. ImPlotTimeFmt_SUs, // :29.428 552 [ :29.428 552 ]
  256. ImPlotTimeFmt_SMs, // :29.428 [ :29.428 ]
  257. ImPlotTimeFmt_S, // :29 [ :29 ]
  258. ImPlotTimeFmt_HrMinSMs, // 7:21:29.428pm [ 19:21:29.428 ]
  259. ImPlotTimeFmt_HrMinS, // 7:21:29pm [ 19:21:29 ]
  260. ImPlotTimeFmt_HrMin, // 7:21pm [ 19:21 ]
  261. ImPlotTimeFmt_Hr // 7pm [ 19:00 ]
  262. };
  263. // Input mapping structure, default values listed in the comments.
  264. struct ImPlotInputMap {
  265. ImGuiMouseButton PanButton; // LMB enables panning when held
  266. ImGuiKeyModFlags PanMod; // none optional modifier that must be held for panning
  267. ImGuiMouseButton FitButton; // LMB fits visible data when double clicked
  268. ImGuiMouseButton ContextMenuButton; // RMB opens plot context menu (if enabled) when clicked
  269. ImGuiMouseButton BoxSelectButton; // RMB begins box selection when pressed and confirms selection when released
  270. ImGuiKeyModFlags BoxSelectMod; // none optional modifier that must be held for box selection
  271. ImGuiMouseButton BoxSelectCancelButton; // LMB cancels active box selection when pressed
  272. ImGuiMouseButton QueryButton; // MMB begins query selection when pressed and end query selection when released
  273. ImGuiKeyModFlags QueryMod; // none optional modifier that must be held for query selection
  274. ImGuiKeyModFlags QueryToggleMod; // Ctrl when held, active box selections turn into queries
  275. ImGuiKeyModFlags HorizontalMod; // Alt expands active box selection/query horizontally to plot edge when held
  276. ImGuiKeyModFlags VerticalMod; // Shift expands active box selection/query vertically to plot edge when held
  277. IMPLOT_API ImPlotInputMap();
  278. };
  279. //-----------------------------------------------------------------------------
  280. // [SECTION] ImPlot Structs
  281. //-----------------------------------------------------------------------------
  282. // Combined date/time format spec
  283. struct ImPlotDateTimeFmt {
  284. ImPlotDateTimeFmt(ImPlotDateFmt date_fmt, ImPlotTimeFmt time_fmt, bool use_24_hr_clk = false, bool use_iso_8601 = false) {
  285. Date = date_fmt;
  286. Time = time_fmt;
  287. UseISO8601 = use_iso_8601;
  288. Use24HourClock = use_24_hr_clk;
  289. }
  290. ImPlotDateFmt Date;
  291. ImPlotTimeFmt Time;
  292. bool UseISO8601;
  293. bool Use24HourClock;
  294. };
  295. // Two part timestamp struct.
  296. struct ImPlotTime {
  297. time_t S; // second part
  298. int Us; // microsecond part
  299. ImPlotTime() { S = 0; Us = 0; }
  300. ImPlotTime(time_t s, int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
  301. void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
  302. double ToDouble() const { return (double)S + (double)Us / 1000000.0; }
  303. static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); }
  304. };
  305. static inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs)
  306. { return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
  307. static inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs)
  308. { return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
  309. static inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs)
  310. { return lhs.S == rhs.S && lhs.Us == rhs.Us; }
  311. static inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs)
  312. { return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
  313. static inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs)
  314. { return rhs < lhs; }
  315. static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)
  316. { return lhs < rhs || lhs == rhs; }
  317. static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)
  318. { return lhs > rhs || lhs == rhs; }
  319. // Colormap data storage
  320. struct ImPlotColormapData {
  321. ImVector<ImU32> Keys;
  322. ImVector<int> KeyCounts;
  323. ImVector<int> KeyOffsets;
  324. ImVector<ImU32> Tables;
  325. ImVector<int> TableSizes;
  326. ImVector<int> TableOffsets;
  327. ImGuiTextBuffer Text;
  328. ImVector<int> TextOffsets;
  329. ImVector<bool> Quals;
  330. ImGuiStorage Map;
  331. int Count;
  332. ImPlotColormapData() { Count = 0; }
  333. int Append(const char* name, const ImU32* keys, int count, bool qual) {
  334. if (GetIndex(name) != -1)
  335. return -1;
  336. KeyOffsets.push_back(Keys.size());
  337. KeyCounts.push_back(count);
  338. Keys.reserve(Keys.size()+count);
  339. for (int i = 0; i < count; ++i)
  340. Keys.push_back(keys[i]);
  341. TextOffsets.push_back(Text.size());
  342. Text.append(name, name + strlen(name) + 1);
  343. Quals.push_back(qual);
  344. ImGuiID id = ImHashStr(name);
  345. int idx = Count++;
  346. Map.SetInt(id,idx);
  347. _AppendTable(idx);
  348. return idx;
  349. }
  350. void _AppendTable(ImPlotColormap cmap) {
  351. int key_count = GetKeyCount(cmap);
  352. const ImU32* keys = GetKeys(cmap);
  353. int off = Tables.size();
  354. TableOffsets.push_back(off);
  355. if (IsQual(cmap)) {
  356. Tables.reserve(key_count);
  357. for (int i = 0; i < key_count; ++i)
  358. Tables.push_back(keys[i]);
  359. TableSizes.push_back(key_count);
  360. }
  361. else {
  362. int max_size = 255 * (key_count-1) + 1;
  363. Tables.reserve(off + max_size);
  364. // ImU32 last = keys[0];
  365. // Tables.push_back(last);
  366. // int n = 1;
  367. for (int i = 0; i < key_count-1; ++i) {
  368. for (int s = 0; s < 255; ++s) {
  369. ImU32 a = keys[i];
  370. ImU32 b = keys[i+1];
  371. ImU32 c = ImMixU32(a,b,s);
  372. // if (c != last) {
  373. Tables.push_back(c);
  374. // last = c;
  375. // n++;
  376. // }
  377. }
  378. }
  379. ImU32 c = keys[key_count-1];
  380. // if (c != last) {
  381. Tables.push_back(c);
  382. // n++;
  383. // }
  384. // TableSizes.push_back(n);
  385. TableSizes.push_back(max_size);
  386. }
  387. }
  388. void RebuildTables() {
  389. Tables.resize(0);
  390. TableSizes.resize(0);
  391. TableOffsets.resize(0);
  392. for (int i = 0; i < Count; ++i)
  393. _AppendTable(i);
  394. }
  395. inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
  396. inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : NULL; }
  397. inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
  398. inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
  399. inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; }
  400. inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; }
  401. inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
  402. inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; }
  403. inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; }
  404. inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; }
  405. inline ImU32 LerpTable(ImPlotColormap cmap, float t) const {
  406. int off = TableOffsets[cmap];
  407. int siz = TableSizes[cmap];
  408. int idx = Quals[cmap] ? ImClamp((int)(siz*t),0,siz-1) : (int)((siz - 1) * t + 0.5f);
  409. return Tables[off + idx];
  410. }
  411. };
  412. // ImPlotPoint with positive/negative error values
  413. struct ImPlotPointError {
  414. double X, Y, Neg, Pos;
  415. ImPlotPointError(double x, double y, double neg, double pos) {
  416. X = x; Y = y; Neg = neg; Pos = pos;
  417. }
  418. };
  419. // Interior plot label/annotation
  420. struct ImPlotAnnotation {
  421. ImVec2 Pos;
  422. ImVec2 Offset;
  423. ImU32 ColorBg;
  424. ImU32 ColorFg;
  425. int TextOffset;
  426. bool Clamp;
  427. };
  428. // Collection of plot labels
  429. struct ImPlotAnnotationCollection {
  430. ImVector<ImPlotAnnotation> Annotations;
  431. ImGuiTextBuffer TextBuffer;
  432. int Size;
  433. ImPlotAnnotationCollection() { Reset(); }
  434. void AppendV(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, va_list args) IM_FMTLIST(7) {
  435. ImPlotAnnotation an;
  436. an.Pos = pos; an.Offset = off;
  437. an.ColorBg = bg; an.ColorFg = fg;
  438. an.TextOffset = TextBuffer.size();
  439. an.Clamp = clamp;
  440. Annotations.push_back(an);
  441. TextBuffer.appendfv(fmt, args);
  442. const char nul[] = "";
  443. TextBuffer.append(nul,nul+1);
  444. Size++;
  445. }
  446. void Append(const ImVec2& pos, const ImVec2& off, ImU32 bg, ImU32 fg, bool clamp, const char* fmt, ...) IM_FMTARGS(7) {
  447. va_list args;
  448. va_start(args, fmt);
  449. AppendV(pos, off, bg, fg, clamp, fmt, args);
  450. va_end(args);
  451. }
  452. const char* GetText(int idx) {
  453. return TextBuffer.Buf.Data + Annotations[idx].TextOffset;
  454. }
  455. void Reset() {
  456. Annotations.shrink(0);
  457. TextBuffer.Buf.shrink(0);
  458. Size = 0;
  459. }
  460. };
  461. // Tick mark info
  462. struct ImPlotTick
  463. {
  464. double PlotPos;
  465. float PixelPos;
  466. ImVec2 LabelSize;
  467. int TextOffset;
  468. bool Major;
  469. bool ShowLabel;
  470. int Level;
  471. ImPlotTick(double value, bool major, bool show_label) {
  472. PlotPos = value;
  473. Major = major;
  474. ShowLabel = show_label;
  475. TextOffset = -1;
  476. Level = 0;
  477. }
  478. };
  479. // Collection of ticks
  480. struct ImPlotTickCollection {
  481. ImVector<ImPlotTick> Ticks;
  482. ImGuiTextBuffer TextBuffer;
  483. float TotalWidthMax;
  484. float TotalWidth;
  485. float TotalHeight;
  486. float MaxWidth;
  487. float MaxHeight;
  488. int Size;
  489. ImPlotTickCollection() { Reset(); }
  490. const ImPlotTick& Append(const ImPlotTick& tick) {
  491. if (tick.ShowLabel) {
  492. TotalWidth += tick.ShowLabel ? tick.LabelSize.x : 0;
  493. TotalHeight += tick.ShowLabel ? tick.LabelSize.y : 0;
  494. MaxWidth = tick.LabelSize.x > MaxWidth ? tick.LabelSize.x : MaxWidth;
  495. MaxHeight = tick.LabelSize.y > MaxHeight ? tick.LabelSize.y : MaxHeight;
  496. }
  497. Ticks.push_back(tick);
  498. Size++;
  499. return Ticks.back();
  500. }
  501. const ImPlotTick& Append(double value, bool major, bool show_label, const char* fmt) {
  502. ImPlotTick tick(value, major, show_label);
  503. if (show_label && fmt != NULL) {
  504. char temp[32];
  505. tick.TextOffset = TextBuffer.size();
  506. snprintf(temp, 32, fmt, tick.PlotPos);
  507. TextBuffer.append(temp, temp + strlen(temp) + 1);
  508. tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
  509. }
  510. return Append(tick);
  511. }
  512. const char* GetText(int idx) const {
  513. return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
  514. }
  515. void Reset() {
  516. Ticks.shrink(0);
  517. TextBuffer.Buf.shrink(0);
  518. TotalWidth = TotalHeight = MaxWidth = MaxHeight = 0;
  519. Size = 0;
  520. }
  521. };
  522. // Axis state information that must persist after EndPlot
  523. struct ImPlotAxis
  524. {
  525. ImPlotAxisFlags Flags;
  526. ImPlotAxisFlags PreviousFlags;
  527. ImPlotRange Range;
  528. float Pixels;
  529. ImPlotOrientation Orientation;
  530. bool Dragging;
  531. bool ExtHovered;
  532. bool AllHovered;
  533. bool Present;
  534. bool HasRange;
  535. double* LinkedMin;
  536. double* LinkedMax;
  537. ImPlotTime PickerTimeMin, PickerTimeMax;
  538. int PickerLevel;
  539. ImU32 ColorMaj, ColorMin, ColorTxt;
  540. ImGuiCond RangeCond;
  541. ImRect HoverRect;
  542. ImPlotAxis() {
  543. Flags = PreviousFlags = ImPlotAxisFlags_None;
  544. Range.Min = 0;
  545. Range.Max = 1;
  546. Dragging = false;
  547. ExtHovered = false;
  548. AllHovered = false;
  549. LinkedMin = LinkedMax = NULL;
  550. PickerLevel = 0;
  551. ColorMaj = ColorMin = ColorTxt = 0;
  552. }
  553. bool SetMin(double _min, bool force=false) {
  554. if (!force && IsLockedMin())
  555. return false;
  556. _min = ImConstrainNan(ImConstrainInf(_min));
  557. if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
  558. _min = ImConstrainLog(_min);
  559. if (ImHasFlag(Flags, ImPlotAxisFlags_Time))
  560. _min = ImConstrainTime(_min);
  561. if (_min >= Range.Max)
  562. return false;
  563. Range.Min = _min;
  564. PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
  565. return true;
  566. };
  567. bool SetMax(double _max, bool force=false) {
  568. if (!force && IsLockedMax())
  569. return false;
  570. _max = ImConstrainNan(ImConstrainInf(_max));
  571. if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
  572. _max = ImConstrainLog(_max);
  573. if (ImHasFlag(Flags, ImPlotAxisFlags_Time))
  574. _max = ImConstrainTime(_max);
  575. if (_max <= Range.Min)
  576. return false;
  577. Range.Max = _max;
  578. PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
  579. return true;
  580. };
  581. void SetRange(double _min, double _max) {
  582. Range.Min = _min;
  583. Range.Max = _max;
  584. Constrain();
  585. PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
  586. PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
  587. }
  588. void SetRange(const ImPlotRange& range) {
  589. SetRange(range.Min, range.Max);
  590. }
  591. void SetAspect(double unit_per_pix) {
  592. double new_size = unit_per_pix * Pixels;
  593. double delta = (new_size - Range.Size()) * 0.5f;
  594. if (IsLocked())
  595. return;
  596. else if (IsLockedMin() && !IsLockedMax())
  597. SetRange(Range.Min, Range.Max + 2*delta);
  598. else if (!IsLockedMin() && IsLockedMax())
  599. SetRange(Range.Min - 2*delta, Range.Max);
  600. else
  601. SetRange(Range.Min - delta, Range.Max + delta);
  602. }
  603. double GetAspect() const { return Range.Size() / Pixels; }
  604. void Constrain() {
  605. Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
  606. Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
  607. if (IsLog()) {
  608. Range.Min = ImConstrainLog(Range.Min);
  609. Range.Max = ImConstrainLog(Range.Max);
  610. }
  611. if (IsTime()) {
  612. Range.Min = ImConstrainTime(Range.Min);
  613. Range.Max = ImConstrainTime(Range.Max);
  614. }
  615. if (Range.Max <= Range.Min)
  616. Range.Max = Range.Min + DBL_EPSILON;
  617. }
  618. inline bool IsLabeled() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
  619. inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
  620. inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
  621. inline bool IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
  622. inline bool IsLockedMin() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
  623. inline bool IsLockedMax() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
  624. inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); }
  625. inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); }
  626. inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
  627. inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
  628. inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
  629. inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
  630. };
  631. // Align plots group data
  632. struct ImPlotAlignmentData {
  633. ImPlotOrientation Orientation;
  634. float PadA;
  635. float PadB;
  636. float PadAMax;
  637. float PadBMax;
  638. ImPlotAlignmentData() {
  639. Orientation = ImPlotOrientation_Vertical;
  640. PadA = PadB = PadAMax = PadBMax = 0;
  641. }
  642. void Begin() { PadAMax = PadBMax = 0; }
  643. void Update(float& pad_a, float& pad_b) {
  644. if (PadAMax < pad_a) PadAMax = pad_a;
  645. if (pad_a < PadA) pad_a = PadA;
  646. if (PadBMax < pad_b) PadBMax = pad_b;
  647. if (pad_b < PadB) pad_b = PadB;
  648. }
  649. void End() { PadA = PadAMax; PadB = PadBMax; }
  650. void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }
  651. };
  652. // State information for Plot items
  653. struct ImPlotItem
  654. {
  655. ImGuiID ID;
  656. ImU32 Color;
  657. int NameOffset;
  658. bool Show;
  659. bool LegendHovered;
  660. bool SeenThisFrame;
  661. ImPlotItem() {
  662. ID = 0;
  663. NameOffset = -1;
  664. Show = true;
  665. SeenThisFrame = false;
  666. LegendHovered = false;
  667. }
  668. ~ImPlotItem() { ID = 0; }
  669. };
  670. // Holds Legend state
  671. struct ImPlotLegendData
  672. {
  673. ImVector<int> Indices;
  674. ImGuiTextBuffer Labels;
  675. bool Hovered;
  676. bool Outside;
  677. bool CanGoInside;
  678. bool FlipSideNextFrame;
  679. ImPlotLocation Location;
  680. ImPlotOrientation Orientation;
  681. ImRect Rect;
  682. ImPlotLegendData() {
  683. CanGoInside = true;
  684. Hovered = Outside = FlipSideNextFrame = false;
  685. Location = ImPlotLocation_North | ImPlotLocation_West;
  686. Orientation = ImPlotOrientation_Vertical;
  687. }
  688. void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
  689. };
  690. // Holds Items and Legend data
  691. struct ImPlotItemGroup
  692. {
  693. ImGuiID ID;
  694. ImPlotLegendData Legend;
  695. ImPool<ImPlotItem> ItemPool;
  696. int ColormapIdx;
  697. ImPlotItemGroup() { ColormapIdx = 0; }
  698. int GetItemCount() const { return ItemPool.GetBufSize(); }
  699. ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */ }
  700. ImPlotItem* GetItem(ImGuiID id) { return ItemPool.GetByKey(id); }
  701. ImPlotItem* GetItem(const char* label_id) { return GetItem(GetItemID(label_id)); }
  702. ImPlotItem* GetOrAddItem(ImGuiID id) { return ItemPool.GetOrAddByKey(id); }
  703. ImPlotItem* GetItemByIndex(int i) { return ItemPool.GetByIndex(i); }
  704. int GetItemIndex(ImPlotItem* item) { return ItemPool.GetIndex(item); }
  705. int GetLegendCount() const { return Legend.Indices.size(); }
  706. ImPlotItem* GetLegendItem(int i) { return ItemPool.GetByIndex(Legend.Indices[i]); }
  707. const char* GetLegendLabel(int i) { return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; }
  708. void Reset() { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; }
  709. };
  710. // Holds Plot state information that must persist after EndPlot
  711. struct ImPlotPlot
  712. {
  713. ImGuiID ID;
  714. ImPlotFlags Flags;
  715. ImPlotFlags PreviousFlags;
  716. ImPlotAxis XAxis;
  717. ImPlotAxis YAxis[IMPLOT_Y_AXES];
  718. ImPlotItemGroup Items;
  719. ImVec2 SelectStart;
  720. ImRect SelectRect;
  721. ImVec2 QueryStart;
  722. ImRect QueryRect;
  723. bool Initialized;
  724. bool Selecting;
  725. bool Selected;
  726. bool ContextLocked;
  727. bool Querying;
  728. bool Queried;
  729. bool DraggingQuery;
  730. bool FrameHovered;
  731. bool FrameHeld;
  732. bool PlotHovered;
  733. int CurrentYAxis;
  734. ImPlotLocation MousePosLocation;
  735. ImRect FrameRect;
  736. ImRect CanvasRect;
  737. ImRect PlotRect;
  738. ImRect AxesRect;
  739. ImPlotPlot() {
  740. Flags = PreviousFlags = ImPlotFlags_None;
  741. XAxis.Orientation = ImPlotOrientation_Horizontal;
  742. for (int i = 0; i < IMPLOT_Y_AXES; ++i)
  743. YAxis[i].Orientation = ImPlotOrientation_Vertical;
  744. SelectStart = QueryStart = ImVec2(0,0);
  745. Initialized = Selecting = Selected = ContextLocked = Querying = Queried = DraggingQuery = false;
  746. CurrentYAxis = 0;
  747. MousePosLocation = ImPlotLocation_South | ImPlotLocation_East;
  748. }
  749. inline bool AnyYInputLocked() const { return YAxis[0].IsInputLocked() || (YAxis[1].Present ? YAxis[1].IsInputLocked() : false) || (YAxis[2].Present ? YAxis[2].IsInputLocked() : false); }
  750. inline bool AllYInputLocked() const { return YAxis[0].IsInputLocked() && (YAxis[1].Present ? YAxis[1].IsInputLocked() : true ) && (YAxis[2].Present ? YAxis[2].IsInputLocked() : true ); }
  751. inline bool IsInputLocked() const { return XAxis.IsInputLocked() && YAxis[0].IsInputLocked() && YAxis[1].IsInputLocked() && YAxis[2].IsInputLocked(); }
  752. };
  753. // Holds subplot data that must persist afer EndSubplot
  754. struct ImPlotSubplot {
  755. ImGuiID ID;
  756. ImPlotSubplotFlags Flags;
  757. ImPlotSubplotFlags PreviousFlags;
  758. ImPlotItemGroup Items;
  759. int Rows;
  760. int Cols;
  761. int CurrentIdx;
  762. ImRect FrameRect;
  763. ImRect GridRect;
  764. ImVec2 CellSize;
  765. ImVector<ImPlotAlignmentData> RowAlignmentData;
  766. ImVector<ImPlotAlignmentData> ColAlignmentData;
  767. ImVector<float> RowRatios;
  768. ImVector<float> ColRatios;
  769. ImVector<ImPlotRange> RowLinkData;
  770. ImVector<ImPlotRange> ColLinkData;
  771. float TempSizes[2];
  772. bool FrameHovered;
  773. ImPlotSubplot() {
  774. Rows = Cols = CurrentIdx = 0;
  775. FrameHovered = false;
  776. Items.Legend.Location = ImPlotLocation_North;
  777. Items.Legend.Orientation = ImPlotOrientation_Horizontal;
  778. Items.Legend.CanGoInside = false;
  779. }
  780. };
  781. // Temporary data storage for upcoming plot
  782. struct ImPlotNextPlotData
  783. {
  784. ImGuiCond XRangeCond;
  785. ImGuiCond YRangeCond[IMPLOT_Y_AXES];
  786. ImPlotRange XRange;
  787. ImPlotRange YRange[IMPLOT_Y_AXES];
  788. bool HasXRange;
  789. bool HasYRange[IMPLOT_Y_AXES];
  790. bool ShowDefaultTicksX;
  791. bool ShowDefaultTicksY[IMPLOT_Y_AXES];
  792. char FmtX[16];
  793. char FmtY[IMPLOT_Y_AXES][16];
  794. bool HasFmtX;
  795. bool HasFmtY[IMPLOT_Y_AXES];
  796. bool FitX;
  797. bool FitY[IMPLOT_Y_AXES];
  798. double* LinkedXmin;
  799. double* LinkedXmax;
  800. double* LinkedYmin[IMPLOT_Y_AXES];
  801. double* LinkedYmax[IMPLOT_Y_AXES];
  802. ImPlotNextPlotData() { Reset(); }
  803. void Reset() {
  804. HasXRange = false;
  805. ShowDefaultTicksX = true;
  806. HasFmtX = false;
  807. FitX = false;
  808. LinkedXmin = LinkedXmax = NULL;
  809. for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
  810. HasYRange[i] = false;
  811. ShowDefaultTicksY[i] = true;
  812. HasFmtY[i] = false;
  813. FitY[i] = false;
  814. LinkedYmin[i] = LinkedYmax[i] = NULL;
  815. }
  816. }
  817. };
  818. // Temporary data storage for upcoming item
  819. struct ImPlotNextItemData {
  820. ImVec4 Colors[5]; // ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar
  821. float LineWeight;
  822. ImPlotMarker Marker;
  823. float MarkerSize;
  824. float MarkerWeight;
  825. float FillAlpha;
  826. float ErrorBarSize;
  827. float ErrorBarWeight;
  828. float DigitalBitHeight;
  829. float DigitalBitGap;
  830. bool RenderLine;
  831. bool RenderFill;
  832. bool RenderMarkerLine;
  833. bool RenderMarkerFill;
  834. bool HasHidden;
  835. bool Hidden;
  836. ImGuiCond HiddenCond;
  837. ImPlotNextItemData() { Reset(); }
  838. void Reset() {
  839. for (int i = 0; i < 5; ++i)
  840. Colors[i] = IMPLOT_AUTO_COL;
  841. LineWeight = MarkerSize = MarkerWeight = FillAlpha = ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
  842. Marker = IMPLOT_AUTO;
  843. HasHidden = Hidden = false;
  844. }
  845. };
  846. // Holds state information that must persist between calls to BeginPlot()/EndPlot()
  847. struct ImPlotContext {
  848. // Plot States
  849. ImPool<ImPlotPlot> Plots;
  850. ImPool<ImPlotSubplot> Subplots;
  851. ImPlotPlot* CurrentPlot;
  852. ImPlotSubplot* CurrentSubplot;
  853. ImPlotItemGroup* CurrentItems;
  854. ImPlotItem* CurrentItem;
  855. ImPlotItem* PreviousItem;
  856. // Tick Marks and Labels
  857. ImPlotTickCollection CTicks;
  858. ImPlotTickCollection XTicks;
  859. ImPlotTickCollection YTicks[IMPLOT_Y_AXES];
  860. float YAxisReference[IMPLOT_Y_AXES];
  861. // Annotation and User Labels
  862. ImPlotAnnotationCollection Annotations;
  863. // Transformations and Data Extents
  864. ImPlotScale Scales[IMPLOT_Y_AXES];
  865. ImRect PixelRange[IMPLOT_Y_AXES];
  866. double Mx;
  867. double My[IMPLOT_Y_AXES];
  868. double LogDenX;
  869. double LogDenY[IMPLOT_Y_AXES];
  870. ImPlotRange ExtentsX;
  871. ImPlotRange ExtentsY[IMPLOT_Y_AXES];
  872. // Data Fitting Flags
  873. bool FitThisFrame;
  874. bool FitX;
  875. bool FitY[IMPLOT_Y_AXES];
  876. // Axis Rendering Flags
  877. bool RenderX;
  878. bool RenderY[IMPLOT_Y_AXES];
  879. // Axis Locking Flags
  880. bool ChildWindowMade;
  881. // Style and Colormaps
  882. ImPlotStyle Style;
  883. ImVector<ImGuiColorMod> ColorModifiers;
  884. ImVector<ImGuiStyleMod> StyleModifiers;
  885. ImPlotColormapData ColormapData;
  886. ImVector<ImPlotColormap> ColormapModifiers;
  887. // Time
  888. tm Tm;
  889. // Temp data for general use
  890. ImVector<double> Temp1, Temp2;
  891. // Misc
  892. int DigitalPlotItemCnt;
  893. int DigitalPlotOffset;
  894. ImPlotNextPlotData NextPlotData;
  895. ImPlotNextItemData NextItemData;
  896. ImPlotInputMap InputMap;
  897. ImPlotPoint MousePos[IMPLOT_Y_AXES];
  898. // Align plots
  899. ImPool<ImPlotAlignmentData> AlignmentData;
  900. ImPlotAlignmentData* CurrentAlignmentH;
  901. ImPlotAlignmentData* CurrentAlignmentV;
  902. };
  903. //-----------------------------------------------------------------------------
  904. // [SECTION] Internal API
  905. // No guarantee of forward compatibility here!
  906. //-----------------------------------------------------------------------------
  907. namespace ImPlot {
  908. //-----------------------------------------------------------------------------
  909. // [SECTION] Context Utils
  910. //-----------------------------------------------------------------------------
  911. // Initializes an ImPlotContext
  912. IMPLOT_API void Initialize(ImPlotContext* ctx);
  913. // Resets an ImPlot context for the next call to BeginPlot
  914. IMPLOT_API void ResetCtxForNextPlot(ImPlotContext* ctx);
  915. // Restes an ImPlot context for the next call to BeginAlignedPlots
  916. IMPLOT_API void ResetCtxForNextAlignedPlots(ImPlotContext* ctx);
  917. // Resets an ImPlot context for the next call to BeginSubplot
  918. IMPLOT_API void ResetCtxForNextSubplot(ImPlotContext* ctx);
  919. //-----------------------------------------------------------------------------
  920. // [SECTION] Input Utils
  921. //-----------------------------------------------------------------------------
  922. // Allows changing how keyboard/mouse interaction works.
  923. IMPLOT_API ImPlotInputMap& GetInputMap();
  924. //-----------------------------------------------------------------------------
  925. // [SECTION] Plot Utils
  926. //-----------------------------------------------------------------------------
  927. // Gets a plot from the current ImPlotContext
  928. IMPLOT_API ImPlotPlot* GetPlot(const char* title);
  929. // Gets the current plot from the current ImPlotContext
  930. IMPLOT_API ImPlotPlot* GetCurrentPlot();
  931. // Busts the cache for every plot in the current context
  932. IMPLOT_API void BustPlotCache();
  933. // Shows a plot's context menu.
  934. IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
  935. //-----------------------------------------------------------------------------
  936. // [SECTION] Subplot Utils
  937. //-----------------------------------------------------------------------------
  938. // Advances to next subplot
  939. IMPLOT_API void SubplotNextCell();
  940. // Shows a subplot's context menu.
  941. IMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot);
  942. //-----------------------------------------------------------------------------
  943. // [SECTION] Item Utils
  944. //-----------------------------------------------------------------------------
  945. // Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect.
  946. IMPLOT_API bool BeginItem(const char* label_id, ImPlotCol recolor_from = -1);
  947. // Ends an item (call only if BeginItem returns true). Pops PlotClipRect.
  948. IMPLOT_API void EndItem();
  949. // Register or get an existing item from the current plot.
  950. IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, bool* just_created = NULL);
  951. // Get a plot item from the current plot.
  952. IMPLOT_API ImPlotItem* GetItem(const char* label_id);
  953. // Gets the current item.
  954. IMPLOT_API ImPlotItem* GetCurrentItem();
  955. // Busts the cache for every item for every plot in the current context.
  956. IMPLOT_API void BustItemCache();
  957. //-----------------------------------------------------------------------------
  958. // [SECTION] Axis Utils
  959. //-----------------------------------------------------------------------------
  960. // Gets the current y-axis for the current plot
  961. static inline int GetCurrentYAxis() { return GImPlot->CurrentPlot->CurrentYAxis; }
  962. // Updates axis ticks, lins, and label colors
  963. IMPLOT_API void UpdateAxisColors(int axis_flag, ImPlotAxis* axis);
  964. // Updates plot-to-pixel space transformation variables for the current plot.
  965. IMPLOT_API void UpdateTransformCache();
  966. // Gets the XY scale for the current plot and y-axis
  967. static inline ImPlotScale GetCurrentScale() { return GImPlot->Scales[GetCurrentYAxis()]; }
  968. // Returns true if the user has requested data to be fit.
  969. static inline bool FitThisFrame() { return GImPlot->FitThisFrame; }
  970. // Extend the the extents of an axis on current plot so that it encompes v
  971. static inline void FitPointAxis(ImPlotAxis& axis, ImPlotRange& ext, double v) {
  972. if (!ImNanOrInf(v) && !(ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale) && v <= 0)) {
  973. ext.Min = v < ext.Min ? v : ext.Min;
  974. ext.Max = v > ext.Max ? v : ext.Max;
  975. }
  976. }
  977. // Extend the the extents of an axis on current plot so that it encompes v
  978. static inline void FitPointMultiAxis(ImPlotAxis& axis, ImPlotAxis& alt, ImPlotRange& ext, double v, double v_alt) {
  979. if (ImHasFlag(axis.Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
  980. return;
  981. if (!ImNanOrInf(v) && !(ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale) && v <= 0)) {
  982. ext.Min = v < ext.Min ? v : ext.Min;
  983. ext.Max = v > ext.Max ? v : ext.Max;
  984. }
  985. }
  986. // Extends the current plot's axes so that it encompasses a vertical line at x
  987. static inline void FitPointX(double x) {
  988. FitPointAxis(GImPlot->CurrentPlot->XAxis, GImPlot->ExtentsX, x);
  989. }
  990. // Extends the current plot's axes so that it encompasses a horizontal line at y
  991. static inline void FitPointY(double y) {
  992. const ImPlotYAxis y_axis = GImPlot->CurrentPlot->CurrentYAxis;
  993. FitPointAxis(GImPlot->CurrentPlot->YAxis[y_axis], GImPlot->ExtentsY[y_axis], y);
  994. }
  995. // Extends the current plot's axes so that it encompasses point p
  996. static inline void FitPoint(const ImPlotPoint& p) {
  997. const ImPlotYAxis y_axis = GImPlot->CurrentPlot->CurrentYAxis;
  998. FitPointMultiAxis(GImPlot->CurrentPlot->XAxis, GImPlot->CurrentPlot->YAxis[y_axis], GImPlot->ExtentsX, p.x, p.y);
  999. FitPointMultiAxis(GImPlot->CurrentPlot->YAxis[y_axis], GImPlot->CurrentPlot->XAxis, GImPlot->ExtentsY[y_axis], p.y, p.x);
  1000. }
  1001. // Returns true if two ranges overlap
  1002. static inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)
  1003. { return r1.Min <= r2.Max && r2.Min <= r1.Max; }
  1004. // Updates pointers for linked axes from axis internal range.
  1005. IMPLOT_API void PushLinkedAxis(ImPlotAxis& axis);
  1006. // Updates axis internal range from points for linked axes.
  1007. IMPLOT_API void PullLinkedAxis(ImPlotAxis& axis);
  1008. // Shows an axis's context menu.
  1009. IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
  1010. // Get format spec for axis
  1011. static inline const char* GetFormatX() { return GImPlot->NextPlotData.HasFmtX ? GImPlot->NextPlotData.FmtX : IMPLOT_LABEL_FMT; }
  1012. static inline const char* GetFormatY(ImPlotYAxis y) { return GImPlot->NextPlotData.HasFmtY[y] ? GImPlot->NextPlotData.FmtY[y] : IMPLOT_LABEL_FMT; }
  1013. //-----------------------------------------------------------------------------
  1014. // [SECTION] Legend Utils
  1015. //-----------------------------------------------------------------------------
  1016. // Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
  1017. IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
  1018. // Calculates the bounding box size of a legend
  1019. IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation);
  1020. // Renders legend entries into a bounding box
  1021. IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation, ImDrawList& DrawList);
  1022. // 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!).
  1023. IMPLOT_API void ShowAltLegend(const char* title_id, ImPlotOrientation orientation = ImPlotOrientation_Vertical, const ImVec2 size = ImVec2(0,0), bool interactable = true);
  1024. // Shows an legends's context menu.
  1025. IMPLOT_API bool ShowLegendContextMenu(ImPlotLegendData& legend, bool visible);
  1026. //-----------------------------------------------------------------------------
  1027. // [SECTION] Tick Utils
  1028. //-----------------------------------------------------------------------------
  1029. // Label a tick with time formatting.
  1030. IMPLOT_API void LabelTickTime(ImPlotTick& tick, ImGuiTextBuffer& buffer, const ImPlotTime& t, ImPlotDateTimeFmt fmt);
  1031. // Populates a list of ImPlotTicks with normal spaced and formatted ticks
  1032. IMPLOT_API void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt);
  1033. // Populates a list of ImPlotTicks with logarithmic space and formatted ticks
  1034. IMPLOT_API void AddTicksLogarithmic(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt);
  1035. // Populates a list of ImPlotTicks with time formatted ticks.
  1036. IMPLOT_API void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollection& ticks);
  1037. // Populates a list of ImPlotTicks with custom spaced and labeled ticks
  1038. IMPLOT_API void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks, const char* fmt);
  1039. // Create a a string label for a an axis value
  1040. IMPLOT_API int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size);
  1041. //-----------------------------------------------------------------------------
  1042. // [SECTION] Styling Utils
  1043. //-----------------------------------------------------------------------------
  1044. // Get styling data for next item (call between Begin/EndItem)
  1045. static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItemData; }
  1046. // Returns true if a color is set to be automatically determined
  1047. static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
  1048. // Returns true if a style color is set to be automaticaly determined
  1049. static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
  1050. // Returns the automatically deduced style color
  1051. IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
  1052. // Returns the style color whether it is automatic or custom set
  1053. static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
  1054. static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
  1055. // Draws vertical text. The position is the bottom left of the text rect.
  1056. IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
  1057. // Draws multiline horizontal text centered.
  1058. IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = NULL);
  1059. // Calculates the size of vertical text
  1060. static inline ImVec2 CalcTextSizeVertical(const char *text) {
  1061. ImVec2 sz = ImGui::CalcTextSize(text);
  1062. return ImVec2(sz.y, sz.x);
  1063. }
  1064. // Returns white or black text given background color
  1065. static inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.5 ? IM_COL32_BLACK : IM_COL32_WHITE; }
  1066. static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
  1067. // Lightens or darkens a color for hover
  1068. static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); }
  1069. // Clamps a label position so that it fits a rect defined by Min/Max
  1070. static inline ImVec2 ClampLabelPos(ImVec2 pos, const ImVec2& size, const ImVec2& Min, const ImVec2& Max) {
  1071. if (pos.x < Min.x) pos.x = Min.x;
  1072. if (pos.y < Min.y) pos.y = Min.y;
  1073. if ((pos.x + size.x) > Max.x) pos.x = Max.x - size.x;
  1074. if ((pos.y + size.y) > Max.y) pos.y = Max.y - size.y;
  1075. return pos;
  1076. }
  1077. // Returns a color from the Color map given an index >= 0 (modulo will be performed).
  1078. IMPLOT_API ImU32 GetColormapColorU32(int idx, ImPlotColormap cmap);
  1079. // Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.
  1080. IMPLOT_API ImU32 NextColormapColorU32();
  1081. // Linearly interpolates a color from the current colormap given t between 0 and 1.
  1082. IMPLOT_API ImU32 SampleColormapU32(float t, ImPlotColormap cmap);
  1083. // Render a colormap bar
  1084. IMPLOT_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous);
  1085. //-----------------------------------------------------------------------------
  1086. // [SECTION] Math and Misc Utils
  1087. //-----------------------------------------------------------------------------
  1088. // Rounds x to powers of 2,5 and 10 for generating axis labels (from Graphics Gems 1 Chapter 11.2)
  1089. IMPLOT_API double NiceNum(double x, bool round);
  1090. // Computes order of magnitude of double.
  1091. static inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(floor(log10(fabs(val)))); }
  1092. // Returns the precision required for a order of magnitude.
  1093. static inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }
  1094. // Returns a floating point precision to use given a value
  1095. static inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }
  1096. // Round a value to a given precision
  1097. static inline double RoundTo(double val, int prec) { double p = pow(10,(double)prec); return floor(val*p+0.5)/p; }
  1098. // Returns the intersection point of two lines A and B (assumes they are not parallel!)
  1099. static inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {
  1100. float v1 = (a1.x * a2.y - a1.y * a2.x); float v2 = (b1.x * b2.y - b1.y * b2.x);
  1101. float v3 = ((a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x));
  1102. return ImVec2((v1 * (b1.x - b2.x) - v2 * (a1.x - a2.x)) / v3, (v1 * (b1.y - b2.y) - v2 * (a1.y - a2.y)) / v3);
  1103. }
  1104. // Fills a buffer with n samples linear interpolated from vmin to vmax
  1105. template <typename T>
  1106. void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
  1107. buffer.resize(n);
  1108. T step = (vmax - vmin) / (n - 1);
  1109. for (int i = 0; i < n; ++i) {
  1110. buffer[i] = vmin + i * step;
  1111. }
  1112. }
  1113. // Offsets and strides a data buffer
  1114. template <typename T>
  1115. static inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) {
  1116. idx = ImPosMod(offset + idx, count);
  1117. return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride);
  1118. }
  1119. // Calculate histogram bin counts and widths
  1120. template <typename T>
  1121. static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
  1122. switch (meth) {
  1123. case ImPlotBin_Sqrt:
  1124. bins_out = (int)ceil(sqrt(count));
  1125. break;
  1126. case ImPlotBin_Sturges:
  1127. bins_out = (int)ceil(1.0 + log2(count));
  1128. break;
  1129. case ImPlotBin_Rice:
  1130. bins_out = (int)ceil(2 * cbrt(count));
  1131. break;
  1132. case ImPlotBin_Scott:
  1133. width_out = 3.49 * ImStdDev(values, count) / cbrt(count);
  1134. bins_out = (int)round(range.Size() / width_out);
  1135. break;
  1136. }
  1137. width_out = range.Size() / bins_out;
  1138. }
  1139. //-----------------------------------------------------------------------------
  1140. // Time Utils
  1141. //-----------------------------------------------------------------------------
  1142. // Returns true if year is leap year (366 days long)
  1143. static inline bool IsLeapYear(int year) {
  1144. return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
  1145. }
  1146. // Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed.
  1147. static inline int GetDaysInMonth(int year, int month) {
  1148. static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  1149. return days[month] + (int)(month == 1 && IsLeapYear(year));
  1150. }
  1151. // Make a UNIX timestamp from a tm struct expressed in UTC time (i.e. GMT timezone).
  1152. IMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm);
  1153. // Make a tm struct expressed in UTC time (i.e. GMT timezone) from a UNIX timestamp.
  1154. IMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
  1155. // Make a UNIX timestamp from a tm struct expressed in local time.
  1156. IMPLOT_API ImPlotTime MkLocTime(struct tm *ptm);
  1157. // Make a tm struct expressed in local time from a UNIX timestamp.
  1158. IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);
  1159. // NB: The following functions only work if there is a current ImPlotContext because the
  1160. // internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime.
  1161. // Make a timestamp from time components.
  1162. // year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999]
  1163. IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);
  1164. // Get year component from timestamp [1970-3000]
  1165. IMPLOT_API int GetYear(const ImPlotTime& t);
  1166. // Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract.
  1167. IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
  1168. // Rounds a timestamp down to nearest unit.
  1169. IMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);
  1170. // Rounds a timestamp up to the nearest unit.
  1171. IMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);
  1172. // Rounds a timestamp up or down to the nearest unit.
  1173. IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
  1174. // Combines the date of one timestamp with the time-of-day of another timestamp.
  1175. IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);
  1176. // Formats the time part of timestamp t into a buffer according to #fmt
  1177. IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt, bool use_24_hr_clk);
  1178. // Formats the date part of timestamp t into a buffer according to #fmt
  1179. IMPLOT_API int FormatDate(const ImPlotTime& t, char* buffer, int size, ImPlotDateFmt fmt, bool use_iso_8601);
  1180. // Formats the time and/or date parts of a timestamp t into a buffer according to #fmt
  1181. IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlotDateTimeFmt fmt);
  1182. // Shows a date picker widget block (year/month/day).
  1183. // #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
  1184. // #t will be set when a day is clicked and the function will return true.
  1185. // #t1 and #t2 are optional dates to highlight.
  1186. IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = NULL, const ImPlotTime* t2 = NULL);
  1187. // Shows a time picker widget block (hour/min/sec).
  1188. // #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
  1189. IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
  1190. } // namespace ImPlot