GCC Code Coverage Report


Directory: ./
File: src/windows-manager.cpp
Date: 2024-10-14 11:04:13
Exec Total Coverage
Lines: 0 652 0.0%
Branches: 0 1482 0.0%

Line Branch Exec Source
1 // Copyright (c) 2015, Joseph Mirabel
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4 // This file is part of gepetto-viewer.
5 // gepetto-viewer is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // gepetto-viewer is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // gepetto-viewer. If not, see <http://www.gnu.org/licenses/>.
16
17 #include "gepetto/viewer/windows-manager.h"
18
19 #include <gepetto/viewer/blender-geom-writer.h>
20 #include <gepetto/viewer/config-osg.h>
21 #include <gepetto/viewer/group-node.h>
22 #include <gepetto/viewer/leaf-node-arrow.h>
23 #include <gepetto/viewer/leaf-node-box.h>
24 #include <gepetto/viewer/leaf-node-capsule.h>
25 #include <gepetto/viewer/leaf-node-collada.h>
26 #include <gepetto/viewer/leaf-node-cone.h>
27 #include <gepetto/viewer/leaf-node-cylinder.h>
28 #include <gepetto/viewer/leaf-node-face.h>
29 #include <gepetto/viewer/leaf-node-ground.h>
30 #include <gepetto/viewer/leaf-node-light.h>
31 #include <gepetto/viewer/leaf-node-line.h>
32 #include <gepetto/viewer/leaf-node-sphere.h>
33 #include <gepetto/viewer/leaf-node-xyzaxis.h>
34 #include <gepetto/viewer/macros.h>
35 #include <gepetto/viewer/node-rod.h>
36 #include <gepetto/viewer/node.h>
37 #include <gepetto/viewer/roadmap-viewer.h>
38 #include <gepetto/viewer/urdf-parser.h>
39 #include <gepetto/viewer/window-manager.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <unistd.h>
43
44 #include <OpenThreads/ScopedLock>
45 #include <algorithm>
46 #include <osgDB/ReaderWriter>
47 #include <osgDB/Registry>
48 #include <osgDB/WriteFile>
49
50 #include "log.hh"
51
52 #define RETURN_FALSE_IF_NODE_EXISTS(name) \
53 if (nodeExists(name)) { \
54 std::cerr << "Node \"" << name << "\" already exists." << std::endl; \
55 return false; \
56 }
57
58 #define RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(name) \
59 if (!nodeExists(name)) { \
60 std::cerr << "Node \"" << name << "\" does not exist." << std::endl; \
61 return false; \
62 }
63
64 #define THROW_IF_NODE_EXISTS(name) \
65 if (nodeExists(name)) { \
66 std::ostringstream oss; \
67 oss << "Node \"" << name << "\" already exists."; \
68 throw std::invalid_argument(oss.str().c_str()); \
69 }
70
71 #define THROW_IF_NODE_DOES_NOT_EXIST(name) \
72 if (!nodeExists(name)) { \
73 std::ostringstream oss; \
74 oss << "Node \"" << name << "\" does not exist."; \
75 throw std::invalid_argument(oss.str().c_str()); \
76 }
77
78 #define FIND_NODE_OF_TYPE_OR_THROW(NodeType, varname, nodename) \
79 NodeType##Ptr_t varname( \
80 dynamic_pointer_cast<NodeType>(getNode(nodename, true))); \
81 if (!varname) { \
82 std::ostringstream oss; \
83 oss << "Node \"" << nodename << "\" is not of type " #NodeType; \
84 throw std::invalid_argument(oss.str().c_str()); \
85 }
86
87 #define RETURN_FALSE_IF_WINDOW_DOES_NOT_EXIST(var, name) \
88 WindowManagerPtr_t var = getWindowManager(name, false); \
89 if (!var) { \
90 std::cerr << "Window \"" << name << "\" does not exist." << std::endl; \
91 return false; \
92 }
93
94 namespace gepetto {
95 namespace viewer {
96 namespace {
97 typedef std::map<std::string, NodePtr_t>::iterator NodeMapIt;
98 typedef std::map<std::string, NodePtr_t>::const_iterator NodeMapConstIt;
99
100 typedef std::map<std::string, GroupNodePtr_t>::iterator GroupNodeMapIt;
101 typedef std::map<std::string, GroupNodePtr_t>::const_iterator
102 GroupNodeMapConstIt;
103
104 typedef ScopedLock ScopedLock;
105 } // namespace
106
107 BlenderFrameCapture::BlenderFrameCapture()
108 : writer_visitor_(new TransformWriterVisitor(
109 new YamlTransformWriter("gepetto_viewer.yaml"))),
110 nodes_() {}
111
112 void BlenderFrameCapture::captureFrame() {
113 using std::invalid_argument;
114 if (!writer_visitor_) throw invalid_argument("Capture writer not defined");
115 if (nodes_.empty()) throw invalid_argument("No node to capture");
116 writer_visitor_->captureFrame(nodes_.begin(), nodes_.end());
117 }
118
119 WindowsManager::WindowsManager()
120 : windowManagers_(),
121 nodes_(),
122 groupNodes_(),
123 roadmapNodes_(),
124 osgFrameMtx_(),
125 configListMtx_(),
126 newNodeConfigurations_(),
127 autoCaptureTransform_(false) {}
128
129 WindowsManager::WindowID WindowsManager::addWindow(
130 std::string winName, WindowManagerPtr_t newWindow) {
131 WindowManagerMap_t::const_iterator it = windowManagers_.find(winName);
132 if (it != windowManagers_.end())
133 throw std::invalid_argument("A window with this name already exists.");
134
135 windowManagers_.insert(std::make_pair(winName, newWindow));
136 addGroup(winName, newWindow->getScene(), false);
137 return winName;
138 }
139
140 WindowsManagerPtr_t WindowsManager::create() {
141 WindowsManagerPtr_t shPtr(new WindowsManager());
142 return shPtr;
143 }
144
145 osgVector4 WindowsManager::getColor(const std::string& colorName) {
146 if (colorName == "blue")
147 return osgVector4(0.f, 0.f, 1.f, 1.f);
148 else if (colorName == "green")
149 return osgVector4(0.f, 1.f, 0.f, 1.f);
150 else if (colorName == "red")
151 return osgVector4(1.f, 0.f, 0.f, 1.f);
152 else if (colorName == "white")
153 return osgVector4(1.f, 1.f, 1.f, 1.f);
154 else
155 return osgVector4(0.f, 0.f, 0.f, 1.f);
156 }
157
158 VisibilityMode WindowsManager::getVisibility(const std::string& vName) {
159 if (vName == "OFF")
160 return VISIBILITY_OFF;
161 else if (vName == "ALWAYS_ON_TOP")
162 return ALWAYS_ON_TOP;
163 else if (vName == "ON")
164 return VISIBILITY_ON;
165 else {
166 log() << "Visibility mode not known, visibility mode can be"
167 " \"ON\",\"OFF\" or \"ALWAYS_ON_TOP\".\n"
168 "Visibility mode set to default = \"ON\"."
169 << std::endl;
170 return VISIBILITY_ON;
171 }
172 }
173
174 WireFrameMode WindowsManager::getWire(const std::string& wireName) {
175 if (wireName == "WIREFRAME")
176 return WIREFRAME;
177 else if (wireName == "FILL_AND_WIREFRAME")
178 return FILL_AND_WIREFRAME;
179 else if (wireName == "FILL")
180 return FILL;
181 else {
182 log() << "Wire mode not known, wire mode can be \"FILL\","
183 "\"WIREFRAME\" or \"FILL_AND_WIREFRAME\".\n"
184 "Wire mode set to default = \"FILL\"."
185 << std::endl;
186 return FILL;
187 }
188 }
189
190 LightingMode WindowsManager::getLight(const std::string& lightName) {
191 if (lightName == "OFF")
192 return LIGHT_INFLUENCE_OFF;
193 else if (lightName == "ON")
194 return LIGHT_INFLUENCE_ON;
195 else {
196 log() << "Lighting mode not known, lighting mode can be "
197 "\"ON\" or \"OFF\".\n"
198 "Lighting mode set to default = \"ON\"."
199 << std::endl;
200 return LIGHT_INFLUENCE_ON;
201 }
202 }
203
204 std::string WindowsManager::parentName(const std::string& name) {
205 std::string::size_type slash = name.find_last_of('/');
206 if (slash == std::string::npos)
207 return "";
208 else
209 return name.substr(0, slash);
210 }
211
212 NodePtr_t WindowsManager::find(const std::string name, GroupNodePtr_t) {
213 NodeMapIt it = nodes_.find(name);
214 if (it == nodes_.end()) {
215 std::string::size_type slash = name.find_first_of('/');
216 if (slash == std::string::npos) return NodePtr_t();
217 GroupNodeMapIt itg = groupNodes_.find(name.substr(0, slash));
218 if (itg == groupNodes_.end()) return NodePtr_t();
219 return find(name.substr(slash + 1), itg->second);
220 }
221 return it->second;
222 }
223
224 bool WindowsManager::nodeExists(const std::string& name) {
225 NodeMapConstIt it = nodes_.find(name);
226 return (it != nodes_.end());
227 }
228
229 NodePtr_t WindowsManager::getNode(const std::string& name,
230 bool throwIfDoesntExist) const {
231 NodeMapConstIt it = nodes_.find(name);
232 if (it == nodes_.end()) {
233 if (throwIfDoesntExist) {
234 std::ostringstream oss;
235 oss << "No node with name \"" << name << "\".";
236 throw std::invalid_argument(oss.str().c_str());
237 } else
238 return NodePtr_t();
239 }
240 return it->second;
241 }
242
243 template <typename Iterator, typename NodeContainer_t>
244 std::size_t WindowsManager::getNodes(const Iterator& begin, const Iterator& end,
245 NodeContainer_t& nodes) {
246 const std::size_t l = nodes.size();
247 for (Iterator it = begin; it != end; ++it) {
248 std::string name(*it);
249 NodePtr_t n = getNode(name);
250 if (n)
251 nodes.push_back(n);
252 else
253 log() << "Node \"" << name << "\" doesn't exist." << std::endl;
254 }
255 return nodes.size() - l;
256 }
257
258 void WindowsManager::initParent(NodePtr_t node, GroupNodePtr_t parent) {
259 if (parent && !parent->hasChild(node)) parent->addChild(node);
260 }
261
262 void WindowsManager::addNode(const std::string& nodeName, NodePtr_t node,
263 bool guessParent) {
264 GroupNodePtr_t parent;
265 if (guessParent) parent = getGroup(parentName(nodeName));
266 addNode(nodeName, node, parent);
267 }
268
269 void WindowsManager::addNode(const std::string& nodeName, NodePtr_t node,
270 GroupNodePtr_t parent) {
271 initParent(node, parent);
272 nodes_[nodeName] = node;
273 }
274
275 void WindowsManager::addGroup(const std::string& groupName,
276 GroupNodePtr_t group, bool guessParent) {
277 GroupNodePtr_t parent;
278 if (guessParent) parent = getGroup(parentName(groupName));
279 addGroup(groupName, group, parent);
280 }
281
282 void WindowsManager::addGroup(const std::string& groupName,
283 GroupNodePtr_t group, GroupNodePtr_t parent) {
284 initParent(group, parent);
285 nodes_[groupName] = group;
286 groupNodes_[groupName] = group;
287 }
288
289 // Public functions
290
291 WindowsManager::WindowID WindowsManager::getWindowID(const std::string& wn) {
292 WindowManagerMap_t::const_iterator it = windowManagers_.find(wn);
293 if (it == windowManagers_.end())
294 throw std::invalid_argument("There is no windows with that name");
295 return wn;
296 }
297
298 void WindowsManager::createScene(const std::string& sceneName) {
299 createGroup(sceneName);
300 }
301
302 void WindowsManager::createSceneWithFloor(const std::string& sceneName) {
303 createScene(sceneName);
304 addFloor((sceneName + "/floor").c_str());
305 }
306
307 bool WindowsManager::addSceneToWindow(const std::string& sceneName,
308 WindowID windowId) {
309 GroupNodePtr_t group = getGroup(sceneName, true);
310 RETURN_FALSE_IF_WINDOW_DOES_NOT_EXIST(window, windowId);
311 ScopedLock lock(osgFrameMutex());
312 window->addNode(group);
313 return true;
314 }
315
316 bool WindowsManager::attachCameraToNode(const std::string& nodeName,
317 const WindowID windowId) {
318 NodePtr_t node = getNode(nodeName, true);
319 RETURN_FALSE_IF_WINDOW_DOES_NOT_EXIST(window, windowId);
320 ScopedLock lock(osgFrameMutex());
321 window->attachCameraToNode(node);
322 return true;
323 }
324
325 bool WindowsManager::detachCamera(const WindowID windowId) {
326 RETURN_FALSE_IF_WINDOW_DOES_NOT_EXIST(window, windowId);
327 ScopedLock lock(osgFrameMutex());
328 window->detachCamera();
329 return true;
330 }
331
332 bool WindowsManager::addFloor(const std::string& floorName) {
333 RETURN_FALSE_IF_NODE_EXISTS(floorName);
334 LeafNodeGroundPtr_t floor = LeafNodeGround::create(floorName);
335 ScopedLock lock(osgFrameMutex());
336 addNode(floorName, floor, true);
337 return true;
338 }
339
340 bool WindowsManager::addBox(const std::string& boxName, const float& boxSize1,
341 const float& boxSize2, const float& boxSize3,
342 const Color_t& color) {
343 RETURN_FALSE_IF_NODE_EXISTS(boxName);
344
345 LeafNodeBoxPtr_t box = LeafNodeBox::create(
346 boxName, osgVector3(.5f * boxSize1, .5f * boxSize2, .5f * boxSize3),
347 color);
348 ScopedLock lock(osgFrameMutex());
349 addNode(boxName, box, true);
350 return true;
351 }
352
353 bool WindowsManager::addCapsule(const std::string& capsuleName,
354 const float radius, const float height,
355 const Color_t& color) {
356 RETURN_FALSE_IF_NODE_EXISTS(capsuleName);
357
358 LeafNodeCapsulePtr_t capsule =
359 LeafNodeCapsule::create(capsuleName, radius, height, color);
360 ScopedLock lock(osgFrameMutex());
361 addNode(capsuleName, capsule, true);
362 return true;
363 }
364
365 bool WindowsManager::addArrow(const std::string& arrowName, const float radius,
366 const float length, const Color_t& color) {
367 RETURN_FALSE_IF_NODE_EXISTS(arrowName);
368
369 LeafNodeArrowPtr_t arrow =
370 LeafNodeArrow::create(arrowName, color, radius, length);
371 ScopedLock lock(osgFrameMutex());
372 addNode(arrowName, arrow, true);
373 return true;
374 }
375
376 bool WindowsManager::addRod(const std::string& rodName, const Color_t& color,
377 const float radius, const float length,
378 short maxCapsule) {
379 RETURN_FALSE_IF_NODE_EXISTS(rodName);
380
381 NodeRodPtr_t rod =
382 NodeRod::create(rodName, color, radius, length, maxCapsule);
383 ScopedLock lock(osgFrameMutex());
384 addNode(rodName, rod, true);
385 for (size_t i = 0; i < (size_t)maxCapsule; i++)
386 addNode(rod->getCapsuleName(i), rod->getCapsule(i), false);
387 return true;
388 }
389
390 bool WindowsManager::resizeCapsule(const std::string& capsuleName,
391 float newHeight) {
392 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeCapsule, cap, capsuleName);
393 ScopedLock lock(osgFrameMutex());
394 cap->setHeight(newHeight);
395 return true;
396 }
397
398 bool WindowsManager::resizeArrow(const std::string& arrowName, float newRadius,
399 float newLength) {
400 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeArrow, arrow, arrowName);
401 ScopedLock lock(osgFrameMutex());
402 arrow->resize(newRadius, newLength);
403 return true;
404 }
405
406 bool WindowsManager::addMesh(const std::string& meshName,
407 const std::string& meshPath) {
408 RETURN_FALSE_IF_NODE_EXISTS(meshName);
409 LeafNodeColladaPtr_t mesh;
410 try {
411 mesh = LeafNodeCollada::create(meshName, urdfParser::getFilename(meshPath));
412 } catch (const std::exception& exc) {
413 log() << exc.what() << std::endl;
414 return false;
415 }
416 ScopedLock lock(osgFrameMutex());
417 addNode(meshName, mesh, true);
418 return true;
419 }
420
421 void WindowsManager::removeLightSources(const std::string& meshName) {
422 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeCollada, mesh, meshName);
423 ScopedLock lock(osgFrameMutex());
424 mesh->removeLightSources();
425 }
426
427 bool WindowsManager::addCone(const std::string& coneName, const float radius,
428 const float height, const Color_t& color) {
429 RETURN_FALSE_IF_NODE_EXISTS(coneName);
430
431 LeafNodeConePtr_t cone =
432 LeafNodeCone::create(coneName, radius, height, color);
433 ScopedLock lock(osgFrameMutex());
434 addNode(coneName, cone, true);
435 return true;
436 }
437
438 bool WindowsManager::addCylinder(const std::string& cylinderName,
439 const float radius, const float height,
440 const Color_t& color) {
441 RETURN_FALSE_IF_NODE_EXISTS(cylinderName);
442
443 LeafNodeCylinderPtr_t cylinder =
444 LeafNodeCylinder::create(cylinderName, radius, height, color);
445 ScopedLock lock(osgFrameMutex());
446 addNode(cylinderName, cylinder, true);
447 return true;
448 }
449
450 bool WindowsManager::addSphere(const std::string& sphereName,
451 const float radius, const Color_t& color) {
452 RETURN_FALSE_IF_NODE_EXISTS(sphereName);
453
454 LeafNodeSpherePtr_t sphere =
455 LeafNodeSphere::create(sphereName, radius, color);
456 ScopedLock lock(osgFrameMutex());
457 addNode(sphereName, sphere, true);
458 return true;
459 }
460
461 bool WindowsManager::addLight(const std::string& lightName, const WindowID wid,
462 const float radius, const Color_t& color) {
463 RETURN_FALSE_IF_NODE_EXISTS(lightName);
464
465 WindowManagerPtr_t wm = getWindowManager(wid, true);
466 LeafNodeLightPtr_t light = LeafNodeLight::create(lightName, radius, color);
467 ScopedLock lock(osgFrameMutex());
468 addNode(lightName, light, true);
469 light->setRoot(wm->getScene());
470 return true;
471 }
472
473 bool WindowsManager::addLine(const std::string& lineName,
474 const osgVector3& pos1, const osgVector3& pos2,
475 const Color_t& color) {
476 RETURN_FALSE_IF_NODE_EXISTS(lineName);
477
478 LeafNodeLinePtr_t line = LeafNodeLine::create(lineName, pos1, pos2, color);
479 ScopedLock lock(osgFrameMutex());
480 addNode(lineName, line, true);
481 return true;
482 }
483
484 bool WindowsManager::setLineStartPoint(const std::string& lineName,
485 const osgVector3& pos1) {
486 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, line, lineName);
487 ScopedLock lock(osgFrameMutex());
488 line->setStartPoint(pos1);
489 return true;
490 }
491
492 bool WindowsManager::setLineEndPoint(const std::string& lineName,
493 const osgVector3& pos2) {
494 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, line, lineName);
495 ScopedLock lock(osgFrameMutex());
496 line->setEndPoint(pos2);
497 return true;
498 }
499
500 bool WindowsManager::setLineExtremalPoints(const std::string& lineName,
501 const osgVector3& pos1,
502 const osgVector3& pos2) {
503 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, line, lineName);
504 ScopedLock lock(osgFrameMutex());
505 line->setStartPoint(pos1);
506 line->setEndPoint(pos2);
507 return true;
508 }
509
510 bool WindowsManager::addCurve(const std::string& curveName,
511 const Vec3ArrayPtr_t& pos, const Color_t& color) {
512 RETURN_FALSE_IF_NODE_EXISTS(curveName);
513 if (pos->size() < 2) {
514 throw std::invalid_argument("Need at least two points");
515 }
516 LeafNodeLinePtr_t curve = LeafNodeLine::create(curveName, pos, color);
517 curve->setMode(GL_LINE_STRIP);
518 ScopedLock lock(osgFrameMutex());
519 addNode(curveName, curve, true);
520 return true;
521 }
522
523 bool WindowsManager::setCurvePoints(const std::string& curveName,
524 const Vec3ArrayPtr_t& pos) {
525 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, curve, curveName);
526 if (pos->size() < 2) {
527 throw std::invalid_argument("Need at least two points");
528 }
529 ScopedLock lock(osgFrameMutex());
530 curve->setPoints(pos);
531 return true;
532 }
533
534 bool WindowsManager::setCurveColors(const std::string& curveName,
535 const Vec4ArrayPtr_t& colors) {
536 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, curve, curveName);
537 ScopedLock lock(osgFrameMutex());
538 curve->setColors(colors);
539 return true;
540 }
541
542 bool WindowsManager::setCurveMode(const std::string& curveName,
543 const GLenum mode) {
544 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, curve, curveName);
545 ScopedLock lock(osgFrameMutex());
546 curve->setMode(mode);
547 return true;
548 }
549
550 bool WindowsManager::setCurvePointsSubset(const std::string& curveName,
551 const int first,
552 const std::size_t count) {
553 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, curve, curveName);
554 ScopedLock lock(osgFrameMutex());
555 curve->setPointsSubset(first, count);
556 return true;
557 }
558
559 bool WindowsManager::setCurveLineWidth(const std::string& curveName,
560 const float& width) {
561 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeLine, curve, curveName);
562 setFloatProperty(curveName, "LineWidth", width);
563 return true;
564 }
565
566 bool WindowsManager::addTriangleFace(const std::string& faceName,
567 const osgVector3& pos1,
568 const osgVector3& pos2,
569 const osgVector3& pos3,
570 const Color_t& color) {
571 RETURN_FALSE_IF_NODE_EXISTS(faceName);
572
573 LeafNodeFacePtr_t face =
574 LeafNodeFace::create(faceName, pos1, pos2, pos3, color);
575 ScopedLock lock(osgFrameMutex());
576 addNode(faceName, face, true);
577 return true;
578 }
579
580 bool WindowsManager::addSquareFace(
581 const std::string& faceName, const osgVector3& pos1, const osgVector3& pos2,
582 const osgVector3& pos3, const osgVector3& pos4, const Color_t& color) {
583 RETURN_FALSE_IF_NODE_EXISTS(faceName);
584
585 LeafNodeFacePtr_t face =
586 LeafNodeFace::create(faceName, pos1, pos2, pos3, pos4, color);
587 ScopedLock lock(osgFrameMutex());
588 addNode(faceName, face, true);
589 return true;
590 }
591
592 bool WindowsManager::setTexture(const std::string& nodeName,
593 const std::string& filename) {
594 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeFace, faceNode, nodeName);
595
596 if (faceNode->nbVertices() != 4) {
597 std::ostringstream oss;
598 oss << "Face should have 4 vertices to apply texture. " << nodeName
599 << " has " << faceNode->nbVertices() << ".";
600 throw std::runtime_error(oss.str());
601 }
602 faceNode->setTexture(filename);
603 return true;
604 }
605
606 bool WindowsManager::addXYZaxis(const std::string& nodeName,
607 const Color_t& color, float radius,
608 float sizeAxis) {
609 RETURN_FALSE_IF_NODE_EXISTS(nodeName);
610
611 LeafNodeXYZAxisPtr_t axis =
612 LeafNodeXYZAxis::create(nodeName, color, radius, sizeAxis);
613 ScopedLock lock(osgFrameMutex());
614 addNode(nodeName, axis, true);
615 return true;
616 }
617
618 bool WindowsManager::createRoadmap(const std::string& roadmapName,
619 const Color_t& colorNode, float radius,
620 float sizeAxis, const Color_t& colorEdge) {
621 RETURN_FALSE_IF_NODE_EXISTS(roadmapName);
622
623 RoadmapViewerPtr_t rm = RoadmapViewer::create(roadmapName, colorNode, radius,
624 sizeAxis, colorEdge);
625 ScopedLock lock(osgFrameMutex());
626 addNode(roadmapName, rm, true);
627 roadmapNodes_[roadmapName] = rm;
628 return true;
629 }
630
631 bool WindowsManager::addEdgeToRoadmap(const std::string& nameRoadmap,
632 const osgVector3& posFrom,
633 const osgVector3& posTo) {
634 if (roadmapNodes_.find(nameRoadmap) == roadmapNodes_.end()) {
635 // no node named nodeName
636 log() << "No roadmap named \"" << nameRoadmap << "\"" << std::endl;
637 return false;
638 } else {
639 RoadmapViewerPtr_t rm_ptr = roadmapNodes_[nameRoadmap];
640 // ScopedLock lock(osgFrameMutex()); mtx is now locked only when required
641 // in addEdge
642 rm_ptr->addEdge(posFrom, posTo, osgFrameMutex());
643 return true;
644 }
645 }
646
647 bool WindowsManager::addNodeToRoadmap(const std::string& nameRoadmap,
648 const Configuration& conf) {
649 if (roadmapNodes_.find(nameRoadmap) == roadmapNodes_.end()) {
650 // no node named nodeName
651 log() << "No roadmap named \"" << nameRoadmap << "\"" << std::endl;
652 return false;
653 } else {
654 RoadmapViewerPtr_t rm_ptr = roadmapNodes_[nameRoadmap];
655 // ScopedLock lock(osgFrameMutex());
656 rm_ptr->addNode(conf.position, conf.quat, osgFrameMutex());
657 return true;
658 }
659 }
660
661 std::vector<std::string> WindowsManager::getNodeList() {
662 std::vector<std::string> l;
663 for (NodeMapIt it = nodes_.begin(); it != nodes_.end(); ++it) {
664 l.push_back(it->first);
665 }
666 return l;
667 }
668
669 std::vector<std::string> WindowsManager::getGroupNodeList(
670 const std::string& group) {
671 std::vector<std::string> l;
672 GroupNodePtr_t g(getGroup(group));
673 if (!g) return l;
674 l.reserve(g->getNumOfChildren());
675 for (std::size_t i = 0; i < g->getNumOfChildren(); ++i)
676 l.push_back(g->getChild(i)->getID());
677 return l;
678 }
679
680 std::vector<std::string> WindowsManager::getSceneList() {
681 std::vector<std::string> l;
682 l.reserve(groupNodes_.size());
683 for (GroupNodeMapConstIt it = groupNodes_.begin(); it != groupNodes_.end();
684 ++it)
685 l.push_back(it->first);
686 return l;
687 }
688
689 std::vector<std::string> WindowsManager::getWindowList() {
690 std::vector<std::string> l;
691 l.reserve(windowManagers_.size());
692 for (WindowManagerMap_t::const_iterator it = windowManagers_.begin();
693 it != windowManagers_.end(); ++it) {
694 l.push_back(it->first);
695 }
696 return l;
697 }
698
699 bool WindowsManager::createGroup(const std::string& groupName) {
700 RETURN_FALSE_IF_NODE_EXISTS(groupName);
701
702 GroupNodePtr_t groupNode = GroupNode::create(groupName);
703 ScopedLock lock(osgFrameMutex());
704 addGroup(groupName, groupNode, true);
705 return true;
706 }
707
708 bool WindowsManager::addURDF(const std::string& urdfName,
709 const std::string& urdfPath) {
710 return loadUDRF(urdfName, urdfPath, true, true);
711 }
712
713 bool WindowsManager::addURDF(const std::string& urdfName,
714 const std::string& urdfPath,
715 const std::string& /*urdfPackagePath*/) {
716 return addURDF(urdfName, urdfPath);
717 }
718
719 bool WindowsManager::addUrdfCollision(const std::string& urdfName,
720 const std::string& urdfPath) {
721 return loadUDRF(urdfName, urdfPath, false, true);
722 }
723
724 bool WindowsManager::addUrdfCollision(const std::string& urdfName,
725 const std::string& urdfPath,
726 const std::string& /*urdfPackagePath*/) {
727 return addUrdfCollision(urdfName, urdfPath);
728 }
729
730 void WindowsManager::addUrdfObjects(const std::string& urdfName,
731 const std::string& urdfPath, bool visual) {
732 loadUDRF(urdfName, urdfPath, visual, false);
733 }
734
735 void WindowsManager::addUrdfObjects(const std::string& urdfName,
736 const std::string& urdfPath,
737 const std::string& /*urdfPackagePath*/,
738 bool visual) {
739 return addUrdfObjects(urdfName, urdfPath, visual);
740 }
741
742 bool WindowsManager::loadUDRF(const std::string& urdfName,
743 const std::string& urdfPath, bool visual,
744 bool linkFrame) {
745 RETURN_FALSE_IF_NODE_EXISTS(urdfName);
746
747 GroupNodePtr_t urdf =
748 urdfParser::parse(urdfName, urdfPath, visual, linkFrame);
749 ScopedLock lock(osgFrameMutex());
750 addGroup(urdfName, urdf, true);
751 NodePtr_t link;
752 for (std::size_t i = 0; i < urdf->getNumOfChildren(); i++) {
753 link = urdf->getChild(i);
754 GroupNodePtr_t groupNode(dynamic_pointer_cast<GroupNode>(link));
755 if (groupNode) {
756 addGroup(link->getID(), groupNode, urdf);
757 for (std::size_t j = 0; j < groupNode->getNumOfChildren(); ++j) {
758 NodePtr_t object(groupNode->getChild(j));
759 addNode(object->getID(), object, groupNode);
760 }
761 } else {
762 addNode(link->getID(), link, urdf);
763 }
764 }
765 return true;
766 }
767
768 bool WindowsManager::addToGroup(const std::string& nodeName,
769 const std::string& groupName) {
770 NodePtr_t node = getNode(nodeName, true);
771 GroupNodePtr_t group = getGroup(groupName, true);
772
773 if (group->hasChild(node)) return false;
774
775 ScopedLock lock(osgFrameMutex()); // if addChild is called in the same time
776 // as osg::frame(), gepetto-viewer crash
777 groupNodes_[groupName]->addChild(nodes_[nodeName]);
778 return true;
779 }
780
781 bool WindowsManager::removeFromGroup(const std::string& nodeName,
782 const std::string& groupName) {
783 if (nodes_.find(nodeName) == nodes_.end() ||
784 groupNodes_.find(groupName) == groupNodes_.end()) {
785 log() << "Node name \"" << nodeName << "\" and/or groupNode \"" << groupName
786 << "\" doesn't exist." << std::endl;
787 return false;
788 } else {
789 ScopedLock lock(osgFrameMutex());
790 groupNodes_[groupName]->removeChild(nodes_[nodeName]);
791 return true;
792 }
793 }
794
795 bool WindowsManager::deleteNode(const std::string& nodeName, bool all) {
796 NodePtr_t n = getNode(nodeName);
797 if (!n)
798 return false;
799 else {
800 /// Check if it is a group
801 GroupNodeMapIt it = groupNodes_.find(nodeName);
802 if (it != groupNodes_.end()) {
803 if (all) {
804 std::vector<std::string> names(it->second->getNumOfChildren());
805 for (std::size_t i = 0; i < names.size(); ++i)
806 names[i] = it->second->getChild(i)->getID();
807 {
808 ScopedLock lock(osgFrameMutex());
809 it->second->removeAllChildren();
810 }
811 for (std::size_t i = 0; i < names.size(); ++i)
812 deleteNode(names[i], all);
813 }
814 {
815 ScopedLock lock(osgFrameMutex());
816 groupNodes_.erase(nodeName);
817 }
818 }
819 GroupNodeMapConstIt itg;
820 ScopedLock lock(osgFrameMutex());
821 for (itg = groupNodes_.begin(); itg != groupNodes_.end(); ++itg) {
822 if (itg->second && itg->second->hasChild(n)) itg->second->removeChild(n);
823 }
824 nodes_.erase(nodeName);
825 return true;
826 }
827 }
828
829 bool WindowsManager::removeObjectFromCache(const std::string& nodeName) {
830 FIND_NODE_OF_TYPE_OR_THROW(LeafNodeCollada, lnc, nodeName);
831 lnc->removeFromCache();
832 return true;
833 }
834
835 bool WindowsManager::applyConfiguration(const std::string& nodeName,
836 const Configuration& configuration) {
837 // TODO should we throw ?
838 if (!configuration.valid()) return false;
839 NodePtr_t updatedNode = getNode(nodeName, false);
840 if (!updatedNode) return false;
841
842 NodeConfiguration newNodeConfiguration;
843 newNodeConfiguration.node = updatedNode;
844 ((Configuration&)newNodeConfiguration) = configuration;
845
846 ScopedLock lock(configListMtx_);
847 newNodeConfigurations_.push_back(newNodeConfiguration);
848 return true;
849 }
850
851 bool WindowsManager::applyConfigurations(
852 const std::vector<std::string>& nodeNames,
853 const std::vector<Configuration>& configurations) {
854 if (nodeNames.size() != configurations.size())
855 throw std::invalid_argument(
856 "Number of node names and configurations must be equal.");
857
858 ScopedLock lock(configListMtx_);
859 newNodeConfigurations_.reserve(newNodeConfigurations_.capacity() +
860 nodeNames.size());
861
862 bool success = true;
863 for (std::size_t i = 0; i < nodeNames.size(); ++i) {
864 NodePtr_t updatedNode = getNode(nodeNames[i], false);
865 if (!updatedNode) {
866 success = false;
867 continue;
868 }
869
870 NodeConfiguration newNodeConfiguration;
871 newNodeConfiguration.node = updatedNode;
872 newNodeConfiguration.position = configurations[i].position;
873 newNodeConfiguration.quat = configurations[i].quat;
874
875 newNodeConfigurations_.push_back(newNodeConfiguration);
876 }
877
878 return success;
879 }
880
881 bool WindowsManager::addLandmark(const std::string& nodeName, float size) {
882 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
883 ScopedLock lock(osgFrameMutex());
884 nodes_[nodeName]->addLandmark(size);
885 return true;
886 }
887
888 bool WindowsManager::deleteLandmark(const std::string& nodeName) {
889 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
890 ScopedLock lock(osgFrameMutex());
891 nodes_[nodeName]->deleteLandmark();
892 return true;
893 }
894
895 Configuration WindowsManager::getStaticTransform(
896 const std::string& nodeName) const {
897 NodePtr_t node = getNode(nodeName, true);
898 return Configuration(node->getStaticPosition(), node->getStaticRotation());
899 }
900
901 bool WindowsManager::setStaticTransform(const std::string& nodeName,
902 const Configuration& transform) {
903 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
904 ScopedLock lock(osgFrameMutex());
905 nodes_[nodeName]->setStaticTransform(transform.position, transform.quat);
906 return true;
907 }
908
909 bool WindowsManager::setVisibility(const std::string& nodeName,
910 const std::string& visibilityMode) {
911 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
912 VisibilityMode visibility = getVisibility(visibilityMode);
913 ScopedLock lock(osgFrameMutex());
914 nodes_[nodeName]->setVisibilityMode(visibility);
915 return true;
916 }
917
918 bool WindowsManager::setScale(const std::string& nodeName,
919 const osgVector3& scale) {
920 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
921 ScopedLock lock(osgFrameMutex());
922 nodes_[nodeName]->setScale(scale);
923 return true;
924 }
925
926 bool WindowsManager::setScale(const std::string& nodeName, const float& scale) {
927 return setScale(nodeName, osgVector3(scale, scale, scale));
928 }
929
930 bool WindowsManager::setScale(const std::string& nodeName,
931 const int& scalePercentage) {
932 return setScale(nodeName, (value_type)scalePercentage / 100);
933 }
934
935 bool WindowsManager::setAlpha(const std::string& nodeName, const float& alpha) {
936 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
937 ScopedLock lock(osgFrameMutex());
938 nodes_[nodeName]->setAlpha(alpha);
939 return true;
940 }
941
942 bool WindowsManager::setAlpha(const std::string& nodeName,
943 const int& alphaPercentage) {
944 return setAlpha(nodeName, (float)alphaPercentage / 100);
945 }
946
947 bool WindowsManager::setColor(const std::string& nodeName,
948 const Color_t& color) {
949 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
950 osgVector4 vecColor(color[0], color[1], color[2], color[3]);
951 ScopedLock lock(osgFrameMutex());
952 nodes_[nodeName]->setColor(vecColor);
953 return true;
954 }
955
956 bool WindowsManager::setWireFrameMode(const std::string& nodeName,
957 const std::string& wireFrameMode) {
958 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
959 WireFrameMode wire = getWire(wireFrameMode);
960 ScopedLock lock(osgFrameMutex());
961 nodes_[nodeName]->setWireFrameMode(wire);
962 return true;
963 }
964
965 bool WindowsManager::setLightingMode(const std::string& nodeName,
966 const std::string& lightingMode) {
967 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
968 LightingMode light = getLight(lightingMode);
969 ScopedLock lock(osgFrameMutex());
970 nodes_[nodeName]->setLightingMode(light);
971 return true;
972 }
973
974 bool WindowsManager::setHighlight(const std::string& nodeName, int state) {
975 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
976 ScopedLock lock(osgFrameMutex());
977 nodes_[nodeName]->setHighlightState(state);
978 return true;
979 }
980
981 bool WindowsManager::setCaptureTransform(
982 const std::string& filename, const std::vector<std::string>& nodeNames) {
983 blenderCapture_.nodes_.clear();
984 std::size_t nb =
985 getNodes(nodeNames.begin(), nodeNames.end(), blenderCapture_.nodes_);
986 blenderCapture_.writer_visitor_->writer_ = new YamlTransformWriter(filename);
987 return nb == nodeNames.size();
988 }
989
990 void WindowsManager::captureTransformOnRefresh(bool autoCapture) {
991 autoCaptureTransform_ = autoCapture;
992 }
993
994 void WindowsManager::captureTransform() {
995 // This requires only a read access to the scene.
996 // The only requirement is that no node get delete while accessing them.
997 // ScopedLock lock(osgFrameMutex());
998 blenderCapture_.captureFrame();
999 }
1000
1001 bool WindowsManager::writeBlenderScript(
1002 const std::string& filename, const std::vector<std::string>& nodeNames) {
1003 std::vector<NodePtr_t> nodes;
1004 std::size_t nb = getNodes(nodeNames.begin(), nodeNames.end(), nodes);
1005 if (nb != nodeNames.size())
1006 throw std::invalid_argument("Could not find one of the nodes");
1007 BlenderGeomWriterVisitor visitor(filename);
1008 for (std::size_t i = 0; i < nodes.size(); ++i) nodes[i]->accept(visitor);
1009 return true;
1010 }
1011
1012 bool WindowsManager::writeNodeFile(const std::string& nodeName,
1013 const std::string& filename) {
1014 RETURN_FALSE_IF_NODE_DOES_NOT_EXIST(nodeName);
1015 ScopedLock lock(osgFrameMutex());
1016 osg::ref_ptr<osgDB::Options> os = new osgDB::Options;
1017 os->setOptionString("NoExtras");
1018 osgDB::ReaderWriter::WriteResult wr = osgDB::Registry::instance()->writeNode(
1019 *nodes_[nodeName]->asGroup(), std::string(filename), os.get());
1020 if (!wr.success()) {
1021 std::ostringstream oss;
1022 oss << "Error writing file " << filename << ": " << wr.message();
1023 throw std::runtime_error(oss.str().c_str());
1024 }
1025 return wr.success();
1026 }
1027
1028 bool WindowsManager::writeWindowFile(const WindowID windowId,
1029 const std::string& filename) {
1030 RETURN_FALSE_IF_WINDOW_DOES_NOT_EXIST(window, windowId);
1031 ScopedLock lock(osgFrameMutex());
1032 bool ret = window->writeNodeFile(std::string(filename));
1033 return ret;
1034 }
1035
1036 WindowManagerPtr_t WindowsManager::getWindowManager(
1037 const WindowID wid, bool throwIfDoesntExist) const {
1038 WindowManagerMap_t::const_iterator it = windowManagers_.find(wid);
1039 if (it != windowManagers_.end())
1040 return it->second;
1041 else if (throwIfDoesntExist)
1042 throw std::invalid_argument("Window ID " + wid + " doesn't exist.");
1043 return WindowManagerPtr_t();
1044 }
1045
1046 GroupNodePtr_t WindowsManager::getGroup(const std::string groupName,
1047 bool throwIfDoesntExist) const {
1048 GroupNodeMapConstIt it = groupNodes_.find(groupName);
1049 if (it == groupNodes_.end()) {
1050 if (throwIfDoesntExist) {
1051 std::ostringstream oss;
1052 oss << "No group with name \"" << groupName << "\".";
1053 throw std::invalid_argument(oss.str().c_str());
1054 } else
1055 return GroupNodePtr_t();
1056 }
1057 return it->second;
1058 }
1059
1060 Configuration WindowsManager::getNodeGlobalTransform(
1061 const std::string nodeName) const {
1062 NodePtr_t node = getNode(nodeName, true);
1063 return node->getGlobalTransform();
1064 }
1065
1066 bool WindowsManager::setBackgroundColor1(const WindowID windowId,
1067 const Color_t& color) {
1068 WindowManagerPtr_t wm = getWindowManager(windowId, true);
1069 ScopedLock lock(osgFrameMutex());
1070 wm->setBackgroundColor1(color);
1071 return true;
1072 }
1073
1074 bool WindowsManager::setBackgroundColor2(const WindowID windowId,
1075 const Color_t& color) {
1076 WindowManagerPtr_t wm = getWindowManager(windowId, true);
1077 ScopedLock lock(osgFrameMutex());
1078 wm->setBackgroundColor2(color);
1079 return true;
1080 }
1081
1082 Configuration WindowsManager::getCameraTransform(const WindowID windowId) {
1083 osg::Quat rot;
1084 osg::Vec3d pos;
1085 WindowManagerPtr_t wm = getWindowManager(windowId, true);
1086 ScopedLock lock(osgFrameMutex());
1087 wm->getCameraTransform(pos, rot);
1088 return Configuration(pos, rot);
1089 }
1090
1091 bool WindowsManager::setCameraTransform(const WindowID windowId,
1092 const Configuration& configuration) {
1093 WindowManagerPtr_t wm = getWindowManager(windowId, true);
1094 ScopedLock lock(osgFrameMutex());
1095 wm->setCameraTransform(configuration.position, configuration.quat);
1096 return true;
1097 }
1098
1099 bool WindowsManager::setCameraToBestFit(const WindowID windowId) {
1100 WindowManagerPtr_t wm = getWindowManager(windowId, true);
1101 ScopedLock lock(osgFrameMutex());
1102 wm->getViewerClone()->home();
1103 return true;
1104 }
1105
1106 std::vector<std::string> WindowsManager::getPropertyNames(
1107 const std::string& nodeName) const {
1108 NodePtr_t node = getNode(nodeName, true);
1109 const Properties::PropertyMap_t& map = node->properties();
1110 std::vector<std::string> names;
1111 names.reserve(map.size());
1112 for (Properties::PropertyMap_t::const_iterator _prop = map.begin();
1113 _prop != map.end(); ++_prop)
1114 names.push_back(_prop->first);
1115 return names;
1116 }
1117
1118 std::vector<std::string> WindowsManager::getPropertyTypes(
1119 const std::string& nodeName) const {
1120 NodePtr_t node = getNode(nodeName, true);
1121 const Properties::PropertyMap_t& map = node->properties();
1122 std::vector<std::string> types;
1123 types.reserve(map.size());
1124 for (Properties::PropertyMap_t::const_iterator _prop = map.begin();
1125 _prop != map.end(); ++_prop)
1126 types.push_back(_prop->second->type());
1127 return types;
1128 }
1129
1130 template <typename Property_t>
1131 Property_t WindowsManager::getProperty(const std::string& nodeName,
1132 const std::string& propName) const {
1133 NodePtr_t node = getNode(nodeName, true);
1134 Property_t value;
1135 if (!node->getProperty<Property_t>(propName, value)) {
1136 throw std::invalid_argument("Could not get the property");
1137 }
1138 return value;
1139 }
1140
1141 template <typename Property_t>
1142 void WindowsManager::setProperty(const std::string& nodeName,
1143 const std::string& propName,
1144 const Property_t& value) {
1145 ScopedLock lock(osgFrameMutex());
1146 NodePtr_t node = getNode(nodeName, true);
1147 if (!node->setProperty<Property_t>(propName, value)) {
1148 throw std::invalid_argument("Could not set the property");
1149 }
1150 }
1151
1152 #define DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(Type, Name) \
1153 Type WindowsManager::get##Name##Property( \
1154 const std::string& nodeName, const std::string& propName) const { \
1155 return getProperty<Type>(nodeName, propName); \
1156 } \
1157 void WindowsManager::set##Name##Property(const std::string& nodeName, \
1158 const std::string& propName, \
1159 const Type& value) { \
1160 setProperty<Type>(nodeName, propName, value); \
1161 }
1162
1163 #define INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(Type) \
1164 template Type WindowsManager::getProperty<Type>(const std::string&, \
1165 const std::string&) const; \
1166 template void WindowsManager::setProperty<Type>( \
1167 const std::string&, const std::string&, const Type&)
1168
1169 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(std::string);
1170 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(osgVector2);
1171 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(osgVector3);
1172 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(osgVector4);
1173 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(float);
1174 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(bool);
1175 INSTANCIATE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(int);
1176
1177 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(std::string, String)
1178 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(osgVector2, Vector2)
1179 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(osgVector3, Vector3)
1180 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(osgVector4, Color)
1181 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(float, Float)
1182 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(bool, Bool)
1183 DEFINE_WINDOWS_MANAGER_GET_SET_PROPERTY_FOR_TYPE(int, Int)
1184
1185 void WindowsManager::callVoidProperty(const std::string& nodeName,
1186 const std::string& propName) {
1187 NodePtr_t node = getNode(nodeName, true);
1188 ScopedLock lock(osgFrameMutex());
1189 if (!node->hasProperty(propName))
1190 throw std::invalid_argument("Could not find the property");
1191 node->callVoidProperty(propName);
1192 }
1193 } /* namespace viewer */
1194
1195 } // namespace gepetto
1196