22#define IMGUI_DEFINE_MATH_OPERATORS
24#include <imgui_internal.h>
37#include <glm/gtc/matrix_transform.hpp>
38#include <glm/gtx/euler_angles.hpp>
49 if (winsize::get().width == 0)
52 int w = 1920,
h = 1080;
56 std::vector<std::string>
const tok =
jevois::split(ws,
"\\s*[,;x]\\s*");
57 if (tok.size() == 2) { w = std::stoi(tok[0]);
h = std::stoi(tok[1]) / 2; }
58 LINFO(
"Detected framebuffer size: " << w <<
'x' <<
h);
62 winsize::set(cv::Size(w,
h));
68 std::vector<EditorItem> fixedcfg
70 {
JEVOIS_ROOT_PATH "/config/videomappings.cfg",
"JeVois videomappings.cfg", EditorSaveAction::RefreshMappings },
71 {
JEVOIS_ROOT_PATH "/config/initscript.cfg",
"JeVois initscript.cfg", EditorSaveAction::Reboot },
72 {
"params.cfg",
"Module's params.cfg", EditorSaveAction::Reload },
73 {
"script.cfg",
"Module's script.cfg", EditorSaveAction::Reload },
75 "JeVois models.yml DNN Zoo Root", EditorSaveAction::Reload },
77 "JeVois opencv.yml DNN Zoo for OpenCV models", EditorSaveAction::Reload },
79 "JeVois npu.yml DNN Zoo for A311D NPU models", EditorSaveAction::Reload },
81 "JeVois spu.yml DNN Zoo for Hailo SPU models", EditorSaveAction::Reload },
83 "JeVois tpu.yml DNN Zoo for Coral TPU models", EditorSaveAction::Reload },
85 "JeVois vpu.yml DNN Zoo for Myriad-X VPU models", EditorSaveAction::Reload },
87 "JeVois ort.yml DNN Zoo for ONNX-Runtime CPU models", EditorSaveAction::Reload },
92 {
".yaml",
".yml" }));
95 std::vector<EditorItem> fixedcode
97 {
"*",
"Module's source code", EditorSaveAction::Reload },
103 {
".py",
".C",
".H",
".cpp",
".hpp",
".c",
".h",
".txt" }));
116 itsEndFrameCalled =
true;
119 itsLastDrawnImage =
nullptr;
120 itsLastDrawnTextLine = -1;
131 itsCfgEditor->refresh();
132 itsCodeEditor->refresh();
137 std::lock_guard<std::mutex> _(itsErrorMtx);
143 itsBackend.getWindowSize(w,
h);
145 if (w == 0)
LFATAL(
"Need to call startFrame() at least once first");
147 float const fov_y = 45.0f;
149 proj = glm::perspective(glm::radians(fov_y),
float(w) /
float(
h), 1.0f,
h * 2.0f);
150 const_cast<float &
>(pixel_perfect_z) = -
float(
h) / (2.0 * tan(fov_y * M_PI / 360.0));
151#ifdef JEVOIS_PLATFORM
153 proj = glm::translate(proj, glm::vec3(0.375f, 0.375f, 0.0f));
155 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, pixel_perfect_z));
158 style::set(style::get());
165 if (std::filesystem::exists(m.
cmakepath())) itsNewMapping = m;
171 if (itsEndFrameCalled ==
false)
LFATAL(
"You need to call endFrame() at the end of your process() function");
174 itsBackend.getWindowSize(w,
h);
179 cv::Size
const siz = winsize::get();
180 bool const fs = fullscreen::get();
181 LINFO(
"OpenGL init " << siz.width <<
'x' << siz.height << (fs ?
" fullscreen" :
""));
182 itsBackend.init(siz.width, siz.height, fs, scale::get(), itsConsLock);
183 rounding::set(
int(rounding::get() * scale::get() + 0.499F));
186 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh); winsize::set(cv::Size(winw, winh));
187 winsize::freeze(
true);
188 fullscreen::freeze(
true);
195 bool shouldclose =
false;
auto const now = std::chrono::steady_clock::now();
196 if (itsBackend.pollEvents(shouldclose)) itsLastEventTime = now;
198 if (shouldclose && allowquit::get())
200 LINFO(
"Closing down on user request...");
205 itsBackend.newFrame();
212 float const hs = hidesecs::get();
215 std::chrono::duration<float> elapsed = now - itsLastEventTime;
216 itsIdle = (elapsed.count() >= hs);
218 else itsIdle =
false;
221 itsEndFrameCalled =
false;
233 float oldval = param.get();
234 if (newval == oldval)
return;
236 ImGui::GetStyle().ScaleAllSizes(newval / oldval);
237 ImGui::GetIO().FontGlobalScale = newval;
238 ImGui::GetStyle().MouseCursorScale = 2.0f;
241 if (oldval) rounding::set(std::min(24,
int(rounding::get() * newval / oldval + 0.499F)));
249 case jevois::gui::GuiStyle::Dark:
250 ImGui::StyleColorsDark();
251 itsCfgEditor->SetPalette(TextEditor::GetDarkPalette());
252 itsCodeEditor->SetPalette(TextEditor::GetDarkPalette());
255 case jevois::gui::GuiStyle::Light:
256 ImGui::StyleColorsLight();
257 ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 0.92f);
258 itsCfgEditor->SetPalette(TextEditor::GetLightPalette());
259 itsCodeEditor->SetPalette(TextEditor::GetLightPalette());
262 case jevois::gui::GuiStyle::Classic:
263 ImGui::StyleColorsClassic();
264 itsCfgEditor->SetPalette(TextEditor::GetRetroBluePalette());
265 itsCodeEditor->SetPalette(TextEditor::GetRetroBluePalette());
273 auto & s = ImGui::GetStyle();
274 s.WindowRounding = newval;
275 s.ChildRounding = newval;
276 s.FrameRounding = newval;
277 s.PopupRounding = newval;
278 s.ScrollbarRounding = newval;
279 s.GrabRounding = newval;
284{
return (itsEndFrameCalled ==
false); }
288 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
291 std::string
const imgname = name + std::to_string(img.
bufindex);
294 auto & im = itsImages[imgname];
300 im.draw(x, y, w,
h, noalias, proj * view);
303 if (isoverlay ==
false)
305 itsLastDrawnImage = & im;
306 itsUsingScaledImage =
false;
307 itsLastDrawnTextLine = -1;
313 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
316 auto & im = itsImages[name];
322 im.draw(x, y, w,
h, noalias, proj * view);
325 if (isoverlay ==
false)
327 itsLastDrawnImage = & im;
328 itsUsingScaledImage =
false;
329 itsLastDrawnTextLine = -1;
335 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
337 itsInputFrame = &frame;
341 std::string
const imgname = name + std::to_string(img.
bufindex);
344 auto & im = itsImages[imgname];
348 im.set(frame, itsBackend.getDisplay());
351 im.draw(x, y, w,
h, noalias, proj * view);
354 itsLastDrawnImage = & im;
356 itsLastDrawnTextLine = -1;
357 if (itsUsingScaledImage)
360 itsScaledImageFacX = float(img.
width) / float(img2.
width);
361 itsScaledImageFacY = float(img.
height) / float(img2.
height);
367 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
371 std::string
const imgname = name + std::to_string(img.
bufindex);
374 auto & im = itsImages2[imgname];
378 im.set2(frame, itsBackend.getDisplay());
381 im.draw(x, y, w,
h, noalias, proj * view);
384 itsLastDrawnImage = & im;
385 itsUsingScaledImage =
false;
386 itsLastDrawnTextLine = -1;
392 if (itsInputFrame ==
nullptr)
393 LFATAL(
"Input frame not available -- only accessible between drawInputFrame() and endFrame()");
394 return itsInputFrame;
403 itsGlobalAlpha = std::abs(1.0F - newval / 15.0F);
406 for (
auto & ip : itsImages) ip.second.twirl(newval);
417 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
418 img = itsLastDrawnImage;
422 std::string nstr = name;
423 auto itr = itsImages.find(nstr);
424 if (itr == itsImages.end())
428 itr = itsImages.find(nstr +
'0');
429 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
435 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
443{
return i2d(ImVec2(x, y), name); }
453 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
454 img = itsLastDrawnImage;
458 std::string nstr = name;
459 auto itr = itsImages.find(nstr);
460 if (itr == itsImages.end())
464 itr = itsImages.find(nstr +
'0');
465 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
471 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
479{
return i2ds(ImVec2(x, y), name); }
484 ImGui::GetBackgroundDrawList()->AddLine(i2d(x1, y1), i2d(x2, y2), col, linethick::get());
490 auto dlb = ImGui::GetBackgroundDrawList();
491 ImVec2
const tl = i2d(x1, y1);
492 ImVec2
const br = i2d(x2, y2);
494 if (filled) dlb->AddRectFilled(tl, br, applyFillAlpha(col));
495 ImDrawFlags
constexpr flags = ImDrawFlags_None;
496 float constexpr rounding = 0.0F;
498 dlb->AddRect(tl, br, col, rounding, flags, linethick::get());
504 auto dlb = ImGui::GetBackgroundDrawList();
505 float const thick = linethick::get();
507 if (filled) dlb->AddConvexPolyFilled(pts, npts, applyFillAlpha(col));
511 for (
size_t i = 0; i < npts - 1; ++i)
513 ImVec2
const & p1 = pts[i];
514 ImVec2
const & p2 = pts[i + 1];
517 if (p1.x != p2.x || p1.y != p2.y) dlb->AddLine(p1, p2, col, thick);
519 dlb->AddLine(pts[npts - 1], pts[0], col, thick);
526 size_t const npts = pts.size();
527 if (npts < 3)
return;
530 for (
int i = 0;
auto const & p : pts) iv[i++] = i2d(p.x, p.y);
532 drawPolyInternal(iv, npts, col, filled);
538 size_t const npts = pts.size();
539 if (npts < 3)
return;
542 for (
int i = 0;
auto const & p : pts) iv[i++] = i2d(p.x, p.y);
544 drawPolyInternal(iv, npts, col, filled);
550 float const * ptr = pts.ptr<
float>(0);
556 if (pts.rows == 1 || pts.cols == 1)
559 int n = std::max(pts.rows, pts.cols);
561 if (std::min(pts.rows, pts.cols) < 3)
return;
562 n /= 2; ImVec2 p[n];
for (
int i = 0; i < n; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
563 drawPolyInternal(p, n, col, filled);
565 else if (pts.rows == 2)
568 if (pts.cols < 3)
return;
569 ImVec2 p[pts.cols];
for (
int i = 0; i < pts.cols; ++i) { p[i] = i2d(ptr[0], ptr[pts.cols]); ++ptr; }
570 drawPolyInternal(p, pts.cols, col, filled);
572 else if (pts.cols == 2)
575 if (pts.rows < 3)
return;
576 ImVec2 p[pts.rows];
for (
int i = 0; i < pts.rows; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
577 drawPolyInternal(p, pts.rows, col, filled);
588 if (pts.cols < 3)
return;
589 ImVec2 p[pts.cols];
for (
int i = 0; i < pts.cols; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
590 drawPolyInternal(p, pts.cols, col, filled);
592 else if (pts.cols == 1)
595 if (pts.rows < 3)
return;
596 ImVec2 p[pts.rows];
for (
int i = 0; i < pts.rows; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
597 drawPolyInternal(p, pts.rows, col, filled);
610 auto dlb = ImGui::GetBackgroundDrawList();
612 ImVec2
const center = i2d(x, y);
613 float const rad = i2ds(r, 0).x;
615 if (filled) dlb->AddCircleFilled(center, rad, applyFillAlpha(col), 0);
617 dlb->AddCircle(center, rad, col, 0, linethick::get());
623 auto dlb = ImGui::GetBackgroundDrawList();
625 ImVec2
const center = i2d(x, y);
626 ImVec2
const rad = i2ds(rx, ry);
628 if (filled) dlb->AddEllipseFilled(center, rad, applyFillAlpha(col), rot, 0 );
630 dlb->AddEllipse(center, rad, col, rot, 0 , linethick::get());
636 ImGui::GetBackgroundDrawList()->AddText(i2d(x, y), col, txt);
642 drawText(x, y, txt.c_str(), col);
648 unsigned char alpha = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
649 alpha = (
unsigned char)(fillalpha::get() * alpha);
650 return (col & ~IM_COL32_A_MASK) | (alpha << IM_COL32_A_SHIFT);
656 if (line == -1) line = ++itsLastDrawnTextLine;
else itsLastDrawnTextLine = line;
657 ImVec2 p = i2d(0, 0, name);
659 p.y += 5.0F + (ImGui::GetFontSize() + 5.0F) * line;
666 ImU32
const c = (col == IM_COL32_BLACK_TRANS) ? ImU32(overlaycolor::get()) : col;
667 ImGui::GetBackgroundDrawList()->AddText(iline(line), c, txt);
673 itext(txt.c_str(), col, line);
678 unsigned short winw,
unsigned short winh)
680 unsigned short ww, wh;
681 if (winw == 0 || winh == 0) itsBackend.getWindowSize(ww, wh);
else { ww = winw; wh = winh; }
690 std::string
const msg =
jevois::sformat(
"%s, Camera: %s:%dx%d%s, Display: RGBA:%dx%d", fpscpu.c_str(),
692 cam2str.c_str(), ww, wh);
694 ImGui::GetBackgroundDrawList()->AddText(ImVec2(10, wh-10-ImGui::GetFontSize()), overlaycolor::get(), msg.c_str());
700 auto itr = itsImages.find(name);
701 if (itr != itsImages.end()) itsImages.erase(itr);
707 auto itr = itsImages2.find(name);
708 if (itr != itsImages2.end()) itsImages2.erase(itr);
716 float fx = 1.0F, fy = 1.0F;
720 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
721 img = itsLastDrawnImage;
722 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
726 std::string nstr = name;
727 auto itr = itsImages.find(nstr);
728 if (itr == itsImages.end())
732 itr = itsImages.find(nstr +
'0');
733 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
739 ImVec2 ret = img->
d2i(p);
740 ret.x *= fx; ret.y *= fy;
746{
return d2i(ImVec2(x, y), name); }
753 float fx = 1.0F, fy = 1.0F;
757 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
758 img = itsLastDrawnImage;
759 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
763 std::string nstr = name;
764 auto itr = itsImages.find(nstr);
765 if (itr == itsImages.end())
769 itr = itsImages.find(nstr +
'0');
770 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
776 ImVec2 ret = img->
d2is(p);
777 ret.x *= fx; ret.y *= fy;
783{
return d2is(ImVec2(x, y), name); }
789 ImGui::GetIO().MouseDrawCursor = ! itsIdle;
792 if (itsIdle ==
false) drawJeVoisGUI();
795 if (itsCompileState != CompilationState::Idle) compileModule();
798 if (itsGlobalAlpha != 1.0F)
800 if (itsGlobalAlpha < 0.0F || itsGlobalAlpha > 1.0F)
802 LERROR(
"Invalid global alpha " << itsGlobalAlpha <<
" -- RESET TO 1.0");
803 itsGlobalAlpha = 1.0F;
807 auto dlb = ImGui::GetBackgroundDrawList();
808 cv::Size
const ws = winsize::get();
809 dlb->AddRectFilled(ImVec2(0, 0), ImVec2(ws.width, ws.height), ImColor(0.0F, 0.0F, 0.0F, 1.0F - itsGlobalAlpha));
814 if (itsBannerTitle.empty() ==
false)
816 ImGui::SetNextWindowPos(ImVec2(800, 500));
817 ImGui::SetNextWindowSize(ImVec2(1000, 400));
818 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
819 ImGui::Begin(
"JeVois-Pro Demo Mode",
nullptr, ImGuiWindowFlags_NoResize |
820 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
821 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
822 ImGui::SetWindowFontScale(1.5F);
823 ImGui::TextUnformatted(
" ");
824 ImGui::TextUnformatted(itsBannerTitle.c_str());
825 ImGui::TextUnformatted(
" ");
826 ImGui::SetWindowFontScale(1.0F);
828 int wrap = ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
829 ImGui::PushTextWrapPos(wrap);
830 ImGui::TextUnformatted(itsBannerMsg.c_str());
831 ImGui::PopTextWrapPos();
833 ImGui::SetCursorPosY(ImGui::GetWindowSize().y - ImGui::CalcTextSize(
"X").y * 2.3F);
836 if (ImGui::Button(
"Skip to Next Demo")) engine()->
nextDemo();
837 ImGui::SetItemDefaultFocus();
838 ImGui::SameLine(600);
839 if (ImGui::Button(
"Abort Demo Mode")) engine()->
abortDemo();
841 ImGui::PopStyleColor();
847 itsInputFrame =
nullptr;
848 itsEndFrameCalled =
true;
855 ImGui::SetNextWindowPos(ImVec2(920, 358), ImGuiCond_FirstUseEver);
856 ImGui::SetNextWindowSize(ImVec2(941, 639), ImGuiCond_FirstUseEver);
858 if (ImGui::Begin(itsWindowTitle.c_str(),
nullptr ))
866 if (ImGui::BeginTabBar(
"##tabs", ImGuiTabBarFlags_None))
869 if (ImGui::BeginTabItem(
"Info"))
875 if (ImGui::BeginTabItem(
"Parameters"))
881 if (ImGui::BeginTabItem(
"Console"))
887 if (ImGui::BeginTabItem(
"Camera"))
893 if (ImGui::BeginTabItem(
"Config"))
895 itsCfgEditor->draw();
899 if (ImGui::BeginTabItem(
"Code"))
901 itsCodeEditor->draw();
905 if (ImGui::BeginTabItem(
"System"))
911 if (ImGui::BeginTabItem(
"Tweaks"))
923 if (itsShowStyleEditor)
925 ImGui::Begin(
"GUI Style Editor", &itsShowStyleEditor);
926 ImGui::ShowStyleEditor();
929 if (itsShowAppMetrics) ImGui::ShowMetricsWindow(&itsShowAppMetrics);
930 if (itsShowImGuiDemo) ImGui::ShowDemoWindow(&itsShowImGuiDemo);
933 if (itsShowHardSerialWin)
936 ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
939 ImGui::Begin(
"Hardware 4-pin Serial Monitor", &itsShowHardSerialWin);
943 ImGui::TextUnformatted(
"No Hardware serial port found!");
945 ImGui::TextUnformatted(
"Check engine:serialdev parameter, and");
946 ImGui::TextUnformatted(
"that engine:serialmonitors is true.");
952 if (itsShowUsbSerialWin)
955 ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
958 ImGui::Begin(
"USB Serial Monitor", &itsShowUsbSerialWin);
962 ImGui::TextUnformatted(
"No USB serial port found!");
964 ImGui::TextUnformatted(
"Check engine:usbserialdev parameter, and");
965 ImGui::TextUnformatted(
"that engine:serialmonitors is true.");
977 if (ImGui::BeginMenuBar())
979 if (ImGui::BeginMenu(
"File"))
981 if (ImGui::MenuItem(
"Quit")) engine()->
quit();
1017 if (ImGui::BeginMenu(
"Tools"))
1019 ImGui::MenuItem(
"ImGui Style Editor", NULL, &itsShowStyleEditor);
1020 ImGui::MenuItem(
"ImGui Metrics/Debugger", NULL, &itsShowAppMetrics);
1021 ImGui::MenuItem(
"ImGui Demo/Doc", NULL, &itsShowImGuiDemo);
1026 ImGui::EndMenuBar();
1033 static std::map<std::string, size_t> mods;
1035 static std::string currstr;
1038 ImGui::AlignTextToFramePadding();
1039 ImGui::TextUnformatted(
"Module:");
1041 ImGui::SetNextItemWidth(6 * ImGui::GetFontSize() + 5);
1042 if (ImGui::Combo(
"##typemachinevisionmodule", &itsVideoMappingListType,
"Pro/GUI\0Legacy\0Headless\0\0")
1043 || currstr.empty() || itsRefreshVideoMappings)
1046 itsRefreshVideoMappings =
false;
1049 switch (itsVideoMappingListType)
1084 default:
LFATAL(
"Internal error, itsVideoMappingListType=" << itsVideoMappingListType);
1088 currstr = e->getCurrentVideoMapping().menustr().c_str();
1094 if (ImGui::BeginCombo(
"##machinevisionmodule", currstr.c_str()))
1096 for (
auto const & m : mods)
1098 bool is_selected =
false;
1099 if (ImGui::Selectable(m.first.c_str(), is_selected))
1101 e->requestSetFormat(m.second);
1113 std::shared_ptr<jevois::Module> m = engine()->
module();
1117 if (itsIcon.loaded() ==
false)
1118 try { itsIcon.load(m->absolutePath(
"icon.png")); }
1122 LERROR(
"This module has no icon -- USING DEFAULT");
1125 if (engine()->getCurrentVideoMapping().ispython) itsIcon.load(
JEVOIS_SHARE_PATH "/icons/py.png");
1131 cv::Mat blank(32, 32, CV_8UC4, 0);
1132 itsIcon.load(blank);
1136 if (itsIcon.loaded())
1138 int const siz = ImGui::CalcTextSize(
" ").x;
1139 itsIcon.draw(ImGui::GetCursorScreenPos(), ImVec2(siz, siz));
1143 if (itsModName.empty())
1145 std::filesystem::path fname = m->absolutePath(
"modinfo.html");
1146 std::ifstream ifs(fname);
1147 if (ifs.is_open() ==
false)
1150 LINFO(
"Recomputing module's modinfo.html ...");
1154 std::string
const cmdout =
1156 "JEVOIS_SRC_ROOT=none jevoispro-modinfo " + vm.
modulename,
true);
1158 if (! std::filesystem::exists(fname))
1159 throw std::runtime_error(
"Failed to create " + vm.
modinfopath() +
": " + cmdout);
1161 catch (...) { itsModName = vm.
modulename; itsModAuth =
"Cannot read file: " + fname.string(); }
1167 for (std::string s; std::getline(ifs, s); )
1173 if (str.empty() ==
false) { itsModName = str; ++state; }
1180 if (str.empty() ==
false) { itsModDesc = str; ++state; }
1186 std::string
const str =
jevois::extractString(s,
"<table class=modinfoauth width=100%>",
"</table>");
1187 if (str.empty() ==
false)
1198 if (str.empty() ==
false)
1202 if (tok.size() >= 3)
1205 else itsModLang =
"Language: Python";
1207 else itsModLang =
"Language: Unknown";
1216 if (str.empty() ==
false)
1220 size_t idx = str2.find_first_not_of(
" ");
if (idx != str2.npos) str2 = str2.substr(idx);
1221 itsModDoc.emplace_back(str2);
1229 if (s ==
"</div></td></tr>") ++state;
1235 if (s.find(
"/h1>") != s.npos || s.find(
"/h2>") != s.npos || s.find(
"/h3>") != s.npos) prefix =
"* ";
1236 if (s.find(
"<li>") != s.npos) prefix =
"- ";
1241 std::string::iterator new_end =
1242 std::unique(ss.begin(), ss.end(), [](
char lhs,
char rhs) { return (lhs == rhs) && (lhs ==
' '); });
1243 ss.erase(new_end, ss.end());
1244 size_t idx = ss.find_first_not_of(
" ");
if (idx != ss.npos) ss = ss.substr(idx);
1245 itsModDoc.push_back(ss);
1256 ImGui::TextUnformatted((
" " + itsModName).c_str());
1257 ImGui::TextUnformatted((
" " + itsModDesc).c_str());
1258 ImGui::TextUnformatted((
" " + itsModAuth +
" " + itsModLang).c_str());
1259 ImGui::TextUnformatted(
" ");
1261 int wrap = ImGui::GetCursorPos().x + ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
1262 if (wrap < 200) wrap = 200;
1263 ImGui::PushTextWrapPos(wrap);
1266 for (std::string
const & s : itsModDoc)
1270 show = ImGui::CollapsingHeader(s.c_str() + 2, ImGuiTreeNodeFlags_DefaultOpen);
1275 else ImGui::TextUnformatted(s.c_str());
1278 ImGui::PopTextWrapPos();
1281 ImGui::TextUnformatted(
"No JeVois Module currently loaded.");
1295 static bool show_frozen =
true;
static bool show_system =
false;
1297 toggleButton(
"Show Frozen Parameters", &show_frozen);
1298 ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize(
"Show System Parameters").x - 30.0f);
1299 toggleButton(
"Show System Parameters", &show_system);
1305 if (c ==
nullptr) { ImGui::TextUnformatted(
"No module loaded.");
return; }
1308 std::set<std::string> pnames, ambig;
1311 std::map<std::string , std::vector<jevois::ParameterSummary>> psm;
1315 if (pnames.insert(psum.
name).second ==
false) ambig.insert(psum.
name);
1316 psm[psum.
category].emplace_back(psum); } );
1319 if (psm.empty()) { ImGui::TextUnformatted(
"This module has no parameters.");
return; }
1323 float maxlen = 0.0f;
1324 for (
auto const & pp : psm)
1327 if (show_frozen ==
false)
1329 bool all_frozen =
true;
1330 for (
auto const & ps : pp.second)
if (ps.frozen ==
false) { all_frozen =
false;
break; }
1331 if (all_frozen)
continue;
1335 if (ImGui::CollapsingHeader(pp.first.c_str()))
1337 ImGui::Columns(3,
"parameters");
1340 for (
auto const & ps : pp.second)
1343 if (ps.frozen && show_frozen ==
false)
continue;
1346 static char wname[16]; snprintf(wname, 16,
"##p%d", widgetnum);
1350 ImGui::AlignTextToFramePadding();
1351 std::string nam = ps.name;
1352 if (ambig.contains(nam))
1356 if (tok.size() >= 2) nam = tok[tok.size()-2] +
':' + nam;
1359 ImGui::TextUnformatted(nam.c_str());
1360 if (ImGui::IsItemHovered()) ImGui::SetTooltip(
"%s", ps.descriptor.c_str());
1361 maxlen = std::max(maxlen, ImGui::CalcTextSize(nam.c_str()).x);
1364 ImGui::NextColumn();
1365 ImGui::AlignTextToFramePadding();
1366 std::string
const & vtype = ps.valuetype;
1368 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str());
1370 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str(),
1371 (
"Allowed values: " + ps.validvalues).c_str());
1374 ImGui::NextColumn();
1375 bool const is_uchar = (vtype ==
"unsigned char");
1376 bool const is_int = (vtype ==
"short" || vtype ==
"int" || vtype ==
"long int" || vtype ==
"long long int");
1377 bool const is_uint = (is_uchar || vtype ==
"unsigned short" || vtype ==
"unsigned int" ||
1378 vtype ==
"unsigned long int" || vtype ==
"unsigned long long int" || vtype ==
"size_t");
1379 bool const is_real = (vtype ==
"float" || vtype ==
"double" || vtype ==
"long double");
1382 int textflags = ImGuiInputTextFlags_EnterReturnsTrue;
1385 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1386 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1387 textflags |= ImGuiInputTextFlags_ReadOnly;
1393 std::string vals = ps.validvalues.substr(6, ps.validvalues.size() - 7);
1396 if (vv.empty() ==
false)
1399 int index = 0;
for (
auto const & v : vv)
if (v == ps.value)
break;
else ++index;
1402 if (combo(wname, vv, index)) setparstr(ps.descriptor, vv[index]);
1412 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1417 long mi = 0, ma = 255;
1418 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &mi, &ma))
1419 setparstr(ps.descriptor, std::to_string(val));
1424 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1425 setparstr(ps.descriptor, std::to_string(val));
1431 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1434 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1435 setparstr(ps.descriptor, std::to_string(val));
1440 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1443 if (ImGui::SliderScalar(wname, ImGuiDataType_S64, &val, &r.
min(), &r.
max()))
1444 setparstr(ps.descriptor, std::to_string(val));
1449 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1452 if (ImGui::SliderScalar(wname, ImGuiDataType_Double, &val, &r.
min(), &r.
max()))
1453 setparstr(ps.descriptor, std::to_string(val));
1458 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1459 if (ImGui::InputText(wname, buf,
sizeof(buf), textflags))
1460 setparstr(ps.descriptor, buf);
1464 else if (vtype ==
"jevois::Range<unsigned char>")
1468 int mi = val.
min(), ma = val.
max();
1469 if (ImGui::DragIntRange2(wname, &mi, &ma, 0, 0, 255,
"Min: %d",
"Max: %d"))
1473 else if (vtype ==
"bool")
1476 if (ImGui::Checkbox(wname, &val)) setparval(ps.descriptor, val);
1479 else if (vtype ==
"ImColor")
1482 if (ImGui::ColorEdit4(wname, (
float *)&val, ImGuiColorEditFlags_AlphaPreview)) setparval(ps.descriptor, val);
1488 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1489 if (ImGui::InputText(wname, buf,
sizeof(buf), textflags))
1490 setparstr(ps.descriptor, buf);
1496 static char rname[24]; snprintf(rname, 24,
"Reset##%d", widgetnum);
1498 if (ImGui::Button(rname)) setparstr(ps.descriptor, ps.defaultvalue);
1504 ImGui::PopItemFlag();
1505 ImGui::PopStyleVar();
1509 ImGui::NextColumn(); ++widgetnum;
1513 ImGui::EndColumns();
1519 ImGui::Columns(3,
"parameters");
1520 ImGui::SetColumnWidth(0, maxlen + ImGui::CalcTextSize(
"XX").x);
1521 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
" (?) ").x);
1522 ImGui::SetColumnWidth(2, 2000);
1523 ImGui::EndColumns();
1533 bool slusb =
false, slhard =
false, schanged =
false;
1537 case jevois::engine::SerPort::None: slusb =
false; slhard =
false;
break;
1538 case jevois::engine::SerPort::All: slusb =
true; slhard =
true;
break;
1539 case jevois::engine::SerPort::Hard: slusb =
false; slhard =
true;
break;
1540 case jevois::engine::SerPort::USB: slusb =
true; slhard =
false;
break;
1542 ImGui::AlignTextToFramePadding();
1543 ImGui::TextUnformatted(
"Log messages:"); ImGui::SameLine();
1544 if (itsUSBserial ==
false)
1546 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1547 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1548 if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1549 ImGui::PopItemFlag();
1550 ImGui::PopStyleVar();
1551#ifdef JEVOIS_PLATFORM
1552 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1554 ImGui::BeginTooltip();
1555 ImGui::TextUnformatted(
"Disabled - enable USB serial in the System tab");
1556 ImGui::EndTooltip();
1559 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1561 ImGui::BeginTooltip();
1562 ImGui::TextUnformatted(
"Disabled - not available on host");
1563 ImGui::EndTooltip();
1567 else if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1569 ImGui::SameLine();
if (toggleButton(
"Hard##serlogh", &slhard)) schanged =
true;
1570 ImGui::SameLine(); toggleButton(
"Cons##serlogc", &itsSerLogEnabled);
1571 ImGui::SameLine(0, 50);
1573 bool sousb =
false, sohard =
false;
1577 case jevois::engine::SerPort::None: sousb =
false; sohard =
false;
break;
1578 case jevois::engine::SerPort::All: sousb =
true; sohard =
true;
break;
1579 case jevois::engine::SerPort::Hard: sousb =
false; sohard =
true;
break;
1580 case jevois::engine::SerPort::USB: sousb =
true; sohard =
false;
break;
1582 ImGui::TextUnformatted(
"Module output:"); ImGui::SameLine();
1583 if (itsUSBserial ==
false)
1585 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1586 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1587 if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1588 ImGui::PopItemFlag();
1589 ImGui::PopStyleVar();
1590#ifdef JEVOIS_PLATFORM
1591 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1593 ImGui::BeginTooltip();
1594 ImGui::TextUnformatted(
"Disabled - enable USB serial in the System tab");
1595 ImGui::EndTooltip();
1598 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1600 ImGui::BeginTooltip();
1601 ImGui::Text(
"Disabled - not available on host");
1602 ImGui::EndTooltip();
1606 else if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1607 ImGui::SameLine();
if (toggleButton(
"Hard##serouth", &sohard)) schanged =
true;
1608 ImGui::SameLine(); toggleButton(
"Cons##seroutc", &itsSerOutEnabled);
1614 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::All);
1619 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::Hard);
1625 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::All);
1630 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::Hard);
1640 int idx = 0;
for (
auto const & v : jevois::modul::SerStyle_Values)
if (v == sp)
break;
else ++idx;
1643 if (combo(
"serstyle", jevois::modul::SerStyle_Strings, idx))
1656{
return itsSerLogEnabled; }
1660{
return itsSerOutEnabled; }
1670 char const * b1txt,
char const * b2txt)
1673 int ret = 0;
int * retptr = default_val ? default_val : &ret;
1676 if (*retptr == 1 || *retptr == 2)
return *retptr;
1679 if (itsOpenModals.find(title) == itsOpenModals.end())
1681 ImGui::OpenPopup(title.c_str());
1682 itsOpenModals.insert(title);
1686 bool dont_ask_me_next_time = (*retptr == 3);
1688 if (ImGui::BeginPopupModal(title.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize))
1690 ImGui::TextUnformatted(text); ImGui::TextUnformatted(
" ");
1694 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1695 ImGui::PushStyleColor(ImGuiCol_FrameBg, 0xf0ffe0e0);
1696 ImGui::Checkbox(
"Don't ask me next time", &dont_ask_me_next_time);
1697 ImGui::PopStyleColor();
1698 ImGui::PopStyleVar();
1700 float const b1w = std::max(120.0F, ImGui::CalcTextSize(b1txt).x + 20.0F);
1701 if (ImGui::Button(b1txt, ImVec2(b1w, 0))) ret = 1;
1702 ImGui::SetItemDefaultFocus();
1704 float const b2w = std::max(120.0F, ImGui::CalcTextSize(b2txt).x + 20.0F);
1705 if (ImGui::Button(b2txt, ImVec2(b2w, 0))) ret = 2;
1710 if (ret == 1 || ret == 2)
1712 ImGui::CloseCurrentPopup();
1713 itsOpenModals.erase(title);
1714 if (dont_ask_me_next_time) *retptr = ret;
1716 else *retptr = dont_ask_me_next_time ? 3 : 0;
1724 return ImGui::Combo(name.c_str(), &selected_index,
1725 [](
void * vec,
int idx,
const char ** out_text)
1727 auto & ve = *static_cast<std::vector<std::string>*>(vec);
1728 if (idx < 0 || idx >= static_cast<int>(ve.size())) return false;
1729 *out_text = ve.at(idx).c_str();
1732 const_cast<void *
>(
static_cast<void const *
>(&items)), items.size());
1738 if (ImGui::GetMouseCursor() != ImGuiMouseCursor_ResizeAll) ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
1743 if (ImGui::IsMouseClicked(0))
1745 tl = ImGui::GetMousePos();
1752 br = ImGui::GetMousePos();
1753 auto dlb = ImGui::GetBackgroundDrawList();
1754 dlb->AddRectFilled(tl, br, applyFillAlpha(col));
1755 ImDrawFlags
constexpr flags = ImDrawFlags_None;
1756 float constexpr rounding = 0.0F;
1757 dlb->AddRect(tl, br, col, rounding, flags, linethick::get());
1759 if (ImGui::IsMouseReleased(0))
1762 int xmin = std::min(tl.x, br.x), xmax = std::max(tl.x, br.x);
1763 int ymin = std::min(tl.y, br.y), ymax = std::max(tl.y, br.y);
1765 if (xmax - xmin < 10 || ymax - ymin < 10)
1769 tl.x = xmin; tl.y = ymin; br.x = xmax; br.y = ymax;
1771 ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
1778 default:
LFATAL(
"Unknown state reached -- make sure you initialize state to 0 when starting a selection");
1785 char const * hint,
char const * hlp)
1787 static char buf[256];
1788 ImGui::AlignTextToFramePadding();
1789 ImGui::TextUnformatted(desc);
1790 ImGui::NextColumn();
1791 helpMarker(desc, hlp);
1792 ImGui::NextColumn();
1793 strncpy(buf, str.c_str(),
sizeof(buf)-1);
1794 if (ImGui::InputTextWithHint(wname, hint, buf,
sizeof(buf))) str = buf;
1795 ImGui::NextColumn();
1801 float const fontw = ImGui::GetFontSize();
1803 static int refresh = 1;
1804 static std::string cpu, mem, ver;
1805 static size_t npu, tpu, vpu, spu;
static int fan;
1819 ImGui::TextUnformatted(cpu.c_str());
1820 ImGui::TextUnformatted(mem.c_str());
1821 ImGui::Text(
"NPU: %zu, TPU: %zu, VPU: %zu, SPU: %zu. Fan: %d%%", npu, tpu, vpu, spu, fan);
1825 drawNewModuleForm();
1829 if (ImGui::Button(
"Open Hardware serial monitor...")) itsShowHardSerialWin =
true;
1831 if (ImGui::Button(
"Open USB serial monitor...")) itsShowUsbSerialWin =
true;
1835 static std::string pingstr;
1836 static int showping = 0;
1837 if (ImGui::Button(
"Ping jevois.usc.edu"))
1839 std::string ret =
jevois::system(
"/usr/bin/ping -c 1 -w 2 jevois.usc.edu");
1841 if (rvec.size() < 2) reportError(
"Unable to ping jevois.usc.edu");
1842 else { pingstr = rvec[1]; showping = 60; }
1847 ImGui::TextUnformatted(pingstr.c_str());
1854 static std::string zip;
1855 static std::string donestr;
1856 static int state = 0;
1858 ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
1859 if (state) flags |= ImGuiInputTextFlags_ReadOnly;
1860 ImGui::SetNextItemWidth(fontw * 6.0F);
1862 if (ImGui::InputText(
"Load Custom DNN", buf,
sizeof(buf), flags)) state = 1;
1868 ImGui::TextUnformatted(
" ");
1873 ImGui::TextUnformatted(
"-- Downloading...");
1874 zip = std::string(buf) +
".zip";
1887 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while loading custom DNN"); state = 0;
break; }
1888 ImGui::TextUnformatted(
"-- Downloading...");
1889 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1895 if (ifs.is_open() ==
false)
1897 reportError(
"Failed to download. Check network connectivity and available disk space.");
1914 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while unpacking custom DNN"); state = 0;
break; }
1915 ImGui::TextUnformatted(
"-- Installing...");
1916 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1918 std::string ret = itsDnnGetFut.get();
1921 donestr =
"-- Invalid file, check DNN download key.";
1923 donestr =
"-- Done. Reload model zoo to take effect.";
1931 ImGui::TextUnformatted(
" ");
1936 ImGui::TextUnformatted(donestr.c_str());
1941#ifdef JEVOIS_PLATFORM
1943 static int bootmode = 0;
1944 ImGui::AlignTextToFramePadding();
1945 ImGui::TextUnformatted(
"On boot, start:");
1947 if (ImGui::Combo(
"##onboot", &bootmode,
"(no change)\0JeVois-Pro\0Ubuntu Console\0Ubuntu Graphical\0\0"))
1952 case 2:
jevois::system(
"systemctl --no-reload set-default multi-user.target");
break;
1953 case 3:
jevois::system(
"systemctl --no-reload set-default graphical.target");
break;
1954 default:
jevois::system(
"systemctl --no-reload set-default jevoispro.target");
break;
1961 static bool gserial =
false;
1963 if (ImGui::Checkbox(
"Enable serial outputs/logs over mini-USB (on next reboot)", &gserial))
1966 ofs << (gserial ? 1 : 0) << std::endl;
1973 static bool show_fan_modal =
false;
1974 if (ImGui::Button(
"Edit fan settings"))
1976 itsCfgEditor->loadFile(
"/lib/systemd/system/jevoispro-fan.service");
1977 show_fan_modal =
true;
1982 static int doit_default = 0;
1983 int ret = modal(
"Ready to edit",
"File will now be loaded in the Config tab of the main window and "
1984 "ready to edit.\nPlease switch to the Config tab in the main window.\n\n"
1985 "When you save it, we will reboot the camera.",
1986 &doit_default,
"Ok",
"Thanks");
1989 case 1: show_fan_modal =
false;
break;
1990 case 2: show_fan_modal =
false;
break;
2004 unsigned int get_v4l2_fmt(
int idx)
2008 case 0:
return V4L2_PIX_FMT_YUYV;
2009 case 1:
return V4L2_PIX_FMT_RGB24;
2010 case 2:
return V4L2_PIX_FMT_RGB32;
2011 case 3:
return V4L2_PIX_FMT_GREY;
2012 case 4:
return V4L2_PIX_FMT_SBGGR16;
2017 unsigned int get_v4l2_idx(
int fcc)
2021 case V4L2_PIX_FMT_YUYV:
return 0;
2022 case V4L2_PIX_FMT_RGB24:
return 1;
2023 case V4L2_PIX_FMT_RGB32:
return 2;
2024 case V4L2_PIX_FMT_GREY:
return 3;
2025 case V4L2_PIX_FMT_SBGGR16:
return 4;
2031 void cookedCopy(std::filesystem::path
const & src, std::filesystem::path
const & dst,
2032 std::string
const & name, std::string
const & vendor, std::string
const & synopsis,
2033 std::string
const & author, std::string
const & email, std::string
const & website,
2034 std::string
const & license, std::string
const & videomapping)
2036 std::ifstream f(src);
2037 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
2038 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
2052 std::ofstream ofs(dst);
2053 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
2054 ofs << str << std::endl;
2055 LINFO(
"Translated copy " << src <<
" => " << dst);
2059 void cookedCmakeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
2060 std::string
const & oldname, std::string
const & newname,
2061 std::string
const & oldvendor, std::string
const & newvendor, std::string
const & synopsis,
2062 std::string
const & author, std::string
const & email, std::string
const & website,
2063 std::string
const & license, std::string
const & videomapping)
2065 std::ifstream f(src);
2066 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
2067 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
2082 std::ofstream ofs(dst);
2083 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
2084 ofs << str << std::endl;
2085 LINFO(
"Translated copy " << src <<
" => " << dst);
2089 void cookedCodeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
2090 std::string
const & oldname, std::string
const & newname)
2092 std::ifstream f(src);
2093 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
2094 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
2112 std::ofstream ofs(dst);
2113 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
2114 ofs << str << std::endl;
2115 LINFO(
"Translated copy " << src <<
" => " << dst);
2122 float const fontw = ImGui::GetFontSize();
2124 static int templ = 0;
2126 ImGui::PushStyleColor(ImGuiCol_PopupBg, 0xf0e0ffe0);
2128 if (ImGui::Button(
"Create new machine vision module..."))
2130 ImGui::OpenPopup(
"Create new machine vision module");
2131 itsIdleBlocked =
true;
2135 ImVec2
const center = ImGui::GetMainViewport()->GetCenter();
2136 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
2137 ImGui::SetNextWindowContentSize(ImVec2(940, 750));
2139 if (ImGui::BeginPopupModal(
"Create new machine vision module", NULL, ImGuiWindowFlags_AlwaysAutoResize))
2143 static std::string name, vendor, synopsis, author, email, website, license, srcvendor, srcname;
2144 static int language = 0;
2145 static int ofmt = 0;
static int ow = 320, oh = 240;
static float ofps = 30.0F;
2146 static int cmode = 0;
2147 static int wdrmode = 0;
2148 static int cfmt = 0;
static int cw = 1920, ch = 1080;
static float cfps = 30.0F;
2149 static int c2fmt = 1;
static int c2w = 512, c2h = 288;
2152 ImGui::AlignTextToFramePadding();
2153 ImGui::TextUnformatted(
"Fill out the details below, or clone from");
2156 static std::map<std::string, size_t> mods;
2157 static std::string currstr =
"...";
2163 if (ImGui::BeginCombo(
"##clonemodule", currstr.c_str()))
2165 for (
auto const & mod : mods)
2167 bool is_selected =
false;
2168 if (ImGui::Selectable(mod.first.c_str(), is_selected))
2170 m = e->getVideoMapping(mod.second);
2171 currstr = mod.first;
2177 { name =
"My" + m.
modulename + std::to_string(i++); }
2184 case jevois::CropType::CropScale: cmode = 0;
break;
2185 case jevois::CropType::Crop: cmode = 1;
break;
2186 case jevois::CropType::Scale: cmode = 2;
break;
2190 case jevois::WDRtype::Linear: wdrmode = 0;
break;
2191 case jevois::WDRtype::DOL: wdrmode = 1;
break;
2193 cfmt = get_v4l2_idx(m.
cfmt); cw = m.
cw; ch = m.
ch; cfps = m.
cfps;
2194 c2fmt = get_v4l2_idx(m.
c2fmt); c2w = m.
c2w; c2h = m.
c2h;
2204 ImGui::Columns(3,
"new module");
2206 newModEntry(
"##NewModname", name,
"Module Name",
"MyModule",
2207 "Required, even when cloning. Must start with an uppercase letter. "
2208 "Will be a folder name under /jevoispro/modules/VendorName");
2210 newModEntry(
"##NewModvendor", vendor,
"Vendor Name",
"MyVendor",
2211 "Required, even when cloning. Must start with an uppercase letter. "
2212 "Will be a folder name under /jevoispro/modules/");
2217 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2218 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2221 newModEntry(
"##NewModsynopsis", synopsis,
"Synopsis",
"Detect Object of type X",
2222 "Optional. Brief description of what the module does.");
2224 newModEntry(
"##NewModauthor", author,
"Author Name",
"John Smith",
"Optional");
2226 newModEntry(
"##NewModemail", email,
"Author Email",
"you@yourcompany.com",
"Optional");
2228 newModEntry(
"##NewModwebsite", website,
"Author Website",
"http://yourcompany.com",
"Optional");
2230 newModEntry(
"##NewModlicense", license,
"License",
"GPL v3",
"Optional");
2233 ImGui::AlignTextToFramePadding();
2234 ImGui::TextUnformatted(
"Module Language");
2235 ImGui::NextColumn();
2236 helpMarker(
"Module Language",
"Machine language to use for your module.");
2237 ImGui::NextColumn();
2238 ImGui::Combo(
"##NewModlanguage", &language,
"Python\0C++\0\0");
2239 ImGui::NextColumn();
2242 ImGui::AlignTextToFramePadding();
2243 ImGui::TextUnformatted(
"Module Template");
2244 ImGui::NextColumn();
2245 helpMarker(
"Module Template",
"Type of placeholder code that will be provided to get your module started.");
2246 ImGui::NextColumn();
2247 if (templ < 3) ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0\0");
2248 else ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0Clone\0\0");
2249 ImGui::NextColumn();
2252 int oflags = ImGuiInputTextFlags_None;
2255 oflags |= ImGuiInputTextFlags_ReadOnly;
2256 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2257 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2260 ImGui::AlignTextToFramePadding();
2261 ImGui::TextUnformatted(
"Module Output");
2262 ImGui::NextColumn();
2263 helpMarker(
"Module Output",
"Output video format for legacy module.");
2264 ImGui::NextColumn();
2265 ImGui::SetNextItemWidth(fontw * 5.0F);
2266 ImGui::Combo(
"##NewModofmt", &ofmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2268 ImGui::SetNextItemWidth(fontw * 4.0F);
2269 ImGui::InputInt(
"##NewModow", &ow, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2271 ImGui::TextUnformatted(
"x");
2273 ImGui::SetNextItemWidth(fontw * 4.0F);
2274 ImGui::InputInt(
"##NewModoh", &oh, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2276 ImGui::TextUnformatted(
"@");
2278 ImGui::SetNextItemWidth(fontw * 4.0F);
2279 ImGui::InputFloat(
"##NewModofps", &ofps, 0.0F, 0.0F,
"%.1f", ImGuiInputTextFlags_CharsDecimal | oflags);
2281 ImGui::TextUnformatted(
"fps");
2282 ImGui::NextColumn();
2286 ImGui::PopItemFlag();
2287 ImGui::PopStyleVar();
2291 ImGui::AlignTextToFramePadding();
2292 ImGui::TextUnformatted(
"Camera Mode");
2293 ImGui::NextColumn();
2294 helpMarker(
"Camera Mode",
"Camera sensor configuration for your module.");
2295 ImGui::NextColumn();
2296 ImGui::SetNextItemWidth(fontw * 18.0F);
2297 ImGui::Combo(
"##NewModcmode", &cmode,
"Dual-resolution (Crop+Scale)\0Single-resolution Crop\0"
2298 "Single-resolution Scale\0\0");
2299 ImGui::NextColumn();
2302 ImGui::AlignTextToFramePadding();
2303 ImGui::TextUnformatted(
"Camera WDR");
2304 ImGui::NextColumn();
2305 helpMarker(
"Camera WDR",
"Camera sensor wide-dynamic-range (WDR) setting for your module. Linear is for no WDR, "
2306 "DOL is for digital overlap (merging short and long exposure frames).");
2307 ImGui::NextColumn();
2308 ImGui::Combo(
"##NewModwdrmode", &wdrmode,
"Linear\0\0");
2310 ImGui::NextColumn();
2313 ImGui::AlignTextToFramePadding();
2314 ImGui::TextUnformatted(
"Camera Format");
2315 ImGui::NextColumn();
2316 helpMarker(
"Camera Format",
"Camera video format to use for input to module and for GUI display.");
2317 ImGui::NextColumn();
2318 ImGui::SetNextItemWidth(fontw * 5.0F);
2319 ImGui::Combo(
"##NewModcfmt", &cfmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2321 ImGui::SetNextItemWidth(fontw * 4.0F);
2322 ImGui::InputInt(
"##NewModcw", &cw, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2324 ImGui::TextUnformatted(
"x");
2326 ImGui::SetNextItemWidth(fontw * 4.0F);
2327 ImGui::InputInt(
"##NewModch", &ch, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2329 ImGui::TextUnformatted(
"@");
2331 ImGui::SetNextItemWidth(fontw * 4.0F);
2332 ImGui::InputFloat(
"##NewModcfps", &cfps, 0.0F, 0.0F,
"%.1f", ImGuiInputTextFlags_CharsDecimal);
2334 ImGui::TextUnformatted(
"fps");
2335 ImGui::NextColumn();
2338 int c2flags = ImGuiInputTextFlags_None;
2341 oflags |= ImGuiInputTextFlags_ReadOnly;
2342 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2343 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2346 ImGui::AlignTextToFramePadding();
2347 ImGui::TextUnformatted(
"Camera Format 2");
2348 ImGui::NextColumn();
2349 helpMarker(
"Camera Format 2",
"Camera video format for the second stream (for processing).");
2350 ImGui::NextColumn();
2351 ImGui::SetNextItemWidth(fontw * 5.0F);
2352 ImGui::Combo(
"##NewModc2fmt", &c2fmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2354 ImGui::SetNextItemWidth(fontw * 4.0F);
2355 ImGui::InputInt(
"##NewModc2w", &c2w, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2357 ImGui::TextUnformatted(
"x");
2359 ImGui::SetNextItemWidth(fontw * 4.0F);
2360 ImGui::InputInt(
"##NewModc2h", &c2h, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2361 ImGui::NextColumn();
2365 ImGui::PopItemFlag();
2366 ImGui::PopStyleVar();
2371 ImGui::PopItemFlag();
2372 ImGui::PopStyleVar();
2376 ImGui::SetColumnWidth(0, fontw * 10.0F);
2377 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
"(?)").x + 30.0F);
2385 ImVec2
const button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
2386 if (ImGui::Button(
"Cancel", button_size))
2388 ImGui::CloseCurrentPopup();
2390 ImGui::PopStyleColor();
2391 itsIdleBlocked =
false;
2396 ImGui::SameLine(0, 540);
2399 if (ImGui::Button(
"Create", button_size))
2402 if (name.empty())
LFATAL(
"New Module cannot have an empty name.");
2403 if (name[0]<
'A' || name[0]>
'Z')
LFATAL(
"New Module name must start with an uppercase letter.");
2404 if (vendor.empty())
LFATAL(
"New Module cannot have empty vendor name.");
2405 LINFO(
"New Module data valid...");
2409 if (std::filesystem::exists(newvdir) ==
false && std::filesystem::create_directory(newvdir) ==
false)
2410 PLFATAL(
"Error creating dir " << newvdir <<
" -- check that you are running as root");
2411 std::filesystem::path
const newmdir = newvdir / name;
2419 std::filesystem::path srcpath = m.
srcpath();
2420 std::filesystem::path cmakepath = m.
cmakepath();
2428 srcname.c_str(), newmdir.c_str());
2430 LINFO(
"Cloned module using: " << copycmd);
2433 unlink((m.
path() +
'/' + srcname +
".C").c_str());
2434 unlink((m.
path() +
'/' + srcname +
".py").c_str());
2435 unlink((m.
path() +
'/' + srcname +
".so").c_str());
2436 std::filesystem::remove_all(m.
path() +
"/__pycache__");
2437 std::filesystem::remove_all(m.
path() +
"/build");
2440 std::ostringstream oss; oss << m; vmstr = oss.
str();
2441 cookedCodeClone(srcpath, m.srcpath(), srcname, name);
2446 if (std::filesystem::exists(cmakepath))
2447 cookedCmakeClone(cmakepath, m.cmakepath(), srcname, name, srcvendor, vendor, synopsis, author,
2448 email, website, license, vmstr);
2451 name, vendor, synopsis, author, email, website, license, vmstr);
2459 if (std::filesystem::exists(newmdir))
2460 LFATAL(
"Directory [" << newmdir <<
"] already exists -- Choose another name");
2461 if (std::filesystem::create_directory(newmdir) ==
false)
2462 PLFATAL(
"Error creating directory [" << newmdir <<
"] for new module. Maybe not running as root?");
2463 LINFO(
"Created new Module directory: " << newmdir);
2470 case 1: m.
ofmt = get_v4l2_fmt(ofmt); m.
ow = ow; m.
oh = oh; m.
ofps = ofps;
break;
2471 case 2: m.
ofmt = 0;
break;
2475 m.
cfmt = get_v4l2_fmt(cfmt);
2476 m.
cw = cw; m.
ch = ch; m.
cfps = cfps;
2483 case 0: m.
wdr = jevois::WDRtype::Linear;
break;
2484 case 1: m.
wdr = jevois::WDRtype::DOL;
break;
2490 case 0: m.
crop = jevois::CropType::CropScale;
2491 m.
c2fmt = get_v4l2_fmt(c2fmt);
2492 m.
c2w = c2w; m.
c2h = c2h;
2494 case 1: m.
crop = jevois::CropType::Crop;
break;
2495 case 2: m.
crop = jevois::CropType::Scale;
break;
2500 std::ostringstream oss; oss << m; vmstr = oss.
str();
2503 std::string code; std::string tname;
2507 tname =
"PyModule.py";
2516 std::filesystem::path dstcmak = m.cmakepath();
2517 cookedCopy(srccmak, dstcmak, name, vendor, synopsis, author, email, website, license, vmstr);
2521 default:
LFATAL(
"Invalid language " << language);
2525 std::filesystem::path dstmod = m.srcpath();
2526 cookedCopy(srcmod, dstmod, name, vendor, synopsis, author, email, website, license, vmstr);
2531 LINFO(
"Added videomapping: " << vmstr);
2538 if (language == 0) runNewModule();
2539 else itsCompileState = CompilationState::Start;
2542 name.clear(); vendor.clear(); synopsis.clear(); currstr =
"...";
2544 ImGui::CloseCurrentPopup();
2545 itsIdleBlocked =
false;
2548 catch (...) { reportAndIgnoreException(); }
2554 ImGui::PopStyleColor();
2561 size_t idx = 0;
size_t foundidx = 12345678;
2563 {
if (itsNewMapping.isSameAs(mm)) foundidx = idx; ++idx; });
2566 else LFATAL(
"Internal error, could not find the module we just created -- CHECK LOGS");
2568 itsRefreshVideoMappings =
true;
2573 else if (itsNewMapping.ofmt != 0 && itsNewMapping.ofmt !=
JEVOISPRO_FMT_GUI) itsVideoMappingListType = 1;
2574 else if (itsNewMapping.ofmt == 0) itsVideoMappingListType = 2;
2575 else LERROR(
"Internal error: cannot determine video mapping list type -- IGNORED");
2581#define L(i,x,y,z)for(F i=x;i<y;i+=z)
2582#define Q(y)sin((y+t)*.03)*(1-sin(t*3)*cos(y/99+t))*9
2583#define H(p,w)L(k,0,5,1)d->AddCircleFilled(p+V(1,-1)*w*k/8,w*(1-k/5),k<4?0xff000000+k*0x554400:-1);
2584#define J(b)L(i,0,h,1){TinyImGUIdemo&o=G[int(i)];if(b*o.z>0)H(o.p,(o.z*.3+4)*o.w)}
2585#define O(b)i=t+1.6+j/99;if(b*sin(i)>0)H(c+v*j+u*(cos(i)*40+Q(j)),30)
2587F w=0;
L(z,4,20,1){w+=z;
L(yy,-l,l,z*2){
F y=yy+fmod(t*z*10,z*2);
L(i,-1,2,2)d->AddCircle(c+v*y+u*i*(w+sin((y+t)/25)*w/30),z,0xff000000+0x110e00*
int(z*z*z/384),12,z/2);}}
2588h=0;
L(y,-l,l,15)
L(b,0,16,1){i=t+b*.2+y/99;
G[
h++]={c+v*y+u*(cos(i)*60+
Q(y)),sinf(i),(b<1||b>14)?2.f:1.5f};}std::sort(
G,
G+
h);
2589 F j=(-2+fmod(t*3,5))*99;
J(-1)
O(-1)a=c+v*-l;
L(y,-l,l,15){b=c+v*y+u*((15-rand())&31)*.1;
L(k,0,9,1)d->AddLine(a-v,b,k<8?0x11222200*k:-1,(9-k)*4);a=b;}
O(1)
J(1)}
2594 if (ImGui::Button(
"Open Style Editor")) itsShowStyleEditor =
true;
2596 if (ImGui::Button(
"Open App Metrics")) itsShowAppMetrics =
true;
2598 if (ImGui::Button(
"Open ImGui Demo")) itsShowImGuiDemo =
true;
2602 float camz = pixel_perfect_z;
2606 static float fudgex = 0.375f;
2607 static float fudgey = 0.375f;
2608 static float fudgez = 0.0f;
2609 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh);
2611 ImGui::SliderFloat(
"OpenGL Camera z", &camz, -2.0f * winh, -1.0f);
2612 ImGui::SliderAngle(
"OpenGL yaw", &yaw, -179.0f, 180.0f);
2613 ImGui::SliderAngle(
"OpenGL pitch", &pitch, -179.0f, 180.0f);
2614 ImGui::SliderAngle(
"OpenGL roll", &roll, -179.0f, 180.0f);
2616 ImGui::SliderFloat(
"fudge x", &fudgex, -1.0f, 1.0f);
2617 ImGui::SliderFloat(
"fudge y", &fudgey, -1.0f, 1.0f);
2618 ImGui::SliderFloat(
"fudge z", &fudgez, -1.0f, 1.0f);
2621 proj = glm::perspective(glm::radians(45.0f),
float(winw) /
float(winh), 1.0f, winh * 2.0f);
2622 proj = glm::translate(proj, glm::vec3(fudgex, fudgey, fudgez));
2625 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, camz));
2626 view *= glm::yawPitchRoll(yaw, pitch, roll);
2642 ImGuiIO& io = ImGui::GetIO();
2643 ImGui::Begin(
"Tiny OpenGL demo", NULL, ImGuiWindowFlags_AlwaysAutoResize);
2644 ImVec2 size(320.0f, 180.0f);
2645 ImGui::InvisibleButton(
"canvas", size);
2646 ImVec2 p0 = ImGui::GetItemRectMin();
2647 ImVec2 p1 = ImGui::GetItemRectMax();
2648 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2649 draw_list->PushClipRect(p0, p1);
2652 mouse_data.x = (io.MousePos.x - p0.x) / size.x;
2653 mouse_data.y = (io.MousePos.y - p0.y) / size.y;
2654 mouse_data.z = io.MouseDownDuration[0];
2655 mouse_data.w = io.MouseDownDuration[1];
2657 drawTinyImGUIdemo(draw_list, p0, p1, size, mouse_data, (
float)ImGui::GetTime());
2658 draw_list->PopClipRect();
2666{ reportErrorOrInfo(err,
false); }
2670{ reportErrorOrInfo(err,
true); }
2677 auto now = std::chrono::steady_clock::now();
2679 std::lock_guard<std::mutex> _(itsErrorMtx);
2682 for (
auto & e : itsErrors)
if (e.err == err) { e.lasttime = now;
return; }
2685 if (itsErrors.size() > 10)
return;
2686 else if (itsErrors.size() == 10)
2688 ErrorData d {
"Too many errors -- TRUNCATING", now, now,
false };
2689 itsErrors.emplace(itsErrors.end(), std::move(d));
2695 itsErrors.emplace(itsErrors.end(), std::move(d));
2703 std::lock_guard<std::mutex> _(itsErrorMtx);
2713 catch (std::exception
const & e)
2714 { reportError(e.what()); }
2715 catch (boost::python::error_already_set & e)
2718 { reportError(
"Unknown error"); }
2723 catch (std::exception
const & e)
2724 { reportError(prefix +
": " + e.what()); }
2725 catch (boost::python::error_already_set & e)
2728 { reportError(prefix +
": Unknown error"); }
2735 reportAndIgnoreException(prefix);
2742 std::lock_guard<std::mutex> _(itsErrorMtx);
2743 if (itsErrors.empty())
return;
2745 bool err_hovered =
false, inf_hovered =
false;
2748 std::vector<char const *> errors, infos;
2749 for (
auto const & e : itsErrors)
2750 if (e.is_info) infos.push_back(e.err.c_str());
2751 else errors.push_back(e.err.c_str());
2753 ImGuiWindowFlags
constexpr window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
2754 ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize;
2755 ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_Always);
2757 float const wrappos = ImGui::GetFontSize() * 35.0f;
2760 if (errors.empty() ==
false)
2762 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xc0e0e0ff);
2763 if (ImGui::Begin(
"Error popup", &show, window_flags))
2765 ImGui::PushTextWrapPos(wrappos);
2766 ImGui::TextUnformatted(
"Error detected! ");
2767 for (
char const * e : errors) { ImGui::Separator(); ImGui::TextUnformatted(e); }
2768 ImGui::PopTextWrapPos();
2770 err_hovered = ImGui::IsWindowHovered();
2771 ImGui::SetNextWindowPos(ImVec2(10.0f, 15.0f + ImGui::GetWindowSize().y), ImGuiCond_Always);
2773 ImGui::PopStyleColor();
2777 if (infos.empty() ==
false)
2779 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xc0d0ffe0);
2780 if (ImGui::Begin(
"Info popup", &show, window_flags))
2782 ImGui::PushTextWrapPos(wrappos);
2783 ImGui::TextUnformatted(
"Info message ");
2784 for (
char const * e : infos) { ImGui::Separator(); ImGui::TextUnformatted(e); }
2785 ImGui::PopTextWrapPos();
2787 inf_hovered = ImGui::IsWindowHovered();
2789 ImGui::PopStyleColor();
2793 auto itr = itsErrors.begin();
2794 while (itr != itsErrors.end())
2797 std::chrono::duration<float> d = std::chrono::steady_clock::now() - itr->lasttime;
2798 std::chrono::duration<float> d2 = std::chrono::steady_clock::now() - itr->firsttime;
2802 if (d.count() >= 1.0f && d2.count() >= 3.0F && inf_hovered ==
false) itr = itsErrors.erase(itr);
2807 if (d.count() >= 1.0f && d2.count() >= 10.0F && err_hovered ==
false) itr = itsErrors.erase(itr);
2817 ImGui::TextUnformatted(
"(?)");
2818 if (ImGui::IsItemHovered())
2820 ImGui::BeginTooltip();
2821 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2822 ImGui::TextUnformatted(msg);
2823 if (msg2) { ImGui::Separator(); ImGui::TextUnformatted(msg2); }
2824 if (msg3) { ImGui::Separator(); ImGui::TextUnformatted(msg3); }
2825 ImGui::PopTextWrapPos();
2826 ImGui::EndTooltip();
2833 bool changed =
false;
2836 ImGui::PushID(name);
2837 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2838 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2839 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(4.0f/7.0f, 0.5f, 0.5f));
2840 if (ImGui::Button(name)) { *val =
false; changed =
true; }
2841 ImGui::PopStyleColor(3);
2844 else if (ImGui::Button(name)) { *val =
true; changed =
true; }
2852 unsigned short winw, winh;
2853 startFrame(winw, winh);
2855 if (itsHeadless.loaded() ==
false)
2860 cv::Mat blank(winh, winw, CV_8UC4, 0);
2861 itsHeadless.load(blank);
2864 if (itsHeadless.loaded()) itsHeadless.draw(ImVec2(0, 0), ImVec2(winw, winh), ImGui::GetBackgroundDrawList());
2872 ImGui::PushStyleColor(ImGuiCol_Text, 0xff0000ff);
2873 ImGui::TextUnformatted(str.c_str());
2874 ImGui::PopStyleColor();
2881 itsBannerTitle = title;
2888 if (itsCompileState == CompilationState::Cmake || itsCompileState == CompilationState::Make ||
2889 itsCompileState == CompilationState::Install || itsCompileState == CompilationState::CPack)
2890 reportError(
"Still compiling... Try again later...");
2891 else if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2892 itsCompileState = CompilationState::Start;
2897 std::filesystem::path
const & fpath = itsCodeEditor->getLoadedFilePath();
2898 std::filesystem::path
const fn = fpath.filename();
2900 if (fn ==
"CMakeLists.txt" || fn.extension() ==
".C")
2902 itsNewMapping = { };
2903 std::filesystem::path p = fpath.parent_path();
2904 itsNewMapping.modulename = p.filename();
2905 itsNewMapping.vendor = p.parent_path().filename();
2906 itsNewMapping.ispython =
false;
2909 if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2910 itsCompileState = CompilationState::Start;
2911 else reportError(
"Cannot find " + itsNewMapping.srcpath() +
" or " + itsNewMapping.cmakepath() +
" -- IGNORED");
2913 else reportError(
"Cannot compile " + fpath.string() +
" -- IGNORED");
2920 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
2922 ImGui::SetNextWindowSize(ImVec2(800, 680), ImGuiCond_FirstUseEver);
2925 int constexpr flags = ImGuiWindowFlags_HorizontalScrollbar;
2926 bool keep_window_open =
true;
2927 if (itsCompileState == CompilationState::Error) ImGui::Begin(
"C++ Module Compilation", &keep_window_open, flags);
2928 else ImGui::Begin(
"C++ Module Compilation",
nullptr, flags);
2930 ImGui::TextUnformatted((
"Compiling " + itsNewMapping.srcpath()).c_str());
2931 ImGui::TextUnformatted((
"Using " + itsNewMapping.cmakepath()).c_str());
2933 std::string
const modpath = itsNewMapping.path();
2934 std::string
const buildpath = modpath +
"/build";
2938 switch (itsCompileState)
2941 case CompilationState::Start:
2942 LINFO(
"Start compiling " << itsNewMapping.srcpath());
2943 itsIdleBlocked =
true;
2944 for (std::string & s : itsCompileMessages) s.clear();
2945 std::filesystem::remove_all(buildpath);
2946 itsCompileState = CompilationState::Cmake;
2951 std::filesystem::path sp(modpath +
"/rebuild.sh");
2953 std::ofstream ofs(sp);
2954 if (ofs.is_open() ==
false)
2955 reportError(
"Cannot write " + sp.string() +
" -- check that you are running as root.");
2959 ofs <<
"#!/bin/sh" << std::endl <<
"set -e" << std::endl;
2960 ofs <<
"cmake -S " << modpath <<
" -B " << buildpath <<
" -DJEVOIS_HARDWARE=PRO"
2961#ifdef JEVOIS_PLATFORM
2962 <<
" -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2965 ofs <<
"JEVOIS_SRC_ROOT=none cmake --build " << buildpath << std::endl;
2966 ofs <<
"cmake --install " << buildpath << std::endl;
2967 ofs <<
"cd " << buildpath <<
2968 " && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/" << std::endl;
2972 using std::filesystem::perms;
2973 std::filesystem::permissions(sp, perms::owner_all | perms::group_read | perms::group_exec |
2974 perms::others_read | perms::others_exec);
2980 case CompilationState::Cmake:
2981 if (compileCommand(
"cmake -S " + modpath +
" -B " + buildpath +
2982 " -DJEVOIS_HARDWARE=PRO"
2983#ifdef JEVOIS_PLATFORM
2984 " -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2986 , itsCompileMessages[0]))
2987 itsCompileState = CompilationState::Make;
2991 case CompilationState::Make:
2992 if (compileCommand(
"JEVOIS_SRC_ROOT=none cmake --build " + buildpath, itsCompileMessages[1]))
2993 itsCompileState = CompilationState::Install;
2997 case CompilationState::Install:
2998 if (compileCommand(
"cmake --install " + buildpath, itsCompileMessages[2]))
2999 itsCompileState = CompilationState::CPack;
3003 case CompilationState::CPack:
3004 if (compileCommand(
"cd " + buildpath +
" && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/",
3005 itsCompileMessages[3]))
3006 itsCompileState = CompilationState::Success;
3010 case CompilationState::Success:
3012 ImGui::TextUnformatted(
"Compilation success!");
3013 ImGui::TextUnformatted(
"See below for details...");
3015 static int run_default = 0;
3016 int ret = modal(
"Success! Run the module now?",
"Compilation success!\n\nA deb package of your module is in "
3017 "/jevoispro/debs/\nif you want to share it.\n\nLoad and run the new module now?",
3018 &run_default,
"Yes",
"No");
3023 itsIdleBlocked =
false;
3024 itsCompileState = CompilationState::Idle;
3029 itsIdleBlocked =
false;
3030 itsCompileState = CompilationState::Idle;
3032 itsRefreshVideoMappings =
true;
3040 case CompilationState::Error:
3042 itsIdleBlocked =
false;
3043 highlightText(
"Compilation failed!");
3044 ImGui::TextUnformatted(
"You may need to edit the two files above.");
3045 ImGui::TextUnformatted(
"See below for details...");
3047 static bool show_modal =
false;
3049 ImGui::AlignTextToFramePadding();
3050 if (ImGui::Button(
"Edit CMakeLists.txt"))
3051 { itsCodeEditor->loadFile(itsNewMapping.cmakepath()); show_modal =
true; }
3053 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
3054 if (ImGui::Button((
"Edit " + itsNewMapping.modulename +
".C").c_str()))
3055 { itsCodeEditor->loadFile(itsNewMapping.srcpath()); show_modal =
true; }
3057 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
3058 if (ImGui::Button(
"Compile again")) itsCompileState = CompilationState::Start;
3064 static int doit_default = 0;
3065 int ret = modal(
"Ready to edit",
"File will now be loaded in the Code tab of the main window and "
3066 "ready to edit. Please switch to the Code tab in the main window.\n\n"
3067 "When you save it, we will try to compile it again.",
3068 &doit_default,
"Close Compilation Window",
"Keep Open");
3071 case 1: show_modal =
false; itsCompileState = CompilationState::Idle;
break;
3072 case 2: show_modal =
false;
break;
3081 LERROR(
"Internal error: invalid compilation state " <<
int(itsCompileState) <<
" -- RESET TO IDLE");
3082 itsCompileState = CompilationState::Idle;
3083 itsIdleBlocked =
false;
3085 }
catch (...) { reportAndIgnoreException(); }
3088 for (std::string & s : itsCompileMessages)
3089 if (s.empty() ==
false)
3091 ImGui::TextUnformatted(s.c_str());
3096 ImGui::PopStyleColor();
3099 if (keep_window_open ==
false) { itsIdleBlocked =
false; itsCompileState = CompilationState::Idle; }
3106 if (itsCompileFut.valid() ==
false)
3109 msg =
"Running: " + cmd +
"\nPlease wait ...\n";
3110 LINFO(
"Running: " + cmd);
3112 else if (itsCompileFut.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready)
3115 msg += itsCompileFut.get() +
"\nSuccess!";
3116 LINFO(
"Success running: " << cmd);
3121 LERROR(
"Failed running: " << cmd);
3122 itsCompileState = CompilationState::Error;
#define JEVOIS_MODULE_PATH
Base path for modules.
#define JEVOIS_CUSTOM_DNN_URL
URL where custom converted DNN models can be downloaded:
#define JEVOIS
Helper string that evaluates to "jevois" or "jevoispro" depending on values of JEVOIS_A33 and JEVOIS_...
#define JEVOIS_VERSION_STRING
Software version, as string.
#define JEVOIS_CUSTOM_DNN_PATH
Directory where custom DNN models are stored:
#define JEVOISPRO_GSERIAL_FILE
Flag file for whether to enable g_serial at boot on jevoispro.
#define JEVOIS_SHARE_PATH
Base path for shared files (e.g., neural network weights, etc)
#define JEVOIS_PYDNN_PATH
Directory where python pre/net/post DNN processors are stored:
#define JEVOIS_ROOT_PATH
Root path for runtime jevois config files, videomappings.cfg, modules, etc.
void drawTinyImGUIdemo(ImDrawList *d, V a, V b, V, ImVec4, F t)
#define JEVOIS_WAIT_GET_FUTURE(f)
Wait for a future to become ready for 5 seconds, get(), warn and ignore exception,...
#define JEVOISPRO_FMT_GUI
JeVois-Pro zero-copy display of camera input frame (to be used as output mode in VideoMapping)
A component of a model hierarchy.
void setParamValUnique(std::string const ¶mdescriptor, T const &val)
Set a parameter value, simple version assuming only one parameter match.
void foreachParam(std::function< void(std::string const &compname, ParameterBase *p)> func, std::string const &cname="")
Run a function on every param we hold.
std::string getParamStringUnique(std::string const ¶mdescriptor) const
Get a parameter value by string, simple version assuming only one parameter match.
void setParamStringUnique(std::string const ¶mdescriptor, std::string const &val)
Set a parameter value by string, simple version assuming only one parameter match.
T getParamValUnique(std::string const ¶mdescriptor) const
Get a parameter value, simple version assuming only one parameter match.
JeVois processing engine - gets images from camera sensor, processes them, and sends results over USB...
void requestSetFormat(int idx)
Use this to request a format change from within process()
void drawCameraGUI()
Draw all camera controls into our GUI.
void nextDemo()
When in demo mode, switch to next demo.
std::shared_ptr< Module > module() const
Get a pointer to our current module (may be null)
void abortDemo()
When in demo mode, abort demo mode.
void quit()
Terminate the program.
VideoMapping const & getCurrentVideoMapping() const
Get the current video mapping.
void reloadVideoMappings()
Re-load video mappings from videomappings.cfg.
void foreachVideoMapping(std::function< void(VideoMapping const &m)> &&func)
Run a function on every video mapping.
Class to hold a GPUtexture, GPUprogram, and other data associated with rendering an image in OpenGL.
ImVec2 i2ds(ImVec2 const &p)
Convert a 2D size from within a rendered image to on-screen.
ImVec2 i2d(ImVec2 const &p)
Convert coordinates of a point from within a rendered image to on-screen.
ImVec2 d2i(ImVec2 const &p)
Convert coordinates of a point from on-screen to within a rendered image.
ImVec2 d2is(ImVec2 const &p)
Convert a 2D size from on-screen to within a rendered image.
Simple console with coloring and completion.
void draw()
Render into ImGui.
Editor panel for JeVois-Pro GUI.
void drawCircle(float x, float y, float r, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw circle over an image.
void endFrame()
Finish current frame and render it.
bool seroutEnabled() const
Tell whether user enabled serout messages to GUI console.
bool combo(std::string const &name, std::vector< std::string > const &items, int &selected_index)
Helper to draw a combobox from a vector of strings.
void resetstate(bool modulechanged=true)
Reset to default state, typically called on Module or video format change.
std::shared_ptr< GUIeditor > itsCfgEditor
ImVec2 iline(int line=-1, char const *name=nullptr)
Get coordinates of the start of a given line of text to be drawn as overlay on top of an image.
void reportAndIgnoreException(std::string const &prefix="")
Report current exception in a modal dialog, then ignore it.
void drawInputFrame(char const *name, InputFrame const &frame, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool casync=false)
Draw the input video frame from the camera using zero-copy.
bool startFrame(unsigned short &w, unsigned short &h)
Start a new rendering frame.
ImVec2 i2ds(ImVec2 p, char const *name=nullptr)
Convert a 2D size from within a rendered image to on-screen.
void drawText(float x, float y, char const *txt, ImU32 col=IM_COL32(128, 255, 128, 255))
Draw text over an image.
void reportErrorOrInfo(std::string const &err, bool is_info)
void drawEllipse(float x, float y, float rx, float ry, float rot=0.0F, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw ellipse over an image.
virtual ~GUIhelper()
Destructor.
void drawRect(float x1, float y1, float x2, float y2, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw rectangular box over an image.
void onParamChange(gui::scale const ¶m, float const &newval) override
bool frameStarted() const
Helper to indicate that startFrame() was called, and thus endFrame() should be called.
void startCompilation()
Compile a newly created module.
void drawInputFrame2(char const *name, InputFrame const &frame, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool casync=false)
Draw the second (scaled) input video frame from the camera using zero-copy.
std::shared_ptr< GUIeditor > itsCodeEditor
void clearErrors()
Clear all errors currently displayed in the JeVois-Pro GUI.
void newModEntry(char const *wname, std::string &str, char const *desc, char const *hint, char const *hlp)
void releaseImage(char const *name)
Release an image.
void iinfo(jevois::InputFrame const &inframe, std::string const &fpscpu, unsigned short winw=0, unsigned short winh=0)
Display processing and video info at bottom of screen.
void helpMarker(char const *msg, char const *msg2=nullptr, char const *msg3=nullptr)
Display a (?) label and show tooltip when it is hovered.
void demoBanner(std::string const &title="", std::string const &msg="")
Display some text in a big banner, used by demo mode.
void highlightText(std::string const &str)
Like ImGui::Textunformatted but in a highlight color (typically, red)
void reportError(std::string const &err)
Report an error in an overlay window.
void headlessDisplay()
Show a message that we are running headless.
ImVec2 i2d(ImVec2 p, char const *name=nullptr)
Convert coordinates of a point from within a rendered image to on-screen.
void reportAndRethrowException(std::string const &prefix="")
Report current exception in a modal dialog, then re-throw it.
bool selectImageBox(int &state, ImVec2 &tl, ImVec2 &br, ImU32 col=IM_COL32(128, 255, 128, 255))
Helper to select a rectangular box by dragging the mouse over the display.
bool idle() const
Check for idle in case startFrame() was called elsewhere.
ImVec2 d2is(ImVec2 p, char const *name=nullptr)
Convert a 2D size from on-screen to within a rendered image.
void drawLine(float x1, float y1, float x2, float y2, ImU32 col=IM_COL32(128, 255, 128, 255))
Draw line over an image.
void itext(char const *txt, ImU32 const &col=IM_COL32_BLACK_TRANS, int line=-1)
Draw some overlay text on top of an image.
void releaseImage2(char const *name)
Release an image, second video stream.
InputFrame const * getInputFrame() const
Get access to the InputFrame last drawn with drawInputFrame()
ImU32 applyFillAlpha(ImU32 col) const
int modal(std::string const &title, char const *text, int *default_val=nullptr, char const *b1txt="Ok", char const *b2txt="Cancel")
Helper to draw a modal with 2 choices.
void drawPoly(std::vector< cv::Point > const &pts, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw polygon over an image.
void drawPolyInternal(ImVec2 const *pts, size_t npts, ImU32 col, bool filled)
void setparstr(std::string const &descriptor, std::string const &val)
std::string itsWindowTitle
bool compileCommand(std::string const &cmd, std::string &msg)
void reportInfo(std::string const &inf)
Report a transient info message in an overlay window.
GUIhelper(std::string const &instance, bool conslock=false)
Constructor.
ImVec2 d2i(ImVec2 p, char const *name=nullptr)
Convert coordinates of a point from on-screen to within a rendered image.
bool toggleButton(char const *name, bool *val)
Helper to draw a toggle button.
void drawImage(char const *name, RawImage const &img, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool isoverlay=false)
Draw a RawImage, copying pixel data to an OpenGL texture.
bool serlogEnabled() const
Tell whether user enabled serlog messages to GUI console.
Simple class to monitor a serial port in the JeVois-Pro GUI.
std::shared_ptr< Comp > getComponent(std::string const &instanceName) const
Get a top-level component by instance name.
Base class for Parameter.
bool hidden() const
Returns whether parameter is hidden.
virtual ParameterSummary const summary() const =0
Get summary info about this parameter.
ParameterSummary provides a summary about a parameter.
std::string name
Plain name of the parameter.
std::string category
Category of the parameter, as a string.
T const & min() const
Return the minimum value.
T const & max() const
Return the maximum value.
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
unsigned int fmt
Pixel format as a V4L2_PIX_FMT_XXX.
size_t bufindex
The index of the data buffer in the kernel driver.
unsigned int width
Image width in pixels.
unsigned int height
Image height in pixels.
Base class for a module that supports standardized serial messages.
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
std::string getSysInfoCPU()
Get CPU info: frequency, thermal, load.
std::string warnAndIgnoreException(std::string const &prefix="")
Convenience function to catch an exception, issue some LERROR (depending on type),...
#define PLFATAL(msg)
Like LDEBUG but appends errno and strerror(errno), to be used when some system call fails.
std::string getSysInfoMem()
Get memory info.
std::string getSysInfoVersion()
Get O.S. version info.
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
std::string getPythonExceptionString(boost::python::error_already_set &)
Python exception translation to string so we can print the traceback to our serlog stream.
std::string shapestr(cv::Mat const &m)
Get a string of the form: "nD AxBxC... TYPE" from an n-dimensional cv::Mat with data type TYPE.
void paramStringToVal(std::string const &valstring, T &result)
Machine-readable conversion from string to T, for use in jevois::Parameter.
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)
Async execution using a thread pool.
std::string extractString(std::string const &str, std::string const &startsep, std::string const &endsep)
Extract a portion of a string between two delimiters.
std::string tolower(std::string const &str)
Convert string to lowercase.
std::string getFileString(char const *fname, int skip=0)
Read one line from a file and return it as a string.
std::string system(std::string const &cmd, bool errtoo=true)
Execute a command and grab stdout output to a string.
std::string join(std::vector< T > const &tokens, std::string const &delimiter)
Concatenate a vector of tokens into a string.
std::string sformat(char const *fmt,...) __attribute__((format(__printf__
Create a string using printf style arguments.
size_t replaceStringAll(std::string &str, std::string const &from, std::string const &to)
Replace all instances of 'from' with 'to'.
bool stringStartsWith(std::string const &str, std::string const &prefix)
Return true if str starts with prefix (including if both strings are equal)
std::string fccstr(unsigned int fcc)
Convert a V4L2 four-cc code (V4L2_PIX_FMT_...) to a 4-char string.
std::vector< std::string > split(std::string const &input, std::string const ®ex="\\s+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async_little(Function &&f, Args &&... args)
Async execution using a thread pool.
Main namespace for all JeVois classes and functions.
size_t getNumInstalledVPUs()
Get the number of Myriad-X VPUs present on this system.
int getFanSpeed()
Get fan speed in percent, only meaningful on JeVois-Pro Platform, all others return 0.
size_t getNumInstalledNPUs()
Get the number of JeVois-Pro NPUs present on this system.
size_t getNumInstalledTPUs()
Get the number of Coral TPUs present on this system.
size_t getNumInstalledSPUs()
Get the number of Hailo8 SPUs present on this system.
bool operator<(TinyImGUIdemo &o)
Simple struct to hold video mapping definitions for the processing Engine.
WDRtype wdr
Type of wide-dynamic-range (WDR) to use, if sensor supports it.
unsigned int cfmt
camera pixel format
unsigned int ow
output width
unsigned int c2fmt
When crop is CropScale, pixel format of the scaled images, otherwise 0.
std::string modinfopath() const
Return the full absolute path and file name of the module's modinfo.html file.
unsigned int c2w
When crop is CropScale, width of the scaled images, otherwise 0.
CropType crop
Type of crop/scale to apply if camera size does not match sensor native.
std::string modulename
Name of the Module that will process this mapping.
std::string str() const
Convenience function to print out the whole mapping in a human-friendly way.
float cfps
camera frame rate in frames/sec
bool ispython
True if the module is written in Python; affects behavior of sopath() only.
std::string menustr2() const
Convenience function to print out the whole mapping in a human-friendly way to be used in a menu.
std::string path() const
Return the full absolute path the module's directory.
unsigned int cw
camera width
float ofps
output frame rate in frames/sec
unsigned int c2h
When crop is CropScale, height of the scaled images, otherwise 0.
unsigned int ch
camera height
unsigned int oh
output height
std::string srcpath() const
Return the full absolute path and file name of the module's .C or .py file.
std::string menustr() const
Convenience function to print out the whole mapping in a human-friendly way to be used in a menu.
std::string vendor
Module creator name, used as a directory to organize the modules.
std::string cmakepath() const
Return the full absolute path and file name of the module's CMakeLists.txt file.
unsigned int ofmt
output pixel format, or 0 for no output over USB