1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-10-09 23:57:26 -04:00

Merge branch 'sergeyn-pr_branch'

This commit is contained in:
Evan Pezent 2020-05-15 08:05:22 -05:00
commit 1353014bce
3 changed files with 65 additions and 63 deletions

View File

@ -48,21 +48,16 @@ You can read releases logs https://github.com/epezent/implot/releases for more d
*/ */
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#endif
#ifndef IMGUI_DEFINE_MATH_OPERATORS #ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
#endif #endif
#include "implot.h"
#include "imgui_internal.h"
#include <implot.h> #ifdef _MSC_VER
#include <imgui_internal.h> #define sprintf sprintf_s
#endif
#define IM_NORMALIZE2F_OVER_ZERO(VX, VY) \ #define IM_NORMALIZE2F_OVER_ZERO(VX, VY) \
{ \ { \
@ -202,8 +197,7 @@ inline void AddTextVertical(ImDrawList *DrawList, const char *text, ImVec2 pos,
pos.y = IM_ROUND(pos.y); pos.y = IM_ROUND(pos.y);
ImFont * font = GImGui->Font; ImFont * font = GImGui->Font;
const ImFontGlyph *glyph; const ImFontGlyph *glyph;
char c; for (char c = *text++; c; c = *text++) {
while ((c = *text++)) {
glyph = font->FindGlyph(c); glyph = font->FindGlyph(c);
if (!glyph) if (!glyph)
continue; continue;
@ -237,7 +231,6 @@ ImVec4 NextColor();
// Structs // Structs
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// Tick mark info /// Tick mark info
struct ImTick { struct ImTick {
ImTick(double value, bool major, bool render_label = true) { ImTick(double value, bool major, bool render_label = true) {
@ -247,9 +240,9 @@ struct ImTick {
} }
double PlotPos; double PlotPos;
float PixelPos; float PixelPos;
bool Major;
ImVec2 Size; ImVec2 Size;
int TextOffset; int TextOffset;
bool Major;
bool RenderLabel; bool RenderLabel;
}; };
@ -298,13 +291,13 @@ struct ImPlotState {
ImPool<ImPlotItem> Items; ImPool<ImPlotItem> Items;
ImRect BB_Legend; ImRect BB_Legend;
bool Selecting;
ImVec2 SelectStart; ImVec2 SelectStart;
bool Selecting;
bool Querying; bool Querying;
bool Queried; bool Queried;
bool DraggingQuery;
ImVec2 QueryStart; ImVec2 QueryStart;
ImRect QueryRect; // relative to BB_grid!! ImRect QueryRect; // relative to BB_grid!!
bool DraggingQuery;
ImPlotAxis XAxis; ImPlotAxis XAxis;
ImPlotAxis YAxis[MAX_Y_AXES]; ImPlotAxis YAxis[MAX_Y_AXES];
@ -342,9 +335,6 @@ struct ImPlotContext {
ImRect BB_Frame; ImRect BB_Frame;
ImRect BB_Canvas; ImRect BB_Canvas;
ImRect BB_Grid; ImRect BB_Grid;
// Hover states
bool Hov_Frame;
bool Hov_Grid;
// Cached Colors // Cached Colors
ImU32 Col_Frame, Col_Bg, Col_Border, ImU32 Col_Frame, Col_Bg, Col_Border,
Col_Txt, Col_TxtDis, Col_Txt, Col_TxtDis,
@ -368,14 +358,15 @@ struct ImPlotContext {
// log scale denominator // log scale denominator
float LogDenX; float LogDenX;
float LogDenY[MAX_Y_AXES]; float LogDenY[MAX_Y_AXES];
// Data extents // Data extents
ImPlotRange ExtentsX; ImPlotRange ExtentsX;
ImPlotRange ExtentsY[MAX_Y_AXES]; ImPlotRange ExtentsY[MAX_Y_AXES];
bool FitThisFrame; bool FitX;
bool FitY[MAX_Y_AXES];
int VisibleItemCount; int VisibleItemCount;
bool FitThisFrame; bool FitX;
bool FitY[MAX_Y_AXES] = {};
// Hover states
bool Hov_Frame;
bool Hov_Grid;
// Render flags // Render flags
bool RenderX, RenderY[MAX_Y_AXES]; bool RenderX, RenderY[MAX_Y_AXES];
// Mouse pos // Mouse pos
@ -457,6 +448,11 @@ inline ImVec2 PixelsToPlot(float x, float y, int y_axis_in = -1) {
return plt; return plt;
} }
ImVec2 PixelsToPlot(const ImVec2& pix, int y_axis) {
return PixelsToPlot(pix.x, pix.y, y_axis);
}
// This function is convenient but should not be used to process a high volume of points. Use the Transformer structs below instead.
inline ImVec2 PlotToPixels(float x, float y, int y_axis_in = -1) { inline ImVec2 PlotToPixels(float x, float y, int y_axis_in = -1) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() Needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() Needs to be called between BeginPlot() and EndPlot()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
@ -474,14 +470,13 @@ inline ImVec2 PlotToPixels(float x, float y, int y_axis_in = -1) {
return pix; return pix;
} }
ImVec2 PixelsToPlot(const ImVec2& pix, int y_axis) { // This function is convenient but should not be used to process a high volume of points. Use the Transformer structs below instead.
return PixelsToPlot(pix.x, pix.y, y_axis);
}
ImVec2 PlotToPixels(const ImVec2& plt, int y_axis) { ImVec2 PlotToPixels(const ImVec2& plt, int y_axis) {
return PlotToPixels(plt.x, plt.y, y_axis); return PlotToPixels(plt.x, plt.y, y_axis);
} }
// Transformer structs
struct Plt2PixLinLin { struct Plt2PixLinLin {
Plt2PixLinLin(int y_axis_in) : y_axis(y_axis_in) {} Plt2PixLinLin(int y_axis_in) : y_axis(y_axis_in) {}
@ -1440,7 +1435,8 @@ class BufferWriter {
private: private:
void VWrite(const char* fmt, va_list argp) { void VWrite(const char* fmt, va_list argp) {
const int written = ::vsnprintf(&Buffer[Pos], Size - Pos - 1, fmt, argp); const int written = ::vsnprintf(&Buffer[Pos], Size - Pos - 1, fmt, argp);
Pos += written; if (written > 0)
Pos += ImMin(size_t(written), Size-Pos-1);
} }
char* const Buffer; char* const Buffer;
@ -1599,7 +1595,10 @@ void EndPlot() {
col_hl_txt = ImGui::GetColorU32(ImLerp(G.Style.Colors[ImGuiCol_Text], item->Color, 0.25f)); col_hl_txt = ImGui::GetColorU32(ImLerp(G.Style.Colors[ImGuiCol_Text], item->Color, 0.25f));
} }
else else
item->Highlight = false; {
item->Highlight = false;
col_hl_txt = gp.Col_Txt;
}
ImU32 iconColor; ImU32 iconColor;
if (hov_legend && icon_bb.Contains(IO.MousePos)) { if (hov_legend && icon_bb.Contains(IO.MousePos)) {
ImVec4 colAlpha = item->Color; ImVec4 colAlpha = item->Color;
@ -1615,8 +1614,7 @@ void EndPlot() {
const char* label = GetLegendLabel(i); const char* label = GetLegendLabel(i);
const char* text_display_end = ImGui::FindRenderedTextEnd(label, NULL); const char* text_display_end = ImGui::FindRenderedTextEnd(label, NULL);
if (label != text_display_end) if (label != text_display_end)
DrawList.AddText(legend_content_bb.Min + legend_padding + ImVec2(legend_icon_size, i * txt_ht), DrawList.AddText(legend_content_bb.Min + legend_padding + ImVec2(legend_icon_size, i * txt_ht), item->Show ? col_hl_txt : gp.Col_TxtDis, label, text_display_end);
item->Show ? (item->Highlight ? col_hl_txt : gp.Col_Txt) : gp.Col_TxtDis, label, text_display_end);
} }
} }
@ -1641,7 +1639,7 @@ void EndPlot() {
// render mouse pos // render mouse pos
if (HasFlag(plot.Flags, ImPlotFlags_MousePos) && gp.Hov_Grid) { if (HasFlag(plot.Flags, ImPlotFlags_MousePos) && gp.Hov_Grid) {
static char buffer[128] = {}; char buffer[128] = {};
BufferWriter writer(buffer, sizeof(buffer)); BufferWriter writer(buffer, sizeof(buffer));
writer.Write("%.2f,%.2f", gp.LastMousePos[0].x, gp.LastMousePos[0].y); writer.Write("%.2f,%.2f", gp.LastMousePos[0].x, gp.LastMousePos[0].y);
@ -2002,23 +2000,23 @@ inline void MarkerRight(ImDrawList& DrawList, const ImVec2& c, float s, bool out
MarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight); MarkerGeneral(DrawList, marker, 3, c, s, outline, col_outline, fill, col_fill, weight);
} }
inline void MarkerAsterisk(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) { inline void MarkerAsterisk(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
ImVec2 marker[6] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f)}; ImVec2 marker[6] = {{SQRT_3_2, 0.5f}, {0, -1}, {-SQRT_3_2, 0.5f}, {SQRT_3_2, -0.5f}, {0, 1}, {-SQRT_3_2, -0.5f}};
TransformMarker(marker, 6, c, s); TransformMarker(marker, 6, c, s);
DrawList.AddLine(marker[0], marker[5], col_outline, weight); DrawList.AddLine(marker[0], marker[5], col_outline, weight);
DrawList.AddLine(marker[1], marker[4], col_outline, weight); DrawList.AddLine(marker[1], marker[4], col_outline, weight);
DrawList.AddLine(marker[2], marker[3], col_outline, weight); DrawList.AddLine(marker[2], marker[3], col_outline, weight);
} }
inline void MarkerPlus(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) { inline void MarkerPlus(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
ImVec2 marker[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)}; ImVec2 marker[4] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
TransformMarker(marker, 4, c, s); TransformMarker(marker, 4, c, s);
DrawList.AddLine(marker[0], marker[2], col_outline, weight); DrawList.AddLine(marker[0], marker[2], col_outline, weight);
DrawList.AddLine(marker[1], marker[3], col_outline, weight); DrawList.AddLine(marker[1], marker[3], col_outline, weight);
} }
inline void MarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bool outline, ImU32 col_outline, bool fill, ImU32 col_fill, float weight) { inline void MarkerCross(ImDrawList& DrawList, const ImVec2& c, float s, bool /*outline*/, ImU32 col_outline, bool /*fill*/, ImU32 /*col_fill*/, float weight) {
ImVec2 marker[4] = {ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)}; ImVec2 marker[4] = {{SQRT_1_2,SQRT_1_2},{SQRT_1_2,-SQRT_1_2},{-SQRT_1_2,-SQRT_1_2},{-SQRT_1_2,SQRT_1_2}};
TransformMarker(marker, 4, c, s); TransformMarker(marker, 4, c, s);
DrawList.AddLine(marker[0], marker[2], col_outline, weight); DrawList.AddLine(marker[0], marker[2], col_outline, weight);
DrawList.AddLine(marker[1], marker[3], col_outline, weight); DrawList.AddLine(marker[1], marker[3], col_outline, weight);
@ -2540,7 +2538,7 @@ void PieChart(const char** label_ids, float* values, int count, const ImVec2& ce
DrawPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5f, a1, col); DrawPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5f, a1, col);
} }
if (show_percents) { if (show_percents) {
static char buffer[8]; char buffer[8];
sprintf(buffer, "%.0f%%", percent * 100); sprintf(buffer, "%.0f%%", percent * 100);
ImVec2 size = ImGui::CalcTextSize(buffer); ImVec2 size = ImGui::CalcTextSize(buffer);
float angle = a0 + (a1 - a0) * 0.5f; float angle = a0 + (a1 - a0) * 0.5f;
@ -2609,9 +2607,10 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of
ImVec2 itemData1 = getter(i1); ImVec2 itemData1 = getter(i1);
ImVec2 itemData2 = getter(i2); ImVec2 itemData2 = getter(i2);
i1 = i2; i1 = i2;
int pixY_0 = line_weight; int pixY_0 = (int)(line_weight);
int pixY_1 = gp.Style.DigitalBitHeight * ImMax(0.0f, itemData1.y); //allow only positive values float pixY_1_float = gp.Style.DigitalBitHeight * ImMax(0.0f, itemData1.y);
int pixY_chPosOffset = ImMax((int)gp.Style.DigitalBitHeight, pixY_1) + gp.Style.DigitalBitGap; 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);
pixYMax = ImMax(pixYMax, pixY_chPosOffset); pixYMax = ImMax(pixYMax, pixY_chPosOffset);
ImVec2 pMin, pMax; ImVec2 pMin, pMax;
pMin.x = gp.PixelRange[ax].Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Range.Min); pMin.x = gp.PixelRange[ax].Min.x + mx * (itemData1.x - gp.CurrentPlot->XAxis.Range.Min);
@ -2621,10 +2620,10 @@ inline void PlotDigitalEx(const char* label_id, Getter getter, int count, int of
pMax.y = (gp.PixelRange[ax].Min.y) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset); pMax.y = (gp.PixelRange[ax].Min.y) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset);
//plot only one rectangle for same digital state //plot only one rectangle for same digital state
while (((s+2) < segments) && (itemData1.y == itemData2.y)) { while (((s+2) < segments) && (itemData1.y == itemData2.y)) {
const int i2 = (i1 + 1) % count; const int i3 = (i1 + 1) % count;
itemData2 = getter(i2); itemData2 = getter(i3);
pMax.x = gp.PixelRange[ax].Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Range.Min); pMax.x = gp.PixelRange[ax].Min.x + mx * (itemData2.x - gp.CurrentPlot->XAxis.Range.Min);
i1 = i2; i1 = i3;
s++; s++;
} }
//do not extend plot outside plot range //do not extend plot outside plot range

View File

@ -23,7 +23,7 @@
// ImPlot v0.2 WIP // ImPlot v0.2 WIP
#pragma once #pragma once
#include <imgui.h> #include "imgui.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Basic types and flags // Basic types and flags

View File

@ -22,18 +22,16 @@
// ImPlot v0.2 WIP // ImPlot v0.2 WIP
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifdef _MSC_VER #include "implot.h"
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#endif
#include <implot.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <cmath> // for 'float' overloads of elementary functions (sin,cos,etc)
#ifdef _MSC_VER
#define sprintf sprintf_s
#endif
namespace { namespace {
@ -468,11 +466,11 @@ void ShowDemoWindow(bool* p_open) {
if (data.size() > 0) if (data.size() > 0)
ImPlot::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float)); ImPlot::Plot("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(float));
if (ImPlot::IsPlotQueried() && data.size() > 0) { if (ImPlot::IsPlotQueried() && data.size() > 0) {
ImPlotLimits range = ImPlot::GetPlotQuery(); ImPlotLimits range2 = ImPlot::GetPlotQuery();
int cnt = 0; int cnt = 0;
ImVec2 avg; ImVec2 avg;
for (int i = 0; i < data.size(); ++i) { for (int i = 0; i < data.size(); ++i) {
if (range.Contains(data[i])) { if (range2.Contains(data[i])) {
avg.x += data[i].x; avg.x += data[i].x;
avg.y += data[i].y; avg.y += data[i].y;
cnt++; cnt++;
@ -659,7 +657,7 @@ void ShowDemoWindow(bool* p_open) {
dataDigital[i].AddPoint(t, sin(2*t) < 0.45); dataDigital[i].AddPoint(t, sin(2*t) < 0.45);
i++; i++;
if (showDigital[i]) if (showDigital[i])
dataDigital[i].AddPoint(t, (int)t % 5); dataDigital[i].AddPoint(t, fmod(t,5.0f));
i++; i++;
if (showDigital[i]) if (showDigital[i])
dataDigital[i].AddPoint(t, sin(2*t) < 0.17); dataDigital[i].AddPoint(t, sin(2*t) < 0.17);
@ -701,13 +699,18 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImGui::BeginDragDropTarget()) { if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT")) { const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT");
if (payload) {
int i = *(int*)payload->Data; int i = *(int*)payload->Data;
showDigital[i] = true; showDigital[i] = true;
} }
else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT")) { else
int i = *(int*)payload->Data; {
showAnalog[i] = true; payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT");
if (payload) {
int i = *(int*)payload->Data;
showAnalog[i] = true;
}
} }
ImGui::EndDragDropTarget(); ImGui::EndDragDropTarget();
} }