aboutsummaryrefslogtreecommitdiff
path: root/3rdparty/implot/implot_internal.h
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/implot/implot_internal.h')
-rw-r--r--3rdparty/implot/implot_internal.h879
1 files changed, 578 insertions, 301 deletions
diff --git a/3rdparty/implot/implot_internal.h b/3rdparty/implot/implot_internal.h
index 3c0d1d5..7895afe 100644
--- a/3rdparty/implot/implot_internal.h
+++ b/3rdparty/implot/implot_internal.h
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-// ImPlot v0.10 WIP
+// ImPlot v0.13 WIP
// You may use this file to debug, understand or extend ImPlot features but we
// don't provide any guarantee of forward compatibility!
@@ -42,6 +42,12 @@
#error Must include implot.h before implot_internal.h
#endif
+
+// Support for pre-1.84 versions. ImPool's GetSize() -> GetBufSize()
+#if (IMGUI_VERSION_NUM < 18303)
+#define GetBufSize GetSize
+#endif
+
//-----------------------------------------------------------------------------
// [SECTION] Constants
//-----------------------------------------------------------------------------
@@ -49,21 +55,24 @@
// Constants can be changed unless stated otherwise. We may move some of these
// to ImPlotStyleVar_ over time.
-// The maximum number of supported y-axes (DO NOT CHANGE THIS)
-#define IMPLOT_Y_AXES 3
-// Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
-#define IMPLOT_ZOOM_RATE 0.1f
// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
#define IMPLOT_MIN_TIME 0
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
#define IMPLOT_MAX_TIME 32503680000
// Default label format for axis labels
-#define IMPLOT_LABEL_FMT "%g"
+#define IMPLOT_LABEL_FORMAT "%g"
+// Max character size for tick labels
+#define IMPLOT_LABEL_MAX_SIZE 32
+// Plot values less than or equal to 0 will be replaced with this on log scale axes
+#define IMPLOT_LOG_ZERO DBL_MIN
//-----------------------------------------------------------------------------
// [SECTION] Macros
//-----------------------------------------------------------------------------
+#define IMPLOT_NUM_X_AXES ImAxis_Y1
+#define IMPLOT_NUM_Y_AXES (ImAxis_COUNT - IMPLOT_NUM_X_AXES)
+
// Split ImU32 color into RGB components [0 255]
#define IM_COL32_SPLIT_RGB(col,r,g,b) \
ImU32 r = ((col >> IM_COL32_R_SHIFT) & 0xFF); \
@@ -78,7 +87,7 @@ struct ImPlotTick;
struct ImPlotAxis;
struct ImPlotAxisColor;
struct ImPlotItem;
-struct ImPlotLegendData;
+struct ImPlotLegend;
struct ImPlotPlot;
struct ImPlotNextPlotData;
@@ -86,7 +95,9 @@ struct ImPlotNextPlotData;
// [SECTION] Context Pointer
//-----------------------------------------------------------------------------
+#ifndef GImPlot
extern IMPLOT_API ImPlotContext* GImPlot; // Current implicit context pointer
+#endif
//-----------------------------------------------------------------------------
// [SECTION] Generic Helpers
@@ -110,11 +121,11 @@ static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }
// Returns always positive modulo (assumes r != 0)
static inline int ImPosMod(int l, int r) { return (l % r + r) % r; }
// Returns true if val is NAN or INFINITY
-static inline bool ImNanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); }
+static inline bool ImNanOrInf(double val) { return !(val >= -DBL_MAX && val <= DBL_MAX) || isnan(val); }
// Turns NANs to 0s
static inline double ImConstrainNan(double val) { return isnan(val) ? 0 : val; }
// Turns infinity to floating point maximums
-static inline double ImConstrainInf(double val) { return val == HUGE_VAL ? DBL_MAX : val == -HUGE_VAL ? - DBL_MAX : val; }
+static inline double ImConstrainInf(double val) { return val >= DBL_MAX ? DBL_MAX : val <= -DBL_MAX ? - DBL_MAX : val; }
// Turns numbers less than or equal to 0 to 0.001 (sort of arbitrary, is there a better way?)
static inline double ImConstrainLog(double val) { return val <= 0 ? 0.001f : val; }
// Turns numbers less than 0 to zero
@@ -137,6 +148,14 @@ static inline void ImMinMaxArray(const T* values, int count, T* min_out, T* max_
}
*min_out = Min; *max_out = Max;
}
+// Finds the sim of an array
+template <typename T>
+static inline T ImSum(const T* values, int count) {
+ T sum = 0;
+ for (int i = 0; i < count; ++i)
+ sum += values[i];
+ return sum;
+}
// Finds the mean of an array
template <typename T>
static inline double ImMean(const T* values, int count) {
@@ -196,42 +215,6 @@ static inline ImU32 ImAlphaU32(ImU32 col, float alpha) {
return col & ~((ImU32)((1.0f-alpha)*255)<<IM_COL32_A_SHIFT);
}
-// Character buffer writer helper (FIXME: Can't we replace this with ImGuiTextBuffer?)
-struct ImBufferWriter
-{
- char* Buffer;
- int Size;
- int Pos;
-
- ImBufferWriter(char* buffer, int size) {
- Buffer = buffer;
- Size = size;
- Pos = 0;
- }
-
- void Write(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- WriteV(fmt, args);
- va_end(args);
- }
-
- void WriteV(const char* fmt, va_list args) {
- const int written = ::vsnprintf(&Buffer[Pos], Size - Pos - 1, fmt, args);
- if (written > 0)
- Pos += ImMin(written, Size-Pos-1);
- }
-};
-
-// Fixed size point array
-template <int N>
-struct ImPlotPointArray {
- inline ImPlotPoint& operator[](int i) { return Data[i]; }
- inline const ImPlotPoint& operator[](int i) const { return Data[i]; }
- inline int Size() { return N; }
- ImPlotPoint Data[N];
-};
-
//-----------------------------------------------------------------------------
// [SECTION] ImPlot Enums
//-----------------------------------------------------------------------------
@@ -282,23 +265,6 @@ enum ImPlotTimeFmt_ { // default [ 24 Hour Clock ]
ImPlotTimeFmt_Hr // 7pm [ 19:00 ]
};
-// Input mapping structure, default values listed in the comments.
-struct ImPlotInputMap {
- ImGuiMouseButton PanButton; // LMB enables panning when held
- ImGuiKeyModFlags PanMod; // none optional modifier that must be held for panning
- ImGuiMouseButton FitButton; // LMB fits visible data when double clicked
- ImGuiMouseButton ContextMenuButton; // RMB opens plot context menu (if enabled) when clicked
- ImGuiMouseButton BoxSelectButton; // RMB begins box selection when pressed and confirms selection when released
- ImGuiKeyModFlags BoxSelectMod; // none optional modifier that must be held for box selection
- ImGuiMouseButton BoxSelectCancelButton; // LMB cancels active box selection when pressed
- ImGuiMouseButton QueryButton; // MMB begins query selection when pressed and end query selection when released
- ImGuiKeyModFlags QueryMod; // none optional modifier that must be held for query selection
- ImGuiKeyModFlags QueryToggleMod; // Ctrl when held, active box selections turn into queries
- ImGuiKeyModFlags HorizontalMod; // Alt expands active box selection/query horizontally to plot edge when held
- ImGuiKeyModFlags VerticalMod; // Shift expands active box selection/query vertically to plot edge when held
- IMPLOT_API ImPlotInputMap();
-};
-
//-----------------------------------------------------------------------------
// [SECTION] ImPlot Structs
//-----------------------------------------------------------------------------
@@ -504,6 +470,54 @@ struct ImPlotAnnotationCollection {
}
};
+struct ImPlotTag {
+ ImAxis Axis;
+ double Value;
+ ImU32 ColorBg;
+ ImU32 ColorFg;
+ int TextOffset;
+};
+
+struct ImPlotTagCollection {
+
+ ImVector<ImPlotTag> Tags;
+ ImGuiTextBuffer TextBuffer;
+ int Size;
+
+ ImPlotTagCollection() { Reset(); }
+
+ void AppendV(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, va_list args) IM_FMTLIST(6) {
+ ImPlotTag tag;
+ tag.Axis = axis;
+ tag.Value = value;
+ tag.ColorBg = bg;
+ tag.ColorFg = fg;
+ tag.TextOffset = TextBuffer.size();
+ Tags.push_back(tag);
+ TextBuffer.appendfv(fmt, args);
+ const char nul[] = "";
+ TextBuffer.append(nul,nul+1);
+ Size++;
+ }
+
+ void Append(ImAxis axis, double value, ImU32 bg, ImU32 fg, const char* fmt, ...) IM_FMTARGS(6) {
+ va_list args;
+ va_start(args, fmt);
+ AppendV(axis, value, bg, fg, fmt, args);
+ va_end(args);
+ }
+
+ const char* GetText(int idx) {
+ return TextBuffer.Buf.Data + Tags[idx].TextOffset;
+ }
+
+ void Reset() {
+ Tags.shrink(0);
+ TextBuffer.Buf.shrink(0);
+ Size = 0;
+ }
+};
+
// Tick mark info
struct ImPlotTick
{
@@ -528,34 +542,29 @@ struct ImPlotTick
struct ImPlotTickCollection {
ImVector<ImPlotTick> Ticks;
ImGuiTextBuffer TextBuffer;
- float TotalWidthMax;
- float TotalWidth;
- float TotalHeight;
- float MaxWidth;
- float MaxHeight;
+ ImVec2 MaxSize;
+ ImVec2 LateSize;
int Size;
ImPlotTickCollection() { Reset(); }
const ImPlotTick& Append(const ImPlotTick& tick) {
if (tick.ShowLabel) {
- TotalWidth += tick.ShowLabel ? tick.LabelSize.x : 0;
- TotalHeight += tick.ShowLabel ? tick.LabelSize.y : 0;
- MaxWidth = tick.LabelSize.x > MaxWidth ? tick.LabelSize.x : MaxWidth;
- MaxHeight = tick.LabelSize.y > MaxHeight ? tick.LabelSize.y : MaxHeight;
+ MaxSize.x = tick.LabelSize.x > MaxSize.x ? tick.LabelSize.x : MaxSize.x;
+ MaxSize.y = tick.LabelSize.y > MaxSize.y ? tick.LabelSize.y : MaxSize.y;
}
Ticks.push_back(tick);
Size++;
return Ticks.back();
}
- const ImPlotTick& Append(double value, bool major, bool show_label, const char* fmt) {
+ const ImPlotTick& Append(double value, bool major, bool show_label, ImPlotFormatter formatter, void* data) {
ImPlotTick tick(value, major, show_label);
- if (show_label && fmt != NULL) {
- char temp[32];
+ if (show_label && formatter != NULL) {
+ char buff[IMPLOT_LABEL_MAX_SIZE];
tick.TextOffset = TextBuffer.size();
- snprintf(temp, 32, fmt, tick.PlotPos);
- TextBuffer.append(temp, temp + strlen(temp) + 1);
+ formatter(tick.PlotPos, buff, sizeof(buff), data);
+ TextBuffer.append(buff, buff + strlen(buff) + 1);
tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
}
return Append(tick);
@@ -565,10 +574,21 @@ struct ImPlotTickCollection {
return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
}
+ void OverrideSize(const ImVec2& size) {
+ MaxSize.x = size.x > MaxSize.x ? size.x : MaxSize.x;
+ MaxSize.y = size.y > MaxSize.y ? size.y : MaxSize.y;
+ }
+
+ void OverrideSizeLate(const ImVec2& size) {
+ LateSize.x = size.x > LateSize.x ? size.x : LateSize.x;
+ LateSize.y = size.y > LateSize.y ? size.y : LateSize.y;
+ }
+
void Reset() {
Ticks.shrink(0);
TextBuffer.Buf.shrink(0);
- TotalWidth = TotalHeight = MaxWidth = MaxHeight = 0;
+ MaxSize = LateSize;
+ LateSize = ImVec2(0,0);
Size = 0;
}
};
@@ -576,37 +596,71 @@ struct ImPlotTickCollection {
// Axis state information that must persist after EndPlot
struct ImPlotAxis
{
- ImPlotAxisFlags Flags;
- ImPlotAxisFlags PreviousFlags;
- ImPlotRange Range;
- float Pixels;
- ImPlotOrientation Orientation;
- bool Dragging;
- bool ExtHovered;
- bool AllHovered;
- bool Present;
- bool HasRange;
- double* LinkedMin;
- double* LinkedMax;
- ImPlotTime PickerTimeMin, PickerTimeMax;
- int PickerLevel;
- ImU32 ColorMaj, ColorMin, ColorTxt;
- ImGuiCond RangeCond;
- ImRect HoverRect;
+ ImGuiID ID;
+ ImPlotAxisFlags Flags;
+ ImPlotAxisFlags PreviousFlags;
+ ImPlotCond RangeCond;
+ ImPlotTickCollection Ticks;
+ ImPlotRange Range;
+ ImPlotRange FitExtents;
+ ImPlotAxis* OrthoAxis;
+ double* LinkedMin;
+ double* LinkedMax;
+ int PickerLevel;
+ ImPlotTime PickerTimeMin, PickerTimeMax;
+ float Datum1, Datum2;
+ float PixelMin, PixelMax;
+ double LinM, LogD;
+ ImRect HoverRect;
+ int LabelOffset;
+ ImU32 ColorMaj, ColorMin, ColorTick, ColorTxt, ColorBg, ColorHov, ColorAct, ColorHiLi;
+ char FormatSpec[16];
+ ImPlotFormatter Formatter;
+ void* FormatterData;
+ bool Enabled;
+ bool Vertical;
+ bool FitThisFrame;
+ bool HasRange;
+ bool HasFormatSpec;
+ bool ShowDefaultTicks;
+ bool Hovered;
+ bool Held;
ImPlotAxis() {
- Flags = PreviousFlags = ImPlotAxisFlags_None;
- Range.Min = 0;
- Range.Max = 1;
- Dragging = false;
- ExtHovered = false;
- AllHovered = false;
- LinkedMin = LinkedMax = NULL;
- PickerLevel = 0;
- ColorMaj = ColorMin = ColorTxt = 0;
+ Flags = PreviousFlags = ImPlotAxisFlags_None;
+ Range.Min = 0;
+ Range.Max = 1;
+ FitExtents.Min = HUGE_VAL;
+ FitExtents.Max = -HUGE_VAL;
+ OrthoAxis = NULL;
+ LinkedMin = LinkedMax = NULL;
+ PickerLevel = 0;
+ Datum1 = Datum2 = 0;
+ PixelMin = PixelMax = 0;
+ LabelOffset = -1;
+ ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
+ ColorHiLi = IM_COL32_BLACK_TRANS;
+ Formatter = NULL;
+ FormatterData = NULL;
+ Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;
+ ShowDefaultTicks = true;
}
- bool SetMin(double _min, bool force=false) {
+ inline void Reset() {
+ Enabled = false;
+ LabelOffset = -1;
+ HasFormatSpec = false;
+ Formatter = NULL;
+ FormatterData = NULL;
+ ShowDefaultTicks = true;
+ FitThisFrame = false;
+ FitExtents.Min = HUGE_VAL;
+ FitExtents.Max = -HUGE_VAL;
+ OrthoAxis = NULL;
+ Ticks.Reset();
+ }
+
+ inline bool SetMin(double _min, bool force=false) {
if (!force && IsLockedMin())
return false;
_min = ImConstrainNan(ImConstrainInf(_min));
@@ -618,10 +672,11 @@ struct ImPlotAxis
return false;
Range.Min = _min;
PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
+ UpdateTransformCache();
return true;
};
- bool SetMax(double _max, bool force=false) {
+ inline bool SetMax(double _max, bool force=false) {
if (!force && IsLockedMax())
return false;
_max = ImConstrainNan(ImConstrainInf(_max));
@@ -633,23 +688,25 @@ struct ImPlotAxis
return false;
Range.Max = _max;
PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
+ UpdateTransformCache();
return true;
};
- void SetRange(double _min, double _max) {
- Range.Min = _min;
- Range.Max = _max;
+ inline void SetRange(double v1, double v2) {
+ Range.Min = ImMin(v1,v2);
+ Range.Max = ImMax(v1,v2);
Constrain();
PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
+ UpdateTransformCache();
}
- void SetRange(const ImPlotRange& range) {
+ inline void SetRange(const ImPlotRange& range) {
SetRange(range.Min, range.Max);
}
- void SetAspect(double unit_per_pix) {
- double new_size = unit_per_pix * Pixels;
+ inline void SetAspect(double unit_per_pix) {
+ double new_size = unit_per_pix * PixelSize();
double delta = (new_size - Range.Size()) * 0.5f;
if (IsLocked())
return;
@@ -661,16 +718,18 @@ struct ImPlotAxis
SetRange(Range.Min - delta, Range.Max + delta);
}
- double GetAspect() const { return Range.Size() / Pixels; }
+ inline float PixelSize() const { return ImAbs(PixelMax - PixelMin); }
+
+ inline double GetAspect() const { return Range.Size() / PixelSize(); }
- void Constrain() {
+ inline void Constrain() {
Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
- if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale)) {
+ if (IsLog()) {
Range.Min = ImConstrainLog(Range.Min);
Range.Max = ImConstrainLog(Range.Max);
}
- if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
+ if (IsTime()) {
Range.Min = ImConstrainTime(Range.Min);
Range.Max = ImConstrainTime(Range.Max);
}
@@ -678,22 +737,114 @@ struct ImPlotAxis
Range.Max = Range.Min + DBL_EPSILON;
}
- inline bool IsLabeled() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
- inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
+ inline void UpdateTransformCache() {
+ LinM = (PixelMax - PixelMin) / Range.Size();
+ LogD = IsLog() ? ImLog10(Range.Max / Range.Min) : 0;
+ }
+
+ inline double PixelsToPlot(float pix) const {
+ double plt = (pix - PixelMin) / LinM + Range.Min;
+ if (IsLog()) {
+ double t = (plt - Range.Min) / Range.Size();
+ plt = ImPow(10, t * LogD) * Range.Min;
+ }
+ return plt;
+ }
+
+ inline float PlotToPixels(double plt) const {
+ if (IsLog()) {
+ plt = plt <= 0.0 ? IMPLOT_LOG_ZERO : plt;
+ double t = ImLog10(plt / Range.Min) / LogD;
+ plt = ImLerp(Range.Min, Range.Max, (float)t);
+ }
+ return (float)(PixelMin + LinM * (plt - Range.Min));
+ }
+
+ inline void ExtendFit(double v) {
+ if (!ImNanOrInf(v) && !(IsLog() && v <= 0)) {
+ FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
+ FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
+ }
+ }
- inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
- inline bool IsRangeLocked() const { return HasRange && RangeCond == ImGuiCond_Always; }
+ inline void ExtendFitWith(ImPlotAxis& alt, double v, double v_alt) {
+ if (ImHasFlag(Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
+ return;
+ if (!ImNanOrInf(v) && !(IsLog() && v <= 0)) {
+ FitExtents.Min = v < FitExtents.Min ? v : FitExtents.Min;
+ FitExtents.Max = v > FitExtents.Max ? v : FitExtents.Max;
+ }
+ }
+
+ inline void ApplyFit(float padding) {
+ const double ext_size = FitExtents.Size() * 0.5;
+ FitExtents.Min -= ext_size * padding;
+ FitExtents.Max += ext_size * padding;
+ if (!IsLockedMin() && !ImNanOrInf(FitExtents.Min))
+ Range.Min = FitExtents.Min;
+ if (!IsLockedMax() && !ImNanOrInf(FitExtents.Max))
+ Range.Max = FitExtents.Max;
+ if (ImAlmostEqual(Range.Min, Range.Max)) {
+ Range.Max += 0.5;
+ Range.Min -= 0.5;
+ }
+ Constrain();
+ UpdateTransformCache();
+ }
- inline bool IsLockedMin() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
- inline bool IsLockedMax() const { return !Present || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
- inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); }
+ inline bool HasLabel() const { return LabelOffset != -1 && !ImHasFlag(Flags, ImPlotAxisFlags_NoLabel); }
+ inline bool HasGridLines() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoGridLines); }
+ inline bool HasTickLabels() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickLabels); }
+ inline bool HasTickMarks() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoTickMarks); }
+ inline bool WillRender() const { return HasGridLines() || HasTickLabels() || HasTickMarks(); }
+ inline bool IsOpposite() const { return ImHasFlag(Flags, ImPlotAxisFlags_Opposite); }
+ inline bool IsInverted() const { return ImHasFlag(Flags, ImPlotAxisFlags_Invert); }
+ inline bool IsForeground() const { return ImHasFlag(Flags, ImPlotAxisFlags_Foreground); }
+ inline bool IsAutoFitting() const { return ImHasFlag(Flags, ImPlotAxisFlags_AutoFit); }
+ inline bool CanInitFit() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoInitialFit) && !HasRange && !LinkedMin && !LinkedMax; }
+ inline bool IsRangeLocked() const { return HasRange && RangeCond == ImPlotCond_Always; }
+ inline bool IsLockedMin() const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMin); }
+ inline bool IsLockedMax() const { return !Enabled || IsRangeLocked() || ImHasFlag(Flags, ImPlotAxisFlags_LockMax); }
+ inline bool IsLocked() const { return IsLockedMin() && IsLockedMax(); }
+ inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); }
+ inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
+ inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
+ inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
+ inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
+ inline bool HasMenus() const { return !ImHasFlag(Flags, ImPlotAxisFlags_NoMenus); }
- inline bool IsInputLockedMin() const { return IsLockedMin() || IsAutoFitting(); }
- inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
- inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
+ void PushLinks() {
+ if (LinkedMin) { *LinkedMin = Range.Min; }
+ if (LinkedMax) { *LinkedMax = Range.Max; }
+ }
- inline bool IsTime() const { return ImHasFlag(Flags, ImPlotAxisFlags_Time); }
- inline bool IsLog() const { return ImHasFlag(Flags, ImPlotAxisFlags_LogScale); }
+ void PullLinks() {
+ if (LinkedMin) { SetMin(*LinkedMin,true); }
+ if (LinkedMax) { SetMax(*LinkedMax,true); }
+ }
+};
+
+// Align plots group data
+struct ImPlotAlignmentData {
+ bool Vertical;
+ float PadA;
+ float PadB;
+ float PadAMax;
+ float PadBMax;
+ ImPlotAlignmentData() {
+ Vertical = true;
+ PadA = PadB = PadAMax = PadBMax = 0;
+ }
+ void Begin() { PadAMax = PadBMax = 0; }
+ void Update(float& pad_a, float& pad_b, float& delta_a, float& delta_b) {
+ float bak_a = pad_a; float bak_b = pad_b;
+ if (PadAMax < pad_a) { PadAMax = pad_a; }
+ if (PadBMax < pad_b) { PadBMax = pad_b; }
+ if (pad_a < PadA) { pad_a = PadA; delta_a = pad_a - bak_a; } else { delta_a = 0; }
+ if (pad_b < PadB) { pad_b = PadB; delta_b = pad_b - bak_b; } else { delta_b = 0; }
+ }
+ void End() { PadA = PadAMax; PadB = PadBMax; }
+ void Reset() { PadA = PadB = PadAMax = PadBMax = 0; }
};
// State information for Plot items
@@ -701,6 +852,7 @@ struct ImPlotItem
{
ImGuiID ID;
ImU32 Color;
+ ImRect LegendHoverRect;
int NameOffset;
bool Show;
bool LegendHovered;
@@ -717,109 +869,207 @@ struct ImPlotItem
~ImPlotItem() { ID = 0; }
};
-// Holds Legend state labels and item references
-struct ImPlotLegendData
+// Holds Legend state
+struct ImPlotLegend
{
- ImVector<int> Indices;
- ImGuiTextBuffer Labels;
+ ImPlotLegendFlags Flags;
+ ImPlotLegendFlags PreviousFlags;
+ ImPlotLocation Location;
+ ImPlotLocation PreviousLocation;
+ ImVector<int> Indices;
+ ImGuiTextBuffer Labels;
+ ImRect Rect;
+ bool Hovered;
+ bool Held;
+ bool CanGoInside;
+
+ ImPlotLegend() {
+ Flags = PreviousFlags = ImPlotLegendFlags_None;
+ CanGoInside = true;
+ Hovered = Held = false;
+ Location = ImPlotLocation_NorthWest;
+ }
+
void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
};
-// Holds Plot state information that must persist after EndPlot
-struct ImPlotPlot
+// Holds Items and Legend data
+struct ImPlotItemGroup
{
ImGuiID ID;
- ImPlotFlags Flags;
- ImPlotFlags PreviousFlags;
- ImPlotAxis XAxis;
- ImPlotAxis YAxis[IMPLOT_Y_AXES];
- ImPlotLegendData LegendData;
- ImPool<ImPlotItem> Items;
- ImVec2 SelectStart;
- ImRect SelectRect;
- ImVec2 QueryStart;
- ImRect QueryRect;
- bool Initialized;
- bool Selecting;
- bool Selected;
- bool ContextLocked;
- bool Querying;
- bool Queried;
- bool DraggingQuery;
- bool LegendHovered;
- bool LegendOutside;
- bool LegendFlipSideNextFrame;
- bool FrameHovered;
- bool PlotHovered;
+ ImPlotLegend Legend;
+ ImPool<ImPlotItem> ItemPool;
int ColormapIdx;
- int CurrentYAxis;
- ImPlotLocation MousePosLocation;
- ImPlotLocation LegendLocation;
- ImPlotOrientation LegendOrientation;
- ImRect FrameRect;
- ImRect CanvasRect;
- ImRect PlotRect;
- ImRect AxesRect;
- ImRect LegendRect;
+
+ ImPlotItemGroup() { ColormapIdx = 0; }
+
+ int GetItemCount() const { return ItemPool.GetBufSize(); }
+ ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */ }
+ ImPlotItem* GetItem(ImGuiID id) { return ItemPool.GetByKey(id); }
+ ImPlotItem* GetItem(const char* label_id) { return GetItem(GetItemID(label_id)); }
+ ImPlotItem* GetOrAddItem(ImGuiID id) { return ItemPool.GetOrAddByKey(id); }
+ ImPlotItem* GetItemByIndex(int i) { return ItemPool.GetByIndex(i); }
+ int GetItemIndex(ImPlotItem* item) { return ItemPool.GetIndex(item); }
+ int GetLegendCount() const { return Legend.Indices.size(); }
+ ImPlotItem* GetLegendItem(int i) { return ItemPool.GetByIndex(Legend.Indices[i]); }
+ const char* GetLegendLabel(int i) { return Legend.Labels.Buf.Data + GetLegendItem(i)->NameOffset; }
+ void Reset() { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; }
+};
+
+// Holds Plot state information that must persist after EndPlot
+struct ImPlotPlot
+{
+ ImGuiID ID;
+ ImPlotFlags Flags;
+ ImPlotFlags PreviousFlags;
+ ImPlotLocation MouseTextLocation;
+ ImPlotMouseTextFlags MouseTextFlags;
+ ImPlotAxis Axes[ImAxis_COUNT];
+ ImGuiTextBuffer TextBuffer;
+ ImPlotItemGroup Items;
+ ImAxis CurrentX;
+ ImAxis CurrentY;
+ ImRect FrameRect;
+ ImRect CanvasRect;
+ ImRect PlotRect;
+ ImRect AxesRect;
+ ImRect SelectRect;
+ ImVec2 SelectStart;
+ int TitleOffset;
+ bool JustCreated;
+ bool Initialized;
+ bool SetupLocked;
+ bool FitThisFrame;
+ bool Hovered;
+ bool Held;
+ bool Selecting;
+ bool Selected;
+ bool ContextLocked;
ImPlotPlot() {
Flags = PreviousFlags = ImPlotFlags_None;
- XAxis.Orientation = ImPlotOrientation_Horizontal;
- for (int i = 0; i < IMPLOT_Y_AXES; ++i)
- YAxis[i].Orientation = ImPlotOrientation_Vertical;
- SelectStart = QueryStart = ImVec2(0,0);
- Initialized = Selecting = Selected = ContextLocked = Querying = Queried = DraggingQuery = LegendHovered = LegendOutside = LegendFlipSideNextFrame = false;
- ColormapIdx = CurrentYAxis = 0;
- LegendLocation = ImPlotLocation_North | ImPlotLocation_West;
- LegendOrientation = ImPlotOrientation_Vertical;
- MousePosLocation = ImPlotLocation_South | ImPlotLocation_East;
+ for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
+ XAxis(i).Vertical = false;
+ for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
+ YAxis(i).Vertical = true;
+ SelectStart = ImVec2(0,0);
+ CurrentX = ImAxis_X1;
+ CurrentY = ImAxis_Y1;
+ MouseTextLocation = ImPlotLocation_South | ImPlotLocation_East;
+ MouseTextFlags = ImPlotMouseTextFlags_None;
+ TitleOffset = -1;
+ JustCreated = true;
+ Initialized = SetupLocked = FitThisFrame = false;
+ Hovered = Held = Selected = Selecting = ContextLocked = false;
+ }
+
+ inline bool IsInputLocked() const {
+ for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i) {
+ if (!XAxis(i).IsInputLocked())
+ return false;
+ }
+ for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i) {
+ if (!YAxis(i).IsInputLocked())
+ return false;
+ }
+ return true;
+ }
+
+ inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
+
+ inline void SetTitle(const char* title) {
+ if (title && ImGui::FindRenderedTextEnd(title, NULL) != title) {
+ TitleOffset = TextBuffer.size();
+ TextBuffer.append(title, title + strlen(title) + 1);
+ }
+ else {
+ TitleOffset = -1;
+ }
+ }
+ inline bool HasTitle() const { return TitleOffset != -1 && !ImHasFlag(Flags, ImPlotFlags_NoTitle); }
+ inline const char* GetTitle() const { return TextBuffer.Buf.Data + TitleOffset; }
+
+ inline ImPlotAxis& XAxis(int i) { return Axes[ImAxis_X1 + i]; }
+ inline const ImPlotAxis& XAxis(int i) const { return Axes[ImAxis_X1 + i]; }
+ inline ImPlotAxis& YAxis(int i) { return Axes[ImAxis_Y1 + i]; }
+ inline const ImPlotAxis& YAxis(int i) const { return Axes[ImAxis_Y1 + i]; }
+
+ inline int EnabledAxesX() {
+ int cnt = 0;
+ for (int i = 0; i < IMPLOT_NUM_X_AXES; ++i)
+ cnt += XAxis(i).Enabled;
+ return cnt;
}
- int GetLegendCount() const { return LegendData.Indices.size(); }
- ImPlotItem* GetLegendItem(int i);
- const char* GetLegendLabel(int i);
+ inline int EnabledAxesY() {
+ int cnt = 0;
+ for (int i = 0; i < IMPLOT_NUM_Y_AXES; ++i)
+ cnt += YAxis(i).Enabled;
+ return cnt;
+ }
+
+ inline void SetAxisLabel(ImPlotAxis& axis, const char* label) {
+ if (label && ImGui::FindRenderedTextEnd(label, NULL) != label) {
+ axis.LabelOffset = TextBuffer.size();
+ TextBuffer.append(label, label + strlen(label) + 1);
+ }
+ else {
+ axis.LabelOffset = -1;
+ }
+ }
+
+ inline const char* GetAxisLabel(const ImPlotAxis& axis) const { return TextBuffer.Buf.Data + axis.LabelOffset; }
+};
- inline bool AnyYInputLocked() const { return YAxis[0].IsInputLocked() || (YAxis[1].Present ? YAxis[1].IsInputLocked() : false) || (YAxis[2].Present ? YAxis[2].IsInputLocked() : false); }
- inline bool AllYInputLocked() const { return YAxis[0].IsInputLocked() && (YAxis[1].Present ? YAxis[1].IsInputLocked() : true ) && (YAxis[2].Present ? YAxis[2].IsInputLocked() : true ); }
- inline bool IsInputLocked() const { return XAxis.IsInputLocked() && YAxis[0].IsInputLocked() && YAxis[1].IsInputLocked() && YAxis[2].IsInputLocked(); }
+// Holds subplot data that must persist afer EndSubplot
+struct ImPlotSubplot {
+ ImGuiID ID;
+ ImPlotSubplotFlags Flags;
+ ImPlotSubplotFlags PreviousFlags;
+ ImPlotItemGroup Items;
+ int Rows;
+ int Cols;
+ int CurrentIdx;
+ ImRect FrameRect;
+ ImRect GridRect;
+ ImVec2 CellSize;
+ ImVector<ImPlotAlignmentData> RowAlignmentData;
+ ImVector<ImPlotAlignmentData> ColAlignmentData;
+ ImVector<float> RowRatios;
+ ImVector<float> ColRatios;
+ ImVector<ImPlotRange> RowLinkData;
+ ImVector<ImPlotRange> ColLinkData;
+ float TempSizes[2];
+ bool FrameHovered;
+ bool HasTitle;
+
+ ImPlotSubplot() {
+ Rows = Cols = CurrentIdx = 0;
+ FrameHovered = false;
+ Items.Legend.Location = ImPlotLocation_North;
+ Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
+ Items.Legend.CanGoInside = false;
+ HasTitle = false;
+ }
};
// Temporary data storage for upcoming plot
struct ImPlotNextPlotData
{
- ImGuiCond XRangeCond;
- ImGuiCond YRangeCond[IMPLOT_Y_AXES];
- ImPlotRange XRange;
- ImPlotRange YRange[IMPLOT_Y_AXES];
- bool HasXRange;
- bool HasYRange[IMPLOT_Y_AXES];
- bool ShowDefaultTicksX;
- bool ShowDefaultTicksY[IMPLOT_Y_AXES];
- char FmtX[16];
- char FmtY[IMPLOT_Y_AXES][16];
- bool HasFmtX;
- bool HasFmtY[IMPLOT_Y_AXES];
- bool FitX;
- bool FitY[IMPLOT_Y_AXES];
- double* LinkedXmin;
- double* LinkedXmax;
- double* LinkedYmin[IMPLOT_Y_AXES];
- double* LinkedYmax[IMPLOT_Y_AXES];
+ ImPlotCond RangeCond[ImAxis_COUNT];
+ ImPlotRange Range[ImAxis_COUNT];
+ bool HasRange[ImAxis_COUNT];
+ bool Fit[ImAxis_COUNT];
+ double* LinkedMin[ImAxis_COUNT];
+ double* LinkedMax[ImAxis_COUNT];
ImPlotNextPlotData() { Reset(); }
void Reset() {
- HasXRange = false;
- ShowDefaultTicksX = true;
- HasFmtX = false;
- FitX = false;
- LinkedXmin = LinkedXmax = NULL;
- for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
- HasYRange[i] = false;
- ShowDefaultTicksY[i] = true;
- HasFmtY[i] = false;
- FitY[i] = false;
- LinkedYmin[i] = LinkedYmax[i] = NULL;
+ for (int i = 0; i < ImAxis_COUNT; ++i) {
+ HasRange[i] = false;
+ Fit[i] = false;
+ LinkedMin[i] = LinkedMax[i] = NULL;
}
}
@@ -843,7 +1093,7 @@ struct ImPlotNextItemData {
bool RenderMarkerFill;
bool HasHidden;
bool Hidden;
- ImGuiCond HiddenCond;
+ ImPlotCond HiddenCond;
ImPlotNextItemData() { Reset(); }
void Reset() {
for (int i = 0; i < 5; ++i)
@@ -857,40 +1107,22 @@ struct ImPlotNextItemData {
// Holds state information that must persist between calls to BeginPlot()/EndPlot()
struct ImPlotContext {
// Plot States
- ImPool<ImPlotPlot> Plots;
- ImPlotPlot* CurrentPlot;
- ImPlotItem* CurrentItem;
- ImPlotItem* PreviousItem;
+ ImPool<ImPlotPlot> Plots;
+ ImPool<ImPlotSubplot> Subplots;
+ ImPlotPlot* CurrentPlot;
+ ImPlotSubplot* CurrentSubplot;
+ ImPlotItemGroup* CurrentItems;
+ ImPlotItem* CurrentItem;
+ ImPlotItem* PreviousItem;
// Tick Marks and Labels
ImPlotTickCollection CTicks;
- ImPlotTickCollection XTicks;
- ImPlotTickCollection YTicks[IMPLOT_Y_AXES];
- float YAxisReference[IMPLOT_Y_AXES];
- // Annotation and User Labels
+ // Annotation and Tabs
ImPlotAnnotationCollection Annotations;
+ ImPlotTagCollection Tags;
- // Transformations and Data Extents
- ImPlotScale Scales[IMPLOT_Y_AXES];
- ImRect PixelRange[IMPLOT_Y_AXES];
- double Mx;
- double My[IMPLOT_Y_AXES];
- double LogDenX;
- double LogDenY[IMPLOT_Y_AXES];
- ImPlotRange ExtentsX;
- ImPlotRange ExtentsY[IMPLOT_Y_AXES];
-
- // Data Fitting Flags
- bool FitThisFrame;
- bool FitX;
- bool FitY[IMPLOT_Y_AXES];
-
- // Axis Rendering Flags
- bool RenderX;
- bool RenderY[IMPLOT_Y_AXES];
-
- // Axis Locking Flags
+ // Flags
bool ChildWindowMade;
// Style and Colormaps
@@ -904,16 +1136,22 @@ struct ImPlotContext {
tm Tm;
// Temp data for general use
- ImVector<double> Temp1, Temp2;
+ ImVector<double> TempDouble1, TempDouble2;
+ ImVector<int> TempInt1;
// Misc
- int VisibleItemCount;
int DigitalPlotItemCnt;
int DigitalPlotOffset;
ImPlotNextPlotData NextPlotData;
ImPlotNextItemData NextItemData;
ImPlotInputMap InputMap;
- ImPlotPoint MousePos[IMPLOT_Y_AXES];
+ bool OpenContextThisFrame;
+ ImGuiTextBuffer MousePosStringBuilder;
+
+ // Align plots
+ ImPool<ImPlotAlignmentData> AlignmentData;
+ ImPlotAlignmentData* CurrentAlignmentH;
+ ImPlotAlignmentData* CurrentAlignmentV;
};
//-----------------------------------------------------------------------------
@@ -930,14 +1168,11 @@ namespace ImPlot {
// Initializes an ImPlotContext
IMPLOT_API void Initialize(ImPlotContext* ctx);
// Resets an ImPlot context for the next call to BeginPlot
-IMPLOT_API void Reset(ImPlotContext* ctx);
-
-//-----------------------------------------------------------------------------
-// [SECTION] Input Utils
-//-----------------------------------------------------------------------------
-
-// Allows changing how keyboard/mouse interaction works.
-IMPLOT_API ImPlotInputMap& GetInputMap();
+IMPLOT_API void ResetCtxForNextPlot(ImPlotContext* ctx);
+// Resets an ImPlot context for the next call to BeginAlignedPlots
+IMPLOT_API void ResetCtxForNextAlignedPlots(ImPlotContext* ctx);
+// Resets an ImPlot context for the next call to BeginSubplot
+IMPLOT_API void ResetCtxForNextSubplot(ImPlotContext* ctx);
//-----------------------------------------------------------------------------
// [SECTION] Plot Utils
@@ -954,6 +1189,27 @@ IMPLOT_API void BustPlotCache();
IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
//-----------------------------------------------------------------------------
+// [SECTION] Setup Utils
+//-----------------------------------------------------------------------------
+
+// Lock Setup and call SetupFinish if necessary.
+static inline void SetupLock() {
+ if (!GImPlot->CurrentPlot->SetupLocked)
+ SetupFinish();
+ GImPlot->CurrentPlot->SetupLocked = true;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Subplot Utils
+//-----------------------------------------------------------------------------
+
+// Advances to next subplot
+IMPLOT_API void SubplotNextCell();
+
+// Shows a subplot's context menu.
+IMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot);
+
+//-----------------------------------------------------------------------------
// [SECTION] Item Utils
//-----------------------------------------------------------------------------
@@ -975,66 +1231,90 @@ IMPLOT_API void BustItemCache();
// [SECTION] Axis Utils
//-----------------------------------------------------------------------------
-// Gets the current y-axis for the current plot
-static inline int GetCurrentYAxis() { return GImPlot->CurrentPlot->CurrentYAxis; }
-// Updates axis ticks, lins, and label colors
-IMPLOT_API void UpdateAxisColors(int axis_flag, ImPlotAxis* axis);
+// Returns true if any enabled axis is locked from user input.
+static inline bool AnyAxesInputLocked(ImPlotAxis* axes, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (axes[i].Enabled && axes[i].IsInputLocked())
+ return true;
+ }
+ return false;
+}
-// Updates plot-to-pixel space transformation variables for the current plot.
-IMPLOT_API void UpdateTransformCache();
-// Gets the XY scale for the current plot and y-axis
-static inline ImPlotScale GetCurrentScale() { return GImPlot->Scales[GetCurrentYAxis()]; }
+// Returns true if all enabled axes are locked from user input.
+static inline bool AllAxesInputLocked(ImPlotAxis* axes, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (axes[i].Enabled && !axes[i].IsInputLocked())
+ return false;
+ }
+ return true;
+}
-// Returns true if the user has requested data to be fit.
-static inline bool FitThisFrame() { return GImPlot->FitThisFrame; }
-// Extend the the extents of an axis on current plot so that it encompes v
-static inline void FitPointAxis(ImPlotAxis& axis, ImPlotRange& ext, double v) {
- if (!ImNanOrInf(v) && !(ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale) && v <= 0)) {
- ext.Min = v < ext.Min ? v : ext.Min;
- ext.Max = v > ext.Max ? v : ext.Max;
+static inline bool AnyAxesHeld(ImPlotAxis* axes, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (axes[i].Enabled && axes[i].Held)
+ return true;
}
+ return false;
}
-// Extend the the extents of an axis on current plot so that it encompes v
-static inline void FitPointMultiAxis(ImPlotAxis& axis, ImPlotAxis& alt, ImPlotRange& ext, double v, double v_alt) {
- if (ImHasFlag(axis.Flags, ImPlotAxisFlags_RangeFit) && !alt.Range.Contains(v_alt))
- return;
- if (!ImNanOrInf(v) && !(ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale) && v <= 0)) {
- ext.Min = v < ext.Min ? v : ext.Min;
- ext.Max = v > ext.Max ? v : ext.Max;
+
+static inline bool AnyAxesHovered(ImPlotAxis* axes, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (axes[i].Enabled && axes[i].Hovered)
+ return true;
}
+ return false;
+}
+
+// Gets the XY scale for the current plot and y-axis (TODO)
+static inline ImPlotScale GetCurrentScale() {
+ ImPlotPlot& plot = *GetCurrentPlot();
+ ImPlotAxis& x = plot.Axes[plot.CurrentX];
+ ImPlotAxis& y = plot.Axes[plot.CurrentY];
+ if (!x.IsLog() && !y.IsLog())
+ return ImPlotScale_LinLin;
+ else if (x.IsLog() && !y.IsLog())
+ return ImPlotScale_LogLin;
+ else if (!x.IsLog() && y.IsLog())
+ return ImPlotScale_LinLog;
+ else
+ return ImPlotScale_LogLog;
+}
+
+// Returns true if the user has requested data to be fit.
+static inline bool FitThisFrame() {
+ return GImPlot->CurrentPlot->FitThisFrame;
}
+
// Extends the current plot's axes so that it encompasses a vertical line at x
static inline void FitPointX(double x) {
- FitPointAxis(GImPlot->CurrentPlot->XAxis, GImPlot->ExtentsX, x);
+ ImPlotPlot& plot = *GetCurrentPlot();
+ ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
+ x_axis.ExtendFit(x);
}
+
// Extends the current plot's axes so that it encompasses a horizontal line at y
static inline void FitPointY(double y) {
- const ImPlotYAxis y_axis = GImPlot->CurrentPlot->CurrentYAxis;
- FitPointAxis(GImPlot->CurrentPlot->YAxis[y_axis], GImPlot->ExtentsY[y_axis], y);
+ ImPlotPlot& plot = *GetCurrentPlot();
+ ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
+ y_axis.ExtendFit(y);
}
+
// Extends the current plot's axes so that it encompasses point p
static inline void FitPoint(const ImPlotPoint& p) {
- const ImPlotYAxis y_axis = GImPlot->CurrentPlot->CurrentYAxis;
- FitPointMultiAxis(GImPlot->CurrentPlot->XAxis, GImPlot->CurrentPlot->YAxis[y_axis], GImPlot->ExtentsX, p.x, p.y);
- FitPointMultiAxis(GImPlot->CurrentPlot->YAxis[y_axis], GImPlot->CurrentPlot->XAxis, GImPlot->ExtentsY[y_axis], p.y, p.x);
+ ImPlotPlot& plot = *GetCurrentPlot();
+ ImPlotAxis& x_axis = plot.Axes[plot.CurrentX];
+ ImPlotAxis& y_axis = plot.Axes[plot.CurrentY];
+ x_axis.ExtendFitWith(y_axis, p.x, p.y);
+ y_axis.ExtendFitWith(x_axis, p.y, p.x);
}
// Returns true if two ranges overlap
static inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)
{ return r1.Min <= r2.Max && r2.Min <= r1.Max; }
-// Updates pointers for linked axes from axis internal range.
-IMPLOT_API void PushLinkedAxis(ImPlotAxis& axis);
-// Updates axis internal range from points for linked axes.
-IMPLOT_API void PullLinkedAxis(ImPlotAxis& axis);
-
// Shows an axis's context menu.
IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
-// Get format spec for axis
-static inline const char* GetFormatX() { return GImPlot->NextPlotData.HasFmtX ? GImPlot->NextPlotData.FmtX : IMPLOT_LABEL_FMT; }
-static inline const char* GetFormatY(ImPlotYAxis y) { return GImPlot->NextPlotData.HasFmtY[y] ? GImPlot->NextPlotData.FmtY[y] : IMPLOT_LABEL_FMT; }
-
//-----------------------------------------------------------------------------
// [SECTION] Legend Utils
//-----------------------------------------------------------------------------
@@ -1042,11 +1322,13 @@ static inline const char* GetFormatY(ImPlotYAxis y) { return GImPlot->NextPlotDa
// Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
// Calculates the bounding box size of a legend
-IMPLOT_API ImVec2 CalcLegendSize(ImPlotPlot& plot, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation);
+IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);
// Renders legend entries into a bounding box
-IMPLOT_API void ShowLegendEntries(ImPlotPlot& plot, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation, ImDrawList& DrawList);
+IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);
// 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!).
-IMPLOT_API void ShowAltLegend(const char* title_id, ImPlotOrientation orientation = ImPlotOrientation_Vertical, const ImVec2 size = ImVec2(0,0), bool interactable = true);
+IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true);
+// Shows an legends's context menu.
+IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible);
//-----------------------------------------------------------------------------
// [SECTION] Tick Utils
@@ -1056,16 +1338,16 @@ IMPLOT_API void ShowAltLegend(const char* title_id, ImPlotOrientation orientatio
IMPLOT_API void LabelTickTime(ImPlotTick& tick, ImGuiTextBuffer& buffer, const ImPlotTime& t, ImPlotDateTimeFmt fmt);
// Populates a list of ImPlotTicks with normal spaced and formatted ticks
-IMPLOT_API void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt);
+IMPLOT_API void AddTicksDefault(const ImPlotRange& range, float pix, bool vertical, ImPlotTickCollection& ticks, ImPlotFormatter formatter, void* data);
// Populates a list of ImPlotTicks with logarithmic space and formatted ticks
-IMPLOT_API void AddTicksLogarithmic(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt);
+IMPLOT_API void AddTicksLogarithmic(const ImPlotRange& range, float pix, bool vertical, ImPlotTickCollection& ticks, ImPlotFormatter formatter, void* data);
+// Populates a list of ImPlotTicks with custom spaced and labeled ticks
+IMPLOT_API void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks, ImPlotFormatter formatter, void* data);
// Populates a list of ImPlotTicks with time formatted ticks.
IMPLOT_API void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollection& ticks);
-// Populates a list of ImPlotTicks with custom spaced and labeled ticks
-IMPLOT_API void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks, const char* fmt);
// Create a a string label for a an axis value
-IMPLOT_API int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size);
+IMPLOT_API void LabelAxisValue(const ImPlotAxis& axis, double value, char* buff, int size, bool round = false);
//-----------------------------------------------------------------------------
// [SECTION] Styling Utils
@@ -1087,13 +1369,15 @@ static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConve
// Draws vertical text. The position is the bottom left of the text rect.
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
+// Draws multiline horizontal text centered.
+IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = NULL);
// Calculates the size of vertical text
static inline ImVec2 CalcTextSizeVertical(const char *text) {
ImVec2 sz = ImGui::CalcTextSize(text);
return ImVec2(sz.y, sz.x);
}
// Returns white or black text given background color
-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; }
+static 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; }
static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
// Lightens or darkens a color for hover
static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); }
@@ -1149,13 +1433,6 @@ void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
}
}
-// Offsets and strides a data buffer
-template <typename T>
-static inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) {
- idx = ImPosMod(offset + idx, count);
- return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride);
-}
-
// Calculate histogram bin counts and widths
template <typename T>
static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {