23 #define IMGUI_DEFINE_MATH_OPERATORS // Access to math operators
24 #include <imgui_internal.h>
36 #include <imgui_internal.h>
37 #include <glm/gtc/matrix_transform.hpp>
38 #include <glm/gtx/euler_angles.hpp>
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));
65 itsWindowTitle =
"JeVois-Pro v" + std::string(JEVOIS_VERSION_STRING);
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 },
74 { JEVOIS_ROOT_PATH
"/share/dnn/models.yml",
75 "JeVois models.yml DNN Zoo Root", EditorSaveAction::Reload },
76 { JEVOIS_ROOT_PATH
"/share/dnn/opencv.yml",
77 "JeVois opencv.yml DNN Zoo for OpenCV models", EditorSaveAction::Reload },
78 { JEVOIS_ROOT_PATH
"/share/dnn/npu.yml",
79 "JeVois npu.yml DNN Zoo for A311D NPU models", EditorSaveAction::Reload },
80 { JEVOIS_ROOT_PATH
"/share/dnn/spu.yml",
81 "JeVois spu.yml DNN Zoo for Hailo SPU models", EditorSaveAction::Reload },
82 { JEVOIS_ROOT_PATH
"/share/dnn/tpu.yml",
83 "JeVois tpu.yml DNN Zoo for Coral TPU models", EditorSaveAction::Reload },
84 { JEVOIS_ROOT_PATH
"/share/dnn/vpu.yml",
85 "JeVois vpu.yml DNN Zoo for Myriad-X VPU models", EditorSaveAction::Reload },
86 { JEVOIS_ROOT_PATH
"/share/dnn/ort.yml",
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));
161 itsUSBserial = ! engine()->getParamStringUnique(
"engine:usbserialdev").empty();
164 jevois::VideoMapping
const & m = engine()->getCurrentVideoMapping();
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);
181 LINFO(
"OpenGL init " << siz.width <<
'x' << siz.height << (fs ?
" fullscreen" :
""));
182 itsBackend.init(siz.width, siz.height, fs,
scale::get(), itsConsLock);
186 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh); winsize::set(cv::Size(winw, winh));
188 fullscreen::freeze();
195 bool shouldclose =
false;
auto const now = std::chrono::steady_clock::now();
196 if (itsBackend.pollEvents(shouldclose)) itsLastEventTime = now;
200 LINFO(
"Closing down on user request...");
205 itsBackend.newFrame();
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.499
F)));
246 jevois::gui::GuiStyle
const & newval)
250 case jevois::gui::GuiStyle::Dark:
251 ImGui::StyleColorsDark();
252 itsCfgEditor->SetPalette(TextEditor::GetDarkPalette());
253 itsCodeEditor->SetPalette(TextEditor::GetDarkPalette());
256 case jevois::gui::GuiStyle::Light:
257 ImGui::StyleColorsLight();
258 ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 0.92f);
259 itsCfgEditor->SetPalette(TextEditor::GetLightPalette());
260 itsCodeEditor->SetPalette(TextEditor::GetLightPalette());
263 case jevois::gui::GuiStyle::Classic:
264 ImGui::StyleColorsClassic();
265 itsCfgEditor->SetPalette(TextEditor::GetRetroBluePalette());
266 itsCodeEditor->SetPalette(TextEditor::GetRetroBluePalette());
274 auto & s = ImGui::GetStyle();
275 s.WindowRounding = newval;
276 s.ChildRounding = newval;
277 s.FrameRounding = newval;
278 s.PopupRounding = newval;
279 s.ScrollbarRounding = newval;
280 s.GrabRounding = newval;
285 {
return (itsEndFrameCalled ==
false); }
289 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
295 auto & im = itsImages[imgname];
301 im.draw(x, y, w,
h, noalias, proj * view);
304 if (isoverlay ==
false)
306 itsLastDrawnImage = & im;
307 itsUsingScaledImage =
false;
308 itsLastDrawnTextLine = -1;
314 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
317 auto & im = itsImages[name];
323 im.draw(x, y, w,
h, noalias, proj * view);
326 if (isoverlay ==
false)
328 itsLastDrawnImage = & im;
329 itsUsingScaledImage =
false;
330 itsLastDrawnTextLine = -1;
336 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
343 auto & im = itsImages[imgname];
347 im.set(frame, itsBackend.getDisplay());
350 im.draw(x, y, w,
h, noalias, proj * view);
353 itsLastDrawnImage = & im;
355 itsLastDrawnTextLine = -1;
356 if (itsUsingScaledImage)
359 itsScaledImageFacX = float(img.
width) / float(img2.
width);
360 itsScaledImageFacY = float(img.
height) / float(img2.
height);
366 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
373 auto & im = itsImages2[imgname];
377 im.set2(frame, itsBackend.getDisplay());
380 im.draw(x, y, w,
h, noalias, proj * view);
383 itsLastDrawnImage = & im;
384 itsUsingScaledImage =
false;
385 itsLastDrawnTextLine = -1;
394 itsGlobalAlpha = std::abs(1.0
F - newval / 15.0
F);
397 for (
auto & ip : itsImages) ip.second.twirl(newval);
408 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
409 img = itsLastDrawnImage;
413 std::string nstr = name;
414 auto itr = itsImages.find(nstr);
415 if (itr == itsImages.end())
419 itr = itsImages.find(nstr +
'0');
420 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
426 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
434 {
return i2d(ImVec2(x, y), name); }
444 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
445 img = itsLastDrawnImage;
449 std::string nstr = name;
450 auto itr = itsImages.find(nstr);
451 if (itr == itsImages.end())
455 itr = itsImages.find(nstr +
'0');
456 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
462 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
470 {
return i2ds(ImVec2(x, y), name); }
475 ImGui::GetBackgroundDrawList()->AddLine(i2d(x1, y1), i2d(x2, y2), col,
linethick::get());
481 auto dlb = ImGui::GetBackgroundDrawList();
482 ImVec2
const tl = i2d(x1, y1);
483 ImVec2
const br = i2d(x2, y2);
485 if (filled) dlb->AddRectFilled(tl, br, applyFillAlpha(col));
487 dlb->AddRect(tl, br, col, 0.0
F, ImDrawCornerFlags_All,
linethick::get());
493 auto dlb = ImGui::GetBackgroundDrawList();
496 if (filled) dlb->AddConvexPolyFilled(pts, npts, applyFillAlpha(col));
500 for (
size_t i = 0; i < npts - 1; ++i) dlb->AddLine(pts[i], pts[i + 1], col, thick);
501 dlb->AddLine(pts[npts - 1], pts[0], col, thick);
508 size_t const npts = pts.size();
510 ImVec2 iv[npts];
int i = 0;
511 for (
auto const & p : pts) iv[i++] = i2d(p.x, p.y);
513 drawPolyInternal(iv, npts, col, filled);
519 size_t const npts = pts.size();
521 ImVec2 iv[npts];
int i = 0;
522 for (
auto const & p : pts) iv[i++] = i2d(p.x, p.y);
524 drawPolyInternal(iv, npts, col, filled);
530 auto dlb = ImGui::GetBackgroundDrawList();
532 ImVec2
const center = i2d(x, y);
533 float const rad = i2ds(r, 0).x;
535 if (filled) dlb->AddCircleFilled(center, rad, applyFillAlpha(col), 0);
543 ImGui::GetBackgroundDrawList()->AddText(i2d(x, y), col, txt);
549 drawText(x, y, txt.c_str(), col);
555 unsigned char alpha = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
557 return (col & ~IM_COL32_A_MASK) | (alpha << IM_COL32_A_SHIFT);
563 if (line == -1) line = ++itsLastDrawnTextLine;
else itsLastDrawnTextLine = line;
564 ImVec2 p = i2d(0, 0, name);
566 p.y += 5.0F + (ImGui::GetFontSize() + 5.0F) * line;
573 ImU32
const c = (col == IM_COL32_BLACK_TRANS) ? ImU32(
overlaycolor::get()) : col;
574 ImGui::GetBackgroundDrawList()->AddText(iline(line), c, txt);
580 itext(txt.c_str(), col, line);
585 unsigned short winw,
unsigned short winh)
587 unsigned short ww, wh;
588 if (winw == 0 || winh == 0) itsBackend.getWindowSize(ww, wh);
else { ww = winw; wh = winh; }
597 std::string
const msg =
jevois::sformat(
"%s, Camera: %s:%dx%d%s, Display: RGBA:%dx%d", fpscpu.c_str(),
599 cam2str.c_str(), ww, wh);
601 ImGui::GetBackgroundDrawList()->AddText(ImVec2(10, wh-10-ImGui::GetFontSize()),
overlaycolor::get(), msg.c_str());
607 auto itr = itsImages.find(name);
608 if (itr != itsImages.end()) itsImages.erase(itr);
614 auto itr = itsImages2.find(name);
615 if (itr != itsImages2.end()) itsImages2.erase(itr);
623 float fx = 1.0F, fy = 1.0F;
627 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
628 img = itsLastDrawnImage;
629 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
633 std::string nstr = name;
634 auto itr = itsImages.find(nstr);
635 if (itr == itsImages.end())
639 itr = itsImages.find(nstr +
'0');
640 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
646 ImVec2 ret = img->
d2i(p);
647 ret.x *= fx; ret.y *= fy;
653 {
return d2i(ImVec2(x, y), name); }
660 float fx = 1.0F, fy = 1.0F;
664 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
665 img = itsLastDrawnImage;
666 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
670 std::string nstr = name;
671 auto itr = itsImages.find(nstr);
672 if (itr == itsImages.end())
676 itr = itsImages.find(nstr +
'0');
677 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
683 ImVec2 ret = img->
d2is(p);
684 ret.x *= fx; ret.y *= fy;
690 {
return d2is(ImVec2(x, y), name); }
696 ImGui::GetIO().MouseDrawCursor = ! itsIdle;
699 if (itsIdle ==
false) drawJeVoisGUI();
702 if (itsCompileState != CompilationState::Idle) compileModule();
705 if (itsGlobalAlpha != 1.0
F)
707 if (itsGlobalAlpha < 0.0F || itsGlobalAlpha > 1.0
F)
709 LERROR(
"Invalid global alpha " << itsGlobalAlpha <<
" -- RESET TO 1.0");
710 itsGlobalAlpha = 1.0F;
714 auto dlb = ImGui::GetBackgroundDrawList();
716 dlb->AddRectFilled(ImVec2(0, 0), ImVec2(ws.width, ws.height), ImColor(0.0
F, 0.0
F, 0.0
F, 1.0
F - itsGlobalAlpha));
721 if (itsBannerTitle.empty() ==
false)
723 ImGui::SetNextWindowPos(ImVec2(800, 500));
724 ImGui::SetNextWindowSize(ImVec2(1000, 400));
725 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
726 ImGui::Begin(
"JeVois-Pro Demo Mode",
nullptr, ImGuiWindowFlags_NoResize |
727 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
728 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
729 ImGui::SetWindowFontScale(1.5
F);
730 ImGui::TextUnformatted(
" ");
731 ImGui::TextUnformatted(itsBannerTitle.c_str());
732 ImGui::TextUnformatted(
" ");
733 ImGui::SetWindowFontScale(1.0
F);
735 int wrap = ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
736 ImGui::PushTextWrapPos(wrap);
737 ImGui::TextUnformatted(itsBannerMsg.c_str());
738 ImGui::PopTextWrapPos();
740 ImGui::SetCursorPosY(ImGui::GetWindowSize().y - ImGui::CalcTextSize(
"X").y * 2.3
F);
743 if (ImGui::Button(
"Skip to Next Demo")) engine()->nextDemo();
744 ImGui::SetItemDefaultFocus();
745 ImGui::SameLine(600);
746 if (ImGui::Button(
"Abort Demo Mode")) engine()->abortDemo();
748 ImGui::PopStyleColor();
754 itsEndFrameCalled =
true;
760 if (ImGui::Begin(itsWindowTitle.c_str(),
nullptr ))
768 if (ImGui::BeginTabBar(
"##tabs", ImGuiTabBarFlags_None))
771 if (ImGui::BeginTabItem(
"Info"))
777 if (ImGui::BeginTabItem(
"Parameters"))
783 if (ImGui::BeginTabItem(
"Console"))
789 if (ImGui::BeginTabItem(
"Camera"))
795 if (ImGui::BeginTabItem(
"Config"))
797 itsCfgEditor->draw();
801 if (ImGui::BeginTabItem(
"Code"))
803 itsCodeEditor->draw();
807 if (ImGui::BeginTabItem(
"System"))
813 if (ImGui::BeginTabItem(
"Tweaks"))
825 if (itsShowStyleEditor)
827 ImGui::Begin(
"GUI Style Editor", &itsShowStyleEditor);
828 ImGui::ShowStyleEditor();
831 if (itsShowAppMetrics) ImGui::ShowMetricsWindow(&itsShowAppMetrics);
832 if (itsShowImGuiDemo) ImGui::ShowDemoWindow(&itsShowImGuiDemo);
841 if (ImGui::BeginMenuBar())
843 if (ImGui::BeginMenu(
"File"))
845 if (ImGui::MenuItem(
"Quit")) engine()->quit();
881 if (ImGui::BeginMenu(
"Tools"))
883 ImGui::MenuItem(
"ImGui Style Editor", NULL, &itsShowStyleEditor);
884 ImGui::MenuItem(
"ImGui Metrics/Debugger", NULL, &itsShowAppMetrics);
885 ImGui::MenuItem(
"ImGui Demo/Doc", NULL, &itsShowImGuiDemo);
897 static std::map<std::string, size_t> mods;
899 static std::string currstr;
902 ImGui::AlignTextToFramePadding();
903 ImGui::Text(
"Module:");
905 ImGui::SetNextItemWidth(6 * ImGui::GetFontSize() + 5);
906 if (ImGui::Combo(
"##typemachinevisionmodule", &itsVideoMappingListType,
"Pro/GUI\0Legacy\0Headless\0\0")
907 || currstr.empty() || itsRefreshVideoMappings)
910 itsRefreshVideoMappings =
false;
913 switch (itsVideoMappingListType)
919 e->foreachVideoMapping([&idx](jevois::VideoMapping
const & m) {
930 e->foreachVideoMapping([&idx](jevois::VideoMapping
const & m) {
941 e->foreachVideoMapping([&idx](jevois::VideoMapping
const & m) {
942 if (m.ofmt == 0) mods[m.menustr()] = idx;
948 default:
LFATAL(
"Internal error, itsVideoMappingListType=" << itsVideoMappingListType);
952 currstr = e->getCurrentVideoMapping().menustr().c_str();
958 if (ImGui::BeginCombo(
"##machinevisionmodule", currstr.c_str()))
960 for (
auto const & m : mods)
962 bool is_selected =
false;
963 if (ImGui::Selectable(m.first.c_str(), is_selected))
965 e->requestSetFormat(m.second);
977 std::shared_ptr<jevois::Module> m = engine()->module();
981 if (itsIcon.loaded() ==
false)
986 LERROR(
"This module has no icon -- USING DEFAULT");
989 if (engine()->getCurrentVideoMapping().ispython) itsIcon.load(JEVOIS_SHARE_PATH
"/icons/py.png");
990 else itsIcon.load(JEVOIS_SHARE_PATH
"/icons/cpp.png");
995 cv::Mat blank(32, 32, CV_8UC4, 0);
1000 if (itsIcon.loaded())
1002 int const siz = ImGui::CalcTextSize(
" ").x;
1003 itsIcon.draw(ImGui::GetCursorScreenPos(), ImVec2(siz, siz));
1007 if (itsModName.empty())
1009 std::filesystem::path fname = m->
absolutePath(
"modinfo.html");
1010 std::ifstream ifs(fname);
1011 if (ifs.is_open() ==
false)
1014 LINFO(
"Recomputing module's modinfo.html ...");
1015 jevois::VideoMapping
const & vm = engine()->getCurrentVideoMapping();
1018 std::string
const cmdout =
1020 "JEVOIS_SRC_ROOT=none jevois-modinfo " + vm.modulename,
true);
1022 if (! std::filesystem::exists(fname))
1023 throw std::runtime_error(
"Failed to create " + vm.modinfopath() +
": " + cmdout);
1025 catch (...) { itsModName = vm.modulename; itsModAuth =
"Cannot read file: " + fname.string(); }
1031 for (std::string s; std::getline(ifs, s); )
1037 if (str.empty() ==
false) { itsModName = str; ++state; }
1044 if (str.empty() ==
false) { itsModDesc = str; ++state; }
1050 std::string
const str =
jevois::extractString(s,
"<table class=modinfoauth width=100%>",
"</table>");
1051 if (str.empty() ==
false)
1062 if (str.empty() ==
false)
1066 if (tok.size() >= 3)
1069 else itsModLang =
"Language: Python";
1071 else itsModLang =
"Language: Unknown";
1080 if (str.empty() ==
false)
1084 size_t idx = str2.find_first_not_of(
" ");
if (idx != str2.npos) str2 = str2.substr(idx);
1085 itsModDoc.emplace_back(str2);
1093 if (s ==
"</div></td></tr>") ++state;
1099 if (s.find(
"/h1>") != s.npos || s.find(
"/h2>") != s.npos || s.find(
"/h3>") != s.npos) prefix =
"* ";
1100 if (s.find(
"<li>") != s.npos) prefix =
"- ";
1105 std::string::iterator new_end =
1106 std::unique(ss.begin(), ss.end(), [](
char lhs,
char rhs) { return (lhs == rhs) && (lhs ==
' '); });
1107 ss.erase(new_end, ss.end());
1108 size_t idx = ss.find_first_not_of(
" ");
if (idx != ss.npos) ss = ss.substr(idx);
1109 itsModDoc.push_back(ss);
1120 ImGui::TextUnformatted((
" " + itsModName).c_str());
1121 ImGui::TextUnformatted((
" " + itsModDesc).c_str());
1122 ImGui::TextUnformatted((
" " + itsModAuth +
" " + itsModLang).c_str());
1123 ImGui::TextUnformatted(
" ");
1125 int wrap = ImGui::GetCursorPos().x + ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
1126 if (wrap < 200) wrap = 200;
1127 ImGui::PushTextWrapPos(wrap);
1130 for (std::string
const & s : itsModDoc)
1134 show = ImGui::CollapsingHeader(s.c_str() + 2, ImGuiTreeNodeFlags_DefaultOpen);
1139 else ImGui::TextUnformatted(s.c_str());
1142 ImGui::PopTextWrapPos();
1145 ImGui::TextUnformatted(
"No JeVois Module currently loaded.");
1151 try { engine()->setParamStringUnique(descriptor, val); }
1159 static bool show_frozen =
true;
static bool show_system =
false;
1161 toggleButton(
"Show Frozen Parameters", &show_frozen);
1162 ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize(
"Show System Parameters").x - 30.0f);
1163 toggleButton(
"Show System Parameters", &show_system);
1169 if (c ==
nullptr) { ImGui::TextUnformatted(
"No module loaded.");
return; }
1172 std::set<std::string> pnames, ambig;
1175 std::map<std::string , std::vector<jevois::ParameterSummary>> psm;
1178 if (pnames.insert(psum.
name).second ==
false) ambig.insert(psum.
name);
1179 psm[psum.
category].push_back(std::move(psum)); } );
1182 if (psm.empty()) { ImGui::Text(
"This module has no parameters.");
return; }
1186 float maxlen = 0.0f;
1187 for (
auto const & pp : psm)
1190 if (show_frozen ==
false)
1192 bool all_frozen =
true;
1193 for (
auto const & ps : pp.second)
if (ps.frozen ==
false) { all_frozen =
false;
break; }
1194 if (all_frozen)
continue;
1198 if (ImGui::CollapsingHeader(pp.first.c_str()))
1200 ImGui::Columns(3,
"parameters");
1203 for (
auto const & ps : pp.second)
1206 if (ps.frozen && show_frozen ==
false)
continue;
1209 static char wname[16]; snprintf(wname, 16,
"##p%d", widgetnum);
1213 ImGui::AlignTextToFramePadding();
1214 std::string nam = ps.name;
1215 if (ambig.contains(nam))
1219 if (tok.size() >= 2) nam = tok[tok.size()-2] +
':' + nam;
1222 ImGui::TextUnformatted(nam.c_str());
1223 if (ImGui::IsItemHovered()) ImGui::SetTooltip(
"%s", ps.descriptor.c_str());
1224 maxlen = std::max(maxlen, ImGui::CalcTextSize(nam.c_str()).x);
1227 ImGui::NextColumn();
1228 ImGui::AlignTextToFramePadding();
1229 std::string
const & vtype = ps.valuetype;
1231 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str());
1233 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str(),
1234 (
"Allowed values: " + ps.validvalues).c_str());
1237 ImGui::NextColumn();
1238 bool const is_uchar = (vtype ==
"unsigned char");
1239 bool const is_int = (vtype ==
"short" || vtype ==
"int" || vtype ==
"long int" || vtype ==
"long long int");
1240 bool const is_uint = (is_uchar || vtype ==
"unsigned short" || vtype ==
"unsigned int" ||
1241 vtype ==
"unsigned long int" || vtype ==
"unsigned long long int" || vtype ==
"size_t");
1242 bool const is_real = (vtype ==
"float" || vtype ==
"double" || vtype ==
"long double");
1247 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1248 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1254 std::string vals = ps.validvalues.substr(6, ps.validvalues.size() - 7);
1257 if (vv.empty() ==
false)
1260 int index = 0;
for (
auto const & v : vv)
if (v == ps.value)
break;
else ++index;
1261 if (ImGui::Combo(wname, &index,
1262 [](
void * vec,
int idx,
const char ** out_text)
1264 auto & ve = *
static_cast<std::vector<std::string>*
>(vec);
1265 if (idx < 0 || idx >=
static_cast<int>(ve.size()))
return false;
1266 *out_text = ve.at(idx).c_str();
1269 static_cast<void *
>(&vv), vv.size()))
1270 setparstr(ps.descriptor, vv[index]);
1280 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1285 long mi = 0, ma = 255;
1286 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &mi, &ma))
1292 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1299 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1302 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1308 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1311 if (ImGui::SliderScalar(wname, ImGuiDataType_S64, &val, &r.
min(), &r.
max()))
1317 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1320 if (ImGui::SliderScalar(wname, ImGuiDataType_Double, &val, &r.
min(), &r.
max()))
1326 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1327 if (ImGui::InputText(wname, buf,
sizeof(buf), ImGuiInputTextFlags_EnterReturnsTrue))
1328 setparstr(ps.descriptor, buf);
1332 else if (vtype ==
"jevois::Range<unsigned char>")
1336 int mi = val.
min(), ma = val.
max();
1337 if (ImGui::DragIntRange2(wname, &mi, &ma, 0, 0, 255,
"Min: %d",
"Max: %d"))
1341 else if (vtype ==
"bool")
1344 if (ImGui::Checkbox(wname, &val)) setparval(ps.descriptor, val);
1347 else if (vtype ==
"ImColor")
1350 if (ImGui::ColorEdit4(wname, (
float *)&val, ImGuiColorEditFlags_AlphaPreview)) setparval(ps.descriptor, val);
1356 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1357 if (ImGui::InputText(wname, buf,
sizeof(buf), ImGuiInputTextFlags_EnterReturnsTrue))
1358 setparstr(ps.descriptor, buf);
1364 static char rname[18]; snprintf(rname, 18,
"Reset##%d", widgetnum);
1366 if (ImGui::Button(rname)) setparstr(ps.descriptor, ps.defaultvalue);
1372 ImGui::PopItemFlag();
1373 ImGui::PopStyleVar();
1377 ImGui::NextColumn(); ++widgetnum;
1387 ImGui::Columns(3,
"parameters");
1388 ImGui::SetColumnWidth(0, maxlen + ImGui::CalcTextSize(
"XX").x);
1389 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
" (?) ").x);
1390 ImGui::SetColumnWidth(2, 2000);
1401 bool slusb =
false, slhard =
false, schanged =
false;
1405 case jevois::engine::SerPort::None: slusb =
false; slhard =
false;
break;
1406 case jevois::engine::SerPort::All: slusb =
true; slhard =
true;
break;
1407 case jevois::engine::SerPort::Hard: slusb =
false; slhard =
true;
break;
1408 case jevois::engine::SerPort::USB: slusb =
true; slhard =
false;
break;
1410 ImGui::AlignTextToFramePadding();
1411 ImGui::Text(
"Log messages:"); ImGui::SameLine();
1412 if (itsUSBserial ==
false)
1414 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1415 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1416 if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1417 ImGui::PopItemFlag();
1418 ImGui::PopStyleVar();
1419 #ifdef JEVOIS_PLATFORM
1420 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1421 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - enable USB serial in the System tab"); ImGui::EndTooltip(); }
1423 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1424 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - not available on host"); ImGui::EndTooltip(); }
1427 else if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1429 ImGui::SameLine();
if (toggleButton(
"Hard##serlogh", &slhard)) schanged =
true;
1430 ImGui::SameLine(); toggleButton(
"Cons##serlogc", &itsSerLogEnabled);
1431 ImGui::SameLine(0, 50);
1433 bool sousb =
false, sohard =
false;
1437 case jevois::engine::SerPort::None: sousb =
false; sohard =
false;
break;
1438 case jevois::engine::SerPort::All: sousb =
true; sohard =
true;
break;
1439 case jevois::engine::SerPort::Hard: sousb =
false; sohard =
true;
break;
1440 case jevois::engine::SerPort::USB: sousb =
true; sohard =
false;
break;
1442 ImGui::Text(
"Module output:"); ImGui::SameLine();
1443 if (itsUSBserial ==
false)
1445 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1446 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1447 if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1448 ImGui::PopItemFlag();
1449 ImGui::PopStyleVar();
1450 #ifdef JEVOIS_PLATFORM
1451 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1452 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - enable USB serial in the System tab"); ImGui::EndTooltip(); }
1454 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1455 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - not available on host"); ImGui::EndTooltip(); }
1458 else if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1459 ImGui::SameLine();
if (toggleButton(
"Hard##serouth", &sohard)) schanged =
true;
1460 ImGui::SameLine(); toggleButton(
"Cons##seroutc", &itsSerOutEnabled);
1466 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::All);
1471 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::Hard);
1477 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::All);
1482 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::Hard);
1495 if (ImGui::Combo(
"serstyle", &idx,
1496 [](
void * vec,
int idx,
const char ** out_text)
1498 auto & ve = *
static_cast<std::vector<std::string>*
>(vec);
1499 if (idx < 0 || idx >=
static_cast<int>(ve.size()))
return false;
1500 *out_text = ve.at(idx).c_str();
1503 const_cast<void *
>(
static_cast<void const *
>(&jevois::module::SerStyle_Strings)),
1504 jevois::module::SerStyle_Strings.size()))
1517 {
return itsSerLogEnabled; }
1521 {
return itsSerOutEnabled; }
1526 engine()->drawCameraGUI();
1531 char const * b1txt,
char const * b2txt)
1534 int ret = 0;
int * retptr = default_val ? default_val : &ret;
1537 if (*retptr == 1 || *retptr == 2)
return *retptr;
1540 if (itsOpenModals.find(title) == itsOpenModals.end())
1542 ImGui::OpenPopup(title.c_str());
1543 itsOpenModals.insert(title);
1547 bool dont_ask_me_next_time = (*retptr == 3);
1549 if (ImGui::BeginPopupModal(title.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize))
1551 ImGui::TextUnformatted(text); ImGui::TextUnformatted(
" ");
1555 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1556 ImGui::PushStyleColor(ImGuiCol_FrameBg, 0xf0ffe0e0);
1557 ImGui::Checkbox(
"Don't ask me next time", &dont_ask_me_next_time);
1558 ImGui::PopStyleColor();
1559 ImGui::PopStyleVar();
1561 float const b1w = std::max(120.0
F, ImGui::CalcTextSize(b1txt).x + 20.0
F);
1562 if (ImGui::Button(b1txt, ImVec2(b1w, 0))) ret = 1;
1563 ImGui::SetItemDefaultFocus();
1565 float const b2w = std::max(120.0
F, ImGui::CalcTextSize(b2txt).x + 20.0
F);
1566 if (ImGui::Button(b2txt, ImVec2(b2w, 0))) ret = 2;
1571 if (ret == 1 || ret == 2)
1573 ImGui::CloseCurrentPopup();
1574 itsOpenModals.erase(title);
1575 if (dont_ask_me_next_time) *retptr = ret;
1577 else *retptr = dont_ask_me_next_time ? 3 : 0;
1584 char const * hint,
char const * hlp)
1586 static char buf[256];
1587 ImGui::AlignTextToFramePadding();
1588 ImGui::TextUnformatted(desc);
1589 ImGui::NextColumn();
1590 helpMarker(desc, hlp);
1591 ImGui::NextColumn();
1592 strncpy(buf, str.c_str(),
sizeof(buf)-1);
1593 if (ImGui::InputTextWithHint(wname, hint, buf,
sizeof(buf))) str = buf;
1594 ImGui::NextColumn();
1600 float const fontw = ImGui::GetFontSize();
1602 static int refresh = 1;
1603 static std::string cpu, mem, ver;
1604 static size_t npu, tpu, vpu, spu;
static int fan;
1617 ImGui::Text(
"JeVois-Pro v%s -- %s", JEVOIS_VERSION_STRING, ver.c_str());
1618 ImGui::Text(cpu.c_str());
1619 ImGui::Text(mem.c_str());
1620 ImGui::Text(
"NPU: %d, TPU: %d, VPU: %d, SPU: %d. Fan: %d%%", npu, tpu, vpu, spu, fan);
1624 drawNewModuleForm();
1628 static std::string pingstr;
1629 static int showping = 0;
1630 if (ImGui::Button(
"Ping jevois.usc.edu"))
1632 std::string ret =
jevois::system(
"/usr/bin/ping -c 1 -w 2 jevois.usc.edu");
1634 if (rvec.size() < 2) reportError(
"Unable to ping jevois.usc.edu");
1635 else { pingstr = rvec[1]; showping = 60; }
1640 ImGui::Text(pingstr.c_str());
1647 static std::string zip;
1648 static std::string donestr;
1649 static int state = 0;
1651 ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
1652 if (state) flags |= ImGuiInputTextFlags_ReadOnly;
1653 ImGui::SetNextItemWidth(fontw * 6.0
F);
1655 if (ImGui::InputText(
"Load Custom DNN", buf,
sizeof(buf), flags)) state = 1;
1666 ImGui::Text(
"-- Downloading...");
1667 zip = std::string(buf) +
".zip";
1671 return jevois::system(
"/usr/bin/curl " JEVOIS_CUSTOM_DNN_URL
"/" + zip +
" -o "
1672 JEVOIS_CUSTOM_DNN_PATH
"/" + zip,
true);
1680 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while loading custom DNN"); state = 0;
break; }
1681 ImGui::Text(
"-- Downloading...");
1682 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1687 std::ifstream ifs(JEVOIS_CUSTOM_DNN_PATH
"/" + zip);
1688 if (ifs.is_open() ==
false)
1690 reportError(
"Failed to download. Check network connectivity and available disk space.");
1697 return jevois::system(
"/usr/bin/unzip -o " JEVOIS_CUSTOM_DNN_PATH
"/" + zip +
1698 " -d " JEVOIS_CUSTOM_DNN_PATH,
true);
1707 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while unpacking custom DNN"); state = 0;
break; }
1708 ImGui::Text(
"-- Installing...");
1709 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1711 std::string ret = itsDnnGetFut.get();
1714 donestr =
"-- Invalid file, check DNN download key.";
1716 donestr =
"-- Done. Reload model zoo to take effect.";
1717 jevois::system(
"/bin/rm " JEVOIS_CUSTOM_DNN_PATH
"/" + zip,
true);
1729 ImGui::Text(donestr.c_str());
1734 #ifdef JEVOIS_PLATFORM
1736 static int bootmode = 0;
1737 ImGui::AlignTextToFramePadding();
1738 ImGui::Text(
"On boot, start:");
1740 if (ImGui::Combo(
"##onboot", &bootmode,
"(no change)\0JeVois-Pro\0Ubuntu Console\0Ubuntu Graphical\0\0"))
1745 case 2:
jevois::system(
"systemctl --no-reload set-default multi-user.target");
break;
1746 case 3:
jevois::system(
"systemctl --no-reload set-default graphical.target");
break;
1747 default:
jevois::system(
"systemctl --no-reload set-default jevoispro.target");
break;
1754 static bool gserial =
false;
1756 if (ImGui::Checkbox(
"Enable serial outputs/logs over mini-USB (on next reboot)", &gserial))
1758 std::ofstream ofs(JEVOISPRO_GSERIAL_FILE);
1759 ofs << (gserial ? 1 : 0) << std::endl;
1766 static bool show_fan_modal =
false;
1767 if (ImGui::Button(
"Edit fan settings"))
1769 itsCfgEditor->loadFile(
"/lib/systemd/system/jevoispro-fan.service");
1770 show_fan_modal =
true;
1775 static int doit_default = 0;
1776 int ret = modal(
"Ready to edit",
"File will now be loaded in the Config tab of the main window and "
1777 "ready to edit.\nPlease switch to the Config tab in the main window.\n\n"
1778 "When you save it, we will reboot the camera.",
1779 &doit_default,
"Ok",
"Thanks");
1782 case 1: show_fan_modal =
false;
break;
1783 case 2: show_fan_modal =
false;
break;
1797 unsigned int get_v4l2_fmt(
int idx)
1801 case 0:
return V4L2_PIX_FMT_YUYV;
1802 case 1:
return V4L2_PIX_FMT_RGB24;
1803 case 2:
return V4L2_PIX_FMT_RGB32;
1804 case 3:
return V4L2_PIX_FMT_GREY;
1805 case 4:
return V4L2_PIX_FMT_SBGGR16;
1810 unsigned int get_v4l2_idx(
int fcc)
1814 case V4L2_PIX_FMT_YUYV:
return 0;
1815 case V4L2_PIX_FMT_RGB24:
return 1;
1816 case V4L2_PIX_FMT_RGB32:
return 2;
1817 case V4L2_PIX_FMT_GREY:
return 3;
1818 case V4L2_PIX_FMT_SBGGR16:
return 4;
1824 void cookedCopy(std::filesystem::path
const & src, std::filesystem::path
const & dst,
1825 std::string
const & name, std::string
const & vendor, std::string
const & synopsis,
1826 std::string
const & author, std::string
const & email, std::string
const & website,
1827 std::string
const & license, std::string
const & videomapping)
1829 std::ifstream f(src);
1830 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
1831 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
1845 std::ofstream ofs(dst);
1846 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
1847 ofs << str << std::endl;
1848 LINFO(
"Translated copy " << src <<
" => " << dst);
1852 void cookedCmakeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
1853 std::string
const & oldname, std::string
const & newname,
1854 std::string
const & oldvendor, std::string
const & newvendor, std::string
const & synopsis,
1855 std::string
const & author, std::string
const & email, std::string
const & website,
1856 std::string
const & license, std::string
const & videomapping)
1858 std::ifstream f(src);
1859 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
1860 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
1875 std::ofstream ofs(dst);
1876 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
1877 ofs << str << std::endl;
1878 LINFO(
"Translated copy " << src <<
" => " << dst);
1882 void cookedCodeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
1883 std::string
const & oldname, std::string
const & newname)
1885 std::ifstream f(src);
1886 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
1887 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
1905 std::ofstream ofs(dst);
1906 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
1907 ofs << str << std::endl;
1908 LINFO(
"Translated copy " << src <<
" => " << dst);
1915 float const fontw = ImGui::GetFontSize();
1917 static int templ = 0;
1919 ImGui::PushStyleColor(ImGuiCol_PopupBg, 0xf0e0ffe0);
1921 if (ImGui::Button(
"Create new machine vision module..."))
1923 ImGui::OpenPopup(
"Create new machine vision module");
1924 itsIdleBlocked =
true;
1928 ImVec2
const center = ImGui::GetMainViewport()->GetCenter();
1929 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1930 ImGui::SetNextWindowContentSize(ImVec2(940, 750));
1932 if (ImGui::BeginPopupModal(
"Create new machine vision module", NULL, ImGuiWindowFlags_AlwaysAutoResize))
1936 static std::string name, vendor, synopsis, author, email, website, license, srcvendor, srcname;
1937 static int language = 0;
1938 static int ofmt = 0;
static int ow = 320, oh = 240;
static float ofps = 30.0F;
1939 static int cmode = 0;
1940 static int wdrmode = 0;
1941 static int cfmt = 0;
static int cw = 1920, ch = 1080;
static float cfps = 30.0F;
1942 static int c2fmt = 1;
static int c2w = 512, c2h = 288;
1943 static jevois::VideoMapping m { };
1945 ImGui::AlignTextToFramePadding();
1946 ImGui::Text(
"Fill out the details below, or clone from");
1949 static std::map<std::string, size_t> mods;
1950 static std::string currstr =
"...";
1953 e->foreachVideoMapping([&idx](jevois::VideoMapping
const & m) { mods[m.menustr2()] = idx++; });
1956 if (ImGui::BeginCombo(
"##clonemodule", currstr.c_str()))
1958 for (
auto const & mod : mods)
1960 bool is_selected =
false;
1961 if (ImGui::Selectable(mod.first.c_str(), is_selected))
1963 m = e->getVideoMapping(mod.second);
1964 currstr = mod.first;
1968 name =
"My" + m.modulename;
int i = 2;
1969 while (std::filesystem::exists(JEVOIS_MODULE_PATH
"/" + vendor +
'/' + name))
1972 language = m.ispython ? 0 : 1;
1974 ofmt = m.ofmt; ow = m.ow; oh = m.oh; ofps = m.ofps;
1977 case jevois::CropType::CropScale: cmode = 0;
break;
1979 case jevois::CropType::Scale: cmode = 2;
break;
1983 case jevois::WDRtype::Linear: wdrmode = 0;
break;
1984 case jevois::WDRtype::DOL: wdrmode = 1;
break;
1986 cfmt = get_v4l2_idx(m.cfmt); cw = m.cw; ch = m.ch; cfps = m.cfps;
1987 c2fmt = get_v4l2_idx(m.c2fmt); c2w = m.c2w; c2h = m.c2h;
1988 srcvendor = m.vendor; srcname = m.modulename;
1997 ImGui::Columns(3,
"new module");
1999 newModEntry(
"##NewModname", name,
"Module Name",
"MyModule",
2000 "Required, even when cloning. Must start with an uppercase letter. "
2001 "Will be a folder name under /jevoispro/modules/VendorName");
2003 newModEntry(
"##NewModvendor", vendor,
"Vendor Name",
"MyVendor",
2004 "Required, even when cloning. Must start with an uppercase letter. "
2005 "Will be a folder name under /jevoispro/modules/");
2010 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2011 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2014 newModEntry(
"##NewModsynopsis", synopsis,
"Synopsis",
"Detect Object of type X",
2015 "Optional. Brief description of what the module does.");
2017 newModEntry(
"##NewModauthor", author,
"Author Name",
"John Smith",
"Optional");
2019 newModEntry(
"##NewModemail", email,
"Author Email",
"you@yourcompany.com",
"Optional");
2021 newModEntry(
"##NewModwebsite", website,
"Author Website",
"http://yourcompany.com",
"Optional");
2023 newModEntry(
"##NewModlicense", license,
"License",
"GPL v3",
"Optional");
2026 ImGui::AlignTextToFramePadding();
2027 ImGui::TextUnformatted(
"Module Language");
2028 ImGui::NextColumn();
2029 helpMarker(
"Module Language",
"Machine language to use for your module.");
2030 ImGui::NextColumn();
2031 ImGui::Combo(
"##NewModlanguage", &language,
"Python\0C++\0\0");
2032 ImGui::NextColumn();
2035 ImGui::AlignTextToFramePadding();
2036 ImGui::TextUnformatted(
"Module Template");
2037 ImGui::NextColumn();
2038 helpMarker(
"Module Template",
"Type of placeholder code that will be provided to get your module started.");
2039 ImGui::NextColumn();
2040 if (templ < 3) ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0\0");
2041 else ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0Clone\0\0");
2042 ImGui::NextColumn();
2045 int oflags = ImGuiInputTextFlags_None;
2048 oflags |= ImGuiInputTextFlags_ReadOnly;
2049 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2050 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2053 ImGui::AlignTextToFramePadding();
2054 ImGui::TextUnformatted(
"Module Output");
2055 ImGui::NextColumn();
2056 helpMarker(
"Module Output",
"Output video format for legacy module.");
2057 ImGui::NextColumn();
2058 ImGui::SetNextItemWidth(fontw * 5.0
F);
2059 ImGui::Combo(
"##NewModofmt", &ofmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2061 ImGui::SetNextItemWidth(fontw * 4.0
F);
2062 ImGui::InputInt(
"##NewModow", &ow, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2066 ImGui::SetNextItemWidth(fontw * 4.0
F);
2067 ImGui::InputInt(
"##NewModoh", &oh, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2071 ImGui::SetNextItemWidth(fontw * 4.0
F);
2072 ImGui::InputFloat(
"##NewModofps", &ofps, 0.0
F, 0.0
F,
"%.1f", ImGuiInputTextFlags_CharsDecimal | oflags);
2075 ImGui::NextColumn();
2079 ImGui::PopItemFlag();
2080 ImGui::PopStyleVar();
2084 ImGui::AlignTextToFramePadding();
2085 ImGui::TextUnformatted(
"Camera Mode");
2086 ImGui::NextColumn();
2087 helpMarker(
"Camera Mode",
"Camera sensor configuration for your module.");
2088 ImGui::NextColumn();
2089 ImGui::SetNextItemWidth(fontw * 18.0
F);
2090 ImGui::Combo(
"##NewModcmode", &cmode,
"Dual-resolution (Crop+Scale)\0Single-resolution Crop\0"
2091 "Single-resolution Scale\0\0");
2092 ImGui::NextColumn();
2095 ImGui::AlignTextToFramePadding();
2096 ImGui::TextUnformatted(
"Camera WDR");
2097 ImGui::NextColumn();
2098 helpMarker(
"Camera WDR",
"Camera sensor wide-dynamic-range (WDR) setting for your module. Linear is for no WDR, "
2099 "DOL is for digital overlap (merging short and long exposure frames).");
2100 ImGui::NextColumn();
2101 ImGui::Combo(
"##NewModwdrmode", &wdrmode,
"Linear\0\0");
2103 ImGui::NextColumn();
2106 ImGui::AlignTextToFramePadding();
2107 ImGui::TextUnformatted(
"Camera Format");
2108 ImGui::NextColumn();
2109 helpMarker(
"Camera Format",
"Camera video format to use for input to module and for GUI display.");
2110 ImGui::NextColumn();
2111 ImGui::SetNextItemWidth(fontw * 5.0
F);
2112 ImGui::Combo(
"##NewModcfmt", &cfmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2114 ImGui::SetNextItemWidth(fontw * 4.0
F);
2115 ImGui::InputInt(
"##NewModcw", &cw, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2119 ImGui::SetNextItemWidth(fontw * 4.0
F);
2120 ImGui::InputInt(
"##NewModch", &ch, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2124 ImGui::SetNextItemWidth(fontw * 4.0
F);
2125 ImGui::InputFloat(
"##NewModcfps", &cfps, 0.0
F, 0.0
F,
"%.1f", ImGuiInputTextFlags_CharsDecimal);
2128 ImGui::NextColumn();
2131 int c2flags = ImGuiInputTextFlags_None;
2134 oflags |= ImGuiInputTextFlags_ReadOnly;
2135 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2136 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2139 ImGui::AlignTextToFramePadding();
2140 ImGui::TextUnformatted(
"Camera Format 2");
2141 ImGui::NextColumn();
2142 helpMarker(
"Camera Format 2",
"Camera video format for the second stream (for processing).");
2143 ImGui::NextColumn();
2144 ImGui::SetNextItemWidth(fontw * 5.0
F);
2145 ImGui::Combo(
"##NewModc2fmt", &c2fmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2147 ImGui::SetNextItemWidth(fontw * 4.0
F);
2148 ImGui::InputInt(
"##NewModc2w", &c2w, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2152 ImGui::SetNextItemWidth(fontw * 4.0
F);
2153 ImGui::InputInt(
"##NewModc2h", &c2h, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2154 ImGui::NextColumn();
2158 ImGui::PopItemFlag();
2159 ImGui::PopStyleVar();
2164 ImGui::PopItemFlag();
2165 ImGui::PopStyleVar();
2169 ImGui::SetColumnWidth(0, fontw * 10.0
F);
2170 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
"(?)").x + 30.0
F);
2178 ImVec2
const button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
2179 if (ImGui::Button(
"Cancel", button_size))
2181 ImGui::CloseCurrentPopup();
2183 ImGui::PopStyleColor();
2184 itsIdleBlocked =
false;
2189 ImGui::SameLine(0, 540);
2192 if (ImGui::Button(
"Create", button_size))
2195 if (name.empty())
LFATAL(
"New Module cannot have an empty name.");
2196 if (name[0]<
'A' || name[0]>
'Z')
LFATAL(
"New Module name must start with an uppercase letter.");
2197 if (vendor.empty())
LFATAL(
"New Module cannot have empty vendor name.");
2198 LINFO(
"New Module data valid...");
2201 std::filesystem::path
const newvdir = JEVOIS_MODULE_PATH
"/" + vendor;
2202 if (std::filesystem::exists(newvdir) ==
false && std::filesystem::create_directory(newvdir) ==
false)
2203 PLFATAL(
"Error creating dir " << newvdir <<
" -- check that you are running as root");
2204 std::filesystem::path
const newmdir = newvdir / name;
2212 std::filesystem::path srcpath = m.srcpath();
2213 std::filesystem::path cmakepath = m.cmakepath();
2217 m.modulename = name;
2220 std::string
const copycmd =
jevois::sformat(
"/bin/cp -ar %s/%s/%s %s", JEVOIS_MODULE_PATH, srcvendor.c_str(),
2221 srcname.c_str(), newmdir.c_str());
2223 LINFO(
"Cloned module using: " << copycmd);
2226 unlink((m.path() +
'/' + srcname +
".C").c_str());
2227 unlink((m.path() +
'/' + srcname +
".py").c_str());
2228 unlink((m.path() +
'/' + srcname +
".so").c_str());
2229 std::filesystem::remove_all(m.path() +
"/__pycache__");
2230 std::filesystem::remove_all(m.path() +
"/build");
2233 std::ostringstream oss; oss << m; vmstr = oss.str();
2234 cookedCodeClone(srcpath, m.srcpath(), srcname, name);
2239 if (std::filesystem::exists(cmakepath))
2240 cookedCmakeClone(cmakepath, m.cmakepath(), srcname, name, srcvendor, vendor, synopsis, author,
2241 email, website, license, vmstr);
2243 cookedCopy(JEVOIS_SHARE_PATH
"/templates/CMakeLists.txt", m.cmakepath(),
2244 name, vendor, synopsis, author, email, website, license, vmstr);
2252 if (std::filesystem::exists(newmdir))
2253 LFATAL(
"Directory [" << newmdir <<
"] already exists -- Choose another name");
2254 if (std::filesystem::create_directory(newmdir) ==
false)
2255 PLFATAL(
"Error creating directory [" << newmdir <<
"] for new module. Maybe not running as root?");
2256 LINFO(
"Created new Module directory: " << newmdir);
2263 case 1: m.ofmt = get_v4l2_fmt(ofmt); m.ow = ow; m.oh = oh; m.ofps = ofps;
break;
2264 case 2: m.ofmt = 0;
break;
2268 m.cfmt = get_v4l2_fmt(cfmt);
2269 m.cw = cw; m.ch = ch; m.cfps = cfps;
2272 m.modulename = name;
2276 case 0: m.wdr = jevois::WDRtype::Linear;
break;
2277 case 1: m.wdr = jevois::WDRtype::DOL;
break;
2283 case 0: m.crop = jevois::CropType::CropScale;
2284 m.c2fmt = get_v4l2_fmt(c2fmt);
2285 m.c2w = c2w; m.c2h = c2h;
2288 case 2: m.crop = jevois::CropType::Scale;
break;
2292 m.ispython = (language == 0);
2293 std::ostringstream oss; oss << m; vmstr = oss.str();
2296 std::string code; std::string tname;
2300 tname =
"PyModule.py";
2308 std::filesystem::path srccmak = JEVOIS_SHARE_PATH
"/templates/CMakeLists.txt";
2309 std::filesystem::path dstcmak = m.cmakepath();
2310 cookedCopy(srccmak, dstcmak, name, vendor, synopsis, author, email, website, license, vmstr);
2314 default:
LFATAL(
"Invalid language " << language);
2317 std::filesystem::path srcmod = JEVOIS_SHARE_PATH
"/templates/" + tname;
2318 std::filesystem::path dstmod = m.srcpath();
2319 cookedCopy(srcmod, dstmod, name, vendor, synopsis, author, email, website, license, vmstr);
2324 LINFO(
"Added videomapping: " << vmstr);
2331 if (language == 0) runNewModule();
2332 else itsCompileState = CompilationState::Start;
2335 name.clear(); vendor.clear(); synopsis.clear(); currstr =
"...";
2337 ImGui::CloseCurrentPopup();
2338 itsIdleBlocked =
false;
2341 catch (...) { reportAndIgnoreException(); }
2347 ImGui::PopStyleColor();
2353 engine()->reloadVideoMappings();
2354 size_t idx = 0;
size_t foundidx = 12345678;
2355 engine()->foreachVideoMapping([&](VideoMapping
const & mm)
2356 {
if (itsNewMapping.isSameAs(mm)) foundidx = idx; ++idx; });
2358 if (foundidx != 12345678) engine()->requestSetFormat(foundidx);
2359 else LFATAL(
"Internal error, could not find the module we just created -- CHECK LOGS");
2361 itsRefreshVideoMappings =
true;
2366 else if (itsNewMapping.ofmt != 0 && itsNewMapping.ofmt !=
JEVOISPRO_FMT_GUI) itsVideoMappingListType = 1;
2367 else if (itsNewMapping.ofmt == 0) itsVideoMappingListType = 2;
2368 else LERROR(
"Internal error: cannot determine video mapping list type -- IGNORED");
2373 using V=ImVec2;
using F=float;
int h;
struct E{
V p;
F z,w;
bool operator<(
E&
o){
return z<
o.z;}};
E G[999];
2374 #define L(i,x,y,z)for(F i=x;i<y;i+=z)
2375 #define Q(y)sin((y+t)*.03)*(1-sin(t*3)*cos(y/99+t))*9
2376 #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);
2377 #define J(b)L(i,0,h,1){E&o=G[int(i)];if(b*o.z>0)H(o.p,(o.z*.3+4)*o.w)}
2378 #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)
2379 void FX(ImDrawList*d,
V a,
V b,
V,ImVec4,
F t){
F i=sin(t)-.7;
V u(cos(i),sin(i)),v(-sin(i),cos(i)),c=(a+b)/2;
F l=300;
2380 F 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);}}
2381 h=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);
2382 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)}
2387 if (ImGui::Button(
"Open Style Editor")) itsShowStyleEditor =
true;
2389 if (ImGui::Button(
"Open App Metrics")) itsShowAppMetrics =
true;
2391 if (ImGui::Button(
"Open ImGui Demo")) itsShowImGuiDemo =
true;
2395 float camz = pixel_perfect_z;
2399 static float fudgex = 0.375f;
2400 static float fudgey = 0.375f;
2401 static float fudgez = 0.0f;
2402 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh);
2404 ImGui::SliderFloat(
"OpenGL Camera z", &camz, -2.0f * winh, -1.0f);
2405 ImGui::SliderAngle(
"OpenGL yaw", &yaw, -179.0f, 180.0f);
2406 ImGui::SliderAngle(
"OpenGL pitch", &pitch, -179.0f, 180.0f);
2407 ImGui::SliderAngle(
"OpenGL roll", &roll, -179.0f, 180.0f);
2409 ImGui::SliderFloat(
"fudge x", &fudgex, -1.0f, 1.0f);
2410 ImGui::SliderFloat(
"fudge y", &fudgey, -1.0f, 1.0f);
2411 ImGui::SliderFloat(
"fudge z", &fudgez, -1.0f, 1.0f);
2414 proj = glm::perspective(glm::radians(45.0f),
float(winw) /
float(winh), 1.0f, winh * 2.0f);
2415 proj = glm::translate(proj, glm::vec3(fudgex, fudgey, fudgez));
2418 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, camz));
2419 view *= glm::yawPitchRoll(yaw, pitch, roll);
2435 ImGuiIO& io = ImGui::GetIO();
2436 ImGui::Begin(
"FX", NULL, ImGuiWindowFlags_AlwaysAutoResize);
2437 ImVec2 size(320.0f, 180.0f);
2438 ImGui::InvisibleButton(
"canvas", size);
2439 ImVec2 p0 = ImGui::GetItemRectMin();
2440 ImVec2 p1 = ImGui::GetItemRectMax();
2441 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2442 draw_list->PushClipRect(p0, p1);
2445 mouse_data.x = (io.MousePos.x - p0.x) / size.x;
2446 mouse_data.y = (io.MousePos.y - p0.y) / size.y;
2447 mouse_data.z = io.MouseDownDuration[0];
2448 mouse_data.w = io.MouseDownDuration[1];
2450 FX(draw_list, p0, p1, size, mouse_data, (
float)ImGui::GetTime());
2451 draw_list->PopClipRect();
2460 auto now = std::chrono::steady_clock::now();
2462 std::lock_guard<std::mutex> _(itsErrorMtx);
2465 for (
auto & e : itsErrors)
if (e.err == err) { e.lasttime = now;
return; }
2468 if (itsErrors.size() > 10)
return;
2469 else if (itsErrors.size() == 10)
2471 ErrorData d {
"Too many errors -- TRUNCATING", now, now };
2472 itsErrors.emplace(itsErrors.end(), std::move(d));
2478 itsErrors.emplace(itsErrors.end(), std::move(d));
2486 std::lock_guard<std::mutex> _(itsErrorMtx);
2496 catch (std::exception
const & e)
2497 { reportError(e.what()); }
2498 catch (boost::python::error_already_set & e)
2501 { reportError(
"Unknown error"); }
2506 catch (std::exception
const & e)
2507 { reportError(prefix +
": " + e.what()); }
2508 catch (boost::python::error_already_set & e)
2511 { reportError(prefix +
": Unknown error"); }
2518 reportAndIgnoreException(prefix);
2525 std::lock_guard<std::mutex> _(itsErrorMtx);
2526 if (itsErrors.empty())
return;
2528 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
2529 ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav;
2531 ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_Always);
2532 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xc0e0e0ff);
2534 static bool show =
true;
2536 if (ImGui::Begin(
"Error detected!", &show, window_flags))
2538 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2539 ImGui::Text(
"Error detected!");
2541 auto itr = itsErrors.begin();
2542 while (itr != itsErrors.end())
2545 std::chrono::duration<float> d = std::chrono::steady_clock::now() - itr->lasttime;
2546 std::chrono::duration<float> d2 = std::chrono::steady_clock::now() - itr->firsttime;
2547 if (d.count() >= 1.0f && d2.count() >= 10.0f && ImGui::IsWindowHovered() ==
false)
2548 itr = itsErrors.erase(itr);
2553 ImGui::TextUnformatted(itr->err.c_str());
2557 ImGui::PopTextWrapPos();
2561 ImGui::PopStyleColor();
2569 if (ImGui::IsItemHovered())
2571 ImGui::BeginTooltip();
2572 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2573 ImGui::TextUnformatted(msg);
2574 if (msg2) { ImGui::Separator(); ImGui::TextUnformatted(msg2); }
2575 if (msg3) { ImGui::Separator(); ImGui::TextUnformatted(msg3); }
2576 ImGui::PopTextWrapPos();
2577 ImGui::EndTooltip();
2584 bool changed =
false;
2587 ImGui::PushID(name);
2588 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2589 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2590 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(4.0f/7.0f, 0.5f, 0.5f));
2591 if (ImGui::Button(name)) { *val =
false; changed =
true; }
2592 ImGui::PopStyleColor(3);
2595 else if (ImGui::Button(name)) { *val =
true; changed =
true; }
2603 unsigned short winw, winh;
2604 startFrame(winw, winh);
2606 if (itsHeadless.loaded() ==
false)
2607 try { itsHeadless.load(JEVOIS_SHARE_PATH
"/icons/headless.png"); }
2611 cv::Mat blank(winh, winw, CV_8UC4, 0);
2612 itsHeadless.load(blank);
2615 if (itsHeadless.loaded()) itsHeadless.draw(ImVec2(0, 0), ImVec2(winw, winh), ImGui::GetBackgroundDrawList());
2623 ImGui::PushStyleColor(ImGuiCol_Text, 0xff0000ff);
2624 ImGui::TextUnformatted(str.c_str());
2625 ImGui::PopStyleColor();
2632 itsBannerTitle = title;
2639 if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2640 itsCompileState = CompilationState::Start;
2642 reportError(
"Cannot find " + itsNewMapping.srcpath() +
" or " + itsNewMapping.cmakepath() +
" -- IGNORED");
2648 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
2650 ImGui::SetNextWindowSize(ImVec2(800, 680), ImGuiCond_FirstUseEver);
2653 int constexpr flags = ImGuiWindowFlags_HorizontalScrollbar;
2654 bool keep_window_open =
true;
2655 if (itsCompileState == CompilationState::Error) ImGui::Begin(
"C++ Module Compilation", &keep_window_open, flags);
2656 else ImGui::Begin(
"C++ Module Compilation",
nullptr, flags);
2658 ImGui::TextUnformatted((
"Compiling " + itsNewMapping.srcpath()).c_str());
2659 ImGui::TextUnformatted((
"Using " + itsNewMapping.cmakepath()).c_str());
2661 std::string
const modpath = itsNewMapping.path();
2662 std::string
const buildpath = modpath +
"/build";
2666 switch (itsCompileState)
2669 case CompilationState::Start:
2670 LINFO(
"Start compiling " << itsNewMapping.srcpath());
2671 itsIdleBlocked =
true;
2672 for (std::string & s : itsCompileMessages) s.clear();
2673 std::filesystem::remove_all(buildpath);
2674 itsCompileState = CompilationState::Cmake;
2678 case CompilationState::Cmake:
2679 if (compileCommand(
"cmake -S " + modpath +
" -B " + buildpath +
2680 " -DJEVOIS_HARDWARE=PRO"
2681 #ifdef JEVOIS_PLATFORM
2682 " -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2684 , itsCompileMessages[0]))
2685 itsCompileState = CompilationState::Make;
2689 case CompilationState::Make:
2690 if (compileCommand(
"JEVOIS_SRC_ROOT=none cmake --build " + buildpath, itsCompileMessages[1]))
2691 itsCompileState = CompilationState::Install;
2695 case CompilationState::Install:
2696 if (compileCommand(
"cmake --install " + buildpath, itsCompileMessages[2]))
2697 itsCompileState = CompilationState::CPack;
2701 case CompilationState::CPack:
2702 if (compileCommand(
"cd " + buildpath +
" && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/",
2703 itsCompileMessages[3]))
2704 itsCompileState = CompilationState::Success;
2708 case CompilationState::Success:
2710 ImGui::TextUnformatted(
"Compilation success!");
2711 ImGui::TextUnformatted(
"See below for details...");
2713 static int run_default = 0;
2714 int ret = modal(
"Success! Run the module now?",
"Compilation success!\n\nA deb package of your module is in "
2715 "/jevoispro/debs/\nif you want to share it.\n\nLoad and run the new module now?",
2716 &run_default,
"Yes",
"No");
2721 itsIdleBlocked =
false;
2722 itsCompileState = CompilationState::Idle;
2727 itsIdleBlocked =
false;
2728 itsCompileState = CompilationState::Idle;
2729 engine()->reloadVideoMappings();
2730 itsRefreshVideoMappings =
true;
2738 case CompilationState::Error:
2740 itsIdleBlocked =
false;
2741 highlightText(
"Compilation failed!");
2742 ImGui::TextUnformatted(
"You may need to edit the two files above.");
2743 ImGui::TextUnformatted(
"See below for details...");
2745 static bool show_modal =
false;
2747 ImGui::AlignTextToFramePadding();
2748 if (ImGui::Button(
"Edit CMakeLists.txt"))
2749 { itsCodeEditor->loadFile(itsNewMapping.cmakepath()); show_modal =
true; }
2751 ImGui::SameLine(); ImGui::Text(
" "); ImGui::SameLine();
2752 if (ImGui::Button((
"Edit " + itsNewMapping.modulename +
".C").c_str()))
2753 { itsCodeEditor->loadFile(itsNewMapping.srcpath()); show_modal =
true; }
2755 ImGui::SameLine(); ImGui::Text(
" "); ImGui::SameLine();
2756 if (ImGui::Button(
"Compile again")) itsCompileState = CompilationState::Start;
2762 static int doit_default = 0;
2763 int ret = modal(
"Ready to edit",
"File will now be loaded in the Code tab of the main window and "
2764 "ready to edit. Please switch to the Code tab in the main window.\n\n"
2765 "When you save it, we will try to compile it again.",
2766 &doit_default,
"Close Compilation Window",
"Keep Open");
2769 case 1: show_modal =
false; itsCompileState = CompilationState::Idle;
break;
2770 case 2: show_modal =
false;
break;
2779 LERROR(
"Internal error: invalid compilation state " <<
int(itsCompileState) <<
" -- RESET TO IDLE");
2780 itsCompileState = CompilationState::Idle;
2781 itsIdleBlocked =
false;
2783 }
catch (...) { reportAndIgnoreException(); }
2786 for (std::string & s : itsCompileMessages)
2787 if (s.empty() ==
false)
2789 ImGui::TextUnformatted(s.c_str());
2794 ImGui::PopStyleColor();
2797 if (keep_window_open ==
false) { itsIdleBlocked =
false; itsCompileState = CompilationState::Idle; }
2804 if (itsCompileFut.valid() ==
false)
2807 msg =
"Running: " + cmd +
"\nPlease wait ...\n";
2808 LINFO(
"Running: " + cmd);
2810 else if (itsCompileFut.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready)
2813 msg += itsCompileFut.get() +
"\nSuccess!";
2814 LINFO(
"Success running: " << cmd);
2819 LERROR(
"Failed running: " << cmd);
2820 itsCompileState = CompilationState::Error;
2827 #endif // JEVOIS_PRO