generated from cpp-best-practices/gui_starter_template
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
leo_widgets.cpp
182 lines (164 loc) · 5.8 KB
/
leo_widgets.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include "leo_widgets.hpp"
#include <cmath>
#include <numbers>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuseless-cast"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include "implot.h"
#pragma GCC diagnostic pop
static void plot_direction(const char *label, float p_value) {
auto &style = ImGui::GetStyle();
const auto radius_outer = 20.0f;
const auto pos = ImGui::GetCursorScreenPos();
const auto center = ImVec2(pos.x + radius_outer, pos.y + radius_outer);
const auto line_height = ImGui::GetTextLineHeight();
auto *draw_list = ImGui::GetWindowDrawList();
const auto angle = 2 * std::numbers::pi_v<float> * p_value;
const auto angle_cos = std::cos(angle);
const auto angle_sin = std::sin(angle);
const auto radius_inner = radius_outer * 0.40f;
ImGui::InvisibleButton(
label, ImVec2(radius_outer * 2, radius_outer * 2 + line_height +
style.ItemInnerSpacing.y));
const auto is_active = ImGui::IsItemActive();
const auto is_hovered = ImGui::IsItemHovered();
draw_list->AddCircleFilled(center, radius_outer,
ImGui::GetColorU32(ImGuiCol_FrameBg), 16);
draw_list->AddLine(ImVec2(center.x + angle_cos * radius_inner,
center.y + angle_sin * radius_inner),
ImVec2(center.x + angle_cos * (radius_outer - 2),
center.y + angle_sin * (radius_outer - 2)),
ImGui::GetColorU32(ImGuiCol_SliderGrabActive), 2.0f);
draw_list->AddCircleFilled(center, radius_inner,
ImGui::GetColorU32(ImGuiCol_FrameBgActive), 16);
draw_list->AddText(
ImVec2(pos.x, pos.y + radius_outer * 2 + style.ItemInnerSpacing.y),
ImGui::GetColorU32(ImGuiCol_Text), label);
if (is_active || is_hovered) {
ImGui::SetNextWindowPos(
ImVec2(pos.x - style.WindowPadding.x, pos.y - line_height -
style.ItemInnerSpacing.y -
style.WindowPadding.y));
ImGui::BeginTooltip();
ImGui::Text("%.3f", double(p_value));
ImGui::EndTooltip();
}
}
template <typename Get> struct plot_trace {
const char *name;
using getter_t = Get;
};
auto make_trace(const char *name, auto getter) {
return plot_trace<decltype(getter)>{name};
}
template <typename G, typename T>
auto plotline(std::span<const T> data, const plot_trace<G> &trace) {
ImPlot::PlotLineG(trace.name, G{}, const_cast<T *>(data.data()),
int(data.size()));
}
template <typename T, typename... TR>
void show_lplot(l_plot &plot_data, const char *yunits, double time,
std::span<const T> data, TR... traces) {
ImGui::SetNextWindowSize(ImVec2(600, 600), ImGuiCond_FirstUseEver);
ImGui::Checkbox("lock##hist", &plot_data.history_limited);
if (plot_data.history_limited) {
ImGui::SameLine();
ImGui::SliderFloat("History", &plot_data.history, 1, 30, "%.1f s");
}
ImGui::Checkbox("lock##scale", &plot_data.scale_limited);
if (plot_data.scale_limited) {
ImGui::SameLine();
ImGui::SliderFloat("Scale", &plot_data.yscale, 1,
std::numeric_limits<int16_t>::max(), "%.1f");
}
if (plot_data.history_limited) {
ImPlot::SetNextPlotLimitsX(time - double(plot_data.history), time,
ImGuiCond_Always);
}
if (plot_data.scale_limited) {
ImPlot::SetNextPlotLimitsY(-double(plot_data.yscale) * 1.1,
double(plot_data.yscale) * 1.1,
ImGuiCond_Always);
}
if (ImPlot::BeginPlot("", "s", yunits, ImVec2(-1, 400))) {
(plotline(data, traces), ...);
ImPlot::EndPlot();
}
}
static auto last_ts(std::span<const imu> data) {
if (data.size() > 0) {
return data.back().ts / 1000.;
}
return 0.;
}
static auto last_ts(std::span<const acc_plot::sample> data) {
if (data.size() > 0) {
return float(data.back().ts);
}
return 0.f;
}
static auto last_ts(std::span<const gyro_plot::sample> data) {
if (data.size() > 0) {
return float(data.back().ts);
}
return 0.f;
}
void gyro_plot::show(std::span<const imu> data, std::span<const float, 3> dir) {
plot_direction("x", dir[0]);
ImGui::SameLine();
plot_direction("y", dir[1]);
ImGui::SameLine();
plot_direction("z", dir[2]);
show_lplot(plt, "nesi", last_ts(data), data,
make_trace("x", getter([](const imu &im) {
return ImPlotPoint(im.ts / 1000., im.gyro[0]);
})),
make_trace("y", getter([](const imu &im) {
return ImPlotPoint(im.ts / 1000., im.gyro[1]);
})),
make_trace("z", getter([](const imu &im) {
return ImPlotPoint(im.ts / 1000., im.gyro[2]);
})));
}
void gyro_plot::show(std::span<const sample> data,
std::span<const float, 3> dir) {
plot_direction("x", dir[0]);
ImGui::SameLine();
plot_direction("y", dir[1]);
ImGui::SameLine();
plot_direction("z", dir[2]);
show_lplot(plt, "nesi", last_ts(data), data,
make_trace("x", getter([](const sample &im) {
return ImPlotPoint{im.ts, im.values[0]};
})),
make_trace("y", getter([](const sample &im) {
return ImPlotPoint{im.ts, im.values[1]};
})),
make_trace("z", getter([](const sample &im) {
return ImPlotPoint{im.ts, im.values[2]};
})));
}
void acc_plot::show(std::span<const sample> d) {
show_lplot(plt, "leandri", last_ts(d), d,
make_trace("x", getter([](const acc_plot::sample &dt) {
return ImPlotPoint{dt.ts, dt.values[0]};
})),
make_trace("y", getter([](const acc_plot::sample &dt) {
return ImPlotPoint{dt.ts, dt.values[1]};
})),
make_trace("z", getter([](const acc_plot::sample &dt) {
return ImPlotPoint{dt.ts, dt.values[2]};
})));
}
void acc_plot::show(std::span<const imu> data) {
show_lplot(plt, "leandri", last_ts(data), data,
make_trace("x", getter([](const imu &im) {
return ImPlotPoint(im.ts / 1000., im.acc[0]);
})),
make_trace("y", getter([](const imu &im) {
return ImPlotPoint(im.ts / 1000., im.acc[1]);
})),
make_trace("z", getter([](const imu &im) {
return ImPlotPoint(im.ts / 1000., im.acc[2]);
})));
}