Skip to content

Commit

Permalink
Make markers automatically cycle; adopt constexpr
Browse files Browse the repository at this point in the history
  • Loading branch information
epezent committed Sep 30, 2023
1 parent 90b92ff commit 76af113
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 84 deletions.
53 changes: 31 additions & 22 deletions implot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ const char* GetStyleColorName(ImPlotCol col) {
const char* GetMarkerName(ImPlotMarker marker) {
switch (marker) {
case ImPlotMarker_None: return "None";
case ImPlotMarker_Auto: return "Auto";
case ImPlotMarker_Circle: return "Circle";
case ImPlotMarker_Square: return "Square";
case ImPlotMarker_Diamond: return "Diamond";
Expand Down Expand Up @@ -687,8 +688,8 @@ bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool hov
// Locators
//-----------------------------------------------------------------------------

static const float TICK_FILL_X = 0.8f;
static const float TICK_FILL_Y = 1.0f;
constexpr float TICK_FILL_X = 0.8f;
constexpr float TICK_FILL_Y = 1.0f;

void Locator_Default(ImPlotTicker& ticker, const ImPlotRange& range, float pixels, bool vertical, ImPlotFormatter formatter, void* formatter_data) {
if (range.Min == range.Max)
Expand Down Expand Up @@ -824,7 +825,7 @@ void AddTicksCustom(const double* values, const char* const labels[], int n, ImP
//-----------------------------------------------------------------------------

// this may not be thread safe?
static const double TimeUnitSpans[ImPlotTimeUnit_COUNT] = {
constexpr double TimeUnitSpans[ImPlotTimeUnit_COUNT] = {
0.000001,
0.001,
1,
Expand All @@ -836,7 +837,7 @@ static const double TimeUnitSpans[ImPlotTimeUnit_COUNT] = {
};

inline ImPlotTimeUnit GetUnitForRange(double range) {
static double cutoffs[ImPlotTimeUnit_COUNT] = {0.001, 1, 60, 3600, 86400, 2629800, 31557600, IMPLOT_MAX_TIME};
constexpr double cutoffs[ImPlotTimeUnit_COUNT] = {0.001, 1, 60, 3600, 86400, 2629800, 31557600, IMPLOT_MAX_TIME};
for (int i = 0; i < ImPlotTimeUnit_COUNT; ++i) {
if (range <= cutoffs[i])
return (ImPlotTimeUnit)i;
Expand All @@ -856,28 +857,28 @@ inline int LowerBoundStep(int max_divs, const int* divs, const int* step, int si

inline int GetTimeStep(int max_divs, ImPlotTimeUnit unit) {
if (unit == ImPlotTimeUnit_Ms || unit == ImPlotTimeUnit_Us) {
static const int step[] = {500,250,200,100,50,25,20,10,5,2,1};
static const int divs[] = {2,4,5,10,20,40,50,100,200,500,1000};
constexpr int step[] = {500,250,200,100,50,25,20,10,5,2,1};
constexpr int divs[] = {2,4,5,10,20,40,50,100,200,500,1000};
return LowerBoundStep(max_divs, divs, step, 11);
}
if (unit == ImPlotTimeUnit_S || unit == ImPlotTimeUnit_Min) {
static const int step[] = {30,15,10,5,1};
static const int divs[] = {2,4,6,12,60};
constexpr int step[] = {30,15,10,5,1};
constexpr int divs[] = {2,4,6,12,60};
return LowerBoundStep(max_divs, divs, step, 5);
}
else if (unit == ImPlotTimeUnit_Hr) {
static const int step[] = {12,6,3,2,1};
static const int divs[] = {2,4,8,12,24};
constexpr int step[] = {12,6,3,2,1};
constexpr int divs[] = {2,4,8,12,24};
return LowerBoundStep(max_divs, divs, step, 5);
}
else if (unit == ImPlotTimeUnit_Day) {
static const int step[] = {14,7,2,1};
static const int divs[] = {2,4,14,28};
constexpr int step[] = {14,7,2,1};
constexpr int divs[] = {2,4,14,28};
return LowerBoundStep(max_divs, divs, step, 4);
}
else if (unit == ImPlotTimeUnit_Mo) {
static const int step[] = {6,3,2,1};
static const int divs[] = {2,4,6,12};
constexpr int step[] = {6,3,2,1};
constexpr int divs[] = {2,4,6,12};
return LowerBoundStep(max_divs, divs, step, 4);
}
return 0;
Expand Down Expand Up @@ -1801,8 +1802,8 @@ static inline void RenderSelectionRect(ImDrawList& DrawList, const ImVec2& p_min
// Input Handling
//-----------------------------------------------------------------------------

static const float MOUSE_CURSOR_DRAG_THRESHOLD = 5.0f;
static const float BOX_SELECT_DRAG_THRESHOLD = 4.0f;
constexpr float MOUSE_CURSOR_DRAG_THRESHOLD = 5.0f;
constexpr float BOX_SELECT_DRAG_THRESHOLD = 4.0f;

bool UpdateInput(ImPlotPlot& plot) {

Expand Down Expand Up @@ -3245,9 +3246,9 @@ void EndPlot() {
// BEGIN/END SUBPLOT
//-----------------------------------------------------------------------------

static const float SUBPLOT_BORDER_SIZE = 1.0f;
static const float SUBPLOT_SPLITTER_HALF_THICKNESS = 4.0f;
static const float SUBPLOT_SPLITTER_FEEDBACK_TIMER = 0.06f;
constexpr float SUBPLOT_BORDER_SIZE = 1.0f;
constexpr float SUBPLOT_SPLITTER_HALF_THICKNESS = 4.0f;
constexpr float SUBPLOT_SPLITTER_FEEDBACK_TIMER = 0.06f;

void SubplotSetCell(int row, int col) {
ImPlotContext& gp = *GImPlot;
Expand Down Expand Up @@ -3871,7 +3872,7 @@ IMPLOT_API void TagYV(double y, const ImVec4& color, const char* fmt, va_list ar
TagV(gp.CurrentPlot->CurrentY, y, color, fmt, args);
}

static const float DRAG_GRAB_HALF_SIZE = 4.0f;
constexpr float DRAG_GRAB_HALF_SIZE = 4.0f;

bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) {
ImGui::PushID("#IMPLOT_DRAG_POINT");
Expand Down Expand Up @@ -4458,6 +4459,14 @@ void PopStyleVar(int count) {
}
}

ImPlotMarker NextMarker() {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr, "NextMarker() needs to be called between BeginPlot() and EndPlot()!");
const int idx = gp.CurrentItems->MarkerIdx % ImPlotMarker_COUNT;
++gp.CurrentItems->MarkerIdx;
return idx;
}

//------------------------------------------------------------------------------
// [Section] Colormaps
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -4531,7 +4540,7 @@ ImU32 NextColormapColorU32() {

ImVec4 NextColormapColor() {
return ImGui::ColorConvertU32ToFloat4(NextColormapColorU32());
}
}

int GetColormapSize(ImPlotColormap cmap) {
ImPlotContext& gp = *GImPlot;
Expand Down Expand Up @@ -5283,7 +5292,7 @@ void ShowMetricsWindow(bool* p_popen) {
ImVec4 temp = ImGui::ColorConvertU32ToFloat4(item->Color);
if (ImGui::ColorEdit4("Color",&temp.x, ImGuiColorEditFlags_NoInputs))
item->Color = ImGui::ColorConvertFloat4ToU32(temp);

ImGui::BulletText("Marker: %s", GetMarkerName(item->Marker));
ImGui::BulletText("NameOffset: %d",item->NameOffset);
ImGui::BulletText("Name: %s", item->NameOffset != -1 ? plot.Items.Legend.Labels.Buf.Data + item->NameOffset : "N/A");
ImGui::BulletText("Hovered: %s",item->LegendHovered ? "true" : "false");
Expand Down
19 changes: 12 additions & 7 deletions implot.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@

// ImPlot version string.
#define IMPLOT_VERSION "0.17"
// Indicates variable should deduced automatically.
#define IMPLOT_AUTO -1
// Special color used to indicate that a color should be deduced automatically.
#define IMPLOT_AUTO_COL ImVec4(0,0,0,-1)
// Macro for templated plotting functions; keeps header clean.
#define IMPLOT_TMP template <typename T> IMPLOT_API

// Indicates variable should deduced automatically.
constexpr int IMPLOT_AUTO = -1;
// Special color used to indicate that a color should be deduced automatically.
constexpr ImVec4 IMPLOT_AUTO_COL = ImVec4(0,0,0,-1);

//-----------------------------------------------------------------------------
// [SECTION] Enums and Types
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -407,7 +408,8 @@ enum ImPlotScale_ {

// Marker specifications.
enum ImPlotMarker_ {
ImPlotMarker_None = -1, // no marker
ImPlotMarker_None = -2, // no marker
ImPlotMarker_Auto = -1, // automatic marker selection
ImPlotMarker_Circle, // a circle marker (default)
ImPlotMarker_Square, // a square maker
ImPlotMarker_Diamond, // a diamond marker
Expand Down Expand Up @@ -1143,7 +1145,10 @@ IMPLOT_API ImVec4 GetLastItemColor();
IMPLOT_API const char* GetStyleColorName(ImPlotCol idx);
// Returns the null terminated string name for an ImPlotMarker.
IMPLOT_API const char* GetMarkerName(ImPlotMarker idx);


// Returns the next marker and advances the marker for the current plot. You need to call this between Begin/EndPlot!
IMPLOT_API ImPlotMarker NextMarker();

//-----------------------------------------------------------------------------
// [SECTION] Colormaps
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -1213,7 +1218,7 @@ IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr);
//-----------------------------------------------------------------------------
// [SECTION] Input Mapping
//-----------------------------------------------------------------------------

// Provides access to input mapping structure for permanent modifications to controls for pan, select, etc.
IMPLOT_API ImPlotInputMap& GetInputMap();

Expand Down
10 changes: 4 additions & 6 deletions implot_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,12 +434,12 @@ void Demo_StairstepPlots() {
ImPlotSpec spec;
spec.Flags = flags;
spec.FillAlpha = 0.25f;
spec.Marker = ImPlotMarker_Circle;
spec.Marker = ImPlotMarker_Auto;
ImPlot::PlotStairs("Post Step (default)", ys1, 21, 0.05f, 0, spec);

spec.Flags = flags|ImPlotStairsFlags_PreStep;
spec.FillAlpha = 0.25f;
spec.Marker = ImPlotMarker_Circle;
spec.Marker = ImPlotMarker_Auto;
ImPlot::PlotStairs("Pre Step", ys2, 21, 0.05f, 0, spec);

ImPlot::EndPlot();
Expand Down Expand Up @@ -576,7 +576,7 @@ void Demo_ErrorBars() {
ImPlot::PlotErrorBars("Scatter", xs, lin2, err2, 5, spec);
spec.Flags = ImPlotErrorBarsFlags_Horizontal;
ImPlot::PlotErrorBars("Scatter", xs, lin2, err3, err4, 5, spec);
ImPlot::PlotScatter("Scatter", xs, lin2, 5);
ImPlot::PlotScatter("Scatter", xs, lin2, 5);

ImPlot::EndPlot();
}
Expand Down Expand Up @@ -943,7 +943,7 @@ void Demo_RealtimePlots() {
//-----------------------------------------------------------------------------

void Demo_MarkersAndText() {
static ImPlotSpec spec;
static ImPlotSpec spec(ImProp_Marker, ImPlotMarker_Auto);
ImGui::DragFloat("Marker Size",&spec.Size,0.1f,2.0f,10.0f,"%.2f px");
ImGui::DragFloat("Marker Weight", &spec.LineWeight,0.05f,0.5f,3.0f,"%.2f px");

Expand All @@ -958,7 +958,6 @@ void Demo_MarkersAndText() {
// filled markers
for (int m = 0; m < ImPlotMarker_COUNT; ++m) {
ImGui::PushID(m);
spec.Marker = m;
spec.FillAlpha = 1.0f;
ImPlot::PlotLine("##Filled", xs, ys, 2, spec);
ImGui::PopID();
Expand All @@ -968,7 +967,6 @@ void Demo_MarkersAndText() {
// open markers
for (int m = 0; m < ImPlotMarker_COUNT; ++m) {
ImGui::PushID(m);
spec.Marker = m;
spec.FillAlpha = 0.0f;
ImPlot::PlotLine("##Open", xs, ys, 2, spec);
ImGui::PopID();
Expand Down
44 changes: 28 additions & 16 deletions implot_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,25 @@
// Constants can be changed unless stated otherwise. We may move some of these
// to ImPlotStyleVar_ over time.

// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
#define IMPLOT_MIN_TIME 0
// Minimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
constexpr double IMPLOT_MIN_TIME = 0;
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
#define IMPLOT_MAX_TIME 32503680000
constexpr double IMPLOT_MAX_TIME = 32503680000;

// Default label format for axis labels
#define IMPLOT_LABEL_FORMAT "%g"
constexpr const char* IMPLOT_LABEL_FORMAT = "%g";
// Max character size for tick labels
#define IMPLOT_LABEL_MAX_SIZE 32
constexpr int IMPLOT_LABEL_MAX_SIZE = 32;

// Number of X axes
constexpr int IMPLOT_NUM_X_AXES = ImAxis_Y1;
// Number of Y axes
constexpr int IMPLOT_NUM_Y_AXES = ImAxis_COUNT - IMPLOT_NUM_X_AXES;

//-----------------------------------------------------------------------------
// [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); \
Expand Down Expand Up @@ -226,9 +229,10 @@ static inline bool ImOverlaps(T min_a, T max_a, T min_b, T max_b) {
// [SECTION] ImPlot Enums
//-----------------------------------------------------------------------------

typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_
typedef int ImPlotDateFmt; // -> enum ImPlotDateFmt_
typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_
typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_
typedef int ImPlotDateFmt; // -> enum ImPlotDateFmt_
typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_
typedef int ImPlotMarkerInternal; // -> enum ImPlotMarkerInternal_

enum ImPlotTimeUnit_ {
ImPlotTimeUnit_Us, // microsecond
Expand Down Expand Up @@ -264,6 +268,10 @@ enum ImPlotTimeFmt_ { // default [ 24 Hour Clock ]
ImPlotTimeFmt_Hr // 7pm [ 19:00 ]
};

enum ImPlotMarkerInternal_ {
ImPlotMarker_Invalid = -3
};

//-----------------------------------------------------------------------------
// [SECTION] Callbacks
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -941,6 +949,7 @@ struct ImPlotItem
{
ImGuiID ID;
ImU32 Color;
ImPlotMarker Marker;
ImRect LegendHoverRect;
int NameOffset;
bool Show;
Expand All @@ -950,6 +959,7 @@ struct ImPlotItem
ImPlotItem() {
ID = 0;
Color = IM_COL32_WHITE;
Marker = ImPlotMarker_None;
NameOffset = -1;
Show = true;
SeenThisFrame = false;
Expand Down Expand Up @@ -993,8 +1003,9 @@ struct ImPlotItemGroup
ImPlotLegend Legend;
ImPool<ImPlotItem> ItemPool;
int ColormapIdx;
ImPlotMarker MarkerIdx;

ImPlotItemGroup() { ID = 0; ColormapIdx = 0; }
ImPlotItemGroup() { ID = 0; ColormapIdx = 0; MarkerIdx = 0; }

int GetItemCount() const { return ItemPool.GetBufSize(); }
ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); /* GetIDWithSeed */ }
Expand Down Expand Up @@ -1178,6 +1189,7 @@ struct ImPlotNextItemData {
float DigitalBitGap; // TODO: remove
bool RenderLine;
bool RenderFill;
bool RenderMarkers;
bool HasHidden;
bool Hidden;
ImPlotCond HiddenCond;
Expand Down Expand Up @@ -1297,12 +1309,12 @@ IMPLOT_API void ShowSubplotsContextMenu(ImPlotSubplot& subplot);
//-----------------------------------------------------------------------------

// Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect.
IMPLOT_API bool BeginItem(const char* label_id, const ImPlotSpec& spec = ImPlotSpec(), const ImVec4& label_col = IMPLOT_AUTO_COL);
IMPLOT_API bool BeginItem(const char* label_id, const ImPlotSpec& spec = ImPlotSpec(), const ImVec4& item_col = IMPLOT_AUTO_COL, ImPlotMarker item_mkr = ImPlotMarker_Invalid);

// Same as above but with fitting functionality.
template <typename _Fitter>
bool BeginItemEx(const char* label_id, const _Fitter& fitter, const ImPlotSpec& spec, const ImVec4& label_col = IMPLOT_AUTO_COL) {
if (BeginItem(label_id, spec, label_col)) {
bool BeginItemEx(const char* label_id, const _Fitter& fitter, const ImPlotSpec& spec, const ImVec4& item_col = IMPLOT_AUTO_COL, ImPlotMarker item_mkr = ImPlotMarker_Invalid) {
if (BeginItem(label_id, spec, item_col, item_mkr)) {
ImPlotPlot& plot = *GetCurrentPlot();
if (plot.FitThisFrame && !ImHasFlag(spec.Flags, ImPlotItemFlags_NoFit))
fitter.Fit(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]);
Expand Down Expand Up @@ -1535,7 +1547,7 @@ static inline bool IsLeapYear(int year) {
}
// Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed.
static inline int GetDaysInMonth(int year, int month) {
static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
constexpr int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return days[month] + (int)(month == 1 && IsLeapYear(year));
}

Expand Down
Loading

0 comments on commit 76af113

Please sign in to comment.