1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-23 02:38:53 -05:00

Merge branch 'item-style'

This commit is contained in:
epezent 2020-08-31 23:24:13 -05:00
commit 9bc5b55766
5 changed files with 764 additions and 719 deletions

View File

@ -333,8 +333,9 @@ void Reset(ImPlotContext* ctx) {
if (ctx->ChildWindowMade) if (ctx->ChildWindowMade)
ImGui::EndChild(); ImGui::EndChild();
ctx->ChildWindowMade = false; ctx->ChildWindowMade = false;
// reset the next plot data // reset the next plot/item data
ctx->NextPlotData = ImPlotNextPlotData(); ctx->NextPlotData = ImPlotNextPlotData();
ctx->NextItemStyle = ImPlotItemStyle();
// reset items count // reset items count
ctx->VisibleItemCount = 0; ctx->VisibleItemCount = 0;
// reset legend items // reset legend items
@ -360,6 +361,7 @@ void Reset(ImPlotContext* ctx) {
ctx->DigitalPlotOffset = 0; ctx->DigitalPlotOffset = 0;
// nullify plot // nullify plot
ctx->CurrentPlot = NULL; ctx->CurrentPlot = NULL;
ctx->CurrentItem = NULL;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -409,13 +411,11 @@ void UpdateTransformCache() {
ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.y : gp.BB_Plot.Max.y, ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.y : gp.BB_Plot.Max.y,
ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.x : gp.BB_Plot.Max.x, ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.x : gp.BB_Plot.Max.x,
ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Max.y : gp.BB_Plot.Min.y); ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Max.y : gp.BB_Plot.Min.y);
gp.My[i] = (gp.PixelRange[i].Max.y - gp.PixelRange[i].Min.y) / gp.CurrentPlot->YAxis[i].Range.Size(); gp.My[i] = (gp.PixelRange[i].Max.y - gp.PixelRange[i].Min.y) / gp.CurrentPlot->YAxis[i].Range.Size();
} }
gp.LogDenX = ImLog10(gp.CurrentPlot->XAxis.Range.Max / gp.CurrentPlot->XAxis.Range.Min); gp.LogDenX = ImLog10(gp.CurrentPlot->XAxis.Range.Max / gp.CurrentPlot->XAxis.Range.Min);
for (int i = 0; i < IMPLOT_Y_AXES; i++) { for (int i = 0; i < IMPLOT_Y_AXES; i++)
gp.LogDenY[i] = ImLog10(gp.CurrentPlot->YAxis[i].Range.Max / gp.CurrentPlot->YAxis[i].Range.Min); gp.LogDenY[i] = ImLog10(gp.CurrentPlot->YAxis[i].Range.Max / gp.CurrentPlot->YAxis[i].Range.Min);
}
gp.Mx = (gp.PixelRange[0].Max.x - gp.PixelRange[0].Min.x) / gp.CurrentPlot->XAxis.Range.Size(); gp.Mx = (gp.PixelRange[0].Max.x - gp.PixelRange[0].Min.x) / gp.CurrentPlot->XAxis.Range.Size();
} }
@ -465,61 +465,6 @@ ImVec2 PlotToPixels(const ImPlotPoint& plt, int y_axis) {
return PlotToPixels(plt.x, plt.y, y_axis); return PlotToPixels(plt.x, plt.y, y_axis);
} }
//-----------------------------------------------------------------------------
// Item Utils
//-----------------------------------------------------------------------------
ImPlotItem* RegisterOrGetItem(const char* label_id) {
ImPlotContext& gp = *GImPlot;
ImGuiID id = ImGui::GetID(label_id);
ImPlotItem* item = gp.CurrentPlot->Items.GetOrAddByKey(id);
if (item->SeenThisFrame)
return item;
item->SeenThisFrame = true;
int idx = gp.CurrentPlot->Items.GetIndex(item);
item->ID = id;
if (ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) {
gp.LegendIndices.push_back(idx);
item->NameOffset = gp.LegendLabels.size();
gp.LegendLabels.append(label_id, label_id + strlen(label_id) + 1);
}
else {
item->Show = true;
}
if (item->Show)
gp.VisibleItemCount++;
return item;
}
ImPlotItem* GetItem(int i) {
ImPlotContext& gp = *GImPlot;
return gp.CurrentPlot->Items.GetByIndex(gp.LegendIndices[i]);
}
ImPlotItem* GetItem(const char* label_id) {
ImPlotContext& gp = *GImPlot;
ImGuiID id = ImGui::GetID(label_id);
return gp.CurrentPlot->Items.GetByKey(id);
}
ImPlotItem* GetItem(const char* plot_title, const char* item_label_id) {
ImPlotState* plot = GetPlot(plot_title);
if (plot) {
ImGuiID id = ImGui::GetID(item_label_id);
return plot->Items.GetByKey(id);
}
return NULL;
}
void BustItemCache() {
ImPlotContext& gp = *GImPlot;
for (int p = 0; p < gp.Plots.GetSize(); ++p) {
ImPlotState& plot = *gp.Plots.GetByIndex(p);
plot.ColormapIdx = 0;
plot.Items.Clear();
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Legend Utils // Legend Utils
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -740,6 +685,17 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
gp.LockPlot = gp.X.Lock && gp.Y[0].Lock && gp.Y[1].Lock && gp.Y[2].Lock; gp.LockPlot = gp.X.Lock && gp.Y[0].Lock && gp.Y[1].Lock && gp.Y[2].Lock;
for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
if (!ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale) && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
gp.Scales[i] = ImPlotScale_LinLin;
else if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale) && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
gp.Scales[i] = ImPlotScale_LogLin;
else if (!ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
gp.Scales[i] = ImPlotScale_LinLog;
else if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
gp.Scales[i] = ImPlotScale_LogLog;
}
// CONSTRAINTS ------------------------------------------------------------ // CONSTRAINTS ------------------------------------------------------------
ConstrainAxis(plot.XAxis); ConstrainAxis(plot.XAxis);
@ -1528,15 +1484,17 @@ void EndPlot() {
col_hl_txt = ImGui::GetColorU32(col_txt); col_hl_txt = ImGui::GetColorU32(col_txt);
} }
ImU32 iconColor; ImU32 iconColor;
ImVec4 item_color = item->Color;
item_color.w = 1;
if (hov_legend && icon_bb.Contains(IO.MousePos)) { if (hov_legend && icon_bb.Contains(IO.MousePos)) {
ImVec4 colAlpha = item->Color; ImVec4 colAlpha = item_color;
colAlpha.w = 0.5f; colAlpha.w = 0.5f;
iconColor = item->Show ? ImGui::GetColorU32(colAlpha) iconColor = item->Show ? ImGui::GetColorU32(colAlpha)
: ImGui::GetColorU32(ImGuiCol_TextDisabled, 0.5f); : ImGui::GetColorU32(ImGuiCol_TextDisabled, 0.5f);
if (IO.MouseClicked[0]) if (IO.MouseClicked[0])
item->Show = !item->Show; item->Show = !item->Show;
} else { } else {
iconColor = item->Show ? ImGui::GetColorU32(item->Color) : col_txt_dis; iconColor = item->Show ? ImGui::GetColorU32(item_color) : col_txt_dis;
} }
DrawList.AddRectFilled(icon_bb.Min, icon_bb.Max, iconColor, 1); DrawList.AddRectFilled(icon_bb.Min, icon_bb.Max, iconColor, 1);
const char* label = GetLegendLabel(i); const char* label = GetLegendLabel(i);
@ -1776,6 +1734,10 @@ ImVec2 GetPlotSize() {
return gp.BB_Plot.GetSize(); return gp.BB_Plot.GetSize();
} }
ImDrawList* GetPlotDrawList() {
return ImGui::GetWindowDrawList();
}
void PushPlotClipRect() { void PushPlotClipRect() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PushPlotClipRect() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PushPlotClipRect() needs to be called between BeginPlot() and EndPlot()!");
@ -2232,7 +2194,7 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
ImGui::ItemSize(bb_frame); ImGui::ItemSize(bb_frame);
if (!ImGui::ItemAdd(bb_frame, 0, &bb_frame)) if (!ImGui::ItemAdd(bb_frame, 0, &bb_frame))
return; return;
ImGui::RenderFrame(bb_frame.Min, bb_frame.Max, ImGui::GetColorU32(ImGuiCol_FrameBg)); ImGui::RenderFrame(bb_frame.Min, bb_frame.Max, GetStyleColorU32(ImPlotCol_FrameBg));
ImRect bb_grad(bb_frame.Min + gp.Style.PlotPadding, bb_frame.Min + ImVec2(bar_w + gp.Style.PlotPadding.x, height - gp.Style.PlotPadding.y)); ImRect bb_grad(bb_frame.Min + gp.Style.PlotPadding, bb_frame.Min + ImVec2(bar_w + gp.Style.PlotPadding.x, height - gp.Style.PlotPadding.y));
int num_cols = GetColormapSize(); int num_cols = GetColormapSize();
@ -2243,18 +2205,20 @@ void ShowColormapScale(double scale_min, double scale_max, float height) {
ImU32 col2 = ImGui::GetColorU32(GetColormapColor(num_cols - 1 - (i+1))); ImU32 col2 = ImGui::GetColorU32(GetColormapColor(num_cols - 1 - (i+1)));
DrawList.AddRectFilledMultiColor(rect.Min, rect.Max, col1, col1, col2, col2); DrawList.AddRectFilledMultiColor(rect.Min, rect.Max, col1, col1, col2, col2);
} }
ImU32 col_border = gp.Style.Colors[ImPlotCol_PlotBorder].w == -1 ? ImGui::GetColorU32(ImGuiCol_Text, 0.5f) : ImGui::GetColorU32(gp.Style.Colors[ImPlotCol_PlotBorder]); ImVec4 col_tik4 = ImGui::GetStyleColorVec4(ImGuiCol_Text);
col_tik4.w *= 0.25f;
const ImU32 col_tick = ImGui::GetColorU32(col_tik4);
ImGui::PushClipRect(bb_frame.Min, bb_frame.Max, true); ImGui::PushClipRect(bb_frame.Min, bb_frame.Max, true);
for (int i = 0; i < ticks.Size; ++i) { for (int i = 0; i < ticks.Size; ++i) {
float ypos = ImRemap((float)ticks.Ticks[i].PlotPos, (float)range.Max, (float)range.Min, bb_grad.Min.y, bb_grad.Max.y); float ypos = ImRemap((float)ticks.Ticks[i].PlotPos, (float)range.Max, (float)range.Min, bb_grad.Min.y, bb_grad.Max.y);
if (ypos < bb_grad.Max.y - 2 && ypos > bb_grad.Min.y + 2) if (ypos < bb_grad.Max.y - 2 && ypos > bb_grad.Min.y + 2)
DrawList.AddLine(ImVec2(bb_grad.Max.x-1, ypos), ImVec2(bb_grad.Max.x - (ticks.Ticks[i].Major ? 10.0f : 5.0f), ypos), col_border, 1.0f); DrawList.AddLine(ImVec2(bb_grad.Max.x-1, ypos), ImVec2(bb_grad.Max.x - (ticks.Ticks[i].Major ? 10.0f : 5.0f), ypos), col_tick, 1.0f);
DrawList.AddText(ImVec2(bb_grad.Max.x-1, ypos) + ImVec2(txt_off, -ticks.Ticks[i].LabelSize.y * 0.5f), ImGui::GetColorU32(ImGuiCol_Text), ticks.GetLabel(i)); DrawList.AddText(ImVec2(bb_grad.Max.x-1, ypos) + ImVec2(txt_off, -ticks.Ticks[i].LabelSize.y * 0.5f), GetStyleColorU32(ImPlotCol_TitleText), ticks.GetLabel(i));
} }
ImGui::PopClipRect(); ImGui::PopClipRect();
DrawList.AddRect(bb_grad.Min, bb_grad.Max, col_border); DrawList.AddRect(bb_grad.Min, bb_grad.Max, GetStyleColorU32(ImPlotCol_PlotBorder));
} }
@ -2361,7 +2325,7 @@ void ShowStyleEditor(ImPlotStyle* ref) {
const char* name = ImPlot::GetStyleColorName(i); const char* name = ImPlot::GetStyleColorName(i);
if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0) { if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0) {
if (IsColorAuto(i)) if (IsColorAuto(i))
ImGui::LogText("colors[ImPlotCol_%s]%*s= IMPLOT_COL_AUTO;\n",name,14 - (int)strlen(name), ""); ImGui::LogText("colors[ImPlotCol_%s]%*s= IMPLOT_AUTO_COL;\n",name,14 - (int)strlen(name), "");
else else
ImGui::LogText("colors[ImPlotCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);\n", ImGui::LogText("colors[ImPlotCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);\n",
name, 14 - (int)strlen(name), "", col.x, col.y, col.z, col.w); name, 14 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
@ -2398,7 +2362,7 @@ void ShowStyleEditor(ImPlotStyle* ref) {
if (is_auto) if (is_auto)
style.Colors[i] = temp; style.Colors[i] = temp;
else else
style.Colors[i] = IMPLOT_COL_AUTO; style.Colors[i] = IMPLOT_AUTO_COL;
BustItemCache(); BustItemCache();
} }
if (!is_auto) if (!is_auto)
@ -2419,7 +2383,7 @@ void ShowStyleEditor(ImPlotStyle* ref) {
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Colors that are set to Auto (i.e. IMPLOT_COL_AUTO) will\n" ImGui::Text("Colors that are set to Auto (i.e. IMPLOT_AUTO_COL) will\n"
"be automatically deduced from your ImGui style or the\n" "be automatically deduced from your ImGui style or the\n"
"current ImPlot Colormap. If you want to style individual\n" "current ImPlot Colormap. If you want to style individual\n"
"plot items, use Push/PopStyleColor around its function."); "plot items, use Push/PopStyleColor around its function.");
@ -2551,31 +2515,31 @@ void StyleColorsAuto(ImPlotStyle* dst) {
style->MinorAlpha = 0.25f; style->MinorAlpha = 0.25f;
colors[ImPlotCol_Line] = IMPLOT_COL_AUTO; colors[ImPlotCol_Line] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Fill] = IMPLOT_COL_AUTO; colors[ImPlotCol_Fill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerOutline] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerFill] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerFill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_ErrorBar] = IMPLOT_COL_AUTO; colors[ImPlotCol_ErrorBar] = IMPLOT_AUTO_COL;
colors[ImPlotCol_FrameBg] = IMPLOT_COL_AUTO; colors[ImPlotCol_FrameBg] = IMPLOT_AUTO_COL;
colors[ImPlotCol_PlotBg] = IMPLOT_COL_AUTO; colors[ImPlotCol_PlotBg] = IMPLOT_AUTO_COL;
colors[ImPlotCol_PlotBorder] = IMPLOT_COL_AUTO; colors[ImPlotCol_PlotBorder] = IMPLOT_AUTO_COL;
colors[ImPlotCol_LegendBg] = IMPLOT_COL_AUTO; colors[ImPlotCol_LegendBg] = IMPLOT_AUTO_COL;
colors[ImPlotCol_LegendBorder] = IMPLOT_COL_AUTO; colors[ImPlotCol_LegendBorder] = IMPLOT_AUTO_COL;
colors[ImPlotCol_LegendText] = IMPLOT_COL_AUTO; colors[ImPlotCol_LegendText] = IMPLOT_AUTO_COL;
colors[ImPlotCol_TitleText] = IMPLOT_COL_AUTO; colors[ImPlotCol_TitleText] = IMPLOT_AUTO_COL;
colors[ImPlotCol_InlayText] = IMPLOT_COL_AUTO; colors[ImPlotCol_InlayText] = IMPLOT_AUTO_COL;
colors[ImPlotCol_PlotBorder] = IMPLOT_COL_AUTO; colors[ImPlotCol_PlotBorder] = IMPLOT_AUTO_COL;
colors[ImPlotCol_XAxis] = IMPLOT_COL_AUTO; colors[ImPlotCol_XAxis] = IMPLOT_AUTO_COL;
colors[ImPlotCol_XAxisGrid] = IMPLOT_COL_AUTO; colors[ImPlotCol_XAxisGrid] = IMPLOT_AUTO_COL;
colors[ImPlotCol_YAxis] = IMPLOT_COL_AUTO; colors[ImPlotCol_YAxis] = IMPLOT_AUTO_COL;
colors[ImPlotCol_YAxisGrid] = IMPLOT_COL_AUTO; colors[ImPlotCol_YAxisGrid] = IMPLOT_AUTO_COL;
colors[ImPlotCol_YAxis2] = IMPLOT_COL_AUTO; colors[ImPlotCol_YAxis2] = IMPLOT_AUTO_COL;
colors[ImPlotCol_YAxisGrid2] = IMPLOT_COL_AUTO; colors[ImPlotCol_YAxisGrid2] = IMPLOT_AUTO_COL;
colors[ImPlotCol_YAxis3] = IMPLOT_COL_AUTO; colors[ImPlotCol_YAxis3] = IMPLOT_AUTO_COL;
colors[ImPlotCol_YAxisGrid3] = IMPLOT_COL_AUTO; colors[ImPlotCol_YAxisGrid3] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Selection] = IMPLOT_COL_AUTO; colors[ImPlotCol_Selection] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Query] = IMPLOT_COL_AUTO; colors[ImPlotCol_Query] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Crosshairs] = IMPLOT_COL_AUTO; colors[ImPlotCol_Crosshairs] = IMPLOT_AUTO_COL;
} }
void StyleColorsClassic(ImPlotStyle* dst) { void StyleColorsClassic(ImPlotStyle* dst) {
@ -2584,10 +2548,10 @@ void StyleColorsClassic(ImPlotStyle* dst) {
style->MinorAlpha = 0.5f; style->MinorAlpha = 0.5f;
colors[ImPlotCol_Line] = IMPLOT_COL_AUTO; colors[ImPlotCol_Line] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Fill] = IMPLOT_COL_AUTO; colors[ImPlotCol_Fill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerOutline] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerFill] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerFill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_ErrorBar] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImPlotCol_ErrorBar] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImPlotCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f); colors[ImPlotCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
colors[ImPlotCol_PlotBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.35f); colors[ImPlotCol_PlotBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.35f);
@ -2616,11 +2580,11 @@ void StyleColorsDark(ImPlotStyle* dst) {
style->MinorAlpha = 0.25f; style->MinorAlpha = 0.25f;
colors[ImPlotCol_Line] = IMPLOT_COL_AUTO; colors[ImPlotCol_Line] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Fill] = IMPLOT_COL_AUTO; colors[ImPlotCol_Fill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerOutline] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerFill] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerFill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_ErrorBar] = IMPLOT_COL_AUTO; colors[ImPlotCol_ErrorBar] = IMPLOT_AUTO_COL;
colors[ImPlotCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f); colors[ImPlotCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
colors[ImPlotCol_PlotBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f); colors[ImPlotCol_PlotBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
colors[ImPlotCol_PlotBorder] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); colors[ImPlotCol_PlotBorder] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
@ -2648,11 +2612,11 @@ void StyleColorsLight(ImPlotStyle* dst) {
style->MinorAlpha = 1.0f; style->MinorAlpha = 1.0f;
colors[ImPlotCol_Line] = IMPLOT_COL_AUTO; colors[ImPlotCol_Line] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Fill] = IMPLOT_COL_AUTO; colors[ImPlotCol_Fill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerOutline] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerFill] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerFill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_ErrorBar] = IMPLOT_COL_AUTO; colors[ImPlotCol_ErrorBar] = IMPLOT_AUTO_COL;
colors[ImPlotCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImPlotCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImPlotCol_PlotBg] = ImVec4(0.42f, 0.57f, 1.00f, 0.13f); colors[ImPlotCol_PlotBg] = ImVec4(0.42f, 0.57f, 1.00f, 0.13f);
colors[ImPlotCol_PlotBorder] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImPlotCol_PlotBorder] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);

