Developer Documentation
viewerControl.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44
45
46//=============================================================================
47//
48// CLASS CoreWidget - IMPLEMENTATION
49//
50//=============================================================================
51
52
53//== INCLUDES =================================================================
54
55#include "CoreWidget.hh"
56
57
58#include <QtConcurrent>
59
60
61#include <OpenFlipper/widgets/snapshotDialog/SnapshotDialog.hh>
62#include <cmath>
63
64#ifdef _MSC_VER
65 #include <ACG/Utils/VSToolsT.hh>
66#endif
67
68#include <ACG/Scenegraph/MaterialNode.hh>
69
70//== IMPLEMENTATION ==========================================================
71
72//=============================================================================
73
75{
77
78 if ( stereoActive_ ) {
79 statusBar_->showMessage(tr("Stereo enabled"));
80 stereoButton_->setIcon( QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"stereo.png") );
81 } else {
82 statusBar_->showMessage(tr("Stereo disabled"));
83 stereoButton_->setIcon( QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"mono.png") );
84 }
85
87
88 for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
89 examiner_widgets_[i]->properties()->stereo(stereoActive_);
90}
91
94
95 QColor backCol((int)bc[0], (int)bc[1], (int)bc[2], (int)bc[3]);
96 QColor c = QColorDialog::getColor(backCol,this);
97
98 if (c != backCol && c.isValid())
99 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets(); ++i )
101 ((double) c.greenF()) ,
102 ((double) c.blueF()) ,
103 1.0));
104
105 OpenFlipperSettings().setValue("Core/Gui/glViewer/defaultBackgroundColor",c);
106
107}
108
111
112 QColor backCol((int)bc[0], (int)bc[1], (int)bc[2], (int)bc[3]);
113 QColor c = QColorDialog::getColor(backCol,this);
114
115 if (c != backCol && c.isValid())
117 ((double) c.greenF()) ,
118 ((double) c.blueF()) ,
119 1.0));
120}
121
122
126}
127
130 std::vector< glViewer* >::iterator it = examiner_widgets_.begin();
131
132 for(; it != examiner_widgets_.end(); ++it)
133 _state ? (*it)->slotShowWheels() : (*it)->slotHideWheels();
134}
135
138 std::vector< glViewer* >::iterator it = examiner_widgets_.begin();
139
140 for(; it != examiner_widgets_.end(); ++it) {
141 _egomode ? (*it)->navigationMode(glViewer::FIRSTPERSON_NAVIGATION) :
142 (*it)->navigationMode(glViewer::NORMAL_NAVIGATION);
143 }
144}
145
148 for ( int i = 0 ; i < PluginFunctions::viewers() ; ++i )
149 examiner_widgets_[i]->home();
150}
151
155}
156
157
160 for ( int i = 0 ; i < PluginFunctions::viewers() ; ++i )
161 examiner_widgets_[i]->setHome();
162}
163
167}
168
169
172 for ( int i = 0 ; i < PluginFunctions::viewers() ; ++i )
173 examiner_widgets_[i]->viewAll();
174}
175
178 examiner_widgets_[PluginFunctions::activeExaminer()]->toggleProjectionMode();
179}
180
183 // Find coordsys node
185 node = PluginFunctions::getSceneGraphRootNode()->find("Core Coordsys Node");
186 if (node != 0) {
187 return dynamic_cast<ACG::SceneGraph::CoordsysNode*> (node)->getProjectionMode();
188 } else {
189 emit statusMessage(QString(tr("getCoordsysProjection(): Could not find coordsys node. Assuming default orthographic projection.")));
191 }
192}
193
196 // Find coordsys node
198 node = PluginFunctions::getSceneGraphRootNode()->find("Core Coordsys Node");
199 if (node != 0) {
203 }
204 else {
206 }
207 } else {
208 emit statusMessage(QString(tr("slotContextSwitchCoordsysProjection(): Could not find coordsys node, thus its projection mode will not be toggled.")));
209 }
210
211 for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
212 examiner_widgets_[i]->updateGL();
213}
214
217 for ( int i = 0 ; i < PluginFunctions::viewers() ; ++i )
218 examiner_widgets_[i]->perspectiveProjection();
219}
220
223 for ( int i = 0 ; i < PluginFunctions::viewers() ; ++i )
224 examiner_widgets_[i]->orthographicProjection();
225}
226
227
230 int enabledCount = 0;
231
232 for ( int i = 0 ; i< PluginFunctions::viewers(); ++i ) {
234 enabledCount++;
235 }
236
237 slotGlobalChangeAnimation (enabledCount == 0);
238}
239
242 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
244}
245
249}
250
251
254 int enabledCount = 0;
255
256 for ( int i = 0 ; i< PluginFunctions::viewers(); ++i ) {
258 enabledCount++;
259 }
260
261 slotGlobalChangeBackFaceCulling (enabledCount == 0);
262}
263
266 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
268
269}
270
274}
275
276
279 int enabledCount = 0;
280
281 for ( int i = 0 ; i< PluginFunctions::viewers(); ++i ) {
283 enabledCount++;
284 }
285
286 slotGlobalChangeTwoSidedLighting (enabledCount == 0);
287}
288
291 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
293}
294
298}
299
300
303 int enabledCount = 0;
304
305 for ( int i = 0 ; i< PluginFunctions::viewers(); ++i ) {
307 enabledCount++;
308 }
309
310 slotGlobalChangeMultisampling (enabledCount == 0);
311}
312
315 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
317}
318
322}
323
324
327 int enabledCount = 0;
328
329 for ( int i = 0 ; i< PluginFunctions::viewers(); ++i ) {
331 enabledCount++;
332 }
333
334 slotGlobalChangeMipmapping (enabledCount == 0);
335}
336
339 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
341}
342
346}
347
350
351 QFileInfo fi(PluginFunctions::viewerProperties().snapshotName());
353
354 // Add leading zeros
355 QString number = QString::number(counter);
356 while ( number.size() < 7 )
357 number = "0" + number;
358
359 QString suggest = fi.baseName() + "." + number + ".";
360
361 QString format="png";
362
363 if (fi.completeSuffix() == "ppm")
364 format="ppmraw";
365
366 if (fi.completeSuffix() == "jpg")
367 format="jpg";
368
369 suggest += format;
370
371 QFileDialog dialog(this);
372 dialog.setFileMode(QFileDialog::AnyFile);
373 dialog.setDefaultSuffix("png");
374 dialog.setNameFilter(tr("Images (*.png *.ppm *.jpg)"));
375 dialog.setFileMode(QFileDialog::AnyFile);
376 dialog.setOption(QFileDialog::DontConfirmOverwrite, false);
377 dialog.setDirectory( fi.path() );
378 dialog.selectFile( suggest );
379 dialog.setAcceptMode(QFileDialog::AcceptSave);
380 dialog.setWindowTitle(tr("Save Snapshot"));
381
382 if (dialog.exec()){
383 QString newName = dialog.selectedFiles()[0];
384
385 if (newName != fi.path() + OpenFlipper::Options::dirSeparator() + suggest)
387
388 QImage image;
390
391 image.save(newName);
392 }
393}
394
395static QString suggestSnapshotFilename(QString mostRecentPath) {
396 if (mostRecentPath.isEmpty()) {
397 mostRecentPath = QString("%1%2snap.0000000.png")
398 .arg(OpenFlipperSettings().value("Core/CurrentDir").toString())
399 .arg(QDir::separator());
400 }
401
402 QFileInfo fi(mostRecentPath);
403 QString path = fi.path();
404
405 if (!fi.exists() && QFileInfo(path).isWritable()) {
406#ifndef NDEBUG
407 std::cout << "suggestSnapshotFilename(): mostRecentPath feasible as "
408 "file name. Using it." << std::endl;
409#endif
410 return mostRecentPath;
411 }
412
413 if (!QFileInfo(path).isWritable()) {
414#ifndef NDEBUG
415 std::cout << "suggestSnapshotFilename(): Most recent path invalid. "
416 "Doesn't exist. Returning empty string." << std::endl;
417#endif
418 return QString();
419 }
420
421 QString base_name = fi.completeBaseName();
422 QString suffix = fi.suffix();
423
424 if (suffix.isEmpty())
425 suffix = "png";
426
427 QRegularExpression base_name_re("(\\D*)(\\d+)?(.*)");
428 //base_name_re.setPatternSyntax(QRegExp::RegExp2);
429 QRegularExpressionMatch match = base_name_re.match(base_name);
430 if (match.capturedStart() < 0) {
431#ifndef NDEBUG
432 std::cout << "suggestSnapshotFilename(): Regexp didn't match. This "
433 "should be impossible." << std::endl;
434#endif
435 return QString();
436 }
437
438 QString pre = match.captured(1),
439 num = match.captured(2),
440 post = match.captured(3);
441
442#ifndef NDEBUG
443 std::cout << (QString("suggestSnapshotFilename(): Decomposition of "
444 "\"%1\": \"%2\", \"%3\", \"%4\"")
445 .arg(base_name)
446 .arg(pre)
447 .arg(num)
448 .arg(post)).toStdString() << std::endl;
449#endif
450
451 if (pre.isEmpty() && num.isEmpty() && post.isEmpty()) {
452 pre = "snap.";
453 }
454
455 size_t num_len = num.length();
456 bool num_is_int;
457 int file_no = num.toInt(&num_is_int);
458 if (!num_is_int) {
459 file_no = 0;
460 num_len = 6;
461 }
462
463 size_t sanity_counter = 0;
464 for (; sanity_counter < 100000; ++file_no, ++sanity_counter) {
465 QString suggested_file_name =
466 QString("%1%2%3%4%5.%6")
467 .arg(path)
468 .arg(QDir::separator())
469 .arg(pre)
470 .arg(file_no, num_len, 10, QLatin1Char('0'))
471 .arg(post)
472 .arg(suffix)
473 ;
474 QFileInfo suggested_fi(suggested_file_name);
475 if (!suggested_fi.exists()){
476#ifndef NDEBUG
477 std::cout << "suggestSnapshotFilename(): Found a feasible file "
478 "name. Returning it." << std::endl;
479#endif
480 return suggested_file_name;
481 }
482 }
483
484#ifndef NDEBUG
485 std::cout << "suggestSnapshotFilename(): No luck incrementing file_no. "
486 "Aborting, returning empty string." << std::endl;
487#endif
488 return QString();
489}
490
493 int w = width();
494 int h = height();
495
496 SnapshotDialog dialog(suggestSnapshotFilename(snapshotName_), false, w, h, 0);
497
498 connect(&dialog, SIGNAL(resizeApplication(int,int)), this, SIGNAL(resizeApplication(int,int)) );
499
500 bool ok = dialog.exec();
501
502 if ( ok ){
503 QString newName = dialog.filename->text();
504
505 OpenFlipperSettings().setValue("Core/CurrentDir", QFileInfo(newName).absolutePath() );
506
507 snapshotName_ = newName;
508 dialog.hide();
509
510 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
511 QScreen* screen = window()->screen();
512 QPixmap pic = screen->grabWindow( winId() );
513 #else
514 QPixmap pic = QPixmap::grabWindow( winId() );
515 #endif
516
517 QPainter painter (&pic);
518
519 //so we have to add the content from the GLContext manually
520 for (std::vector< glViewer* >::iterator iter = examiner_widgets_.begin(); iter != examiner_widgets_.end(); ++iter)
521 {
522 if (*iter)
523 {
524 QImage fillImage;
525
526 (*iter)->snapshot(fillImage, (*iter)->glWidth() , (*iter)->glHeight());
527
528 QPoint localPos = QPoint((*iter)->pos().x(),(*iter)->pos().y());
529 QPointF pos = glView_->mapTo(this,localPos);
530 painter.drawImage(pos,fillImage);
531 }
532 }
533
534 pic.save(newName);
535 }
536
537 emit resizeApplication(w,h);
538}
539
542
543 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
544 QScreen* screen = window()->screen();
545 QPixmap pix = screen->grabWindow( winId() );
546 #else
547 QPixmap pix = QPixmap::grabWindow( winId() );
548 #endif
549
550 // Write image asynchronously
551 QImage* pic = new QImage( pix.toImage() );
552 writeImageAsynchronously(pic, suggestSnapshotFilename(snapshotName_));
553}
554
555void CoreWidget::viewerSnapshot(QString file_name, bool store_comments,
556 bool comments_visible_only, bool comments_targeted_only,
557 bool store_material_info, int snapshot_width, int snapshot_height,
558 bool snapshot_transparent, bool hide_coord_sys,
559 int snapshot_multisampling, bool store_view) {
560
561 if (snapshot_height < 0) {
562 int w = glView_->width();
563 int h = glView_->height();
564 snapshot_height = static_cast<int>(round(
565 static_cast<double>(snapshot_width) / w * h));
566 }
567
568 QString comments;
569 if (store_comments) {
571 comments_visible_only,
572 comments_targeted_only).join("\n");
573 }
574
575 QString materials;
576 if (ACG::SceneGraph::Material::support_json_serialization() &&
577 //if (ACG::SceneGraph::Material::CP_JSON_SERIALIZABLE &&
578 store_material_info) {
580 comments_visible_only,
581 comments_targeted_only).join("\n");
582 }
583
584 //now take the snapshot
585 switch ( baseLayout_->mode() ){
586
587 case QtMultiViewLayout::SingleView:
588 {
589 QImage finalImage;
590
592 snapshot_width, snapshot_height,
593 snapshot_transparent, hide_coord_sys,
594 snapshot_multisampling);
595
596 if (!comments.isEmpty())
597 finalImage.setText("Mesh Comments", comments);
598 if (!materials.isEmpty())
599 finalImage.setText("Mesh Materials", materials);
600 if (store_view) {
601 QSize window_size;
602 if (isMaximized())
603 window_size = QSize(-width(), -height());
604 else
605 window_size = QSize (width(), height());
606
607 int splitter_size = 0;
608 if (OpenFlipperSettings().value("Core/Gui/ToolBoxes/ToolBoxOnTheRight",true).toBool())
609 splitter_size = toolSplitter_->sizes()[1];
610 else
611 splitter_size = toolSplitter_->sizes()[0];
612
613 QString view;
614 examiner_widgets_[PluginFunctions::activeExaminer()]->encodeView(view, window_size, splitter_size);
615 finalImage.setText("View", view);
616 }
617 finalImage.save(file_name);
618
619 break;
620 }
621 case QtMultiViewLayout::DoubleView:
622 {
623 int w = snapshot_height;
624
625 double relSizeW = static_cast<double>( examiner_widgets_[0]->glWidth() / static_cast<double>( glScene_->width() ) );
626
627 //Get the images
628 QImage img[2];
629 examiner_widgets_[0]->snapshot(
630 img[0], static_cast<int>(relSizeW * w),
631 snapshot_width, snapshot_transparent,
632 hide_coord_sys);
633 examiner_widgets_[1]->snapshot(
634 img[1], static_cast<int>(relSizeW * w),
635 snapshot_width, snapshot_transparent,
636 hide_coord_sys);
637
638 QImage finalImage(img[0].width() + img[1].width() +2, img[0].height(),
639 QImage::Format_ARGB32_Premultiplied);
640
641 QPainter painter(&finalImage);
642
643 painter.fillRect(0,0,finalImage.width(),
644 finalImage.height(), QBrush(Qt::gray));
645
646 painter.drawImage(QRectF( 0, 0, img[0].width(), img[0].height()),img[0],
647 QRectF( 0, 0, img[0].width(), img[0].height()) );
648 painter.drawImage(QRectF(img[0].width()+2, 0, img[1].width(), img[1].height()),img[1],
649 QRectF( 0, 0, img[1].width(), img[1].height()) );
650
651 if (!comments.isEmpty())
652 finalImage.setText("Mesh Comments", comments);
653 finalImage.save(file_name);
654
655 break;
656 }
657
658 case QtMultiViewLayout::Grid:
659 {
660 // Relative size of first viewer (in relation to the other viewers
661 double relSizeW = (double)examiner_widgets_[0]->glWidth() / (double)glScene_->width();
662 double relSizeH = (double)examiner_widgets_[0]->glHeight() / (double)glScene_->height();
663
664 QImage img0,img1,img2,img3;
665
666 examiner_widgets_[0]->snapshot(img0,
667 (int)((double)snapshot_width * relSizeW),
668 (int)((double)snapshot_height * relSizeH),
669 snapshot_transparent, hide_coord_sys);
670 examiner_widgets_[1]->snapshot(img1,
671 (int)((double)snapshot_width * (1.0 - relSizeW)),
672 (int)((double)snapshot_height * relSizeH),
673 snapshot_transparent, hide_coord_sys);
674 examiner_widgets_[2]->snapshot(img2,
675 (int)((double)snapshot_width * relSizeW),
676 (int)((double)snapshot_height * (1.0 - relSizeH)),
677 snapshot_transparent, hide_coord_sys);
678 examiner_widgets_[3]->snapshot(img3,
679 (int)((double)snapshot_width * (1.0 - relSizeW)),
680 (int)((double)snapshot_height * (1.0 - relSizeH)),
681 snapshot_transparent, hide_coord_sys);
682
683 QImage finalImage(img0.width() + img1.width()+2,
684 img0.height() + img2.height()+2,
685 QImage::Format_ARGB32_Premultiplied);
686
687 QPainter painter(&finalImage);
688
689 painter.fillRect(0,0,finalImage.width(), finalImage.height(), QBrush(Qt::gray));
690
691 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
692 QRectF( 0, 0, img0.width(), img0.height()) );
693 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
694 QRectF( 0, 0, img1.width(), img1.height()) );
695 painter.drawImage(QRectF( 0,img0.height()+2, img2.width(), img2.height()),img2,
696 QRectF( 0, 0, img2.width(), img2.height()) );
697 painter.drawImage(QRectF(img0.width()+2, img0.height()+2, img3.width(), img3.height()),img3,
698 QRectF( 0, 0, img3.width(), img3.height()) );
699
700 if (!comments.isEmpty())
701 finalImage.setText("Mesh Comments", comments);
702 finalImage.save(file_name);
703
704 break;
705 }
706 case QtMultiViewLayout::HSplit:
707 {
708 // Relative size of first viewer (in relation to the other viewers
709 double relSizeW = (double)examiner_widgets_[0]->glWidth() / (double)glScene_->width();
710 double relSizeH1 = (double)examiner_widgets_[1]->glHeight() / (double)glScene_->height();
711 double relSizeH2 = (double)examiner_widgets_[2]->glHeight() / (double)glScene_->height();
712 double relSizeH3 = (double)examiner_widgets_[3]->glHeight() / (double)glScene_->height();
713
714 QImage img0,img1,img2,img3;
715
716 examiner_widgets_[0]->snapshot(img0,
717 (int)((double)snapshot_width * relSizeW), snapshot_height,
718 snapshot_transparent, hide_coord_sys);
719 examiner_widgets_[1]->snapshot(img1,
720 (int)((double)snapshot_width * (1.0 - relSizeW)),
721 relSizeH1 * (double)snapshot_height,
722 snapshot_transparent, hide_coord_sys);
723 examiner_widgets_[2]->snapshot(img2,
724 (int)((double)snapshot_width * (1.0 - relSizeW)),
725 relSizeH2 * (double)snapshot_height,
726 snapshot_transparent, hide_coord_sys);
727 examiner_widgets_[3]->snapshot(img3,
728 (int)((double)snapshot_width * (1.0 - relSizeW)),
729 relSizeH3 * (double)snapshot_height,
730 snapshot_transparent, hide_coord_sys);
731
732 QImage finalImage(img0.width() + img1.width() +2, img0.height(), QImage::Format_ARGB32_Premultiplied);
733
734 QPainter painter(&finalImage);
735
736 painter.fillRect(0,0,finalImage.width(), finalImage.height(), QBrush(Qt::gray));
737
738 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
739 QRectF( 0, 0, img0.width(), img0.height()) );
740 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
741 QRectF( 0, 0, img1.width(), img1.height()) );
742 painter.drawImage(QRectF(img0.width()+2, img1.height()+2, img2.width(), img2.height()),img2,
743 QRectF( 0, 0, img2.width(), img2.height()) );
744 painter.drawImage(QRectF(img0.width()+2, img1.height()+img2.height()+4, img3.width(),img3.height()),img3,
745 QRectF( 0, 0, img3.width(), img3.height()) );
746
747 if (!comments.isEmpty())
748 finalImage.setText("Mesh Comments", comments);
749 finalImage.save(file_name);
750
751 break;
752 }
753 default: break;
754
755 }
756}
757
760 int w = glView_->width();
761 int h = glView_->height();
762
763 SnapshotDialog dialog(suggestSnapshotFilename(snapshotName_), true, w, h, 0);
764
765 if (!ACG::SceneGraph::Material::support_json_serialization())
766 dialog.metaData_storeMatInfo_cb->setVisible(false);
767
768 bool ok = dialog.exec();
769
770 if (ok){
771 QString newName = dialog.filename->text();
772
773 OpenFlipperSettings().setValue("Core/CurrentDir", QFileInfo(newName).absolutePath() );
774
775 snapshotName_ = newName;
776
777 const bool storeComments = dialog.metaData_storeComments_cb->isChecked();
778 const bool comments_visible_only =
779 dialog.metaData_comments_visibleOnly_cb->isChecked();
780 const bool comments_targeted_only =
781 dialog.metaData_comments_targetedOnly_cb->isChecked();
782 const bool store_material_info =
783 dialog.metaData_storeMatInfo_cb->isChecked();
784 const int snapshot_width = dialog.snapWidth->value();
785 const int snapshot_height = dialog.snapHeight->value();
786 const bool snapshot_transparent = dialog.transparent->isChecked();
787 const bool hide_coord_sys = dialog.hideCoordsys->isChecked();
788 const int snapshot_multisampling =
789 dialog.multisampling->isChecked() ?
790 dialog.num_samples->value() : 1;
791 const bool store_view = dialog.metaData_storeView_cb->isChecked();
792
793 viewerSnapshot(newName, storeComments, comments_visible_only,
794 comments_targeted_only, store_material_info, snapshot_width,
795 snapshot_height, snapshot_transparent, hide_coord_sys,
796 snapshot_multisampling, store_view);
797 }
798 //glView_->resize(w, h);
799}
800
803
804 switch ( baseLayout_->mode() ){
805
806 case QtMultiViewLayout::SingleView:
807 {
808 QImage* finalImage = new QImage();
809
810 examiner_widgets_[PluginFunctions::activeExaminer()]->snapshot(*finalImage);
811
812 writeImageAsynchronously(finalImage, suggestSnapshotFilename(snapshotName_));
813
814 break;
815 }
816 case QtMultiViewLayout::DoubleView:
817 {
818 //Get the images
819 QImage img[2];
820 examiner_widgets_[0]->snapshot(img[0]);
821 examiner_widgets_[1]->snapshot(img[1]);
822
823 QImage* finalImage = new QImage(img[0].width() + img[1].width() +2, img[0].height(), QImage::Format_ARGB32_Premultiplied);
824
825 QPainter painter(finalImage);
826
827 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
828
829 painter.drawImage(QRectF( 0, 0, img[0].width(), img[0].height()),img[0],
830 QRectF( 0, 0, img[0].width(), img[0].height()) );
831 painter.drawImage(QRectF(img[0].width()+2, 0, img[1].width(), img[1].height()),img[1],
832 QRectF( 0, 0, img[1].width(), img[1].height()) );
833
834 writeImageAsynchronously(finalImage, suggestSnapshotFilename(snapshotName_));
835
836 break;
837 }
838
839 case QtMultiViewLayout::Grid:
840 {
841 QImage img0,img1,img2,img3;
842
843 examiner_widgets_[0]->snapshot(img0);
844 examiner_widgets_[1]->snapshot(img1);
845 examiner_widgets_[2]->snapshot(img2);
846 examiner_widgets_[3]->snapshot(img3);
847
848 QImage* finalImage = new QImage(img0.width() + img1.width() + 2, img0.height() + img2.height() + 2, QImage::Format_ARGB32_Premultiplied);
849
850 QPainter painter(finalImage);
851
852 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
853
854 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
855 QRectF( 0, 0, img0.width(), img0.height()) );
856 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
857 QRectF( 0, 0, img1.width(), img1.height()) );
858 painter.drawImage(QRectF( 0, img0.height()+2, img2.width(), img2.height()),img2,
859 QRectF( 0, 0, img2.width(), img2.height()) );
860 painter.drawImage(QRectF(img0.width()+2, img0.height()+2, img3.width(), img3.height()),img3,
861 QRectF( 0, 0, img3.width(), img3.height()) );
862
863 writeImageAsynchronously(finalImage, suggestSnapshotFilename(snapshotName_));
864
865 break;
866 }
867 case QtMultiViewLayout::HSplit:
868 {
869 QImage img0,img1,img2,img3;
870
871 examiner_widgets_[0]->snapshot(img0);
872 examiner_widgets_[1]->snapshot(img1);
873 examiner_widgets_[2]->snapshot(img2);
874 examiner_widgets_[3]->snapshot(img3);
875
876 QImage* finalImage = new QImage(img0.width() + img1.width() + 2, img0.height(), QImage::Format_ARGB32_Premultiplied);
877
878 QPainter painter(finalImage);
879
880 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
881
882 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
883 QRectF( 0, 0, img0.width(), img0.height()) );
884 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
885 QRectF( 0, 0, img1.width(), img1.height()) );
886 painter.drawImage(QRectF(img0.width()+2, img1.height()+2, img2.width(), img2.height()),img2,
887 QRectF( 0, 0, img2.width(), img2.height()) );
888 painter.drawImage(QRectF(img0.width()+2, img1.height()+img2.height()+4, img3.width(),img3.height()),img3,
889 QRectF( 0, 0, img3.width(), img3.height()) );
890
891 writeImageAsynchronously(finalImage, suggestSnapshotFilename(snapshotName_));
892
893 break;
894 }
895 default: break;
896
897 }
898}
899
900void CoreWidget::applicationSnapshotName(const QString& _name) {
901 snapshotName_ = _name;
902}
903
904
905void writeImageQImage(QImage* _image, const QString& _name) {
906
907 _image->save(_name);
908 delete _image;
909}
910
911void CoreWidget::writeImageAsynchronously(QImage* _image, const QString& _name) {
912
913 QFuture<void>* future = new QFuture<void>();
914 *future = QtConcurrent::run(writeImageQImage, _image, _name);
915 QFutureWatcher<void>* watcher = new QFutureWatcher<void>();
916 watcher->setFuture(*future);
917
918 watcher_garbage_.insert(std::pair<QFutureWatcher<void>*,QFuture<void>*>(watcher, future));
919
920 connect(watcher, SIGNAL(finished()), this, SLOT(delete_garbage()));
921}
922
923
924
925void CoreWidget::delete_garbage() {
926
927 QObject* obj = QObject::sender();
928 QFutureWatcher<void>* watcher = dynamic_cast<QFutureWatcher<void>*>(obj);
929 if(!watcher) {
930 return;
931 }
932
933 map_mutex_.lock();
934
935 std::map<QFutureWatcher<void>*,QFuture<void>*>::iterator f;
936 f = watcher_garbage_.find(watcher);
937 if(f != watcher_garbage_.end()) {
938 delete f->second;
939 delete f->first;
940 watcher_garbage_.erase(f);
941 }
942
943 map_mutex_.unlock();
944}
945
948}
949
950void CoreWidget::slotSetView( QString view ) {
952}
953
955 const unsigned int viewerId = PluginFunctions::activeExaminer();
956
957 QSize windowSize(0, 0);
958 int splitterWidth = 0;
959 QSize viewportSize(0, 0);
960 examiner_widgets_[viewerId]->decodeView (
961 view, &windowSize, &splitterWidth, &viewportSize);
962
963 if (windowSize.height() != 0 && windowSize.width() != 0) {
964 if (windowSize.width() < 0) {
965 windowSize *= -1;
966 showNormal();
967 resize(windowSize);
968 showMaximized();
969 } else {
970 showNormal();
971 resize(windowSize);
972 }
973 }
974
975 if (splitterWidth > 0) {
976 QList<int> splitter_sizes = toolSplitter_->sizes();
977 if (splitter_sizes.size() < 2) {
978 std::cerr << "The tool splitter has less than two children. This "
979 "shouldn't happen." << std::endl;
980 } else {
981 const size_t primary_idx = OpenFlipperSettings().value(
982 "Core/Gui/ToolBoxes/ToolBoxOnTheRight",true).toBool()
983 ? 1 : 0;
984
985 const int diff = splitterWidth - splitter_sizes[primary_idx];
986 splitter_sizes[primary_idx] += diff;
987 splitter_sizes[1-primary_idx] -= diff;
988 }
989 toolSplitter_->setSizes(splitter_sizes);
990 }
991
992 /*
993 * Viewport size has precedence. Manipulate window size so that the
994 * viewport size is matched exactly.
995 */
996 if (viewportSize.width() > 0 && viewportSize.height() > 0) {
997 /*
998 * Try twice: Sometimes sizes of elements get readjusted after resizing
999 * and the viewport will not have the desired size.
1000 */
1001 for (int i = 0; i < 2; ++i) {
1002 const QSize cur_viewport_size = examiner_widgets_[viewerId]->size().toSize();
1003 if (cur_viewport_size != viewportSize) {
1004 std::cout << "Stored viewport size is " << viewportSize.width()
1005 << " x " << viewportSize.height() << ". Actual size is "
1006 << cur_viewport_size.width() << " x "
1007 << cur_viewport_size.height() << ". Resizing window."
1008 << std::endl;
1009
1010 showNormal();
1011 QSize diff = viewportSize - cur_viewport_size;
1012 resize(size() + diff);
1013 const QSize new_viewport_size =
1014 examiner_widgets_[viewerId]->size().toSize();
1015 diff = viewportSize - new_viewport_size;
1016 if (diff.width() != 0) {
1017 std::cout << "New viewport size is "
1018 << new_viewport_size.width()
1019 << " x " << new_viewport_size.height() << "."
1020 << " Moving splitter by " << diff.width() << "."
1021 << std::endl;
1022 // Move splitter.
1023 QList<int> splitter_sizes = toolSplitter_->sizes();
1024 if (splitter_sizes.size() < 2) {
1025 std::cerr << "The tool splitter has less than two children. This "
1026 "shouldn't happen." << std::endl;
1027 } else {
1028 const size_t primary_idx = OpenFlipperSettings().value(
1029 "Core/Gui/ToolBoxes/ToolBoxOnTheRight",true).toBool()
1030 ? 0 : 1;
1031
1032 splitter_sizes[primary_idx] += diff.width();
1033 splitter_sizes[1-primary_idx] -= diff.width();
1034 }
1035 toolSplitter_->setSizes(splitter_sizes);
1036
1037 }
1038 } else {
1039 break;
1040 }
1041 }
1042 }
1043}
1044
1046{
1047 QSize size;
1048 int splitterWidth;
1049 examiner_widgets_[PluginFunctions::activeExaminer()]->actionPasteView(&size,&splitterWidth);
1050
1051 //resize the toolbox and splitter
1052 if (splitterWidth != -1)
1053 {
1054 QList<int> sizes;
1055
1056 //std::cerr << "Sizes : " << size[0] << " " << size[1] << " " << sum_size << std::endl;
1057
1058 bool onRight = OpenFlipperSettings().value("Core/Gui/ToolBoxes/ToolBoxOnTheRight",true).toBool();
1059 if (onRight)
1060 {
1061 sizes.push_back(size.width() - splitterWidth);
1062 sizes.push_back(splitterWidth);
1063 }
1064 else
1065 {
1066 sizes.push_back(splitterWidth);
1067 sizes.push_back(size.width() - splitterWidth);
1068 }
1069
1070 toolSplitter_->setSizes(sizes);
1071 }
1072
1073 //resize window
1074 if (size.isValid())
1075 {
1076 if (size == QSize(0,0))
1077 {
1078 showMaximized();
1079 }
1080 else
1081 {
1082 showNormal();
1083 resizeApplication(size.width(),size.height());
1084 }
1085 }
1086}
1087
1089 QSize size;
1090 if (isMaximized())
1091 size = QSize(0,0);
1092 else
1093 size = QSize (width(),height());
1094
1095 int splitter_size = 0;
1096 if (OpenFlipperSettings().value("Core/Gui/ToolBoxes/ToolBoxOnTheRight",true).toBool())
1097 splitter_size = toolSplitter_->sizes()[1];
1098 else
1099 splitter_size = toolSplitter_->sizes()[0];
1100
1101 const bool make_c_string = (QApplication::keyboardModifiers() & Qt::ControlModifier);
1103 size, splitter_size, make_c_string);
1104}
1105
1107
1109 ACG::SceneGraph::BaseNode* coordSys = root->find("Core Coordsys Node");
1110
1111 if (coordSys == 0){
1112 emit log( LOGERR, tr("CoordSys Node not found"));
1113 return;
1114 }
1115
1116if (_visible)
1117 coordSys->show();
1118 else
1119 coordSys->hide();
1120
1121 for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
1122 examiner_widgets_[i]->updateGL();
1123
1124}
1125
1127
1128 PluginFunctions::setFixedView( _action->data().toInt() );
1129 if (_action->data().toInt() != PluginFunctions::VIEW_FREE)
1131
1132 // Update view
1134}
1135
1137
1139 if (!_lock)
1140 PluginFunctions::setFixedView( PluginFunctions::VIEW_FREE );
1141}
1142
1145}
1146
1149}
1150
1153}
1154
1157}
1158
1159//=============================================================================
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
@ LOGERR
void hide()
Hide Node: set status to HideNode.
Definition: BaseNode.hh:405
void show()
Show node: set status to Active.
Definition: BaseNode.hh:407
ChildIter find(BaseNode *_node)
Definition: BaseNode.hh:346
@ ORTHOGRAPHIC_PROJECTION
orthographic
Definition: CoordsysNode.hh:89
void setProjectionMode(const ProjectionMode _mode)
set mode to either ORTHOGRAPHIC_PROJECTION or PERSPECTIVE_PROJECTION
ProjectionMode getProjectionMode() const
get current projection mode
void slotContextHomeView()
Set the active viewer to home position.
void slotSetContextBackgroundColor()
Set Background Color for one viewer.
void slotLocalChangeBackFaceCulling(bool _backFaceCulling)
Set backface culling for active viewer.
void strafeRight()
When using first person mode strafe to the right.
void slotCopyView()
Copy view from the last active examiner.
void slotGlobalChangeAnimation(bool _animation)
Set the animation mode for all viewers.
void slotPasteView()
Paste the view to the last active examiner.
QToolButton * stereoButton_
Called by Plugins to add a Toolbar.
Definition: CoreWidget.hh:832
void slotGlobalToggleBackFaceCulling()
If backface culling is disabled in all viewers, enable it in all viewers. Otherwise disable it.
void slotGlobalToggleMultisampling()
If multisampling is disabled in all viewers, enable it in all viewers. Otherwise disable it.
std::vector< glViewer * > examiner_widgets_
Examiner Widget.
Definition: CoreWidget.hh:684
void slotGlobalChangeBackFaceCulling(bool _backFaceCulling)
Set backface culling for all viewers.
void slotLocalChangeMultisampling(bool _multisampling)
Set multisampling for active viewer.
QtGLGraphicsScene * glScene_
graphics scene used to paint gl context and widgets
Definition: CoreWidget.hh:717
void slotSetViewingDirection(QAction *_action)
Change the viewing direction from context-menu.
void slotPasteViewAndWindow()
Paste the view, the window and toolbox size to the last active examiner.
CursorPainter * cursorPainter_
Cursor handling.
Definition: CoreWidget.hh:757
void applicationSnapshotName(const QString &_name)
Set the snapshot name.
void slotGlobalToggleTwoSidedLighting()
If two-sided lighting is disabled in all viewers, enable it in all viewers. Otherwise disable it.
void slotGlobalPerspectiveProjection()
Toggle projection mode of all viewers to perspective projection.
void slotSwitchNavigation(bool _egomode)
Switch navigation mode.
void slotContextViewAll()
Change view on active viewer to view complete scene.
void slotGlobalChangeTwoSidedLighting(bool _lighting)
Set two-sided lighting for all viewers.
bool stereoActive_
The viewer with id _viewerId changed its draw Mode.
Definition: CoreWidget.hh:1450
void slotGlobalToggleAnimation()
If animation is disabled in all viewers, enable it in all viewers. Otherwise disable it.
void viewerSnapshotDialog()
Create a snapshot of the whole app with fileDialog.
void slotCoordSysVisibility(bool _visible)
Hide coordinate systems in all viewers.
void slotGlobalToggleMipmapping()
If mipmapping is disabled in all viewers, enable it in all viewers. Otherwise disable it.
void applicationSnapshotDialog()
Create a snapshot of the whole app with fileDialog.
void slotSetGlobalBackgroundColor()
Set Background Color for all viewers at once.
void slotGlobalChangeMultisampling(bool _multisampling)
Set multisampling for all viewers.
QtMultiViewLayout * baseLayout_
Base layout that holds gl views.
Definition: CoreWidget.hh:726
void slotContextSetHomeView()
Set the active viewers home position.
void slotToggleStereoMode()
Enable or disable Stereo.
void slotSetView(QString view)
Set the supplied serialized view.
void slotContextSwitchCoordsysProjection()
Toggle coordsys projection mode of the active viewer.
void slotLocalChangeMipmapping(bool _mipmapping)
Set mipmapping for active viewer.
void strafeLeft()
When using first person mode strafe to the left.
void moveBack()
When using first person mode move backward.
void viewerSnapshot()
Create a snapshot of the whole app.
void slotSwitchWheels(bool _state)
Show / hide wheels.
void slotGlobalViewAll()
Change view on all viewers to view complete scene.
void slotSetViewAndWindowGeometry(QString view)
Set the supplied serialized view.
void slotLocalChangeTwoSidedLighting(bool _lighting)
Set two-sided lighting for active viewer.
QtGLGraphicsView * glView_
graphics view that holds the gl scene
Definition: CoreWidget.hh:720
void slotLocalChangeAnimation(bool _animation)
Set the animation mode for active viewer.
void applicationSnapshot()
Create a snapshot of the whole app.
void slotGlobalChangeMipmapping(bool _multisampling)
Set mipmapping for all viewers.
void slotContextSwitchProjection()
Toggle projection mode of the active viewer.
QString snapshotName_
Create a snapshot of the whole app with fileDialog.
Definition: CoreWidget.hh:1028
void slotGlobalHomeView()
Set the viewer to home position.
void slotGlobalSetHomeView()
Set the home position for all viewers.
void slotLockRotation(bool _lock)
Lock rotation in current examiner widget.
void slotGlobalOrthographicProjection()
Toggle projection mode of all viewers to orthographic projection.
void slotExaminerSnapshot()
Create a snapshot of the last active examiner.
void moveForward()
When using first person mode move forward.
QSplitter * toolSplitter_
Spliter between toplevel objects and toolbox.
Definition: CoreWidget.hh:738
ACG::SceneGraph::CoordsysNode::ProjectionMode getCoordsysProjection()
Toggle coordsys projection mode of the active viewer.
void setEnabled(bool _enabled)
Enabled/Disables gl cursor painting.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
MultiViewMode mode() const
Retruns current layout modes.
void animation(bool _state)
set 2-sided lighting on/off
ACG::Vec4f backgroundColor()
Get current background color.
void twoSidedLighting(bool _state)
set 2-sided lighting on/off
void mipmapping(bool _state)
set mipmapping on/off
void snapshotCounter(const int _counter)
bool backFaceCulling()
Get current state of backface culling.
void multisampling(bool _state)
set multisampling on/off
void snapshotBaseFileName(const QString &_fname)
@ NORMAL_NAVIGATION
Normal mode.
@ FIRSTPERSON_NAVIGATION
First person mode.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
QStringList collectObjectMaterials(bool visibleOnly, bool targetedOnly)
QStringList collectObjectComments(bool visibleOnly, bool targetedOnly)
int viewers()
Get the number of viewers.
void setFixedView(int _mode, int _viewer)
Set a fixed View for a viewer.
void allowRotation(bool _mode, int _viewer)
unsigned int activeExaminer()
Get the id of the examiner which got the last mouse events.
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node