The open source OpenXR runtime
at main 1669 lines 68 kB view raw
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; 86struct ImPlotNextPlotData; 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 278struct ImPlotDateTimeSpec { 279 ImPlotDateTimeSpec() {} 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. 293struct ImPlotTime { 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 319struct ImPlotColormapData { 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 421struct ImPlotPointError { 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 429struct ImPlotAnnotation { 430 ImVec2 Pos; 431 ImVec2 Offset; 432 ImU32 ColorBg; 433 ImU32 ColorFg; 434 int TextOffset; 435 bool Clamp; 436 ImPlotAnnotation() { 437 ColorBg = ColorFg = 0; 438 TextOffset = 0; 439 Clamp = false; 440 } 441}; 442 443// Collection of plot labels 444struct ImPlotAnnotationCollection { 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) { 453 ImPlotAnnotation an; 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 491struct ImPlotTagCollection { 492 493 ImVector<ImPlotTag> Tags; 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 532struct ImPlotTick 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 554struct ImPlotTicker { 555 ImVector<ImPlotTick> 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 624struct ImPlotAxis 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 917struct ImPlotAlignmentData { 918 bool Vertical; 919 float PadA; 920 float PadB; 921 float PadAMax; 922 float PadBMax; 923 ImPlotAlignmentData() { 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 940struct ImPlotItem 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 963struct ImPlotLegend 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 990struct ImPlotItemGroup 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 1013struct ImPlotPlot 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 1118struct ImPlotSubplot { 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 1153struct ImPlotNextPlotData 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 1175struct ImPlotNextItemData { 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() 1204struct ImPlotContext { 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; 1219 ImPlotTagCollection Tags; 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 1648struct Formatter_Time_Data { 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) { 1656 Formatter_Time_Data* ftd = (Formatter_Time_Data*)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