View File

@ -25,7 +25,16 @@
#pragma once #pragma once
#include "imgui.h" #include "imgui.h"
//-----------------------------------------------------------------------------
// Macros and Defines
//-----------------------------------------------------------------------------
// ImPlot version string
#define IMPLOT_VERSION "0.5 WIP" #define IMPLOT_VERSION "0.5 WIP"
// 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)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Forward Declarations and Basic Types // Forward Declarations and Basic Types
@ -73,13 +82,13 @@ enum ImPlotAxisFlags_ {
// Plot styling colors. // Plot styling colors.
enum ImPlotCol_ { enum ImPlotCol_ {
// item related colors // item styling colors
ImPlotCol_Line, // plot line/outline color (defaults to next unused color in current colormap) ImPlotCol_Line, // plot line/outline color (defaults to next unused color in current colormap)
ImPlotCol_Fill, // plot fill color for bars (defaults to the current line color) ImPlotCol_Fill, // plot fill color for bars (defaults to the current line color)
ImPlotCol_MarkerOutline, // marker outline color (defaults to the current line color) ImPlotCol_MarkerOutline, // marker outline color (defaults to the current line color)
ImPlotCol_MarkerFill, // marker fill color (defaults to the current line color) ImPlotCol_MarkerFill, // marker fill color (defaults to the current line color)
ImPlotCol_ErrorBar, // error bar color (defaults to ImGuiCol_Text) ImPlotCol_ErrorBar, // error bar color (defaults to ImGuiCol_Text)
// plot related colors // plot styling colors
ImPlotCol_FrameBg, // plot frame background color (defaults to ImGuiCol_FrameBg) ImPlotCol_FrameBg, // plot frame background color (defaults to ImGuiCol_FrameBg)
ImPlotCol_PlotBg, // plot area background color (defaults to ImGuiCol_WindowBg) ImPlotCol_PlotBg, // plot area background color (defaults to ImGuiCol_WindowBg)
ImPlotCol_PlotBorder, // plot area border color (defaults to ImGuiCol_Border) ImPlotCol_PlotBorder, // plot area border color (defaults to ImGuiCol_Border)
@ -133,7 +142,7 @@ enum ImPlotStyleVar_ {
// Marker specifications. // Marker specifications.
enum ImPlotMarker_ { enum ImPlotMarker_ {
ImPlotMarker_None, // no marker ImPlotMarker_None = -1, // no marker
ImPlotMarker_Circle, // a circle marker ImPlotMarker_Circle, // a circle marker
ImPlotMarker_Square, // a square maker ImPlotMarker_Square, // a square maker
ImPlotMarker_Diamond, // a diamond marker ImPlotMarker_Diamond, // a diamond marker
@ -204,8 +213,8 @@ struct ImPlotStyle {
float ErrorBarWeight; // = 1.5, error bar whisker weight in pixels float ErrorBarWeight; // = 1.5, error bar whisker weight in pixels
float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels
float DigitalBitGap; // = 4, digital channels bit padding gap in pixels float DigitalBitGap; // = 4, digital channels bit padding gap in pixels
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
// plot styling variables // plot styling variables
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
float PlotBorderSize; // = 1, line thickness of border around plot area float PlotBorderSize; // = 1, line thickness of border around plot area
float MinorAlpha; // = 0.25 alpha multiplier applied to minor axis grid lines float MinorAlpha; // = 0.25 alpha multiplier applied to minor axis grid lines
ImVec2 MajorTickLen; // = 10,10 major tick lengths for X and Y axes ImVec2 MajorTickLen; // = 10,10 major tick lengths for X and Y axes
@ -266,8 +275,8 @@ void SetCurrentContext(ImPlotContext* ctx);
// Starts a 2D plotting context. If this function returns true, EndPlot() must // Starts a 2D plotting context. If this function returns true, EndPlot() must
// be called, e.g. "if (BeginPlot(...)) { ... EndPlot(); }". #title_id must // be called, e.g. "if (BeginPlot(...)) { ... EndPlot(); }". #title_id must
// be unique. If you need to avoid ID collisions or don't want to display a // be unique. If you need to avoid ID collisions or don't want to display a
// title in the plot, use double hashes (e.g. "MyPlot##Hidden"). If #x_label // title in the plot, use double hashes (e.g. "MyPlot##Hidden" or "##NoTitle").
// and/or #y_label are provided, axes labels will be displayed. // If #x_label and/or #y_label are provided, axes labels will be displayed.
bool BeginPlot(const char* title_id, bool BeginPlot(const char* title_id,
const char* x_label = NULL, const char* x_label = NULL,
const char* y_label = NULL, const char* y_label = NULL,
@ -381,17 +390,20 @@ void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char** lab
void SetPlotYAxis(int y_axis); void SetPlotYAxis(int y_axis);
// Convert pixels to a position in the current plot's coordinate system. A negative y_axis uses the current value of SetPlotYAxis (0 initially). // Convert pixels to a position in the current plot's coordinate system. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
ImPlotPoint PixelsToPlot(const ImVec2& pix, int y_axis = -1); ImPlotPoint PixelsToPlot(const ImVec2& pix, int y_axis = IMPLOT_AUTO);
ImPlotPoint PixelsToPlot(float x, float y, int y_axis = -1); ImPlotPoint PixelsToPlot(float x, float y, int y_axis = IMPLOT_AUTO);
// Convert a position in the current plot's coordinate system to pixels. A negative y_axis uses the current value of SetPlotYAxis (0 initially). // Convert a position in the current plot's coordinate system to pixels. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
ImVec2 PlotToPixels(const ImPlotPoint& plt, int y_axis = -1); ImVec2 PlotToPixels(const ImPlotPoint& plt, int y_axis = IMPLOT_AUTO);
ImVec2 PlotToPixels(double x, double y, int y_axis = -1); ImVec2 PlotToPixels(double x, double y, int y_axis = IMPLOT_AUTO);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Plot Queries // Plot Queries
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Use these functions to retrieve information about the current plot. They
// MUST be called between BeginPlot and EndPlot!
// Get the current Plot position (top-left) in pixels. // Get the current Plot position (top-left) in pixels.
ImVec2 GetPlotPos(); ImVec2 GetPlotPos();
// Get the curent Plot size in pixels. // Get the curent Plot size in pixels.
@ -403,18 +415,18 @@ bool IsPlotXAxisHovered();
// Returns true if the YAxis[n] plot area in the current plot is hovered. // Returns true if the YAxis[n] plot area in the current plot is hovered.
bool IsPlotYAxisHovered(int y_axis = 0); bool IsPlotYAxisHovered(int y_axis = 0);
// Returns the mouse position in x,y coordinates of the current plot. A negative y_axis uses the current value of SetPlotYAxis (0 initially). // Returns the mouse position in x,y coordinates of the current plot. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
ImPlotPoint GetPlotMousePos(int y_axis = -1); ImPlotPoint GetPlotMousePos(int y_axis = IMPLOT_AUTO);
// Returns the current plot axis range. A negative y_axis uses the current value of SetPlotYAxis (0 initially). // Returns the current plot axis range. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
ImPlotLimits GetPlotLimits(int y_axis = -1); ImPlotLimits GetPlotLimits(int y_axis = IMPLOT_AUTO);
// Returns true if the current plot is being queried. // Returns true if the current plot is being queried.
bool IsPlotQueried(); bool IsPlotQueried();
// Returns the current plot query bounds. // Returns the current plot query bounds.
ImPlotLimits GetPlotQuery(int y_axis = -1); ImPlotLimits GetPlotQuery(int y_axis = IMPLOT_AUTO);
// Returns true if a plot item legend entry is hovered. // Returns true if a plot item legend entry is hovered.
bool IsLegendEntryHovered(const char* label_id); bool IsLegendEntryHovered(const char* label_id);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Plot and Item Styling and Colormaps // Plot and Item Styling
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Provides access to plot style structure for permanant modifications to colors, sizes, etc. // Provides access to plot style structure for permanant modifications to colors, sizes, etc.
@ -429,14 +441,14 @@ void StyleColorsDark(ImPlotStyle* dst = NULL);
// Style colors for ImGui "Light". // Style colors for ImGui "Light".
void StyleColorsLight(ImPlotStyle* dst = NULL); void StyleColorsLight(ImPlotStyle* dst = NULL);
// Special color used to indicate that a style color should be deduced automatically from ImGui style or ImPlot colormaps. // Use PushStyleX to temporarily modify your ImPlotStyle. The modification
#define IMPLOT_COL_AUTO ImVec4(0,0,0,-1) // will last until the matching call to PopStyleX. You MUST call a pop for
// every push, otherwise you will leak memory! This behaves just like ImGui.
// Temporarily modify a plot color. Don't forget to call PopStyleColor! // Temporarily modify a plot color. Don't forget to call PopStyleColor!
void PushStyleColor(ImPlotCol idx, ImU32 col); void PushStyleColor(ImPlotCol idx, ImU32 col);
// Temporarily modify a plot color. Don't forget to call PopStyleColor!
void PushStyleColor(ImPlotCol idx, const ImVec4& col); void PushStyleColor(ImPlotCol idx, const ImVec4& col);
// Undo temporary color modification. // Undo temporary color modification. Undo multiple pushes at once by increasing count.
void PopStyleColor(int count = 1); void PopStyleColor(int count = 1);
// Temporarily modify a style variable of float type. Don't forget to call PopStyleVar! // Temporarily modify a style variable of float type. Don't forget to call PopStyleVar!
@ -445,9 +457,39 @@ void PushStyleVar(ImPlotStyleVar idx, float val);
void PushStyleVar(ImPlotStyleVar idx, int val); void PushStyleVar(ImPlotStyleVar idx, int val);
// Temporarily modify a style variable of ImVec2 type. Don't forget to call PopStyleVar! // Temporarily modify a style variable of ImVec2 type. Don't forget to call PopStyleVar!
void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val); void PushStyleVar(ImPlotStyleVar idx, const ImVec2& val);
// Undo temporary style modification. // Undo temporary style modification. Undo multiple pushes at once by increasing count.
void PopStyleVar(int count = 1); void PopStyleVar(int count = 1);
// The following can be used to modify the style of the next plot item ONLY. They do
// NOT require calls to PopStyleX. Leave style attributes you don't want modified to
// IMPLOT_AUTO or IMPLOT_AUTO_COL. Automatic styles will be deduced from the current
// values in the your ImPlotStyle or from Colormap data.
// Set the line color and weight for the next item only.
void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO);
// Set the fill color for the next item only.
void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);
// Set the marker style for the next item only.
void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL);
// Set the error bar style for the next item only.
void SetNextErrorBarStyle(const ImVec4& col = IMPLOT_AUTO_COL, float size = IMPLOT_AUTO, float weight = IMPLOT_AUTO);
// Returns the null terminated string name for an ImPlotCol.
const char* GetStyleColorName(ImPlotCol color);
//-----------------------------------------------------------------------------
// Colormaps
//-----------------------------------------------------------------------------
// Item styling is based on Colormaps when the relevant ImPlotCol is set to
// IMPLOT_AUTO_COL (default). Several built in colormaps are available and can be
// toggled in the demo. You can push/pop or set your own colormaps as well.
// The Colormap data will be ignored and a custom color will be used if you have either:
// 1) Modified an item style color in your ImPlotStyle to anything but IMPLOT_AUTO_COL.
// 2) Pushed an item style color using PushStyleColor().
// 3) Set the next item style with a SetNextXStyle function.
// Temporarily switch to one of the built-in colormaps. // Temporarily switch to one of the built-in colormaps.
void PushColormap(ImPlotColormap colormap); void PushColormap(ImPlotColormap colormap);
// Temporarily switch to your custom colormap. The pointer data must persist until the matching call to PopColormap! // Temporarily switch to your custom colormap. The pointer data must persist until the matching call to PopColormap!
@ -458,22 +500,18 @@ void PopColormap(int count = 1);
void SetColormap(const ImVec4* colormap, int size); void SetColormap(const ImVec4* colormap, int size);
// Permanently switch to one of the built-in colormaps. If samples is greater than 1, the map will be linearly resampled. Don't call this each frame. // Permanently switch to one of the built-in colormaps. If samples is greater than 1, the map will be linearly resampled. Don't call this each frame.
void SetColormap(ImPlotColormap colormap, int samples = 0); void SetColormap(ImPlotColormap colormap, int samples = 0);
// Returns the size of the current colormap. // Returns the size of the current colormap.
int GetColormapSize(); int GetColormapSize();
// Returns a color from the Color map given an index >= 0 (modulo will be performed) // Returns a color from the Color map given an index >= 0 (modulo will be performed).
ImVec4 GetColormapColor(int index); ImVec4 GetColormapColor(int index);
// Linearly interpolates a color from the current colormap given t between 0 and 1. // Linearly interpolates a color from the current colormap given t between 0 and 1.
ImVec4 LerpColormap(float t); ImVec4 LerpColormap(float t);
// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired. // Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired.
ImVec4 NextColormapColor(); ImVec4 NextColormapColor();
// Renders a vertical color scale using the current color map. Call this outside of Begin/EndPlot.
const char* GetStyleColorName(ImPlotCol color);
// Returns a null terminated string name for a built-in colormap
const char* GetColormapName(ImPlotColormap colormap);
// Renders a vertical color scale using the current color map.
void ShowColormapScale(double scale_min, double scale_max, float height); void ShowColormapScale(double scale_min, double scale_max, float height);
// Returns a null terminated string name for a built-in colormap.
const char* GetColormapName(ImPlotColormap colormap);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Miscellaneous // Miscellaneous
@ -489,6 +527,8 @@ void ShowStyleEditor(ImPlotStyle* ref = NULL);
// Add basic help/info block (not a window): how to manipulate ImPlot as an end-user. // Add basic help/info block (not a window): how to manipulate ImPlot as an end-user.
void ShowUserGuide(); void ShowUserGuide();
// Get the plot draw list for rendering to the current plot area.
ImDrawList* GetPlotDrawList();
// Push clip rect for rendering to current plot area. // Push clip rect for rendering to current plot area.
void PushPlotClipRect(); void PushPlotClipRect();
// Pop plot clip rect. // Pop plot clip rect.

View File

@ -236,16 +236,11 @@ void ShowDemoWindow(bool* p_open) {
xs2[i] = i * 0.1f; xs2[i] = i * 0.1f;
ys2[i] = xs2[i] * xs2[i]; ys2[i] = xs2[i] * xs2[i];
} }
static float weight = ImPlot::GetStyle().LineWeight;
ImGui::BulletText("Anti-aliasing can be enabled from the plot's context menu (see Help)."); ImGui::BulletText("Anti-aliasing can be enabled from the plot's context menu (see Help).");
ImGui::DragFloat("Line Weight", &weight, 0.05f, 1.0f, 5.0f, "%.2f px");
if (ImPlot::BeginPlot("Line Plot", "x", "f(x)")) { if (ImPlot::BeginPlot("Line Plot", "x", "f(x)")) {
ImPlot::PushStyleVar(ImPlotStyleVar_LineWeight, weight);
ImPlot::PlotLine("sin(x)", xs1, ys1, 1001); ImPlot::PlotLine("sin(x)", xs1, ys1, 1001);
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Circle); ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);
ImPlot::PlotLine("x^2", xs2, ys2, 11); ImPlot::PlotLine("x^2", xs2, ys2, 11);
ImPlot::PopStyleVar(2);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@ -325,11 +320,10 @@ void ShowDemoWindow(bool* p_open) {
if (ImPlot::BeginPlot("Scatter Plot", NULL, NULL)) { if (ImPlot::BeginPlot("Scatter Plot", NULL, NULL)) {
ImPlot::PlotScatter("Data 1", xs1, ys1, 100); ImPlot::PlotScatter("Data 1", xs1, ys1, 100);
ImPlot::PushStyleVar(ImPlotStyleVar_MarkerSize, 6);
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Square);
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f); ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6, ImVec4(0,1,0,0.5f), IMPLOT_AUTO, ImVec4(0,1,0,1));
ImPlot::PlotScatter("Data 2", xs2, ys2, 50); ImPlot::PlotScatter("Data 2", xs2, ys2, 50);
ImPlot::PopStyleVar(3); ImPlot::PopStyleVar();
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@ -378,29 +372,25 @@ void ShowDemoWindow(bool* p_open) {
static t_float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f}; static t_float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f};
static t_float err3[5] = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f}; static t_float err3[5] = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f};
static t_float err4[5] = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f}; static t_float err4[5] = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f};
static float size = ImPlot::GetStyle().ErrorBarSize;
static float weight = ImPlot::GetStyle().ErrorBarWeight;
ImGui::DragFloat("Error Bar Size", &size, 0.1f, 0, 10,"%.2f px");
ImGui::DragFloat("Error Bar Weight",&weight,0.01f,1,3,"%.2f px");
ImPlot::SetNextPlotLimits(0, 6, 0, 10); ImPlot::SetNextPlotLimits(0, 6, 0, 10);
if (ImPlot::BeginPlot("##ErrorBars",NULL,NULL)) { if (ImPlot::BeginPlot("##ErrorBars",NULL,NULL)) {
ImPlot::PushStyleVar(ImPlotStyleVar_ErrorBarSize, size);
ImPlot::PushStyleVar(ImPlotStyleVar_ErrorBarWeight, weight);
ImPlot::PlotBars("Bar", xs, bar, 5, 0.5f); ImPlot::PlotBars("Bar", xs, bar, 5, 0.5f);
// error bars can be grouped with the associated item by using the same label ID
ImPlot::PlotErrorBars("Bar", xs, bar, err1, 5); ImPlot::PlotErrorBars("Bar", xs, bar, err1, 5);
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Circle);
ImPlot::PushStyleColor(ImPlotCol_ErrorBar, ImPlot::GetColormapColor(1)); ImPlot::SetNextErrorBarStyle(ImPlot::GetColormapColor(1), 0);
ImPlot::PlotErrorBars("Line", xs, lin1, err1, err2, 5); ImPlot::PlotErrorBars("Line", xs, lin1, err1, err2, 5);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);
ImPlot::PlotLine("Line", xs, lin1, 5); ImPlot::PlotLine("Line", xs, lin1, 5);
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Square);
ImPlot::PushStyleColor(ImPlotCol_ErrorBar, ImPlot::GetColormapColor(2)); ImPlot::PushStyleColor(ImPlotCol_ErrorBar, ImPlot::GetColormapColor(2));
ImPlot::PlotErrorBars("Scatter", xs, lin2, err2, 5); ImPlot::PlotErrorBars("Scatter", xs, lin2, err2, 5);
ImPlot::PlotErrorBarsH("Scatter", xs, lin2, err3, err4, 5); ImPlot::PlotErrorBarsH("Scatter", xs, lin2, err3, err4, 5);
ImPlot::PopStyleColor();
ImPlot::PlotScatter("Scatter", xs, lin2, 5); ImPlot::PlotScatter("Scatter", xs, lin2, 5);
ImPlot::PopStyleVar(4);
ImPlot::PopStyleColor(2);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@ -517,7 +507,7 @@ void ShowDemoWindow(bool* p_open) {
// two methods of plotting Data // two methods of plotting Data
// as ImVec2* (or ImPlot*): // as ImVec2* (or ImPlot*):
ImPlot::PlotLine("Data 1", &rdata1.Data[0], rdata1.Data.size()); ImPlot::PlotLine("Data 1", &rdata1.Data[0], rdata1.Data.size());
// as float*, float* (or double*, double*) // as float*, float* (or double*, double*) with stride of 2 * sizeof
ImPlot::PlotLine("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(t_float)); ImPlot::PlotLine("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(t_float));
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -534,37 +524,30 @@ void ShowDemoWindow(bool* p_open) {
t_float xs[2] = {1,4}; t_float xs[2] = {1,4};
t_float ys[2] = {10,11}; t_float ys[2] = {10,11};
ImPlot::PushStyleVar(ImPlotStyleVar_MarkerSize, mk_size);
ImPlot::PushStyleVar(ImPlotStyleVar_MarkerWeight, mk_weight);
// filled markers // filled markers
for (int m = 1; m < ImPlotMarker_COUNT; ++m) { for (int m = 1; m < ImPlotMarker_COUNT; ++m) {
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, m);
ImGui::PushID(m); ImGui::PushID(m);
ImPlot::SetNextMarkerStyle(m, mk_size, IMPLOT_AUTO_COL, mk_weight);
ImPlot::PlotLine("##Filled", xs, ys, 2); ImPlot::PlotLine("##Filled", xs, ys, 2);
ImGui::PopID(); ImGui::PopID();
ImPlot::PopStyleVar();
ys[0]--; ys[1]--; ys[0]--; ys[1]--;
} }
xs[0] = 6; xs[1] = 9; ys[0] = 10; ys[1] = 11; xs[0] = 6; xs[1] = 9; ys[0] = 10; ys[1] = 11;
// open markers // open markers
ImPlot::PushStyleColor(ImPlotCol_MarkerFill, ImVec4(0,0,0,0));
for (int m = 1; m < ImPlotMarker_COUNT; ++m) { for (int m = 1; m < ImPlotMarker_COUNT; ++m) {
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, m);
ImGui::PushID(m); ImGui::PushID(m);
ImPlot::SetNextMarkerStyle(m, mk_size, ImVec4(0,0,0,0), mk_weight);
ImPlot::PlotLine("##Open", xs, ys, 2); ImPlot::PlotLine("##Open", xs, ys, 2);
ImGui::PopID(); ImGui::PopID();
ImPlot::PopStyleVar();
ys[0]--; ys[1]--; ys[0]--; ys[1]--;
} }
ImPlot::PopStyleColor();
ImPlot::PopStyleVar(2);
ImPlot::PlotText("Filled Markers", 2.5f, 6.0f); ImPlot::PlotText("Filled Markers", 2.5f, 6.0f);
ImPlot::PlotText("Open Markers", 7.5f, 6.0f); ImPlot::PlotText("Open Markers", 7.5f, 6.0f);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,0,1,1)); ImPlot::PushStyleColor(ImPlotCol_InlayText, ImVec4(1,0,1,1));
ImPlot::PlotText("Vertical Text", 5.0f, 6.0f, true); ImPlot::PlotText("Vertical Text", 5.0f, 6.0f, true);
ImGui::PopStyleColor(); ImPlot::PopStyleColor();
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -652,7 +635,6 @@ void ShowDemoWindow(bool* p_open) {
ImPlotPoint pt = ImPlot::GetPlotMousePos(); ImPlotPoint pt = ImPlot::GetPlotMousePos();
data.push_back(t_float2((t_float)pt.x, (t_float)pt.y)); data.push_back(t_float2((t_float)pt.x, (t_float)pt.y));
} }
ImPlot::PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Diamond);
if (data.size() > 0) if (data.size() > 0)
ImPlot::PlotScatter("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(t_float)); ImPlot::PlotScatter("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(t_float));
if (ImPlot::IsPlotQueried() && data.size() > 0) { if (ImPlot::IsPlotQueried() && data.size() > 0) {
@ -669,10 +651,10 @@ void ShowDemoWindow(bool* p_open) {
if (cnt > 0) { if (cnt > 0) {
avg.x = avg.x / cnt; avg.x = avg.x / cnt;
avg.y = avg.y / cnt; avg.y = avg.y / cnt;
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square);
ImPlot::PlotScatter("Average", &avg.x, &avg.y, 1); ImPlot::PlotScatter("Average", &avg.x, &avg.y, 1);
} }
} }
ImPlot::PopStyleVar();
range = ImPlot::GetPlotLimits(); range = ImPlot::GetPlotLimits();
query = ImPlot::GetPlotQuery(); query = ImPlot::GetPlotQuery();
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -1045,8 +1027,8 @@ void ShowDemoWindow(bool* p_open) {
ImVec2 rmin = ImPlot::PlotToPixels(ImPlotPoint(0.25f, 0.75f)); ImVec2 rmin = ImPlot::PlotToPixels(ImPlotPoint(0.25f, 0.75f));
ImVec2 rmax = ImPlot::PlotToPixels(ImPlotPoint(0.75f, 0.25f)); ImVec2 rmax = ImPlot::PlotToPixels(ImPlotPoint(0.75f, 0.25f));
ImPlot::PushPlotClipRect(); ImPlot::PushPlotClipRect();
ImGui::GetWindowDrawList()->AddCircleFilled(cntr,20,IM_COL32(255,255,0,255),20); ImPlot::GetPlotDrawList()->AddCircleFilled(cntr,20,IM_COL32(255,255,0,255),20);
ImGui::GetWindowDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255)); ImPlot::GetPlotDrawList()->AddRect(rmin, rmax, IM_COL32(128,0,255,255));
ImPlot::PopPlotClipRect(); ImPlot::PopPlotClipRect();
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -1124,10 +1106,10 @@ void StyleSeaborn() {
ImPlotStyle& style = ImPlot::GetStyle(); ImPlotStyle& style = ImPlot::GetStyle();
ImVec4* colors = style.Colors; ImVec4* colors = style.Colors;
colors[ImPlotCol_Line] = IMPLOT_COL_AUTO; colors[ImPlotCol_Line] = IMPLOT_AUTO_COL;
colors[ImPlotCol_Fill] = IMPLOT_COL_AUTO; colors[ImPlotCol_Fill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerOutline] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerOutline] = IMPLOT_AUTO_COL;
colors[ImPlotCol_MarkerFill] = IMPLOT_COL_AUTO; colors[ImPlotCol_MarkerFill] = IMPLOT_AUTO_COL;
colors[ImPlotCol_ErrorBar] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); colors[ImPlotCol_ErrorBar] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
colors[ImPlotCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImPlotCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImPlotCol_PlotBg] = ImVec4(0.92f, 0.92f, 0.95f, 1.00f); colors[ImPlotCol_PlotBg] = ImVec4(0.92f, 0.92f, 0.95f, 1.00f);
@ -1200,26 +1182,19 @@ int BinarySearch(const double* arr, int l, int r, double x) {
} }
void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip, float width_percent, ImVec4 bullCol, ImVec4 bearCol) { void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip, float width_percent, ImVec4 bullCol, ImVec4 bearCol) {
// get current implot context // begin plot item
ImPlotContext* implot = ImPlot::GetCurrentContext(); if (ImPlot::BeginItem(label_id)) {
// register item
ImPlotItem* item = ImPlot::RegisterOrGetItem(label_id);
// override legend icon color // override legend icon color
item->Color = ImVec4(1,1,1,1); ImPlot::GetCurrentItem()->Color = ImVec4(1,1,1,1);
// return if item not shown (i.e. hidden by legend button)
if (!item->Show)
return;
// fit data if requested // fit data if requested
if (implot->FitThisFrame) { if (ImPlot::FitThisFrame()) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
ImPlot::FitPoint(ImPlotPoint(xs[i], lows[i])); ImPlot::FitPoint(ImPlotPoint(xs[i], lows[i]));
ImPlot::FitPoint(ImPlotPoint(xs[i], highs[i])); ImPlot::FitPoint(ImPlotPoint(xs[i], highs[i]));
} }
} }
// get ImGui window DrawList // get ImGui window DrawList
ImDrawList* draw_list = ImGui::GetWindowDrawList(); ImDrawList* draw_list = ImPlot::GetPlotDrawList();
// push clip rect for the current plot
ImPlot::PushPlotClipRect();
// calc real value width // calc real value width
double half_width = count > 1 ? (xs[1] - xs[0]) * width_percent : width_percent; double half_width = count > 1 ? (xs[1] - xs[0]) * width_percent : width_percent;
// render data // render data
@ -1232,23 +1207,18 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens
draw_list->AddLine(low_pos, high_pos, color); draw_list->AddLine(low_pos, high_pos, color);
draw_list->AddRectFilled(open_pos, close_pos, color); draw_list->AddRectFilled(open_pos, close_pos, color);
} }
// pop clip rect for the current plot
ImPlot::PopPlotClipRect();
// custom tool // custom tool
if (!ImPlot::IsPlotHovered() || !tooltip) if (ImPlot::IsPlotHovered() && tooltip) {
return;
ImPlotPoint mouse = ImPlot::GetPlotMousePos(); ImPlotPoint mouse = ImPlot::GetPlotMousePos();
mouse.x = round(mouse.x); mouse.x = round(mouse.x);
float tool_l = ImPlot::PlotToPixels(mouse.x - half_width * 1.5, mouse.y).x; float tool_l = ImPlot::PlotToPixels(mouse.x - half_width * 1.5, mouse.y).x;
float tool_r = ImPlot::PlotToPixels(mouse.x + half_width * 1.5, mouse.y).x; float tool_r = ImPlot::PlotToPixels(mouse.x + half_width * 1.5, mouse.y).x;
float tool_t = ImPlot::GetPlotPos().y; float tool_t = ImPlot::GetPlotPos().y;
float tool_b = tool_t + ImPlot::GetPlotSize().y; float tool_b = tool_t + ImPlot::GetPlotSize().y;
ImPlot::PushPlotClipRect();
draw_list->AddRectFilled(ImVec2(tool_l, tool_t), ImVec2(tool_r, tool_b), IM_COL32(0,255,255,64)); draw_list->AddRectFilled(ImVec2(tool_l, tool_t), ImVec2(tool_r, tool_b), IM_COL32(0,255,255,64));
ImPlot::PopPlotClipRect();
// find mouse location index // find mouse location index
int idx = BinarySearch(xs, 0, count - 1, mouse.x); int idx = BinarySearch(xs, 0, count - 1, mouse.x);
// render tool tip // render tool tip (won't be affected by plot clip rect)
if (idx != -1) { if (idx != -1) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::Text("Day: %.0f", xs[idx]); ImGui::Text("Day: %.0f", xs[idx]);
@ -1259,6 +1229,10 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
} }
// end plot item
ImPlot::EndItem();
}
}
} // namespace MyImplot } // namespace MyImplot
@ -1334,9 +1308,8 @@ void ShowBenchmarkTool() {
if (running) { if (running) {
for (int i = 0; i < L; ++i) { for (int i = 0; i < L; ++i) {
ImGui::PushID(i); ImGui::PushID(i);
ImPlot::PushStyleColor(ImPlotCol_Line, items[i].Col); ImPlot::SetNextLineStyle(items[i].Col);
ImPlot::PlotLine("##item", items[i].Data, 1000); ImPlot::PlotLine("##item", items[i].Data, 1000);
ImPlot::PopStyleColor();
ImGui::PopID(); ImGui::PopID();
} }
} }

View File

@ -143,6 +143,20 @@ struct ImArray {
const int Size = N; const int Size = N;
}; };
//-----------------------------------------------------------------------------
// [SECTION] ImPlot Enums
//-----------------------------------------------------------------------------
typedef int ImPlotScale; // -> enum ImPlotScale_
// XY axes scaling combinations
enum ImPlotScale_ {
ImPlotScale_LinLin, // linear x, linear y
ImPlotScale_LogLin, // log x, linear y
ImPlotScale_LinLog, // linear x, log y
ImPlotScale_LogLog // log x, log y
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImPlot Structs // [SECTION] ImPlot Structs
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -285,7 +299,6 @@ struct ImPlotItem
{ {
ImGuiID ID; ImGuiID ID;
ImVec4 Color; ImVec4 Color;
ImPlotMarker Marker;
int NameOffset; int NameOffset;
bool Show; bool Show;
bool Highlight; bool Highlight;
@ -294,7 +307,6 @@ struct ImPlotItem
ImPlotItem() { ImPlotItem() {
ID = 0; ID = 0;
Color = ImPlot::NextColormapColor(); Color = ImPlot::NextColormapColor();
Marker = ImPlotMarker_None;
NameOffset = -1; NameOffset = -1;
Show = true; Show = true;
SeenThisFrame = false; SeenThisFrame = false;
@ -321,7 +333,6 @@ struct ImPlotState
bool Queried; bool Queried;
bool DraggingQuery; bool DraggingQuery;
int ColormapIdx; int ColormapIdx;
int MarkerIdx;
int CurrentYAxis; int CurrentYAxis;
ImPlotState() { ImPlotState() {
@ -358,11 +369,37 @@ struct ImPlotNextPlotData
} }
}; };
// Temporary data storage for upcoming item
struct ImPlotItemStyle {
ImVec4 Colors[5]; // ImPlotCol_Line, ImPlotCol_Fill, ImPlotCol_MarkerOutline, ImPlotCol_MarkerFill, ImPlotCol_ErrorBar
float LineWeight;
ImPlotMarker Marker;
float MarkerSize;
float MarkerWeight;
float FillAlpha;
float ErrorBarSize;
float ErrorBarWeight;
float DigitalBitHeight;
float DigitalBitGap;
bool RenderLine;
bool RenderFill;
bool RenderMarkerLine;
bool RenderMarkerFill;
ImPlotItemStyle() {
for (int i = 0; i < 5; ++i)
Colors[i] = IMPLOT_AUTO_COL;
LineWeight = MarkerWeight = FillAlpha = ErrorBarSize =
ErrorBarSize = ErrorBarWeight = DigitalBitHeight = DigitalBitGap = IMPLOT_AUTO;
Marker = IMPLOT_AUTO;
}
};
// Holds state information that must persist between calls to BeginPlot()/EndPlot() // Holds state information that must persist between calls to BeginPlot()/EndPlot()
struct ImPlotContext { struct ImPlotContext {
// Plot States // Plot States
ImPool<ImPlotState> Plots; ImPool<ImPlotState> Plots;
ImPlotState* CurrentPlot; ImPlotState* CurrentPlot;
ImPlotItem* CurrentItem;
// Legend // Legend
ImVector<int> LegendIndices; ImVector<int> LegendIndices;
@ -385,6 +422,7 @@ struct ImPlotContext {
float YAxisReference[IMPLOT_Y_AXES]; float YAxisReference[IMPLOT_Y_AXES];
// Transformations and Data Extents // Transformations and Data Extents
ImPlotScale Scales[IMPLOT_Y_AXES];
ImRect PixelRange[IMPLOT_Y_AXES]; ImRect PixelRange[IMPLOT_Y_AXES];
double Mx; double Mx;
double My[IMPLOT_Y_AXES]; double My[IMPLOT_Y_AXES];
@ -423,6 +461,7 @@ struct ImPlotContext {
int DigitalPlotItemCnt; int DigitalPlotItemCnt;
int DigitalPlotOffset; int DigitalPlotOffset;
ImPlotNextPlotData NextPlotData; ImPlotNextPlotData NextPlotData;
ImPlotItemStyle NextItemStyle;
ImPlotInputMap InputMap; ImPlotInputMap InputMap;
ImPlotPoint MousePos[IMPLOT_Y_AXES]; ImPlotPoint MousePos[IMPLOT_Y_AXES];
}; };
@ -461,6 +500,17 @@ void BustPlotCache();
void UpdateTransformCache(); void UpdateTransformCache();
// Extends the current plots axes so that it encompasses point p // Extends the current plots axes so that it encompasses point p
void FitPoint(const ImPlotPoint& p); void FitPoint(const ImPlotPoint& p);
// Returns true if the user has requested data to be fit.
inline bool FitThisFrame() { return GImPlot->FitThisFrame; }
// Gets the current y-axis for the current plot
inline int GetCurrentYAxis() { return GImPlot->CurrentPlot->CurrentYAxis; }
// Gets the XY scale for the current plot and y-axis
inline ImPlotScale GetCurrentScale() { return GImPlot->Scales[GetCurrentYAxis()]; }
// Begins a new item. Returns false if the item should not be plotted. Pushes PlotClipRect.
bool BeginItem(const char* label_id, ImPlotCol recolor_from = -1);
// Ends an item (call only if BeginItem returns true). Pops PlotClipRect.
void EndItem();
// Register or get an existing item from the current plot // Register or get an existing item from the current plot
ImPlotItem* RegisterOrGetItem(const char* label_id); ImPlotItem* RegisterOrGetItem(const char* label_id);
@ -470,9 +520,20 @@ ImPlotItem* GetItem(int i);
ImPlotItem* GetItem(const char* label_id); ImPlotItem* GetItem(const char* label_id);
// Gets a plot item from a specific plot // Gets a plot item from a specific plot
ImPlotItem* GetItem(const char* plot_title, const char* item_label_id); ImPlotItem* GetItem(const char* plot_title, const char* item_label_id);
// Gets the current item
ImPlotItem* GetCurrentItem();
// Busts the cache for every item for every plot in the current context. // Busts the cache for every item for every plot in the current context.
void BustItemCache(); void BustItemCache();
// Get styling data for next item (call between Begin/EndItem)
inline const ImPlotItemStyle& GetItemStyle() { return GImPlot->NextItemStyle; }
// Recolors an item legend icon from an the current ImPlotCol if it is not automatic (i.e. alpha != -1)
inline void TryRecolorItem(ImPlotItem* item, ImPlotCol idx) {
if (GImPlot->Style.Colors[idx].w != -1)
item->Color = GImPlot->Style.Colors[idx];
}
// Returns the number of entries in the current legend // Returns the number of entries in the current legend
int GetLegendCount(); int GetLegendCount();
// Gets the ith entry string for the current legend // Gets the ith entry string for the current legend
@ -500,8 +561,6 @@ double NiceNum(double x, bool round);
void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL); void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
// Calculates the size of vertical text // Calculates the size of vertical text
ImVec2 CalcTextSizeVertical(const char *text); ImVec2 CalcTextSizeVertical(const char *text);
// Returns white or black text given background color
inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.729 ? IM_COL32_BLACK : IM_COL32_WHITE; }
// Returns true if val is NAN or INFINITY // Returns true if val is NAN or INFINITY
inline bool NanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); } inline bool NanOrInf(double val) { return val == HUGE_VAL || val == -HUGE_VAL || isnan(val); }
@ -551,68 +610,17 @@ ImVec4 LerpColormap(const ImVec4* colormap, int size, float t);
// Resamples a colormap. #size_out must be greater than 1. // Resamples a colormap. #size_out must be greater than 1.
void ResampleColormap(const ImVec4* colormap_in, int size_in, ImVec4* colormap_out, int size_out); void ResampleColormap(const ImVec4* colormap_in, int size_in, ImVec4* colormap_out, int size_out);
// Returns true if a color is set to be automatically determined
inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
// Returns true if a style color is set to be automaticaly determined // Returns true if a style color is set to be automaticaly determined
inline bool IsColorAuto(ImPlotCol idx) { return GImPlot->Style.Colors[idx].w == -1; } inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
// Returns the automatically deduced style color // Returns the automatically deduced style color
ImVec4 GetAutoColor(ImPlotCol idx); ImVec4 GetAutoColor(ImPlotCol idx);
// Returns the style color whether it is automatic or custom set // Returns the style color whether it is automatic or custom set
inline ImVec4 GetStyleColorVec4(ImPlotCol idx) {return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; } inline ImVec4 GetStyleColorVec4(ImPlotCol idx) {return IsColorAuto(idx) ? GetAutoColor(idx) : GImPlot->Style.Colors[idx]; }
inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); } inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
// Returns white or black text given background color
// Recolors an item legend icon from an the current ImPlotCol if it is not automatic (i.e. alpha != -1) inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.729 ? IM_COL32_BLACK : IM_COL32_WHITE; }
inline void TryRecolorItem(ImPlotItem* item, ImPlotCol idx) {
if (GImPlot->Style.Colors[idx].w != -1)
item->Color = GImPlot->Style.Colors[idx];
}
// Returns true if lines will render (e.g. basic lines, bar outlines)
inline bool WillLineRender() {
return GImPlot->Style.Colors[ImPlotCol_Line].w != 0 && GImPlot->Style.LineWeight > 0;
}
// Returns true if fills will render (e.g. shaded plots, bar fills)
inline bool WillFillRender() {
return GImPlot->Style.Colors[ImPlotCol_Fill].w != 0 && GImPlot->Style.FillAlpha > 0;
}
// Returns true if marker outlines will render
inline bool WillMarkerOutlineRender() {
return GImPlot->Style.Colors[ImPlotCol_MarkerOutline].w != 0 && GImPlot->Style.MarkerWeight > 0;
}
// Returns true if mark fill will render
inline bool WillMarkerFillRender() {
return GImPlot->Style.Colors[ImPlotCol_MarkerFill].w != 0 && GImPlot->Style.FillAlpha > 0;
}
// Gets the line color for an item
inline ImVec4 GetLineColor(ImPlotItem* item) {
return IsColorAuto(ImPlotCol_Line) ? item->Color : GImPlot->Style.Colors[ImPlotCol_Line];
}
// Gets the fill color for an item
inline ImVec4 GetItemFillColor(ImPlotItem* item) {
ImVec4 col = IsColorAuto(ImPlotCol_Fill) ? item->Color : GImPlot->Style.Colors[ImPlotCol_Fill];
col.w *= GImPlot->Style.FillAlpha;
return col;
}
// Gets the marker outline color for an item
inline ImVec4 GetMarkerOutlineColor(ImPlotItem* item) {
return IsColorAuto(ImPlotCol_MarkerOutline) ? GetLineColor(item) : GImPlot->Style.Colors[ImPlotCol_MarkerOutline];
}
// Gets the marker fill color for an item
inline ImVec4 GetMarkerFillColor(ImPlotItem* item) {
ImVec4 col = IsColorAuto(ImPlotCol_MarkerFill) ? GetLineColor(item) :GImPlot->Style.Colors[ImPlotCol_MarkerFill];
col.w *= GImPlot->Style.FillAlpha;
return col;
}
// Gets the error bar color
inline ImVec4 GetErrorBarColor() {
return GetStyleColorVec4(ImPlotCol_ErrorBar);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Internal / Experimental Plotters // [SECTION] Internal / Experimental Plotters

View File

@ -44,6 +44,163 @@
namespace ImPlot { namespace ImPlot {
//-----------------------------------------------------------------------------
// Item Utils
//-----------------------------------------------------------------------------
ImPlotItem* RegisterOrGetItem(const char* label_id) {
ImPlotContext& gp = *GImPlot;
ImGuiID id = ImGui::GetID(label_id);
ImPlotItem* item = gp.CurrentPlot->Items.GetOrAddByKey(id);
if (item->SeenThisFrame)
return item;
item->SeenThisFrame = true;
int idx = gp.CurrentPlot->Items.GetIndex(item);
item->ID = id;
if (ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) {
gp.LegendIndices.push_back(idx);
item->NameOffset = gp.LegendLabels.size();
gp.LegendLabels.append(label_id, label_id + strlen(label_id) + 1);
}
else {
item->Show = true;
}
if (item->Show)
gp.VisibleItemCount++;
return item;
}
ImPlotItem* GetItem(int i) {
ImPlotContext& gp = *GImPlot;
return gp.CurrentPlot->Items.GetByIndex(gp.LegendIndices[i]);
}
ImPlotItem* GetItem(const char* label_id) {
ImPlotContext& gp = *GImPlot;
ImGuiID id = ImGui::GetID(label_id);
return gp.CurrentPlot->Items.GetByKey(id);
}
ImPlotItem* GetItem(const char* plot_title, const char* item_label_id) {
ImPlotState* plot = GetPlot(plot_title);
if (plot) {
ImGuiID id = ImGui::GetID(item_label_id);
return plot->Items.GetByKey(id);
}
return NULL;
}
ImPlotItem* GetCurrentItem() {
ImPlotContext& gp = *GImPlot;
return gp.CurrentItem;
}
void BustItemCache() {
ImPlotContext& gp = *GImPlot;
for (int p = 0; p < gp.Plots.GetSize(); ++p) {
ImPlotState& plot = *gp.Plots.GetByIndex(p);
plot.ColormapIdx = 0;
plot.Items.Clear();
}
}
// Begins a new item. Returns false if the item should not be plotted.
bool BeginItem(const char* label_id, ImPlotCol recolor_from) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotX() needs to be called between BeginPlot() and EndPlot()!");
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show) {
// reset next item data
gp.NextItemStyle = ImPlotItemStyle();
return false;
}
else {
// set current item
gp.CurrentItem = item;
ImPlotItemStyle& s = gp.NextItemStyle;
// override item color
if (recolor_from != -1) {
if (!IsColorAuto(s.Colors[recolor_from]))
item->Color = s.Colors[recolor_from];
else if (!IsColorAuto(gp.Style.Colors[recolor_from]))
item->Color = gp.Style.Colors[recolor_from];
}
// stage next item colors
s.Colors[ImPlotCol_Line] = IsColorAuto(s.Colors[ImPlotCol_Line]) ? ( IsColorAuto(ImPlotCol_Line) ? item->Color : gp.Style.Colors[ImPlotCol_Line] ) : s.Colors[ImPlotCol_Line];
s.Colors[ImPlotCol_Fill] = IsColorAuto(s.Colors[ImPlotCol_Fill]) ? ( IsColorAuto(ImPlotCol_Fill) ? item->Color : gp.Style.Colors[ImPlotCol_Fill] ) : s.Colors[ImPlotCol_Fill];
s.Colors[ImPlotCol_MarkerOutline] = IsColorAuto(s.Colors[ImPlotCol_MarkerOutline]) ? ( IsColorAuto(ImPlotCol_MarkerOutline) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerOutline] ) : s.Colors[ImPlotCol_MarkerOutline];
s.Colors[ImPlotCol_MarkerFill] = IsColorAuto(s.Colors[ImPlotCol_MarkerFill]) ? ( IsColorAuto(ImPlotCol_MarkerFill) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerFill] ) : s.Colors[ImPlotCol_MarkerFill];
s.Colors[ImPlotCol_ErrorBar] = IsColorAuto(s.Colors[ImPlotCol_ErrorBar]) ? ( GetStyleColorVec4(ImPlotCol_ErrorBar) ) : s.Colors[ImPlotCol_ErrorBar];
// stage next item style vars
s.LineWeight = s.LineWeight < 0 ? gp.Style.LineWeight : s.LineWeight;
s.Marker = s.Marker < 0 ? gp.Style.Marker : s.Marker;
s.MarkerSize = s.MarkerSize < 0 ? gp.Style.MarkerSize : s.MarkerSize;
s.MarkerWeight = s.MarkerWeight < 0 ? gp.Style.MarkerWeight : s.MarkerWeight;
s.FillAlpha = s.FillAlpha < 0 ? gp.Style.FillAlpha : s.FillAlpha;
s.ErrorBarSize = s.ErrorBarSize < 0 ? gp.Style.ErrorBarSize : s.ErrorBarSize;
s.ErrorBarWeight = s.ErrorBarWeight < 0 ? gp.Style.ErrorBarWeight : s.ErrorBarWeight;
s.DigitalBitHeight = s.DigitalBitHeight < 0 ? gp.Style.DigitalBitHeight : s.DigitalBitHeight;
s.DigitalBitGap = s.DigitalBitGap < 0 ? gp.Style.DigitalBitGap : s.DigitalBitGap;
// apply alpha modifier(s)
s.Colors[ImPlotCol_Fill].w *= s.FillAlpha;
// s.Colors[ImPlotCol_MarkerFill].w *= s.FillAlpha; // TODO: this should be separate, if it at all
// apply highlight mods
if (item->Highlight) {
s.LineWeight *= 2;
s.MarkerWeight *= 2;
// TODO: highlight fills?
}
// set render flags
s.RenderLine = s.Colors[ImPlotCol_Line].w > 0 && s.LineWeight > 0;
s.RenderFill = s.Colors[ImPlotCol_Fill].w > 0;
s.RenderMarkerLine = s.Colors[ImPlotCol_MarkerOutline].w > 0 && s.MarkerWeight > 0;
s.RenderMarkerFill = s.Colors[ImPlotCol_MarkerFill].w > 0;
// push rendering clip rect
PushPlotClipRect();
return true;
}
}
// Ends an item (call only if BeginItem returns true)
void EndItem() {
ImPlotContext& gp = *GImPlot;
// pop rendering clip rect
PopPlotClipRect();
// reset next item data
gp.NextItemStyle = ImPlotItemStyle();
// set current item
gp.CurrentItem = NULL;
}
void SetNextLineStyle(const ImVec4& col, float weight) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_Line] = col;
gp.NextItemStyle.LineWeight = weight;
}
void SetNextFillStyle(const ImVec4& col, float alpha) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_Fill] = col;
gp.NextItemStyle.FillAlpha = alpha;
}
void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Marker = marker;
gp.NextItemStyle.Colors[ImPlotCol_MarkerFill] = fill;
gp.NextItemStyle.MarkerSize = size;
gp.NextItemStyle.Colors[ImPlotCol_MarkerOutline] = outline;
gp.NextItemStyle.MarkerWeight = weight;
}
void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_ErrorBar] = col;
gp.NextItemStyle.ErrorBarSize = size;
gp.NextItemStyle.ErrorBarWeight = weight;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// GETTERS // GETTERS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -202,10 +359,11 @@ struct GetterError {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Transforms convert points in plot space (i.e. ImPlotPoint) to pixel space (i.e. ImVec2) // Transforms convert points in plot space (i.e. ImPlotPoint) to pixel space (i.e. ImVec2)
// TODO: Cache transformation variables
// Transforms points for linear x and linear y space // Transforms points for linear x and linear y space
struct TransformerLinLin { struct TransformerLinLin {
TransformerLinLin(int y_axis) : YAxis(y_axis) {} TransformerLinLin() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) { inline ImVec2 operator()(double x, double y) {
@ -219,7 +377,7 @@ struct TransformerLinLin {
// Transforms points for log x and linear y space // Transforms points for log x and linear y space
struct TransformerLogLin { struct TransformerLogLin {
TransformerLogLin(int y_axis) : YAxis(y_axis) {} TransformerLogLin() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) { inline ImVec2 operator()(double x, double y) {
@ -235,7 +393,7 @@ struct TransformerLogLin {
// Transforms points for linear x and log y space // Transforms points for linear x and log y space
struct TransformerLinLog { struct TransformerLinLog {
TransformerLinLog(int y_axis) : YAxis(y_axis) {} TransformerLinLog() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) { inline ImVec2 operator()(double x, double y) {
@ -250,7 +408,7 @@ struct TransformerLinLog {
// Transforms points for log x and log y space // Transforms points for log x and log y space
struct TransformerLogLog { struct TransformerLogLog {
TransformerLogLog(int y_axis) : YAxis(y_axis) {} TransformerLogLog() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) { inline ImVec2 operator()(double x, double y) {
@ -583,9 +741,8 @@ inline void RenderMarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bo
} }
template <typename Transformer, typename Getter> template <typename Transformer, typename Getter>
inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& DrawList, bool rend_mk_line, ImU32 col_mk_line, bool rend_mk_fill, ImU32 col_mk_fill) { inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& DrawList, ImPlotMarker marker, float size, bool rend_mk_line, ImU32 col_mk_line, float weight, bool rend_mk_fill, ImU32 col_mk_fill) {
static void (*marker_table[])(ImDrawList&, const ImVec2&, float s, bool, ImU32, bool, ImU32, float) = { static void (*marker_table[])(ImDrawList&, const ImVec2&, float s, bool, ImU32, bool, ImU32, float) = {
NULL,
RenderMarkerCircle, RenderMarkerCircle,
RenderMarkerSquare, RenderMarkerSquare,
RenderMarkerDiamond , RenderMarkerDiamond ,
@ -601,7 +758,7 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImVec2 c = transformer(getter(i)); ImVec2 c = transformer(getter(i));
if (gp.BB_Plot.Contains(c)) if (gp.BB_Plot.Contains(c))
marker_table[gp.Style.Marker](DrawList, c, gp.Style.MarkerSize, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, gp.Style.MarkerWeight); marker_table[marker](DrawList, c, size, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill, weight);
} }
} }
@ -610,159 +767,145 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
inline void PlotEx(const char* label_id, Getter getter) inline void PlotLineEx(const char* label_id, Getter getter) {
{ if (BeginItem(label_id, ImPlotCol_Line)) {
ImPlotContext& gp = *GImPlot; if (FitThisFrame()) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotEx() needs to be called between BeginPlot() and EndPlot()!");
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
TryRecolorItem(item, ImPlotCol_Line);
// find data extents
if (gp.FitThisFrame) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
FitPoint(p); FitPoint(p);
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
ImDrawList& DrawList = *ImGui::GetWindowDrawList(); ImDrawList& DrawList = *GetPlotDrawList();
ImPlotState* plot = gp.CurrentPlot; if (getter.Count > 1 && s.RenderLine) {
const int y_axis = plot->CurrentYAxis; const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
switch (GetCurrentScale()) {
PushPlotClipRect(); case ImPlotScale_LinLin: RenderLineStrip(getter, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
// render line case ImPlotScale_LogLin: RenderLineStrip(getter, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
if (getter.Count > 1 && WillLineRender()) { case ImPlotScale_LinLog: RenderLineStrip(getter, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
ImU32 col_line = ImGui::GetColorU32(GetLineColor(item)); case ImPlotScale_LogLog: RenderLineStrip(getter, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight; }
if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale))
RenderLineStrip(getter, TransformerLogLog(y_axis), DrawList, line_weight, col_line);
else if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale))
RenderLineStrip(getter, TransformerLogLin(y_axis), DrawList, line_weight, col_line);
else if (ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale))
RenderLineStrip(getter, TransformerLinLog(y_axis), DrawList, line_weight, col_line);
else
RenderLineStrip(getter, TransformerLinLin(y_axis), DrawList, line_weight, col_line);
} }
// render markers // render markers
if (gp.Style.Marker != ImPlotMarker_None) { if (s.Marker != ImPlotMarker_None) {
const bool rend_mk_line = WillMarkerOutlineRender(); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
const bool rend_mk_fill = WillMarkerFillRender(); const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
const ImU32 col_mk_line = ImGui::GetColorU32(GetMarkerOutlineColor(item)); switch (GetCurrentScale()) {
const ImU32 col_mk_fill = ImGui::GetColorU32(GetMarkerFillColor(item)); case ImPlotScale_LinLin: RenderMarkers(getter, TransformerLinLin(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) case ImPlotScale_LogLin: RenderMarkers(getter, TransformerLogLin(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
RenderMarkers(getter, TransformerLogLog(y_axis), DrawList, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill); case ImPlotScale_LinLog: RenderMarkers(getter, TransformerLinLog(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
else if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale)) case ImPlotScale_LogLog: RenderMarkers(getter, TransformerLogLog(), DrawList, s.Marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
RenderMarkers(getter, TransformerLogLin(y_axis), DrawList, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill); }
else if (ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) }
RenderMarkers(getter, TransformerLinLog(y_axis), DrawList, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill); EndItem();
else
RenderMarkers(getter, TransformerLinLin(y_axis), DrawList, rend_mk_line, col_mk_line, rend_mk_fill, col_mk_fill);
} }
PopPlotClipRect();
} }
// float // float
void PlotLine(const char* label_id, const float* values, int count, int offset, int stride) { void PlotLine(const char* label_id, const float* values, int count, int offset, int stride) {
GetterYs<float> getter(values,count,offset,stride); GetterYs<float> getter(values,count,offset,stride);
PlotEx(label_id, getter); PlotLineEx(label_id, getter);
} }
void PlotLine(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { void PlotLine(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) {
GetterXsYs<float> getter(xs,ys,count,offset,stride); GetterXsYs<float> getter(xs,ys,count,offset,stride);
return PlotEx(label_id, getter); return PlotLineEx(label_id, getter);
} }
void PlotLine(const char* label_id, const ImVec2* data, int count, int offset) { void PlotLine(const char* label_id, const ImVec2* data, int count, int offset) {
GetterImVec2 getter(data, count, offset); GetterImVec2 getter(data, count, offset);
return PlotEx(label_id, getter); return PlotLineEx(label_id, getter);
} }
// double // double
void PlotLine(const char* label_id, const double* values, int count, int offset, int stride) { void PlotLine(const char* label_id, const double* values, int count, int offset, int stride) {
GetterYs<double> getter(values,count,offset,stride); GetterYs<double> getter(values,count,offset,stride);
PlotEx(label_id, getter); PlotLineEx(label_id, getter);
} }
void PlotLine(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) { void PlotLine(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) {
GetterXsYs<double> getter(xs,ys,count,offset,stride); GetterXsYs<double> getter(xs,ys,count,offset,stride);
return PlotEx(label_id, getter); return PlotLineEx(label_id, getter);
} }
void PlotLine(const char* label_id, const ImPlotPoint* data, int count, int offset) { void PlotLine(const char* label_id, const ImPlotPoint* data, int count, int offset) {
GetterImPlotPoint getter(data, count, offset); GetterImPlotPoint getter(data, count, offset);
return PlotEx(label_id, getter); return PlotLineEx(label_id, getter);
} }
// custom // custom
void PlotLine(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) { void PlotLine(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
GetterFuncPtrImPlotPoint getter(getter_func,data, count, offset); GetterFuncPtrImPlotPoint getter(getter_func,data, count, offset);
return PlotEx(label_id, getter); return PlotLineEx(label_id, getter);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT SCATTER // PLOT SCATTER
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
inline int PushScatterStyle() { template <typename Getter>
int vars = 1; inline void PlotScatterEx(const char* label_id, Getter getter) {
PushStyleVar(ImPlotStyleVar_LineWeight, 0); if (BeginItem(label_id, ImPlotCol_MarkerOutline)) {
if (GetStyle().Marker == ImPlotMarker_None) { if (FitThisFrame()) {
PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Circle); for (int i = 0; i < getter.Count; ++i) {
vars++; ImPlotPoint p = getter(i);
FitPoint(p);
}
}
const ImPlotItemStyle& s = GetItemStyle();
ImDrawList& DrawList = *GetPlotDrawList();
// render markers
ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle : s.Marker;
if (marker != ImPlotMarker_None) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderMarkers(getter, TransformerLinLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
case ImPlotScale_LogLin: RenderMarkers(getter, TransformerLogLin(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
case ImPlotScale_LinLog: RenderMarkers(getter, TransformerLinLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
case ImPlotScale_LogLog: RenderMarkers(getter, TransformerLogLog(), DrawList, marker, s.MarkerSize, s.RenderMarkerLine, col_line, s.MarkerWeight, s.RenderMarkerFill, col_fill); break;
}
}
EndItem();
} }
return vars;
} }
// float // float
void PlotScatter(const char* label_id, const float* values, int count, int offset, int stride) { void PlotScatter(const char* label_id, const float* values, int count, int offset, int stride) {
int vars = PushScatterStyle(); GetterYs<float> getter(values,count,offset,stride);
PlotLine(label_id, values, count, offset, stride); PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
void PlotScatter(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { void PlotScatter(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) {
int vars = PushScatterStyle(); GetterXsYs<float> getter(xs,ys,count,offset,stride);
PlotLine(label_id, xs, ys, count, offset, stride); return PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
void PlotScatter(const char* label_id, const ImVec2* data, int count, int offset) { void PlotScatter(const char* label_id, const ImVec2* data, int count, int offset) {
int vars = PushScatterStyle(); GetterImVec2 getter(data, count, offset);
PlotLine(label_id, data, count, offset); return PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
// double // double
void PlotScatter(const char* label_id, const double* values, int count, int offset, int stride) { void PlotScatter(const char* label_id, const double* values, int count, int offset, int stride) {
int vars = PushScatterStyle(); GetterYs<double> getter(values,count,offset,stride);
PlotLine(label_id, values, count, offset, stride); PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
void PlotScatter(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) { void PlotScatter(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) {
int vars = PushScatterStyle(); GetterXsYs<double> getter(xs,ys,count,offset,stride);
PlotLine(label_id, xs, ys, count, offset, stride); return PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
void PlotScatter(const char* label_id, const ImPlotPoint* data, int count, int offset) { void PlotScatter(const char* label_id, const ImPlotPoint* data, int count, int offset) {
int vars = PushScatterStyle(); GetterImPlotPoint getter(data, count, offset);
PlotLine(label_id, data, count, offset); return PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
// custom // custom
void PlotScatter(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset) { void PlotScatter(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
int vars = PushScatterStyle(); GetterFuncPtrImPlotPoint getter(getter_func,data, count, offset);
PlotLine(label_id, getter, data, count, offset); return PlotScatterEx(label_id, getter);
PopStyleVar(vars);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -771,19 +914,8 @@ void PlotScatter(const char* label_id, ImPlotPoint (*getter)(void* data, int idx
template <typename Getter1, typename Getter2> template <typename Getter1, typename Getter2>
inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) { inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) {
ImPlotContext& gp = *GImPlot; if (BeginItem(label_id, ImPlotCol_Fill)) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotShaded() needs to be called between BeginPlot() and EndPlot()!"); if (FitThisFrame()) {
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
TryRecolorItem(item, ImPlotCol_Fill);
if (!WillFillRender())
return;
// find data extents
if (gp.FitThisFrame) {
for (int i = 0; i < ImMin(getter1.Count, getter2.Count); ++i) { for (int i = 0; i < ImMin(getter1.Count, getter2.Count); ++i) {
ImPlotPoint p1 = getter1(i); ImPlotPoint p1 = getter1(i);
ImPlotPoint p2 = getter2(i); ImPlotPoint p2 = getter2(i);
@ -791,27 +923,22 @@ inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2)
FitPoint(p2); FitPoint(p2);
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
ImDrawList & DrawList = *ImGui::GetWindowDrawList(); ImDrawList & DrawList = *GetPlotDrawList();
ImPlotState* plot = gp.CurrentPlot; if (s.RenderFill) {
const int y_axis = plot->CurrentYAxis; ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
switch (GetCurrentScale()) {
ImU32 col = ImGui::GetColorU32(GetItemFillColor(item)); case ImPlotScale_LinLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLin>(getter1,getter2,TransformerLinLin(), col), DrawList); break;
case ImPlotScale_LogLin: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLin>(getter1,getter2,TransformerLogLin(), col), DrawList); break;
PushPlotClipRect(); case ImPlotScale_LinLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLog>(getter1,getter2,TransformerLinLog(), col), DrawList); break;
if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) case ImPlotScale_LogLog: RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLog>(getter1,getter2,TransformerLogLog(), col), DrawList); break;
RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLog>(getter1,getter2,TransformerLogLog(y_axis), col), DrawList); }
else if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale)) }
RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLogLin>(getter1,getter2,TransformerLogLin(y_axis), col), DrawList); EndItem();
else if (ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) }
RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLog>(getter1,getter2,TransformerLinLog(y_axis), col), DrawList);
else
RenderPrimitives(ShadedRenderer<Getter1,Getter2,TransformerLinLin>(getter1,getter2,TransformerLinLin(y_axis), col), DrawList);
PopPlotClipRect();
} }
// float // float
void PlotShaded(const char* label_id, const float* values, int count, float y_ref, int offset, int stride) { void PlotShaded(const char* label_id, const float* values, int count, float y_ref, int offset, int stride) {
GetterYs<float> getter1(values,count,offset,stride); GetterYs<float> getter1(values,count,offset,stride);
GetterYRef<float> getter2(y_ref, count); GetterYRef<float> getter2(y_ref, count);
@ -859,47 +986,39 @@ void PlotShaded(const char* label_id, ImPlotPoint (*g1)(void* data, int idx), vo
// PLOT BAR V // PLOT BAR V
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// TODO: Migrate to RenderPrimitives
template <typename Getter, typename TWidth> template <typename Getter, typename TWidth>
void PlotBarsEx(const char* label_id, Getter getter, TWidth width) { void PlotBarsEx(const char* label_id, Getter getter, TWidth width) {
ImPlotContext& gp = *GImPlot; if (BeginItem(label_id, ImPlotCol_Fill)) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBars() needs to be called between BeginPlot() and EndPlot()!");
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
TryRecolorItem(item, ImPlotCol_Fill);
const TWidth half_width = width / 2; const TWidth half_width = width / 2;
// find data extents if (FitThisFrame()) {
if (gp.FitThisFrame) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
FitPoint(ImPlotPoint(p.x - half_width, p.y)); FitPoint(ImPlotPoint(p.x - half_width, p.y));
FitPoint(ImPlotPoint(p.x + half_width, 0)); FitPoint(ImPlotPoint(p.x + half_width, 0));
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
ImU32 col_line = ImGui::GetColorU32(GetLineColor(item)); ImDrawList& DrawList = *GetPlotDrawList();
ImU32 col_fill = ImGui::GetColorU32(GetItemFillColor(item)); ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
const bool rend_fill = WillFillRender(); ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
bool rend_line = WillLineRender(); bool rend_line = s.RenderLine;
if (rend_fill && col_line == col_fill) if (s.RenderFill && col_line == col_fill)
rend_line = false; rend_line = false;
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
PushPlotClipRect();
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
if (p.y == 0) if (p.y == 0)
continue; continue;
ImVec2 a = PlotToPixels(p.x - half_width, p.y); ImVec2 a = PlotToPixels(p.x - half_width, p.y);
ImVec2 b = PlotToPixels(p.x + half_width, 0); ImVec2 b = PlotToPixels(p.x + half_width, 0);
if (rend_fill) if (s.RenderFill)
DrawList.AddRectFilled(a, b, col_fill); DrawList.AddRectFilled(a, b, col_fill);
if (rend_line) if (rend_line)
DrawList.AddRect(a, b, col_line, 0, ImDrawCornerFlags_All, gp.Style.LineWeight); DrawList.AddRect(a, b, col_line, 0, ImDrawCornerFlags_All, s.LineWeight);
}
EndItem();
} }
PopPlotClipRect();
} }
// float // float
@ -938,45 +1057,35 @@ void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int i
template <typename Getter, typename THeight> template <typename Getter, typename THeight>
void PlotBarsHEx(const char* label_id, Getter getter, THeight height) { void PlotBarsHEx(const char* label_id, Getter getter, THeight height) {
ImPlotContext& gp = *GImPlot; if (BeginItem(label_id, ImPlotCol_Fill)) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBarsH() needs to be called between BeginPlot() and EndPlot()!");
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
TryRecolorItem(item, ImPlotCol_Fill);
const THeight half_height = height / 2; const THeight half_height = height / 2;
// find data extents if (FitThisFrame()) {
if (gp.FitThisFrame) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
FitPoint(ImPlotPoint(0, p.y - half_height)); FitPoint(ImPlotPoint(0, p.y - half_height));
FitPoint(ImPlotPoint(p.x, p.y + half_height)); FitPoint(ImPlotPoint(p.x, p.y + half_height));
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
ImU32 col_line = ImGui::GetColorU32(GetLineColor(item)); ImDrawList& DrawList = *GetPlotDrawList();
ImU32 col_fill = ImGui::GetColorU32(GetItemFillColor(item)); ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
const bool rend_fill = WillFillRender(); ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
bool rend_line = WillLineRender(); bool rend_line = s.RenderLine;
if (rend_fill && col_line == col_fill) if (s.RenderFill && col_line == col_fill)
rend_line = false; rend_line = false;
PushPlotClipRect();
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
if (p.x == 0) if (p.x == 0)
continue; continue;
ImVec2 a = PlotToPixels(0, p.y - half_height); ImVec2 a = PlotToPixels(0, p.y - half_height);
ImVec2 b = PlotToPixels(p.x, p.y + half_height); ImVec2 b = PlotToPixels(p.x, p.y + half_height);
if (rend_fill) if (s.RenderFill)
DrawList.AddRectFilled(a, b, col_fill); DrawList.AddRectFilled(a, b, col_fill);
if (rend_line) if (rend_line)
DrawList.AddRect(a, b, col_line, 0, ImDrawCornerFlags_All, gp.Style.LineWeight); DrawList.AddRect(a, b, col_line, 0, ImDrawCornerFlags_All, s.LineWeight);
}
EndItem();
} }
PopPlotClipRect();
} }
// float // float
@ -1013,40 +1122,31 @@ void PlotBarsH(const char* label_id, ImPlotPoint (*getter_func)(void* data, int
template <typename Getter> template <typename Getter>
void PlotErrorBarsEx(const char* label_id, Getter getter) { void PlotErrorBarsEx(const char* label_id, Getter getter) {
ImPlotContext& gp = *GImPlot; if (BeginItem(label_id)) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBars() needs to be called between BeginPlot() and EndPlot()!"); if (FitThisFrame()) {
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
// find data extents
if (gp.FitThisFrame) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPointError e = getter(i); ImPlotPointError e = getter(i);
FitPoint(ImPlotPoint(e.X , e.Y - e.Neg)); FitPoint(ImPlotPoint(e.X , e.Y - e.Neg));
FitPoint(ImPlotPoint(e.X , e.Y + e.Pos )); FitPoint(ImPlotPoint(e.X , e.Y + e.Pos ));
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
const ImU32 col = ImGui::GetColorU32(GetErrorBarColor()); ImDrawList& DrawList = *GetPlotDrawList();
const bool rend_whisker = gp.Style.ErrorBarSize > 0; const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
const float half_whisker = gp.Style.ErrorBarSize * 0.5f; const bool rend_whisker = s.ErrorBarSize > 0;
const float half_whisker = s.ErrorBarSize * 0.5f;
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
PushPlotClipRect();
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPointError e = getter(i); ImPlotPointError e = getter(i);
ImVec2 p1 = PlotToPixels(e.X, e.Y - e.Neg); ImVec2 p1 = PlotToPixels(e.X, e.Y - e.Neg);
ImVec2 p2 = PlotToPixels(e.X, e.Y + e.Pos); ImVec2 p2 = PlotToPixels(e.X, e.Y + e.Pos);
DrawList.AddLine(p1,p2,col, gp.Style.ErrorBarWeight); DrawList.AddLine(p1,p2,col, s.ErrorBarWeight);
if (rend_whisker) { if (rend_whisker) {
DrawList.AddLine(p1 - ImVec2(half_whisker, 0), p1 + ImVec2(half_whisker, 0), col, gp.Style.ErrorBarWeight); DrawList.AddLine(p1 - ImVec2(half_whisker, 0), p1 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight);
DrawList.AddLine(p2 - ImVec2(half_whisker, 0), p2 + ImVec2(half_whisker, 0), col, gp.Style.ErrorBarWeight); DrawList.AddLine(p2 - ImVec2(half_whisker, 0), p2 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight);
} }
} }
PopPlotClipRect(); EndItem();
}
} }
// float // float
@ -1077,40 +1177,31 @@ void PlotErrorBars(const char* label_id, const double* xs, const double* ys, con
template <typename Getter> template <typename Getter>
void PlotErrorBarsHEx(const char* label_id, Getter getter) { void PlotErrorBarsHEx(const char* label_id, Getter getter) {
ImPlotContext& gp = *GImPlot; if (BeginItem(label_id)) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBarsH() needs to be called between BeginPlot() and EndPlot()!"); if (FitThisFrame()) {
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
// find data extents
if (gp.FitThisFrame) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPointError e = getter(i); ImPlotPointError e = getter(i);
FitPoint(ImPlotPoint(e.X - e.Neg, e.Y)); FitPoint(ImPlotPoint(e.X - e.Neg, e.Y));
FitPoint(ImPlotPoint(e.X + e.Pos, e.Y)); FitPoint(ImPlotPoint(e.X + e.Pos, e.Y));
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
const ImU32 col = ImGui::GetColorU32(GetErrorBarColor()); ImDrawList& DrawList = *GetPlotDrawList();
const bool rend_whisker = gp.Style.ErrorBarSize > 0; const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
const float half_whisker = gp.Style.ErrorBarSize * 0.5f; const bool rend_whisker = s.ErrorBarSize > 0;
const float half_whisker = s.ErrorBarSize * 0.5f;
ImDrawList& DrawList = *ImGui::GetWindowDrawList();
PushPlotClipRect();
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPointError e = getter(i); ImPlotPointError e = getter(i);
ImVec2 p1 = PlotToPixels(e.X - e.Neg, e.Y); ImVec2 p1 = PlotToPixels(e.X - e.Neg, e.Y);
ImVec2 p2 = PlotToPixels(e.X + e.Pos, e.Y); ImVec2 p2 = PlotToPixels(e.X + e.Pos, e.Y);
DrawList.AddLine(p1, p2, col, gp.Style.ErrorBarWeight); DrawList.AddLine(p1, p2, col, s.ErrorBarWeight);
if (rend_whisker) { if (rend_whisker) {
DrawList.AddLine(p1 - ImVec2(0, half_whisker), p1 + ImVec2(0, half_whisker), col, gp.Style.ErrorBarWeight); DrawList.AddLine(p1 - ImVec2(0, half_whisker), p1 + ImVec2(0, half_whisker), col, s.ErrorBarWeight);
DrawList.AddLine(p2 - ImVec2(0, half_whisker), p2 + ImVec2(0, half_whisker), col, gp.Style.ErrorBarWeight); DrawList.AddLine(p2 - ImVec2(0, half_whisker), p2 + ImVec2(0, half_whisker), col, s.ErrorBarWeight);
} }
} }
PopPlotClipRect(); EndItem();
}
} }
// float // float
@ -1155,25 +1246,20 @@ inline void RenderPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, doub
template <typename T> template <typename T>
void PlotPieChartEx(const char** label_ids, const T* values, int count, T x, T y, T radius, bool normalize, const char* fmt, T angle0) { void PlotPieChartEx(const char** label_ids, const T* values, int count, T x, T y, T radius, bool normalize, const char* fmt, T angle0) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & DrawList = *ImGui::GetWindowDrawList(); ImDrawList & DrawList = *GetPlotDrawList();
T sum = 0; T sum = 0;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
sum += values[i]; sum += values[i];
normalize = normalize || sum > 1.0f; normalize = normalize || sum > 1.0f;
ImPlotPoint center(x,y); ImPlotPoint center(x,y);
PushPlotClipRect(); PushPlotClipRect();
T a0 = angle0 * 2 * IM_PI / 360.0f; T a0 = angle0 * 2 * IM_PI / 360.0f;
T a1 = angle0 * 2 * IM_PI / 360.0f; T a1 = angle0 * 2 * IM_PI / 360.0f;
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
ImPlotItem* item = RegisterOrGetItem(label_ids[i]);
ImU32 col = ImGui::GetColorU32(GetItemFillColor(item));
T percent = normalize ? values[i] / sum : values[i]; T percent = normalize ? values[i] / sum : values[i];
a1 = a0 + 2 * IM_PI * percent; a1 = a0 + 2 * IM_PI * percent;
if (item->Show) { if (BeginItem(label_ids[i])) {
ImU32 col = ImGui::GetColorU32(GetCurrentItem()->Color);
if (percent < 0.5) { if (percent < 0.5) {
RenderPieSlice(DrawList, center, radius, a0, a1, col); RenderPieSlice(DrawList, center, radius, a0, a1, col);
} }
@ -1181,6 +1267,7 @@ void PlotPieChartEx(const char** label_ids, const T* values, int count, T x, T y
RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5f, col); RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5f, col);
RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5f, a1, col); RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5f, a1, col);
} }
EndItem();
} }
a0 = a1; a0 = a1;
} }
@ -1197,7 +1284,7 @@ void PlotPieChartEx(const char** label_ids, const T* values, int count, T x, T y
ImVec2 size = ImGui::CalcTextSize(buffer); ImVec2 size = ImGui::CalcTextSize(buffer);
T angle = a0 + (a1 - a0) * 0.5f; T angle = a0 + (a1 - a0) * 0.5f;
ImVec2 pos = PlotToPixels(center.x + 0.5f * radius * cos(angle), center.y + 0.5f * radius * sin(angle)); ImVec2 pos = PlotToPixels(center.x + 0.5f * radius * cos(angle), center.y + 0.5f * radius * sin(angle));
ImU32 col = CalcTextColor(GetItemFillColor(item)); ImU32 col = CalcTextColor(item->Color);
DrawList.AddText(pos - size * 0.5f, col, buffer); DrawList.AddText(pos - size * 0.5f, col, buffer);
} }
a0 = a1; a0 = a1;
@ -1265,29 +1352,21 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
template <typename T> template <typename T>
void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T scale_min, T scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T scale_min, T scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotHeatmap() needs to be called between BeginPlot() and EndPlot()!");
IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!"); IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!");
ImPlotItem* item = RegisterOrGetItem(label_id); if (BeginItem(label_id)) {
if (!item->Show) if (FitThisFrame()) {
return;
if (gp.FitThisFrame) {
FitPoint(bounds_min); FitPoint(bounds_min);
FitPoint(bounds_max); FitPoint(bounds_max);
} }
ImDrawList& DrawList = *ImGui::GetWindowDrawList(); ImDrawList& DrawList = *GetPlotDrawList();
ImGui::PushClipRect(gp.BB_Plot.Min, gp.BB_Plot.Max, true); switch (GetCurrentScale()) {
ImPlotState* plot = gp.CurrentPlot; case ImPlotScale_LinLin: RenderHeatmap(TransformerLinLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
int y_axis = plot->CurrentYAxis; case ImPlotScale_LogLin: RenderHeatmap(TransformerLogLin(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) case ImPlotScale_LinLog: RenderHeatmap(TransformerLinLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
RenderHeatmap(TransformerLogLog(y_axis), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); case ImPlotScale_LogLog: RenderHeatmap(TransformerLogLog(), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); break;
else if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale)) }
RenderHeatmap(TransformerLogLin(y_axis), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); EndItem();
else if (ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) }
RenderHeatmap(TransformerLinLog(y_axis), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max);
else
RenderHeatmap(TransformerLinLin(y_axis), DrawList, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max);
ImGui::PopClipRect();
} }
// float // float
@ -1304,23 +1383,16 @@ void PlotHeatmap(const char* label_id, const double* values, int rows, int cols,
// PLOT DIGITAL // PLOT DIGITAL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// TODO: Make this behave like all the other plot types
template <typename Getter> template <typename Getter>
inline void PlotDigitalEx(const char* label_id, Getter getter) inline void PlotDigitalEx(const char* label_id, Getter getter) {
{ if (BeginItem(label_id, ImPlotCol_Fill)) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotDigital() needs to be called between BeginPlot() and EndPlot()!"); ImDrawList& DrawList = *GetPlotDrawList();
const ImPlotItemStyle& s = GetItemStyle();
ImPlotItem* item = RegisterOrGetItem(label_id); if (getter.Count > 1 && s.RenderFill) {
if (!item->Show) const int y_axis = GetCurrentYAxis();
return;
TryRecolorItem(item, ImPlotCol_Line);
// render digital signals as "pixel bases" rectangles
PushPlotClipRect();
if (getter.Count > 1 && WillLineRender()) {
ImDrawList & DrawList = *ImGui::GetWindowDrawList();
const float line_weight = item->Highlight ? gp.Style.LineWeight * 2 : gp.Style.LineWeight;
const int y_axis = gp.CurrentPlot->CurrentYAxis;
int pixYMax = 0; int pixYMax = 0;
ImPlotPoint itemData1 = getter(0); ImPlotPoint itemData1 = getter(0);
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
@ -1330,11 +1402,11 @@ inline void PlotDigitalEx(const char* label_id, Getter getter)
continue; continue;
} }
if (NanOrInf(itemData2.y)) itemData2.y = ConstrainNan(ConstrainInf(itemData2.y)); if (NanOrInf(itemData2.y)) itemData2.y = ConstrainNan(ConstrainInf(itemData2.y));
int pixY_0 = (int)(line_weight); int pixY_0 = (int)(s.LineWeight);
itemData1.y = ImMax(0.0, itemData1.y); itemData1.y = ImMax(0.0, itemData1.y);
float pixY_1_float = gp.Style.DigitalBitHeight * (float)itemData1.y; float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y;
int pixY_1 = (int)(pixY_1_float); //allow only positive values int pixY_1 = (int)(pixY_1_float); //allow only positive values
int pixY_chPosOffset = (int)(ImMax(gp.Style.DigitalBitHeight, pixY_1_float) + gp.Style.DigitalBitGap); int pixY_chPosOffset = (int)(ImMax(s.DigitalBitHeight, pixY_1_float) + s.DigitalBitGap);
pixYMax = ImMax(pixYMax, pixY_chPosOffset); pixYMax = ImMax(pixYMax, pixY_chPosOffset);
ImVec2 pMin = PlotToPixels(itemData1); ImVec2 pMin = PlotToPixels(itemData1);
ImVec2 pMax = PlotToPixels(itemData2); ImVec2 pMax = PlotToPixels(itemData2);
@ -1356,16 +1428,17 @@ inline void PlotDigitalEx(const char* label_id, Getter getter)
if (pMax.x > gp.PixelRange[y_axis].Max.x) pMax.x = gp.PixelRange[y_axis].Max.x; if (pMax.x > gp.PixelRange[y_axis].Max.x) pMax.x = gp.PixelRange[y_axis].Max.x;
//plot a rectangle that extends up to x2 with y1 height //plot a rectangle that extends up to x2 with y1 height
if ((pMax.x > pMin.x) && (gp.BB_Plot.Contains(pMin) || gp.BB_Plot.Contains(pMax))) { if ((pMax.x > pMin.x) && (gp.BB_Plot.Contains(pMin) || gp.BB_Plot.Contains(pMax))) {
ImVec4 colAlpha = item->Color; // ImVec4 colAlpha = item->Color;
colAlpha.w = item->Highlight ? 1.0f : 0.9f; // colAlpha.w = item->Highlight ? 1.0f : 0.9f;
DrawList.AddRectFilled(pMin, pMax, ImGui::GetColorU32(colAlpha)); DrawList.AddRectFilled(pMin, pMax, ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]));
} }
itemData1 = itemData2; itemData1 = itemData2;
} }
gp.DigitalPlotItemCnt++; gp.DigitalPlotItemCnt++;
gp.DigitalPlotOffset += pixYMax; gp.DigitalPlotOffset += pixYMax;
} }
PopPlotClipRect(); EndItem();
}
} }
// float // float
@ -1391,39 +1464,26 @@ void PlotDigital(const char* label_id, ImPlotPoint (*getter_func)(void* data, in
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
void PlotRectsEx(const char* label_id, Getter getter) { void PlotRectsEx(const char* label_id, Getter getter) {
ImPlotContext& gp = *GImPlot; if (BeginItem(label_id, ImPlotCol_Fill)) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotRects() needs to be called between BeginPlot() and EndPlot()!"); if (FitThisFrame()) {
ImPlotItem* item = RegisterOrGetItem(label_id);
if (!item->Show)
return;
TryRecolorItem(item, ImPlotCol_Fill);
if (!WillFillRender())
return;
if (gp.FitThisFrame) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
FitPoint(p); FitPoint(p);
} }
} }
const ImPlotItemStyle& s = GetItemStyle();
ImDrawList & DrawList = *ImGui::GetWindowDrawList(); if (s.RenderFill) {
ImPlotState* plot = gp.CurrentPlot; ImDrawList& DrawList = *GetPlotDrawList();
const int y_axis = plot->CurrentYAxis; ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
ImU32 col = ImGui::GetColorU32(GetItemFillColor(item)); switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderPrimitives(RectRenderer<Getter,TransformerLinLin>(getter, TransformerLinLin(), col), DrawList); break;
PushPlotClipRect(); case ImPlotScale_LogLin: RenderPrimitives(RectRenderer<Getter,TransformerLogLin>(getter, TransformerLogLin(), col), DrawList); break;
if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale) && ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) case ImPlotScale_LinLog: RenderPrimitives(RectRenderer<Getter,TransformerLinLog>(getter, TransformerLinLog(), col), DrawList); break;
RenderPrimitives(RectRenderer<Getter,TransformerLogLog>(getter, TransformerLogLog(y_axis), col), DrawList); case ImPlotScale_LogLog: RenderPrimitives(RectRenderer<Getter,TransformerLogLog>(getter, TransformerLogLog(), col), DrawList); break;
else if (ImHasFlag(plot->XAxis.Flags, ImPlotAxisFlags_LogScale)) }
RenderPrimitives(RectRenderer<Getter,TransformerLogLin>(getter, TransformerLogLin(y_axis), col), DrawList); }
else if (ImHasFlag(plot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) EndItem();
RenderPrimitives(RectRenderer<Getter,TransformerLinLog>(getter, TransformerLinLog(y_axis), col), DrawList); }
else
RenderPrimitives(RectRenderer<Getter,TransformerLinLin>(getter, TransformerLinLin(y_axis), col), DrawList);
PopPlotClipRect();
} }
// float // float
@ -1456,9 +1516,9 @@ void PlotText(const char* text, float x, float y, bool vertical, const ImVec2& p
// double // double
void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) { void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & DrawList = *ImGui::GetWindowDrawList(); ImDrawList & DrawList = *GetPlotDrawList();
PushPlotClipRect(); PushPlotClipRect();
ImU32 colTxt = ImGui::GetColorU32(ImGuiCol_Text); ImU32 colTxt = GetStyleColorU32(ImPlotCol_InlayText);
if (vertical) { if (vertical) {
ImVec2 ctr = CalcTextSizeVertical(text) * 0.5f; ImVec2 ctr = CalcTextSizeVertical(text) * 0.5f;
ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + ImVec2(-ctr.x, ctr.y) + pixel_offset; ImVec2 pos = PlotToPixels(ImPlotPoint(x,y)) + ImVec2(-ctr.x, ctr.y) + pixel_offset;