mirror of
https://github.com/gwm17/implot.git
synced 2024-11-23 02:38:53 -05:00
fix crashing caused by legend refactors, add ShowMetricsWindow (WIP)
This commit is contained in:
parent
eb935d0b4f
commit
96e0fd9c57
86
implot.cpp
86
implot.cpp
|
@ -132,14 +132,16 @@ ImPlotStyle::ImPlotStyle() {
|
|||
UseISO8601 = false;
|
||||
}
|
||||
|
||||
ImPlotItem* ImPlotLegend::GetItem(int i) {
|
||||
return Plot->Items.GetByIndex(Indices[i]);
|
||||
ImPlotItem* ImPlotPlot::GetLegendItem(int i) {
|
||||
IM_ASSERT(Items.GetSize() > 0);
|
||||
return Items.GetByIndex(LegendData.Indices[i]);
|
||||
}
|
||||
|
||||
const char* ImPlotLegend::GetLabel(int i) {
|
||||
ImPlotItem* item = GetItem(i);
|
||||
IM_ASSERT(item->NameOffset != -1 && item->NameOffset < Labels.Buf.Size);
|
||||
return Labels.Buf.Data + item->NameOffset;
|
||||
const char* ImPlotPlot::GetLegendLabel(int i) {
|
||||
ImPlotItem* item = GetLegendItem(i);
|
||||
IM_ASSERT(item != NULL);
|
||||
IM_ASSERT(item->NameOffset != -1 && item->NameOffset < LegendData.Labels.Buf.Size);
|
||||
return LegendData.Labels.Buf.Data + item->NameOffset;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -541,16 +543,16 @@ ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlot
|
|||
return pos;
|
||||
}
|
||||
|
||||
ImVec2 CalcLegendSize(ImPlotLegend& legend, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orn) {
|
||||
ImVec2 CalcLegendSize(ImPlotPlot& plot, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orn) {
|
||||
// vars
|
||||
const int nItems = legend.Count();
|
||||
const int nItems = plot.GetLegendCount();
|
||||
const float txt_ht = ImGui::GetTextLineHeight();
|
||||
const float icon_size = txt_ht;
|
||||
// get label max width
|
||||
float max_label_width = 0;
|
||||
float sum_label_width = 0;
|
||||
for (int i = 0; i < nItems; ++i) {
|
||||
const char* label = legend.GetLabel(i);
|
||||
const char* label = plot.GetLegendLabel(i);
|
||||
const float label_width = ImGui::CalcTextSize(label, NULL, true).x;
|
||||
max_label_width = label_width > max_label_width ? label_width : max_label_width;
|
||||
sum_label_width += label_width;
|
||||
|
@ -562,7 +564,7 @@ ImVec2 CalcLegendSize(ImPlotLegend& legend, const ImVec2& pad, const ImVec2& spa
|
|||
return legend_size;
|
||||
}
|
||||
|
||||
void ShowLegendEntries(ImPlotLegend& legend, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orn, ImDrawList& DrawList) {
|
||||
void ShowLegendEntries(ImPlotPlot& plot, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orn, ImDrawList& DrawList) {
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
// vars
|
||||
const float txt_ht = ImGui::GetTextLineHeight();
|
||||
|
@ -572,9 +574,9 @@ void ShowLegendEntries(ImPlotLegend& legend, const ImRect& legend_bb, bool inter
|
|||
ImU32 col_txt_dis = ImGui::GetColorU32(col_txt * ImVec4(1,1,1,0.25f));
|
||||
// render each legend item
|
||||
float sum_label_width = 0;
|
||||
for (int i = 0; i < legend.Count(); ++i) {
|
||||
ImPlotItem* item = legend.GetItem(i);
|
||||
const char* label = legend.GetLabel(i);
|
||||
for (int i = 0; i < plot.GetLegendCount(); ++i) {
|
||||
ImPlotItem* item = plot.GetLegendItem(i);
|
||||
const char* label = plot.GetLegendLabel(i);
|
||||
const float label_width = ImGui::CalcTextSize(label, NULL, true).x;
|
||||
const ImVec2 top_left = orn == ImPlotOrientation_Vertical ?
|
||||
legend_bb.Min + pad + ImVec2(0, i * (txt_ht + spacing.y)) :
|
||||
|
@ -1240,6 +1242,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
|
||||
bool just_created = gp.Plots.GetByKey(ID) == NULL;
|
||||
gp.CurrentPlot = gp.Plots.GetOrAddByKey(ID);
|
||||
gp.CurrentPlot->ID = ID;
|
||||
ImPlotPlot &plot = *gp.CurrentPlot;
|
||||
|
||||
plot.CurrentYAxis = 0;
|
||||
|
@ -1366,8 +1369,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
gp.BB_Axes = gp.BB_Frame;
|
||||
|
||||
// outside legend adjustments
|
||||
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoLegend) && plot.Legend.Count() > 0 && plot.LegendOutside) {
|
||||
const ImVec2 legend_size = CalcLegendSize(plot.Legend, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation);
|
||||
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoLegend) && plot.GetLegendCount() > 0 && plot.LegendOutside) {
|
||||
const ImVec2 legend_size = CalcLegendSize(plot, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation);
|
||||
const bool west = ImHasFlag(plot.LegendLocation, ImPlotLocation_West) && !ImHasFlag(plot.LegendLocation, ImPlotLocation_East);
|
||||
const bool east = ImHasFlag(plot.LegendLocation, ImPlotLocation_East) && !ImHasFlag(plot.LegendLocation, ImPlotLocation_West);
|
||||
const bool north = ImHasFlag(plot.LegendLocation, ImPlotLocation_North) && !ImHasFlag(plot.LegendLocation, ImPlotLocation_South);
|
||||
|
@ -1822,7 +1825,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
}
|
||||
ImGui::PopClipRect();
|
||||
// clear legend
|
||||
plot.Legend.Reset();
|
||||
plot.LegendData.Reset();
|
||||
// push plot ID into stack
|
||||
ImGui::PushID(ID);
|
||||
return true;
|
||||
|
@ -2293,8 +2296,8 @@ void EndPlot() {
|
|||
for (int i = 0; i < plot.Items.GetSize(); ++i)
|
||||
plot.Items.GetByIndex(i)->LegendHovered = false;
|
||||
// render legend
|
||||
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoLegend) && plot.Legend.Count() > 0) {
|
||||
const ImVec2 legend_size = CalcLegendSize(plot.Legend, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation);
|
||||
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoLegend) && plot.GetLegendCount() > 0) {
|
||||
const ImVec2 legend_size = CalcLegendSize(plot, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation);
|
||||
const ImVec2 legend_pos = GetLocationPos(plot.LegendOutside ? gp.BB_Frame : gp.BB_Plot,
|
||||
legend_size,
|
||||
plot.LegendLocation,
|
||||
|
@ -2311,7 +2314,7 @@ void EndPlot() {
|
|||
ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
|
||||
DrawList.AddRectFilled(legend_bb.Min, legend_bb.Max, col_bg);
|
||||
DrawList.AddRect(legend_bb.Min, legend_bb.Max, col_bd);
|
||||
ShowLegendEntries(plot.Legend, legend_bb, plot.LegendHovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation, DrawList);
|
||||
ShowLegendEntries(plot, legend_bb, plot.LegendHovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation, DrawList);
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
if (plot.LegendFlipSide) {
|
||||
|
@ -2899,7 +2902,7 @@ void ShowAltLegend(const char* title_id, ImPlotOrientation orientation, const Im
|
|||
ImVec2 legend_size;
|
||||
ImVec2 default_size = gp.Style.LegendPadding * 2;
|
||||
if (plot != NULL) {
|
||||
legend_size = CalcLegendSize(plot->Legend, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, orientation);
|
||||
legend_size = CalcLegendSize(*plot, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, orientation);
|
||||
default_size = legend_size + gp.Style.LegendPadding * 2;
|
||||
}
|
||||
ImVec2 frame_size = ImGui::CalcItemSize(size, default_size.x, default_size.y);
|
||||
|
@ -2919,7 +2922,7 @@ void ShowAltLegend(const char* title_id, ImPlotOrientation orientation, const Im
|
|||
DrawList.AddRectFilled(legend_bb.Min, legend_bb.Max, col_bg);
|
||||
DrawList.AddRect(legend_bb.Min, legend_bb.Max, col_bd);
|
||||
// render entries
|
||||
ShowLegendEntries(plot->Legend, legend_bb, interactable, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, orientation, DrawList);
|
||||
ShowLegendEntries(*plot, legend_bb, interactable, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, orientation, DrawList);
|
||||
}
|
||||
DrawList.PopClipRect();
|
||||
}
|
||||
|
@ -3630,6 +3633,47 @@ void ShowUserGuide() {
|
|||
ImGui::BulletText("Click legend label icons to show/hide plot items.");
|
||||
}
|
||||
|
||||
void ShowMetricsWindow(bool* p_popen) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
// ImGuiContext& g = *GImGui;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::Begin("ImPlot Metrics", p_popen);
|
||||
ImGui::Text("ImPlot " IMPLOT_VERSION);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
|
||||
ImGui::Separator();
|
||||
int n_plots = gp.Plots.GetSize();
|
||||
if (ImGui::TreeNode("Plots","Plots (%d)", n_plots)) {
|
||||
for (int p = 0; p < n_plots; ++p) {
|
||||
ImPlotPlot* plot = gp.Plots.GetByIndex(p);
|
||||
ImGui::PushID(p);
|
||||
if (ImGui::TreeNode("Plot", "Plot [ID=%u]", plot->ID)) {
|
||||
int n_items = plot->Items.GetSize();
|
||||
if (ImGui::TreeNode("Items", "Items (%d)", n_items)) {
|
||||
for (int i = 0; i < n_items; ++i) {
|
||||
ImPlotItem* item = plot->Items.GetByIndex(i);
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::TreeNode("Item", "Item [ID=%u]", item->ID)) {
|
||||
ImGui::Bullet(); ImGui::Checkbox("Show", &item->Show);
|
||||
ImGui::Bullet(); ImGui::ColorEdit4("Color",&item->Color.x, ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::Bullet(); ImGui::Value("NameOffset",item->NameOffset);
|
||||
ImGui::Bullet(); ImGui::Text("Name: %s", item->NameOffset != -1 ? plot->LegendData.Labels.Buf.Data + item->NameOffset : "N/A");
|
||||
ImGui::Bullet(); ImGui::Value("Hovered",item->LegendHovered);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1, const ImPlotTime* t2) {
|
||||
|
||||
ImGui::PushID(id);
|
||||
|
|
2
implot.h
2
implot.h
|
@ -669,6 +669,8 @@ IMPLOT_API bool ShowColormapSelector(const char* label);
|
|||
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL);
|
||||
// Add basic help/info block (not a window): how to manipulate ImPlot as an end-user.
|
||||
IMPLOT_API void ShowUserGuide();
|
||||
// Shows ImPlot metrics/debug information.
|
||||
IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL);
|
||||
|
||||
// Sets the current _ImGui_ context. This is ONLY necessary if you are compiling
|
||||
// ImPlot as a DLL (not recommended) separate from your ImGui compilation. It
|
||||
|
|
|
@ -136,12 +136,16 @@ struct HugeTimeData {
|
|||
void ShowDemoWindow(bool* p_open) {
|
||||
double DEMO_TIME = ImGui::GetTime();
|
||||
static bool show_imgui_metrics = false;
|
||||
static bool show_implot_metrics = false;
|
||||
static bool show_imgui_style_editor = false;
|
||||
static bool show_implot_style_editor = false;
|
||||
static bool show_implot_benchmark = false;
|
||||
if (show_imgui_metrics) {
|
||||
ImGui::ShowMetricsWindow(&show_imgui_metrics);
|
||||
}
|
||||
if (show_implot_metrics) {
|
||||
ImPlot::ShowMetricsWindow(&show_implot_metrics);
|
||||
}
|
||||
if (show_imgui_style_editor) {
|
||||
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
|
||||
ImGui::ShowStyleEditor();
|
||||
|
@ -166,6 +170,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
if (ImGui::BeginMenuBar()) {
|
||||
if (ImGui::BeginMenu("Tools")) {
|
||||
ImGui::MenuItem("Metrics (ImGui)", NULL, &show_imgui_metrics);
|
||||
ImGui::MenuItem("Metrics (ImPlot)", NULL, &show_implot_metrics);
|
||||
ImGui::MenuItem("Style Editor (ImGui)", NULL, &show_imgui_style_editor);
|
||||
ImGui::MenuItem("Style Editor (ImPlot)", NULL, &show_implot_style_editor);
|
||||
ImGui::MenuItem("Benchmark", NULL, &show_implot_benchmark);
|
||||
|
|
|
@ -51,7 +51,7 @@ struct ImPlotAxis;
|
|||
struct ImPlotAxisState;
|
||||
struct ImPlotAxisColor;
|
||||
struct ImPlotItem;
|
||||
struct ImPlotLegend;
|
||||
struct ImPlotLegendData;
|
||||
struct ImPlotPlot;
|
||||
struct ImPlotNextPlotData;
|
||||
|
||||
|
@ -515,27 +515,22 @@ struct ImPlotItem
|
|||
};
|
||||
|
||||
// Holds Legend state labels and item references
|
||||
struct ImPlotLegend
|
||||
struct ImPlotLegendData
|
||||
{
|
||||
ImPlotPlot* Plot;
|
||||
ImVector<int> Indices;
|
||||
ImGuiTextBuffer Labels;
|
||||
|
||||
ImPlotLegend(ImPlotPlot* plot) { Plot = plot; }
|
||||
void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
|
||||
int Count() const { return Indices.size(); }
|
||||
ImPlotItem* GetItem(int i);
|
||||
const char* GetLabel(int i);
|
||||
};
|
||||
|
||||
// Holds Plot state information that must persist after EndPlot
|
||||
struct ImPlotPlot
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImPlotFlags Flags;
|
||||
ImPlotFlags PreviousFlags;
|
||||
ImPlotAxis XAxis;
|
||||
ImPlotAxis YAxis[IMPLOT_Y_AXES];
|
||||
ImPlotLegend Legend;
|
||||
ImPlotLegendData LegendData;
|
||||
ImPool<ImPlotItem> Items;
|
||||
ImVec2 SelectStart;
|
||||
ImVec2 QueryStart;
|
||||
|
@ -553,7 +548,7 @@ struct ImPlotPlot
|
|||
ImPlotLocation LegendLocation;
|
||||
ImPlotOrientation LegendOrientation;
|
||||
|
||||
ImPlotPlot() : Legend(this) {
|
||||
ImPlotPlot() {
|
||||
Flags = PreviousFlags = ImPlotFlags_None;
|
||||
XAxis.Direction = ImPlotOrientation_Horizontal;
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; ++i)
|
||||
|
@ -566,6 +561,9 @@ struct ImPlotPlot
|
|||
MousePosLocation = ImPlotLocation_South | ImPlotLocation_East;
|
||||
}
|
||||
|
||||
int GetLegendCount() const { return LegendData.Indices.size(); }
|
||||
ImPlotItem* GetLegendItem(int i);
|
||||
const char* GetLegendLabel(int i);
|
||||
};
|
||||
|
||||
// Temporary data storage for upcoming plot
|
||||
|
@ -803,9 +801,9 @@ IMPLOT_API void ShowAxisContextMenu(ImPlotAxisState& state, bool time_allowed =
|
|||
// Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
|
||||
IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
|
||||
// Calculates the bounding box size of a legend
|
||||
IMPLOT_API ImVec2 CalcLegendSize(ImPlotLegend& legend, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation);
|
||||
IMPLOT_API ImVec2 CalcLegendSize(ImPlotPlot& plot, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation);
|
||||
// Renders legend entries into a bounding box
|
||||
IMPLOT_API void ShowLegendEntries(ImPlotLegend& legend, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation, ImDrawList& DrawList);
|
||||
IMPLOT_API void ShowLegendEntries(ImPlotPlot& plot, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, ImPlotOrientation orientation, ImDrawList& DrawList);
|
||||
// Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window!).
|
||||
IMPLOT_API void ShowAltLegend(const char* title_id, ImPlotOrientation orientation = ImPlotOrientation_Vertical, const ImVec2 size = ImVec2(0,0), bool interactable = true);
|
||||
|
||||
|
|
|
@ -60,9 +60,9 @@ ImPlotItem* RegisterOrGetItem(const char* label_id, bool* just_created) {
|
|||
int idx = gp.CurrentPlot->Items.GetIndex(item);
|
||||
item->ID = id;
|
||||
if (ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) {
|
||||
gp.CurrentPlot->Legend.Indices.push_back(idx);
|
||||
item->NameOffset = gp.CurrentPlot->Legend.Labels.size();
|
||||
gp.CurrentPlot->Legend.Labels.append(label_id, label_id + strlen(label_id) + 1);
|
||||
gp.CurrentPlot->LegendData.Indices.push_back(idx);
|
||||
item->NameOffset = gp.CurrentPlot->LegendData.Labels.size();
|
||||
gp.CurrentPlot->LegendData.Labels.append(label_id, label_id + strlen(label_id) + 1);
|
||||
}
|
||||
else {
|
||||
item->Show = true;
|
||||
|
@ -131,6 +131,7 @@ void BustItemCache() {
|
|||
ImPlotPlot& plot = *gp.Plots.GetByIndex(p);
|
||||
plot.ColormapIdx = 0;
|
||||
plot.Items.Clear();
|
||||
plot.LegendData.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user