ViewerWidget.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @package ArmarX::
17* @author Mirko Waechter ( mirko.waechter at kit dot edu)
18* @date 2012
19* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23#include "ViewerWidget.h"
24
25#include <ArmarXGui/applications/ArmarXGui/ui_ViewerWidget.h>
26#include <ArmarXGui/applications/ArmarXGui/ui_ViewerWidgetConfigDialog.h>
27
28// Coin3D & SoQt
29#include <QCheckBox>
30#include <QColorDialog>
31#include <QComboBox>
32#include <QDialog>
33#include <QDialogButtonBox>
34#include <QGridLayout>
35#include <QLabel>
36#include <QPushButton>
37#include <QShortcut>
38#include <QToolBar>
39
40#include "../ArmarXMainWindow.h"
41#include <Inventor/actions/SoLineHighlightRenderAction.h>
42#include <Inventor/actions/SoSearchAction.h>
43#include <Inventor/nodes/SoCamera.h>
44#include <Inventor/nodes/SoNode.h>
45#include <Inventor/nodes/SoSeparator.h>
46
47namespace armarx
48{
49#define ARMARX_ORGANIZATION "KIT"
50#define ARMARX_GUI_APPLICATION_NAME "ArmarXGUI"
51
52#define VIEWER_SETTINGS_AA "AntiAliasing"
53#define VIEWER_SETTINGS_BACKGROUND_COLOR "BackgroundColor"
54#define VIEWER_SETTINGS_TRANSPARENCY_TYPE "TransparencyType"
55
57 ui(new Ui_Viewer3DWidget),
58 customToolbar(NULL),
59 settingsFile(armarx::ArmarXDataPath::GetDefaultUserConfigPath() + "/" +
60 ARMARX_GUI_APPLICATION_NAME + ".conf"),
61 settings(QString(settingsFile.c_str()), QSettings::NativeFormat),
62 viewingModeAction(NULL)
63 {
64 configDialog = nullptr;
65 configDialogUi = nullptr;
66 }
67
69 {
70 ARMARX_INFO << "~Viewer3DWidget()";
71 viewer.reset();
72
73 delete configDialogUi;
74 delete ui;
75 }
76
77 void
79 {
80 if (!viewer)
81 {
82 return;
83 }
84
85 auto l = viewer->getScopedLock();
86
88 {
89 viewer->setSceneGraph(emptyNode);
90 }
91 else
92 {
93 QString sceneName = cb3DViewers->itemText(index);
94
95 ARMARX_INFO << "Setting 3D scene: " << sceneName;
96
97 SoNode* node = sceneMap[sceneName].node;
98 bool initializeView =
99 find(selectedViews.begin(), selectedViews.end(), node) == selectedViews.end();
100 viewer->setSceneGraph(node);
101
102 if (initializeView)
103 {
104 if (initialCameraPoses.find(sceneName) != initialCameraPoses.end())
105 {
106 CameraPose p = initialCameraPoses[sceneName];
107
108 viewer->getCamera()->position.setValue(
109 p.position[0], p.position[1], p.position[2]);
110 viewer->getCamera()->orientation.setValue(
111 p.orientation[0], p.orientation[1], p.orientation[2], p.orientation[3]);
112 viewer->getCamera()->focalDistance.setValue(p.focalDistance);
113 }
114 else
115 {
116 viewer->viewAll();
117 }
118
119 selectedViews.push_back(node);
120 }
121 }
122 }
123
124 void
125 Viewer3DWidget::loadSettings(QSettings* settings)
126 {
127 std::set<QString> sceneNames;
128 for (auto& key : settings->allKeys())
129 {
130 if (key.startsWith("camera."))
131 {
132 sceneNames.insert(key.split('.').at(1));
133 }
134 }
135
136 for (auto& scene : sceneNames)
137 {
138 CameraPose p;
139
140 p.position[0] = settings->value("camera." + scene + ".pos_x").toFloat();
141 p.position[1] = settings->value("camera." + scene + ".pos_y").toFloat();
142 p.position[2] = settings->value("camera." + scene + ".pos_z").toFloat();
143
144 p.orientation[0] = settings->value("camera." + scene + ".ori_q1").toFloat();
145 p.orientation[1] = settings->value("camera." + scene + ".ori_q2").toFloat();
146 p.orientation[2] = settings->value("camera." + scene + ".ori_q3").toFloat();
147 p.orientation[3] = settings->value("camera." + scene + ".ori_q4").toFloat();
148
149 p.focalDistance = settings->value("camera." + scene + ".focalDistance").toFloat();
150
151 initialCameraPoses[scene] = p;
152 }
153
154 // clear initialized views and reset node to apply loaded settings
155 if (viewer)
156 {
157 auto l = viewer->getScopedLock();
158
159 selectedViews.clear();
160 setNode(cb3DViewers->currentIndex());
161 }
162 }
163
164 void
165 Viewer3DWidget::saveSettings(QSettings* settings)
166 {
167 for (auto& scene : sceneMap.toStdMap())
168 {
169 SoSearchAction a;
170 a.setType(SoCamera::getClassTypeId(), true);
171 a.setInterest(SoSearchAction::FIRST);
172 a.apply(scene.second.node);
173
174 if (!a.getPath())
175 {
176 continue;
177 }
178
179 SoCamera* cameraNode = (SoCamera*)a.getPath()->getTail();
180 QString sceneName = scene.first;
181
182 settings->setValue("camera." + sceneName + ".pos_x",
183 cameraNode->position.getValue().getValue()[0]);
184 settings->setValue("camera." + sceneName + ".pos_y",
185 cameraNode->position.getValue().getValue()[1]);
186 settings->setValue("camera." + sceneName + ".pos_z",
187 cameraNode->position.getValue().getValue()[2]);
188
189 settings->setValue("camera." + sceneName + ".ori_q1",
190 cameraNode->orientation.getValue().getValue()[0]);
191 settings->setValue("camera." + sceneName + ".ori_q2",
192 cameraNode->orientation.getValue().getValue()[1]);
193 settings->setValue("camera." + sceneName + ".ori_q3",
194 cameraNode->orientation.getValue().getValue()[2]);
195 settings->setValue("camera." + sceneName + ".ori_q4",
196 cameraNode->orientation.getValue().getValue()[3]);
197
198 settings->setValue("camera." + sceneName + ".focalDistance",
199 cameraNode->focalDistance.getValue());
200 }
201 }
202
203 void
204 Viewer3DWidget::setMainWindow(QMainWindow* mainWindow)
205 {
207 ArmarXMainWindow* guiMainWindow = qobject_cast<ArmarXMainWindow*>(getMainWindow());
208 connect(guiMainWindow,
209 SIGNAL(updateSceneList(QMap<QString, Viewer3DInfo>)),
210 this,
211 SLOT(sceneListUpdated(QMap<QString, Viewer3DInfo>)));
212 sceneListUpdated(guiMainWindow->viewer3DMap);
213 }
214
215 void
217 {
218 ui->setupUi(getWidget());
219 getWidget()->setContentsMargins(1, 1, 1, 1);
220 getWidget()->setFocusPolicy(Qt::WheelFocus);
221
222 QGridLayout* grid = new QGridLayout();
223 grid->setContentsMargins(0, 0, 0, 0);
224 getWidget()->setLayout(grid);
225 getWidget()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
226
227 QWidget* view1 = new QWidget(getWidget());
228 view1->setMinimumSize(100, 100);
229 view1->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
230
231 viewer.reset(new CoinViewer(view1, "", TRUE, SoQtExaminerViewer::BUILD_POPUP));
232 if (mutex3D)
233 {
234 viewer->setMutex(mutex3D);
235 }
236
237 // setup
238 viewer->setBackgroundColor(SbColor(1.0f, 1.0f, 1.0f));
239 viewer->setAccumulationBuffer(false);
240
241 emptyNode = new SoSeparator();
242 emptyNode->ref();
243 viewer->setSceneGraph(emptyNode);
244
245 viewer->setFeedbackVisibility(true);
246 viewer->setGLRenderAction(new SoLineHighlightRenderAction());
247 viewer->viewAll();
248
249 // show everything
250 viewer->show();
251
252 cb3DViewers = new QComboBox(getWidget());
253 label = new QLabel("Scene:");
255 new QPushButton(QIcon(":/icons/configure-3.png"), "", getWidget());
256 sceneConfigDialogButton->setToolTip("Configure Scene");
257 grid->addWidget(view1, 0, 0, 1, 3);
258 grid->addWidget(label, 1, 0);
259 grid->addWidget(cb3DViewers, 1, 1);
260 grid->addWidget(sceneConfigDialogButton, 1, 2);
261 grid->setColumnMinimumWidth(2, 20);
262 sceneConfigDialogButton->setEnabled(false);
263 connect(cb3DViewers, SIGNAL(activated(int)), this, SLOT(select3DView(int)));
264 connect(cb3DViewers, SIGNAL(currentIndexChanged(int)), this, SLOT(select3DView(int)));
266 &QPushButton::pressed,
267 this,
268 [this]()
269 {
270 int index = cb3DViewers->currentIndex();
271 if (index >= 0 && index < cb3DViewers->count())
272 {
273 QString sceneName = cb3DViewers->itemText(index);
274 auto sceneConfigDialog = sceneMap[sceneName].sceneConfigDialog;
275
276 if (sceneConfigDialog)
277 {
278 sceneConfigDialog->open();
279 }
280 }
281 });
282
283 // Create config dialog
284 configDialog = new QDialog(ArmarXWidgetController::getMainWindow());
285 configDialogUi = new Ui_ViewerWidgetConfigDialog;
286 configDialogUi->setupUi(configDialog);
287
288 connect(
289 configDialogUi->buttonBox, SIGNAL(accepted()), this, SLOT(configDialogApplySettings()));
290 connect(configDialogUi->buttonBox->button(QDialogButtonBox::Save),
291 SIGNAL(clicked()),
292 this,
294 connect(configDialogUi->pushButtonPickColor,
295 SIGNAL(pressed()),
296 this,
297 SLOT(configDialogPickColor()));
298
299
301
302
303 ArmarXMainWindow* guiMainWindow =
304 qobject_cast<ArmarXMainWindow*>(ArmarXWidgetController::getMainWindow());
305 if (guiMainWindow)
306 {
307 sceneListUpdated(guiMainWindow->viewer3DMap);
308 }
309 }
310
311 void
313 {
314 this->mutex3D = mutex3D;
315 if (viewer)
316 {
317 viewer->setMutex(mutex3D);
318 }
319 }
320
321 QPointer<QWidget>
323 {
324 if (customToolbar)
325 {
326 if (parent != customToolbar->parent())
327 {
328 customToolbar->setParent(parent);
329 }
330
331 return customToolbar;
332 }
333
334 customToolbar = new QToolBar(parent);
335 customToolbar->setIconSize(QSize(16, 16));
336 customToolbar->addAction(
337 QIcon(":/icons/configure-3.png"), "Configure", this, SLOT(configDialogOpen()));
338
339 viewingModeAction = customToolbar->addAction(
340 QIcon(":/icons/hand.svg"), "Viewing Mode (V)", this, SLOT(toggleViewingMode()));
341 viewingModeAction->setShortcut(QKeySequence(Qt::Key_V));
342 viewingModeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
343 getWidget()->addAction(viewingModeAction);
344 viewingModeAction->setCheckable(true);
345 viewingModeAction->setChecked(true);
346
347 QAction* viewAllAction =
348 new QAction(QIcon(":icons/zoom-original-2.png"), "View All (A)", getWidget());
349 customToolbar->addAction(viewAllAction);
350 viewAllAction->setShortcut(QKeySequence(tr("A")));
351 viewAllAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
352 connect(viewAllAction, SIGNAL(triggered()), this, SLOT(viewAll()));
353 getWidget()->addAction(viewAllAction);
354
355 return customToolbar;
356 }
357
358 void
360 {
361 // ARMARX_INFO << "Selecting 3d viewer entry " << index;
362 if (index >= 0 && index < cb3DViewers->count())
363 {
364 QString sceneName = cb3DViewers->itemText(index);
365 auto sceneConfigDialog = sceneMap[sceneName].sceneConfigDialog;
366
367 sceneConfigDialogButton->setEnabled(sceneConfigDialog != nullptr);
368 }
369 else
370 {
371 sceneConfigDialogButton->setEnabled(false);
372 }
373 setNode(index);
374 }
375
376 void
377 Viewer3DWidget::sceneListUpdated(QMap<QString, Viewer3DInfo> sceneMap)
378 {
379 if (!viewer)
380 {
381 return;
382 }
383
384 auto l = viewer->getScopedLock();
385 // ARMARX_INFO << "scene map size: " << sceneMap.size();
386 this->sceneMap = sceneMap;
387 int oldIndex = cb3DViewers->currentIndex();
388
389 if (oldIndex < 0)
390 {
391 oldIndex = 0;
392 }
393
394 cb3DViewers->clear();
395 QMap<QString, Viewer3DInfo>::iterator it = sceneMap.begin();
396 std::vector<SoNode*> newSelectedList;
397
398 for (; it != sceneMap.end(); it++)
399 {
400 cb3DViewers->addItem(it.key());
401
402 if (find(selectedViews.begin(), selectedViews.end(), it.value().node) !=
403 selectedViews.end())
404 {
405 newSelectedList.push_back(it.value().node);
406 }
407 }
408
409 selectedViews = newSelectedList;
410
411 if (oldIndex < cb3DViewers->count())
412 {
413 select3DView(oldIndex);
414 // cb3DViewers->setCurrentIndex(oldIndex);
415 }
416
417 // ARMARX_INFO << "SceneList updated";
418 }
419
420 void
422 {
423 if (!color.isValid())
424 {
425 color = QColorDialog::getColor();
426 }
427
428 if (color.isValid())
429 {
430 QPalette p;
431 p.setColor(QPalette::Button, color);
432 configDialogUi->pushButtonPickColor->setPalette(p);
433 }
434 }
435
436 void
438 {
439 viewer->setViewing(!viewer->isViewing());
440 viewingModeAction->setChecked(viewer->isViewing());
441
442 ARMARX_INFO << "Viewing mode " << (viewer->isViewing() ? "enabled" : "disabled");
443 }
444
445 void
447 {
448 if (viewer)
449 {
450 viewer->viewAll();
451 }
452 }
453
454 void
456 {
457 SbColor c = viewer->getBackgroundColor();
458 configDialogPickColor(QColor(255 * c[0], 255 * c[1], 255 * c[2]));
459
460 configDialog->show();
461 }
462
463 void
465 {
466 int numPasses = 0;
467
468 if (configDialogUi->checkBoxMultipass->isChecked())
469 {
470 numPasses = pow(2, (configDialogUi->comboBoxMultipass->currentIndex() + 1));
471 }
472 viewer->setAccumulationBuffer(false);
473 viewer->setAntialiasing((numPasses > 0), numPasses);
474 ARMARX_INFO << "Multipass Anti Aliasing: " << numPasses << "x";
475
476 QColor color = configDialogUi->pushButtonPickColor->palette().color(QPalette::Button);
477 viewer->setBackgroundColor(
478 SbColor(color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0));
479 ARMARX_INFO << "Background Color: (" << color.red() << ", " << color.green() << ", "
480 << color.blue() << ")";
481
482 if (configDialogUi->checkBoxTransparency->isChecked())
483 {
484 switch (configDialogUi->comboBoxTransparencyType->currentIndex())
485 {
486 case 0:
487 viewer->setTransparencyType(SoGLRenderAction::BLEND);
488 break;
489
490 case 1:
491 viewer->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
492 break;
493
494 case 2:
495 viewer->setTransparencyType(SoGLRenderAction::SORTED_LAYERS_BLEND);
496 break;
497
498 default:
499 ARMARX_WARNING << "Unknown transparency type set";
500 break;
501 }
502 }
503 else
504 {
505 viewer->setAlphaChannel(false);
506 viewer->setTransparencyType(SoGLRenderAction::NONE);
507 ARMARX_INFO << "Transparency disabled";
508 }
509 }
510
511 void
513 {
514 if (!configDialogUi->checkBoxTransparency->isChecked())
515 {
516 settings.setValue(VIEWER_SETTINGS_TRANSPARENCY_TYPE, -1);
517 }
518 else
519 {
520 settings.setValue(VIEWER_SETTINGS_TRANSPARENCY_TYPE,
521 configDialogUi->comboBoxTransparencyType->currentIndex());
522 }
523
524 if (!configDialogUi->checkBoxMultipass->isChecked())
525 {
526 settings.setValue(VIEWER_SETTINGS_AA, -1);
527 }
528 else
529 {
530 settings.setValue(VIEWER_SETTINGS_AA,
531 configDialogUi->comboBoxMultipass->currentIndex());
532 }
533
534 settings.setValue(VIEWER_SETTINGS_BACKGROUND_COLOR,
535 configDialogUi->pushButtonPickColor->palette().color(QPalette::Button));
536 }
537
538 void
540 {
541 int transparencyType = settings.value(VIEWER_SETTINGS_TRANSPARENCY_TYPE, 1).toInt();
542 configDialogUi->checkBoxTransparency->setChecked(transparencyType != -1);
543 configDialogUi->comboBoxTransparencyType->setCurrentIndex(transparencyType);
544
545 int antiAliasing = settings.value(VIEWER_SETTINGS_AA, -1).toInt();
546 configDialogUi->checkBoxMultipass->setChecked(antiAliasing != -1);
547 configDialogUi->comboBoxMultipass->setCurrentIndex(antiAliasing);
548
549 QColor backgroundColor =
550 settings.value(VIEWER_SETTINGS_BACKGROUND_COLOR, QColor(255, 255, 255)).value<QColor>();
551 if (backgroundColor.isValid())
552 {
553 QPalette p;
554 p.setColor(QPalette::Button, backgroundColor);
555 configDialogUi->pushButtonPickColor->setPalette(p);
556 }
557
559 }
560
561 void
565
566 void
570
571 void
573 {
574 cb3DViewers->setVisible(false);
575 label->setVisible(false);
576 sceneConfigDialogButton->setVisible(false);
577 }
578
579 void
581 {
582 cb3DViewers->setVisible(true);
583 label->setVisible(true);
584 sceneConfigDialogButton->setVisible(true);
585 }
586} // namespace armarx
uint8_t index
constexpr T c
#define VIEWER_SETTINGS_BACKGROUND_COLOR
#define VIEWER_SETTINGS_TRANSPARENCY_TYPE
#define VIEWER_SETTINGS_AA
The ArmarXDataPath class provides static methods to handle ArmarX data directories.
The ArmarXMainWindow class.
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
std::shared_ptr< RecursiveMutex > RecursiveMutexPtr
std::shared_ptr< std::recursive_mutex > mutex3D
virtual QMainWindow * getMainWindow()
Returns the ArmarX MainWindow.
virtual void setMainWindow(QMainWindow *mainWindow)
void select3DView(int index)
QPointer< QLabel > label
void onInitComponent() override
Pure virtual hook for the subclass.
QPointer< QPushButton > sceneConfigDialogButton
QPointer< QWidget > getCustomTitlebarWidget(QWidget *parent=0) override
getTitleToolbar returns a pointer to the a toolbar widget of this controller.
Viewer3DWidget(QWidget *parent=0)
void configDialogPickColor(QColor color=QColor::Invalid)
void setNode(int index)
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
void onUnlockWidget() override
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
void setMutex3D(RecursiveMutexPtr const &mutex3D) override
This mutex is used to protect 3d scene updates.
SoSeparator * emptyNode
QPointer< QComboBox > cb3DViewers
void postDocking() override
postDocking is called after the widget has been docked into the main window.
void sceneListUpdated(QMap< QString, Viewer3DInfo > sceneMap)
void onConnectComponent() override
Pure virtual hook for the subclass.
void setMainWindow(QMainWindow *mainWindow) override
void onLockWidget() override
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file offers overloads of toIce() and fromIce() functions for STL container types.