World_gui.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2020 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
10 #include <mrpt/core/format.h>
11 #include <mrpt/core/lock_helper.h>
12 #include <mrpt/core/round.h>
13 #include <mrpt/math/TLine3D.h>
14 #include <mrpt/math/TObject3D.h>
15 #include <mrpt/math/geometry.h>
16 #include <mrpt/opengl/CFBORender.h>
19 #include <mrpt/version.h>
20 #include <mvsim/World.h>
21 
22 #include <rapidxml.hpp>
23 
24 #include "xml_utils.h"
25 #if MRPT_VERSION >= 0x204
26 #include <mrpt/system/thread_name.h>
27 #endif
28 
29 using namespace mvsim;
30 using namespace std;
31 
33 {
34  parse_xmlnode_children_as_param(node, params, {}, "[World::TGUI_Options]");
35 }
36 
37 // Text labels unique IDs:
38 size_t ID_GLTEXT_CLOCK = 0;
39 
42 bool World::is_GUI_open() const { return !!m_gui.gui_win; }
44 void World::close_GUI() { m_gui.gui_win.reset(); }
45 
46 // Add top menu subwindow:
48 {
49 #if MRPT_VERSION >= 0x211
50  nanogui::Window* winMenu = gui_win->createManagedSubWindow("Control");
51 #else
52  nanogui::Window* winMenu = new nanogui::Window(gui_win.get(), "Control");
53 #endif
54 
55  // Place control UI at the top-left corner:
56  gui_win->getSubWindowsUI()->setPosition({1, 1});
57 
58  winMenu->setPosition({1, 80});
59  winMenu->setLayout(new nanogui::BoxLayout(
60  nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 5));
61 
62  winMenu->add<nanogui::Button>("Quit", ENTYPO_ICON_ARROW_BOLD_LEFT)
63  ->setCallback([this]() {
64  gui_win->setVisible(false);
65  nanogui::leave();
66  });
67 
68  winMenu
69  ->add<nanogui::CheckBox>(
70  "Orthogonal view",
71  [&](bool b) { gui_win->camera().setCameraProjective(!b); })
72  ->setChecked(m_parent.m_gui_options.ortho);
73 
74  std::vector<std::string> lstVehicles;
75  lstVehicles.reserve(m_parent.m_vehicles.size() + 1);
76 
77  lstVehicles.push_back("[none]"); // None
78  for (const auto& v : m_parent.m_vehicles) lstVehicles.push_back(v.first);
79 
80  winMenu->add<nanogui::Label>("Camera follows:");
81  auto cbFollowVeh = winMenu->add<nanogui::ComboBox>(lstVehicles);
82  cbFollowVeh->setSelectedIndex(0);
83  cbFollowVeh->setCallback([this, lstVehicles](int idx) {
84  if (idx == 0)
85  m_parent.m_gui_options.follow_vehicle.clear();
86  else if (idx <= static_cast<int>(m_parent.m_vehicles.size()))
87  m_parent.m_gui_options.follow_vehicle = lstVehicles[idx];
88  });
89 }
90 
91 // Add Status window
93 {
94 #if MRPT_VERSION >= 0x211
95  nanogui::Window* w = gui_win->createManagedSubWindow("Status");
96 #else
97  nanogui::Window* w = new nanogui::Window(gui_win.get(), "Status");
98 #endif
99 
100  w->setPosition({140, 80});
101  w->setLayout(new nanogui::BoxLayout(
102  nanogui::Orientation::Vertical, nanogui::Alignment::Fill));
103  w->setFixedWidth(270);
104 
105 #if MRPT_VERSION < 0x211
106  w->buttonPanel()
107  ->add<nanogui::Button>("", ENTYPO_ICON_CROSS)
108  ->setCallback([w]() { w->setVisible(false); });
109 #endif
110 
111  lbCpuUsage = w->add<nanogui::Label>(" ");
112  lbStatuses.resize(5);
113  for (size_t i = 0; i < lbStatuses.size(); i++)
114  lbStatuses[i] = w->add<nanogui::Label>(" ");
115 }
116 
117 // Add editor window
119 {
120 #if MRPT_VERSION >= 0x211
121 #if MRPT_VERSION >= 0x231
122  const auto subwinIdx = gui_win->getSubwindowCount();
123 #endif
124  nanogui::Window* w = gui_win->createManagedSubWindow("Editor");
125 #else
126  nanogui::Window* w = new nanogui::Window(gui_win.get(), "Editor");
127 #endif
128 
129  const int pnWidth = 250, pnHeight = 200;
130 
131  w->setPosition({1, 230});
132  w->setLayout(new nanogui::BoxLayout(
133  nanogui::Orientation::Vertical, nanogui::Alignment::Fill, 3, 3));
134  w->setFixedWidth(pnWidth);
135 
136 #if MRPT_VERSION < 0x211
137  w->buttonPanel()
138  ->add<nanogui::Button>("", ENTYPO_ICON_CROSS)
139  ->setCallback([w]() { w->setVisible(false); });
140 #endif
141 
142  w->add<nanogui::Label>("Selected object", "sans-bold");
143 
144  if (!m_parent.m_simulableObjects.empty())
145  {
146  auto tab = w->add<nanogui::TabWidget>();
147 
148  nanogui::Widget* tabs[3] = {
149  tab->createTab("Vehicles"), tab->createTab("Blocks"),
150  tab->createTab("Elements")};
151 
152  tab->setActiveTab(0);
153 
154  for (auto t : tabs)
155  t->setLayout(new nanogui::BoxLayout(
156  nanogui::Orientation::Vertical, nanogui::Alignment::Minimum, 3,
157  3));
158 
159  nanogui::VScrollPanel* vscrolls[3] = {
160  tabs[0]->add<nanogui::VScrollPanel>(),
161  tabs[1]->add<nanogui::VScrollPanel>(),
162  tabs[2]->add<nanogui::VScrollPanel>()};
163 
164  for (auto vs : vscrolls) vs->setFixedSize({pnWidth, pnHeight});
165 
166  // vscroll should only have *ONE* child. this is what `wrapper`
167  // is for
168  nanogui::Widget* wrappers[3];
169  for (int i = 0; i < 3; i++)
170  {
171  wrappers[i] = vscrolls[i]->add<nanogui::Widget>();
172  wrappers[i]->setFixedSize({pnWidth, pnHeight});
173  wrappers[i]->setLayout(new nanogui::GridLayout(
174  nanogui::Orientation::Horizontal, 1 /*columns */,
175  nanogui::Alignment::Minimum, 3, 3));
176  }
177 
178  for (const auto& o : m_parent.m_simulableObjects)
179  {
180  InfoPerObject ipo;
181 
182  const auto& name = o.first;
183  bool isVehicle = false;
184  if (auto v = dynamic_cast<VehicleBase*>(o.second.get()); v)
185  {
186  isVehicle = true;
187  ipo.visual = dynamic_cast<VisualObject*>(v);
188  }
189  bool isBlock = false;
190  if (auto v = dynamic_cast<Block*>(o.second.get()); v)
191  {
192  isBlock = true;
193  ipo.visual = dynamic_cast<VisualObject*>(v);
194  }
195  bool isWorldElement = false;
196  if (auto v = dynamic_cast<WorldElementBase*>(o.second.get()); v)
197  {
198  isWorldElement = true;
199  ipo.visual = dynamic_cast<VisualObject*>(v);
200  }
201  auto wrapper =
202  isVehicle ? wrappers[0] : (isBlock ? wrappers[1] : wrappers[2]);
203 
204  std::string label = name;
205  if (label.empty()) label = "(unnamed)";
206 
207  auto cb = wrapper->add<nanogui::CheckBox>(label);
208  ipo.cb = cb;
209  ipo.simulable = o.second;
210  gui_cbObjects.emplace_back(ipo);
211 
212  cb->setChecked(false);
213  cb->setCallback([cb, ipo, this](bool check) {
214  // deselect former one:
215  if (gui_selectedObject.visual)
216  gui_selectedObject.visual->showBoundingBox(false);
217  if (gui_selectedObject.cb)
218  gui_selectedObject.cb->setChecked(false);
219  gui_selectedObject = InfoPerObject();
220 
221  cb->setChecked(check);
222 
223  // If checked, show bounding box:
224  if (ipo.visual && check)
225  {
226  gui_selectedObject = ipo;
227  ipo.visual->showBoundingBox(true);
228  }
229 
230  const bool btnsEnabled = !!gui_selectedObject.simulable;
231  for (auto b : btns_selectedOps) b->setEnabled(btnsEnabled);
232  });
233  }
234  }
235 
236  w->add<nanogui::Label>(" ");
237 
238  btnReplaceObject = w->add<nanogui::Button>("Click to replace...");
239  btnReplaceObject->setFlags(nanogui::Button::Flags::ToggleButton);
240  btns_selectedOps.push_back(btnReplaceObject);
241 
242  {
243  auto pn = w->add<nanogui::Widget>();
244  pn->setLayout(new nanogui::BoxLayout(
245  nanogui::Orientation::Horizontal, nanogui::Alignment::Fill, 2, 2));
246  pn->add<nanogui::Label>("Reorient:");
247  auto slAngle = pn->add<nanogui::Slider>();
248  slAngle->setRange({-M_PI, M_PI});
249  slAngle->setCallback([this](float v) {
250  if (!gui_selectedObject.simulable) return;
251  auto p = gui_selectedObject.simulable->getPose();
252  p.yaw = v;
253  gui_selectedObject.simulable->setPose(p);
254  });
255  slAngle->setFixedWidth(150);
256  btns_selectedOps.push_back(slAngle);
257  }
258 
259  auto btnPlaceCoords = w->add<nanogui::Button>("Replace by coordinates...");
260  btns_selectedOps.push_back(btnPlaceCoords);
261  btnPlaceCoords->setCallback([this]() {
262  //
263  if (!gui_selectedObject.simulable) return;
264 
265  auto* formPose = new nanogui::Window(gui_win.get(), "Enter new pose");
266  formPose->setLayout(new nanogui::GridLayout(
267  nanogui::Orientation::Horizontal, 2, nanogui::Alignment::Fill, 5));
268 
269  nanogui::TextBox* lbs[3];
270 
271  formPose->add<nanogui::Label>("x coordinate:");
272  lbs[0] = formPose->add<nanogui::TextBox>();
273  formPose->add<nanogui::Label>("y coordinate:");
274  lbs[1] = formPose->add<nanogui::TextBox>();
275  formPose->add<nanogui::Label>("Orientation:");
276  lbs[2] = formPose->add<nanogui::TextBox>();
277 
278  for (int i = 0; i < 3; i++)
279  {
280  lbs[i]->setEditable(true);
281  lbs[i]->setFixedSize({100, 20});
282  lbs[i]->setValue("0.0");
283  lbs[i]->setUnits(i == 2 ? "[deg]" : "[m]");
284  lbs[i]->setDefaultValue("0.0");
285  lbs[i]->setFontSize(16);
286  lbs[i]->setFormat("[-]?[0-9]*\\.?[0-9]+");
287  }
288 
289  const auto pos = gui_selectedObject.simulable->getPose();
290  lbs[0]->setValue(std::to_string(pos.x));
291  lbs[1]->setValue(std::to_string(pos.y));
292  lbs[2]->setValue(std::to_string(mrpt::RAD2DEG(pos.yaw)));
293 
294  formPose->add<nanogui::Label>("");
295  formPose->add<nanogui::Label>("");
296 
297  formPose->add<nanogui::Button>("Cancel")->setCallback(
298  [formPose]() { formPose->dispose(); });
299 
300  formPose->add<nanogui::Button>("Accept")->setCallback(
301  [formPose, this, lbs]() {
302  gui_selectedObject.simulable->setPose(
303  {// X:
304  std::stod(lbs[0]->value()),
305  // Y:
306  std::stod(lbs[1]->value()),
307  // Z:
308  .0,
309  // Yaw
310  mrpt::DEG2RAD(std::stod(lbs[2]->value())),
311  // Pitch
312  0.0,
313  // Roll:
314  0.0});
315  formPose->dispose();
316  });
317 
318  formPose->setModal(true);
319  formPose->center();
320  formPose->setVisible(true);
321  });
322 
323  for (auto b : btns_selectedOps) b->setEnabled(false);
324 
325  // Minimize subwindow:
326 #if MRPT_VERSION >= 0x231
327  gui_win->subwindowMinimize(subwinIdx);
328 #else
329  if (auto btnMinimize =
330  dynamic_cast<nanogui::Button*>(w->buttonPanel()->children().at(0));
331  btnMinimize)
332  {
333  btnMinimize->callback()(); // "push" button
334  }
335 #endif
336 
337 } // end "editor" window
338 
340 {
341  try
342  {
343  MRPT_LOG_DEBUG("[World::internal_GUI_thread] Started.");
344 
345  // Start GUI:
346  nanogui::init();
347 
348  mrpt::gui::CDisplayWindowGUI_Params cp;
349  cp.maximized = m_gui_options.start_maximized;
350 
351  m_gui.gui_win = mrpt::gui::CDisplayWindowGUI::Create(
352  "mvsim", m_gui_options.win_w, m_gui_options.win_h, cp);
353 
354  // Add a background scene:
355  auto scene = mrpt::opengl::COpenGLScene::Create();
356  {
357  std::lock_guard<std::mutex> lck(
358  m_gui.gui_win->background_scene_mtx);
359  m_gui.gui_win->background_scene = std::move(scene);
360  }
361 
362  // Only if the world is empty: at least introduce a ground grid:
363  if (m_world_elements.empty())
364  {
365  auto we = WorldElementBase::factory(this, nullptr, "groundgrid");
366  m_world_elements.push_back(we);
367  }
368 
369  // Windows:
370  m_gui.prepare_top_menu();
371  m_gui.prepare_status_window();
372  m_gui.prepare_editor_window();
373 
374  // Finish GUI setup:
375  m_gui.gui_win->performLayout();
376  auto& cam = m_gui.gui_win->camera();
377 
378  cam.setCameraPointing(0.0f, .0f, .0f);
379  cam.setCameraProjective(!m_gui_options.ortho);
380  cam.setZoomDistance(m_gui_options.camera_distance);
381 
382  // Main GUI loop
383  // ---------------------
384  m_gui.gui_win->drawAll();
385  m_gui.gui_win->setVisible(true);
386 
387  // Listen for keyboard events:
388  m_gui.gui_win->setKeyboardCallback([&](int key, int /*scancode*/,
389  int action, int modifiers) {
390  if (action != GLFW_PRESS && action != GLFW_REPEAT) return false;
391 
392  auto lck = mrpt::lockHelper(m_lastKeyEvent_mtx);
393 
394  m_lastKeyEvent.keycode = key;
395  m_lastKeyEvent.modifierShift = (modifiers & GLFW_MOD_SHIFT) != 0;
396  m_lastKeyEvent.modifierCtrl = (modifiers & GLFW_MOD_CONTROL) != 0;
397  m_lastKeyEvent.modifierSuper = (modifiers & GLFW_MOD_SUPER) != 0;
398  m_lastKeyEvent.modifierAlt = (modifiers & GLFW_MOD_ALT) != 0;
399 
400  m_lastKeyEventValid = true;
401 
402  return false;
403  });
404 
405  m_gui_thread_running = true;
406 
407  // The GUI must be closed from this same thread. Use a shared atomic
408  // bool:
409  m_gui.gui_win->setLoopCallback([&]() {
410  if (m_gui_thread_must_close) nanogui::leave();
411 
412  // Update all GUI elements:
413  ASSERT_(m_gui.gui_win->background_scene);
414  internalUpdate3DSceneObjects(m_gui.gui_win->background_scene);
415 
416  internal_process_pending_gui_user_tasks();
417 
418 #if 0
419  // Quick test for camera sensor first test
420  static mrpt::opengl::CFBORender fbo(800, 640, true);
421  mrpt::img::CImage im;
422 
423  auto& cam =
424  m_gui.gui_win->background_scene->getViewport()->getCamera();
425  auto camBackup = cam;
426  cam.set6DOFMode(true);
427  auto p = mrpt::poses::CPose3D(
428  this->m_vehicles.begin()->second->getPose());
429  using namespace mrpt; // _deg
430  p += mrpt::poses::CPose3D(0, 0, 0, 90.0_deg, 0, 90.0_deg);
431  p += mrpt::poses::CPose3D(0.5, 0, 0.5, 0, 0, 0);
432  cam.setPose(p);
433 
434  fbo.getFrame(*m_gui.gui_win->background_scene, im);
435 
436  cam = camBackup;
437 
438  static int i = 0;
439  im.saveToFile(mrpt::format("camera_%004i.png", i++));
440 #endif
441 
442  // handle mouse operations:
443  m_gui.handle_mouse_operations();
444  });
445 
446  const int refresh_ms =
447  std::max(1, mrpt::round(1000 / m_gui_options.refresh_fps));
448 
450  "[World::internal_GUI_thread] Using GUI FPS=%i (T=%i ms)",
451  m_gui_options.refresh_fps, refresh_ms);
452 
453  nanogui::mainloop(refresh_ms);
454 
455  MRPT_LOG_DEBUG("[World::internal_GUI_thread] Mainloop ended.");
456 
457  m_gui.gui_win.reset();
458 
459  nanogui::shutdown();
460  }
461  catch (const std::exception& e)
462  {
464  "[internal_GUI_init] Exception: " << mrpt::exception_to_str(e));
465  }
466  m_gui_thread_running = false;
467 }
468 
470 {
471  MRPT_START
472  if (!gui_win) return;
473 
474  mrpt::opengl::COpenGLViewport::Ptr vp;
475  {
476  auto lck = mrpt::lockHelper(gui_win->background_scene_mtx);
477  vp = gui_win->background_scene->getViewport();
478  }
479  ASSERT_(vp);
480 
481  const auto mousePt = gui_win->mousePos();
483  vp->get3DRayForPixelCoord(mousePt.x(), mousePt.y(), ray);
484 
485  // Create a 3D plane, e.g. Z=0
486  const auto ground_plane =
487  mrpt::math::TPlane::From3Points({0, 0, 0}, {1, 0, 0}, {0, 1, 0});
488 
489  // Intersection of the line with the plane:
490  mrpt::math::TObject3D inters;
491  mrpt::math::intersect(ray, ground_plane, inters);
492 
493  // Interpret the intersection as a point, if there is an
494  // intersection:
495  if (inters.getPoint(clickedPt))
496  {
497  // Move object to the position picked by the user:
498  // vp->getByClass<CDisk>(0)->setLocation(clickedPt);
499  }
500 
501 #if MRPT_VERSION >= 0x211
502  const auto screen = gui_win->screen();
503  const bool leftClick = screen->mouseState() == 0x01;
504 
505  // Replace object?
506  if (btnReplaceObject && btnReplaceObject->pushed())
507  {
508  static bool isReplacing = false;
509 
510  // Start of replace? When the button push is released:
511  if (!isReplacing && !leftClick)
512  {
513  isReplacing = true;
514  }
515  if (gui_selectedObject.simulable)
516  {
517  // btnReplaceObject->screen()->setCursor()
518 
519  mrpt::math::TPose3D p = gui_selectedObject.simulable->getPose();
520  p.x = clickedPt.x;
521  p.y = clickedPt.y;
522 
523  gui_selectedObject.simulable->setPose(p);
524  }
525  if (isReplacing && leftClick)
526  {
527  isReplacing = false;
528  btnReplaceObject->setPushed(false);
529  }
530  }
531 #endif
532 
533  MRPT_END
534 }
535 
537 {
538  m_gui_user_pending_tasks_mtx.lock();
539 
540  for (const auto& task : m_gui_user_pending_tasks)
541  {
542  task();
543  }
544  m_gui_user_pending_tasks.clear();
545 
546  m_gui_user_pending_tasks_mtx.unlock();
547 }
548 
550  mrpt::opengl::COpenGLScene::Ptr& gl_scene)
551 {
552  // Update view of map elements
553  // -----------------------------
554  m_timlogger.enter("update_GUI.2.map-elements");
555 
556  for (auto& e : m_world_elements) e->guiUpdate(*gl_scene);
557 
558  m_timlogger.leave("update_GUI.2.map-elements");
559 
560  // Update view of vehicles
561  // -----------------------------
562  m_timlogger.enter("update_GUI.3.vehicles");
563 
564  for (auto& v : m_vehicles) v.second->guiUpdate(*gl_scene);
565 
566  m_timlogger.leave("update_GUI.3.vehicles");
567 
568  // Update view of blocks
569  // -----------------------------
570  m_timlogger.enter("update_GUI.4.blocks");
571 
572  for (auto& v : m_blocks) v.second->guiUpdate(*gl_scene);
573 
574  m_timlogger.leave("update_GUI.4.blocks");
575 
576  // Other messages
577  // -----------------------------
578  m_timlogger.enter("update_GUI.5.text-msgs");
579  {
580  // 1st line: time
581  double cpu_usage_ratio =
582  std::max(1e-10, m_timlogger.getMeanTime("run_simulation.cpu_dt")) /
583  std::max(1e-10, m_timlogger.getMeanTime("run_simulation.dt"));
584 
585  if (m_gui.lbCpuUsage)
586  m_gui.lbCpuUsage->setCaption(mrpt::format(
587  "Time: %s (CPU usage: %.03f%%)",
588  mrpt::system::formatTimeInterval(this->m_simul_time).c_str(),
589  cpu_usage_ratio * 100.0));
590 
591  // User supplied-lines:
592  m_gui_msg_lines_mtx.lock();
593  const std::string msg_lines = m_gui_msg_lines;
594  m_gui_msg_lines_mtx.unlock();
595 
596  if (!msg_lines.empty())
597  {
598  MRPT_TODO("Split lines?");
599  m_gui.lbStatuses[0]->setCaption(msg_lines);
600  }
601  m_gui.lbStatuses[1]->setCaption(
602  std::string("Mouse: ") + m_gui.clickedPt.asString());
603  }
604 
605  m_timlogger.leave("update_GUI.5.text-msgs");
606 
607  // Camera follow modes:
608  // -----------------------
609  if (!m_gui_options.follow_vehicle.empty())
610  {
611  auto it = m_vehicles.find(m_gui_options.follow_vehicle);
612  if (it == m_vehicles.end())
613  {
614  static bool warn1st = true;
615  if (warn1st)
616  {
618  "GUI: Camera set to follow vehicle named '%s' which "
619  "can't "
620  "be found!",
621  m_gui_options.follow_vehicle.c_str());
622  warn1st = true;
623  }
624  }
625  else
626  {
627  const mrpt::poses::CPose2D pose = it->second->getCPose2D();
628  m_gui.gui_win->camera().setCameraPointing(pose.x(), pose.y(), 0.0f);
629  }
630  }
631 }
632 
634 {
635  // First call?
636  // -----------------------
637  {
638  auto lock = mrpt::lockHelper(m_gui_thread_start_mtx);
639  if (!m_gui_thread_running && !m_gui_thread.joinable())
640  {
641  MRPT_LOG_DEBUG("[update_GUI] Launching GUI thread...");
642 
643  m_gui_thread = std::thread(&World::internal_GUI_thread, this);
644 #if MRPT_VERSION >= 0x204
645  mrpt::system::thread_name("guiThread", m_gui_thread);
646 #endif
647  for (int timeout = 0; timeout < 300; timeout++)
648  {
649  std::this_thread::sleep_for(std::chrono::milliseconds(10));
650  if (m_gui_thread_running) break;
651  }
652 
653  if (!m_gui_thread_running)
654  {
655  THROW_EXCEPTION("Timeout waiting for GUI to open!");
656  }
657  else
658  {
659  MRPT_LOG_DEBUG("[update_GUI] GUI thread started.");
660  }
661  }
662  }
663 
664  if (!m_gui.gui_win)
665  {
667  5.0,
668  "[World::update_GUI] GUI window has been closed, but note that "
669  "simulation keeps running.");
670  return;
671  }
672 
673  m_timlogger.enter("update_GUI"); // Don't count initialization, since that
674  // is a total outlier and lacks interest!
675 
676  m_gui_msg_lines_mtx.lock();
677  m_gui_msg_lines = guiparams->msg_lines;
678  m_gui_msg_lines_mtx.unlock();
679 
680  m_timlogger.leave("update_GUI");
681 
682  // Key-strokes:
683  // -----------------------
684  if (guiparams && m_lastKeyEventValid)
685  {
686  auto lck = mrpt::lockHelper(m_lastKeyEvent_mtx);
687 
688  guiparams->keyevent = std::move(m_lastKeyEvent);
689  m_lastKeyEventValid = false;
690  }
691 }
void getFrame(const COpenGLScene &scene, mrpt::utils::CImage &image)
const GLdouble * v
void prepare_editor_window()
Definition: World_gui.cpp:118
This file contains rapidxml parser and DOM implementation.
ROSCPP_DECL bool check()
void prepare_top_menu()
Definition: World_gui.cpp:47
size_t ID_GLTEXT_CLOCK
Definition: World_gui.cpp:38
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node, const char *class_name=nullptr)
nanogui::CheckBox * cb
Definition: World.h:350
void parse_xmlnode_children_as_param(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="")
Definition: xml_utils.cpp:179
#define THROW_EXCEPTION(msg)
GLubyte GLubyte GLubyte GLubyte w
GLdouble GLdouble t
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
#define M_PI
void internalUpdate3DSceneObjects(mrpt::opengl::COpenGLScene::Ptr &gl_scene)
Definition: World_gui.cpp:549
std::string BASE_IMPEXP formatTimeInterval(const double timeSeconds)
scene
#define MRPT_LOG_DEBUG(_STRING)
Simulable::Ptr simulable
Definition: World.h:351
GLsizei const GLfloat * value
MRPT_TODO("Modify ping to run on Windows + Test this")
TGUIKeyEvent keyevent
Keystrokes in the window are returned here.
Definition: World.h:114
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
void internal_GUI_thread()
Definition: World_gui.cpp:339
#define MRPT_END
bool is_GUI_open() const
Forces closing the GUI window, if any.
Definition: World_gui.cpp:42
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
GLuint const GLchar * name
GLfloat GLfloat p
std::string msg_lines
Messages to show.
Definition: World.h:115
void showBoundingBox(bool show)
#define MRPT_START
action
void handle_mouse_operations()
Definition: World_gui.cpp:469
#define ASSERT_(f)
GLfloat * params
void prepare_status_window()
Definition: World_gui.cpp:92
int round(const T value)
void parse_from(const rapidxml::xml_node< char > &node)
Definition: World_gui.cpp:32
#define MRPT_LOG_ERROR_STREAM(__CONTENTS)
GLdouble GLdouble GLdouble b
#define MRPT_LOG_THROTTLE_WARN(_PERIOD_SECONDS, _STRING)
void update_GUI(TUpdateGUIParams *params=nullptr)
Definition: World_gui.cpp:633
bool BASE_IMPEXP intersect(const TSegment3D &s1, const TSegment3D &s2, TObject3D &obj)
void internal_process_pending_gui_user_tasks()
Definition: World_gui.cpp:536
GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble f
void close_GUI()
a previous call to update_GUI()
Definition: World_gui.cpp:44


mvsim
Author(s):
autogenerated on Fri May 7 2021 03:05:51