58 #include <QtConcurrent> 61 #include <OpenFlipper/widgets/snapshotDialog/SnapshotDialog.hh> 65 #include <ACG/Utils/VSToolsT.hh> 68 #include <ACG/Scenegraph/MaterialNode.hh> 79 statusBar_->showMessage(tr(
"Stereo enabled"));
80 stereoButton_->setIcon( QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"stereo.png") );
82 statusBar_->showMessage(tr(
"Stereo disabled"));
83 stereoButton_->setIcon( QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"mono.png") );
88 for (
unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
95 QColor backCol((
int)bc[0], (
int)bc[1], (
int)bc[2], (
int)bc[3]);
96 QColor c = QColorDialog::getColor(backCol,
this);
98 if (c != backCol && c.isValid())
99 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets(); ++i )
101 ((
double) c.greenF()) ,
102 ((
double) c.blueF()) ,
112 QColor backCol((
int)bc[0], (
int)bc[1], (
int)bc[2], (
int)bc[3]);
113 QColor c = QColorDialog::getColor(backCol,
this);
115 if (c != backCol && c.isValid())
117 ((
double) c.greenF()) ,
118 ((
double) c.blueF()) ,
133 _state ? (*it)->slotShowWheels() : (*it)->slotHideWheels();
189 emit statusMessage(QString(tr(
"getCoordsysProjection(): Could not find coordsys node. Assuming default orthographic projection.")));
208 emit statusMessage(QString(tr(
"slotContextSwitchCoordsysProjection(): Could not find coordsys node, thus its projection mode will not be toggled.")));
211 for (
unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
230 int enabledCount = 0;
242 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
254 int enabledCount = 0;
266 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
279 int enabledCount = 0;
291 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
303 int enabledCount = 0;
315 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
327 int enabledCount = 0;
339 for ( uint i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
355 QString number = QString::number(counter);
356 while ( number.size() < 7 )
357 number =
"0" + number;
359 QString suggest = fi.baseName() +
"." + number +
".";
361 QString format=
"png";
363 if (fi.completeSuffix() ==
"ppm")
366 if (fi.completeSuffix() ==
"jpg")
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"));
383 QString newName = dialog.selectedFiles()[0];
385 if (newName != fi.path() + OpenFlipper::Options::dirSeparator() + suggest)
395 static QString suggestSnapshotFilename(QString mostRecentPath) {
396 if (mostRecentPath.isEmpty()) {
397 mostRecentPath = QString(
"%1%2snap.0000000.png")
399 .arg(QDir::separator());
402 QFileInfo fi(mostRecentPath);
403 QString path = fi.path();
405 if (!fi.exists() && QFileInfo(path).isWritable()) {
407 std::cout <<
"suggestSnapshotFilename(): mostRecentPath feasible as " 408 "file name. Using it." << std::endl;
410 return mostRecentPath;
413 if (!QFileInfo(path).isWritable()) {
415 std::cout <<
"suggestSnapshotFilename(): Most recent path invalid. " 416 "Doesn't exist. Returning empty string." << std::endl;
421 QString base_name = fi.completeBaseName();
422 QString suffix = fi.suffix();
424 if (suffix.isEmpty())
427 QRegExp base_name_re(
"(\\D*)(\\d+)?(.*)");
428 base_name_re.setPatternSyntax(QRegExp::RegExp2);
429 if (!base_name_re.exactMatch(base_name)) {
431 std::cout <<
"suggestSnapshotFilename(): Regexp didn't match. This " 432 "should be impossible." << std::endl;
437 QString pre = base_name_re.cap(1),
438 num = base_name_re.cap(2),
439 post = base_name_re.cap(3);
442 std::cout << (QString(
"suggestSnapshotFilename(): Decomposition of " 443 "\"%1\": \"%2\", \"%3\", \"%4\"")
447 .arg(post)).toStdString() << std::endl;
450 if (pre.isEmpty() && num.isEmpty() && post.isEmpty()) {
454 size_t num_len = num.length();
456 int file_no = num.toInt(&num_is_int);
462 size_t sanity_counter = 0;
463 for (; sanity_counter < 100000; ++file_no, ++sanity_counter) {
464 QString suggested_file_name =
465 QString(
"%1%2%3%4%5.%6")
467 .arg(QDir::separator())
469 .arg(file_no, num_len, 10, QLatin1Char(
'0'))
473 QFileInfo suggested_fi(suggested_file_name);
474 if (!suggested_fi.exists()){
476 std::cout <<
"suggestSnapshotFilename(): Found a feasible file " 477 "name. Returning it." << std::endl;
479 return suggested_file_name;
484 std::cout <<
"suggestSnapshotFilename(): No luck incrementing file_no. " 485 "Aborting, returning empty string." << std::endl;
497 connect(&dialog, SIGNAL(resizeApplication(
int,
int)),
this, SIGNAL(resizeApplication(
int,
int)) );
499 bool ok = dialog.exec();
502 QString newName = dialog.filename->text();
509 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) 510 QScreen* screen = window()->screen();
511 QPixmap pic = screen->grabWindow( winId() );
513 QPixmap pic = QPixmap::grabWindow( winId() );
516 QPainter painter (&pic);
525 (*iter)->snapshot(fillImage, (*iter)->glWidth() , (*iter)->glHeight());
527 QPoint localPos = QPoint((*iter)->pos().x(),(*iter)->pos().y());
528 QPointF pos =
glView_->mapTo(
this,localPos);
529 painter.drawImage(pos,fillImage);
536 emit resizeApplication(w,h);
542 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) 543 QScreen* screen = window()->screen();
544 QPixmap pix = screen->grabWindow( winId() );
546 QPixmap pix = QPixmap::grabWindow( winId() );
550 QImage* pic =
new QImage( pix.toImage() );
551 writeImageAsynchronously(pic, suggestSnapshotFilename(
snapshotName_));
555 bool comments_visible_only,
bool comments_targeted_only,
556 bool store_material_info,
int snapshot_width,
int snapshot_height,
557 bool snapshot_transparent,
bool hide_coord_sys,
558 int snapshot_multisampling,
bool store_view) {
560 if (snapshot_height < 0) {
563 snapshot_height =
static_cast<int>(round(
564 static_cast<double>(snapshot_width) / w * h));
568 if (store_comments) {
570 comments_visible_only,
571 comments_targeted_only).join(
"\n");
575 if (ACG::SceneGraph::Material::support_json_serialization() &&
577 store_material_info) {
579 comments_visible_only,
580 comments_targeted_only).join(
"\n");
586 case QtMultiViewLayout::SingleView:
591 snapshot_width, snapshot_height,
592 snapshot_transparent, hide_coord_sys,
593 snapshot_multisampling);
595 if (!comments.isEmpty())
596 finalImage.setText(
"Mesh Comments", comments);
597 if (!materials.isEmpty())
598 finalImage.setText(
"Mesh Materials", materials);
602 window_size = QSize(-width(), -height());
604 window_size = QSize (width(), height());
606 int splitter_size = 0;
614 finalImage.setText(
"View", view);
616 finalImage.save(file_name);
620 case QtMultiViewLayout::DoubleView:
622 int w = snapshot_height;
629 img[0], static_cast<int>(relSizeW * w),
630 snapshot_width, snapshot_transparent,
633 img[1], static_cast<int>(relSizeW * w),
634 snapshot_width, snapshot_transparent,
637 QImage finalImage(img[0].width() + img[1].width() +2, img[0].height(),
638 QImage::Format_ARGB32_Premultiplied);
640 QPainter painter(&finalImage);
642 painter.fillRect(0,0,finalImage.width(),
643 finalImage.height(), QBrush(Qt::gray));
645 painter.drawImage(QRectF( 0, 0, img[0].width(), img[0].height()),img[0],
646 QRectF( 0, 0, img[0].width(), img[0].height()) );
647 painter.drawImage(QRectF(img[0].width()+2, 0, img[1].width(), img[1].height()),img[1],
648 QRectF( 0, 0, img[1].width(), img[1].height()) );
650 if (!comments.isEmpty())
651 finalImage.setText(
"Mesh Comments", comments);
652 finalImage.save(file_name);
657 case QtMultiViewLayout::Grid:
663 QImage img0,img1,img2,img3;
666 (
int)((
double)snapshot_width * relSizeW),
667 (
int)((
double)snapshot_height * relSizeH),
668 snapshot_transparent, hide_coord_sys);
670 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
671 (
int)((
double)snapshot_height * relSizeH),
672 snapshot_transparent, hide_coord_sys);
674 (
int)((
double)snapshot_width * relSizeW),
675 (
int)((
double)snapshot_height * (1.0 - relSizeH)),
676 snapshot_transparent, hide_coord_sys);
678 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
679 (
int)((
double)snapshot_height * (1.0 - relSizeH)),
680 snapshot_transparent, hide_coord_sys);
682 QImage finalImage(img0.width() + img1.width()+2,
683 img0.height() + img2.height()+2,
684 QImage::Format_ARGB32_Premultiplied);
686 QPainter painter(&finalImage);
688 painter.fillRect(0,0,finalImage.width(), finalImage.height(), QBrush(Qt::gray));
690 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
691 QRectF( 0, 0, img0.width(), img0.height()) );
692 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
693 QRectF( 0, 0, img1.width(), img1.height()) );
694 painter.drawImage(QRectF( 0,img0.height()+2, img2.width(), img2.height()),img2,
695 QRectF( 0, 0, img2.width(), img2.height()) );
696 painter.drawImage(QRectF(img0.width()+2, img0.height()+2, img3.width(), img3.height()),img3,
697 QRectF( 0, 0, img3.width(), img3.height()) );
699 if (!comments.isEmpty())
700 finalImage.setText(
"Mesh Comments", comments);
701 finalImage.save(file_name);
705 case QtMultiViewLayout::HSplit:
713 QImage img0,img1,img2,img3;
716 (
int)((
double)snapshot_width * relSizeW), snapshot_height,
717 snapshot_transparent, hide_coord_sys);
719 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
720 relSizeH1 * (
double)snapshot_height,
721 snapshot_transparent, hide_coord_sys);
723 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
724 relSizeH2 * (
double)snapshot_height,
725 snapshot_transparent, hide_coord_sys);
727 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
728 relSizeH3 * (
double)snapshot_height,
729 snapshot_transparent, hide_coord_sys);
731 QImage finalImage(img0.width() + img1.width() +2, img0.height(), QImage::Format_ARGB32_Premultiplied);
733 QPainter painter(&finalImage);
735 painter.fillRect(0,0,finalImage.width(), finalImage.height(), QBrush(Qt::gray));
737 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
738 QRectF( 0, 0, img0.width(), img0.height()) );
739 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
740 QRectF( 0, 0, img1.width(), img1.height()) );
741 painter.drawImage(QRectF(img0.width()+2, img1.height()+2, img2.width(), img2.height()),img2,
742 QRectF( 0, 0, img2.width(), img2.height()) );
743 painter.drawImage(QRectF(img0.width()+2, img1.height()+img2.height()+4, img3.width(),img3.height()),img3,
744 QRectF( 0, 0, img3.width(), img3.height()) );
746 if (!comments.isEmpty())
747 finalImage.setText(
"Mesh Comments", comments);
748 finalImage.save(file_name);
764 if (!ACG::SceneGraph::Material::support_json_serialization())
765 dialog.metaData_storeMatInfo_cb->setVisible(
false);
767 bool ok = dialog.exec();
770 QString newName = dialog.filename->text();
776 const bool storeComments = dialog.metaData_storeComments_cb->isChecked();
777 const bool comments_visible_only =
778 dialog.metaData_comments_visibleOnly_cb->isChecked();
779 const bool comments_targeted_only =
780 dialog.metaData_comments_targetedOnly_cb->isChecked();
781 const bool store_material_info =
782 dialog.metaData_storeMatInfo_cb->isChecked();
783 const int snapshot_width = dialog.snapWidth->value();
784 const int snapshot_height = dialog.snapHeight->value();
785 const bool snapshot_transparent = dialog.transparent->isChecked();
786 const bool hide_coord_sys = dialog.hideCoordsys->isChecked();
787 const int snapshot_multisampling =
788 dialog.multisampling->isChecked() ?
789 dialog.num_samples->value() : 1;
790 const bool store_view = dialog.metaData_storeView_cb->isChecked();
793 comments_targeted_only, store_material_info, snapshot_width,
794 snapshot_height, snapshot_transparent, hide_coord_sys,
795 snapshot_multisampling, store_view);
805 case QtMultiViewLayout::SingleView:
807 QImage* finalImage =
new QImage();
811 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
815 case QtMultiViewLayout::DoubleView:
822 QImage* finalImage =
new QImage(img[0].width() + img[1].width() +2, img[0].height(), QImage::Format_ARGB32_Premultiplied);
824 QPainter painter(finalImage);
826 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
828 painter.drawImage(QRectF( 0, 0, img[0].width(), img[0].height()),img[0],
829 QRectF( 0, 0, img[0].width(), img[0].height()) );
830 painter.drawImage(QRectF(img[0].width()+2, 0, img[1].width(), img[1].height()),img[1],
831 QRectF( 0, 0, img[1].width(), img[1].height()) );
833 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
838 case QtMultiViewLayout::Grid:
840 QImage img0,img1,img2,img3;
847 QImage* finalImage =
new QImage(img0.width() + img1.width() + 2, img0.height() + img2.height() + 2, QImage::Format_ARGB32_Premultiplied);
849 QPainter painter(finalImage);
851 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
853 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
854 QRectF( 0, 0, img0.width(), img0.height()) );
855 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
856 QRectF( 0, 0, img1.width(), img1.height()) );
857 painter.drawImage(QRectF( 0, img0.height()+2, img2.width(), img2.height()),img2,
858 QRectF( 0, 0, img2.width(), img2.height()) );
859 painter.drawImage(QRectF(img0.width()+2, img0.height()+2, img3.width(), img3.height()),img3,
860 QRectF( 0, 0, img3.width(), img3.height()) );
862 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
866 case QtMultiViewLayout::HSplit:
868 QImage img0,img1,img2,img3;
875 QImage* finalImage =
new QImage(img0.width() + img1.width() + 2, img0.height(), QImage::Format_ARGB32_Premultiplied);
877 QPainter painter(finalImage);
879 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
881 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
882 QRectF( 0, 0, img0.width(), img0.height()) );
883 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
884 QRectF( 0, 0, img1.width(), img1.height()) );
885 painter.drawImage(QRectF(img0.width()+2, img1.height()+2, img2.width(), img2.height()),img2,
886 QRectF( 0, 0, img2.width(), img2.height()) );
887 painter.drawImage(QRectF(img0.width()+2, img1.height()+img2.height()+4, img3.width(),img3.height()),img3,
888 QRectF( 0, 0, img3.width(), img3.height()) );
890 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
904 void writeImageQImage(QImage* _image,
const QString _name) {
910 void CoreWidget::writeImageAsynchronously(QImage* _image,
const QString _name) {
912 QFuture<void>* future =
new QFuture<void>();
913 *future = QtConcurrent::run(writeImageQImage, _image, _name);
914 QFutureWatcher<void>* watcher =
new QFutureWatcher<void>();
915 watcher->setFuture(*future);
917 watcher_garbage_.insert(std::pair<QFutureWatcher<void>*,QFuture<void>*>(watcher, future));
919 connect(watcher, SIGNAL(finished()),
this, SLOT(delete_garbage()));
924 void CoreWidget::delete_garbage() {
926 QObject* obj = QObject::sender();
927 QFutureWatcher<void>* watcher =
dynamic_cast<QFutureWatcher<void>*
>(obj);
934 std::map<QFutureWatcher<void>*,QFuture<void>*>::iterator f;
935 f = watcher_garbage_.find(watcher);
936 if(f != watcher_garbage_.end()) {
939 watcher_garbage_.erase(f);
956 QSize windowSize(0, 0);
957 int splitterWidth = 0;
958 QSize viewportSize(0, 0);
960 view, &windowSize, &splitterWidth, &viewportSize);
962 if (windowSize.height() != 0 && windowSize.width() != 0) {
963 if (windowSize.width() < 0) {
974 if (splitterWidth > 0) {
976 if (splitter_sizes.size() < 2) {
977 std::cerr <<
"The tool splitter has less than two children. This " 978 "shouldn't happen." << std::endl;
981 "Core/Gui/ToolBoxes/ToolBoxOnTheRight",
true).toBool()
984 const int diff = splitterWidth - splitter_sizes[primary_idx];
985 splitter_sizes[primary_idx] += diff;
986 splitter_sizes[1-primary_idx] -= diff;
995 if (viewportSize.width() > 0 && viewportSize.height() > 0) {
1000 for (
int i = 0; i < 2; ++i) {
1002 if (cur_viewport_size != viewportSize) {
1003 std::cout <<
"Stored viewport size is " << viewportSize.width()
1004 <<
" x " << viewportSize.height() <<
". Actual size is " 1005 << cur_viewport_size.width() <<
" x " 1006 << cur_viewport_size.height() <<
". Resizing window." 1010 QSize diff = viewportSize - cur_viewport_size;
1011 resize(size() + diff);
1012 const QSize new_viewport_size =
1014 diff = viewportSize - new_viewport_size;
1015 if (diff.width() != 0) {
1016 std::cout <<
"New viewport size is " 1017 << new_viewport_size.width()
1018 <<
" x " << new_viewport_size.height() <<
"." 1019 <<
" Moving splitter by " << diff.width() <<
"." 1023 if (splitter_sizes.size() < 2) {
1024 std::cerr <<
"The tool splitter has less than two children. This " 1025 "shouldn't happen." << std::endl;
1028 "Core/Gui/ToolBoxes/ToolBoxOnTheRight",
true).toBool()
1031 splitter_sizes[primary_idx] += diff.width();
1032 splitter_sizes[1-primary_idx] -= diff.width();
1051 if (splitterWidth != -1)
1060 sizes.push_back(size.width() - splitterWidth);
1061 sizes.push_back(splitterWidth);
1065 sizes.push_back(splitterWidth);
1066 sizes.push_back(size.width() - splitterWidth);
1075 if (size == QSize(0,0))
1082 resizeApplication(size.width(),size.height());
1092 size = QSize (width(),height());
1094 int splitter_size = 0;
1100 const bool make_c_string = (QApplication::keyboardModifiers() & Qt::ControlModifier);
1102 size, splitter_size, make_c_string);
1111 emit log(
LOGERR, tr(
"CoordSys Node not found"));
1120 for (
unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
1128 if (_action->data().toInt() != PluginFunctions::VIEW_FREE)
void animation(bool _state)
set 2-sided lighting on/off
void setEnabled(bool _enabled)
Enabled/Disables gl cursor painting.
void twoSidedLighting(bool _state)
set 2-sided lighting on/off
ProjectionMode
projection mode
void show()
Show node: set status to Active.
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
void setProjectionMode(const ProjectionMode _mode)
set mode to either ORTHOGRAPHIC_PROJECTION or PERSPECTIVE_PROJECTION
QStringList collectObjectComments(bool visibleOnly, bool targetedOnly)
void mipmapping(bool _state)
set mipmapping on/off
QStringList collectObjectMaterials(bool visibleOnly, bool targetedOnly)
unsigned int activeExaminer()
Get the id of the examiner which got the last mouse events.
void setFixedView(int _mode, int _viewer)
Set a fixed View for a viewer.
bool backFaceCulling()
Get current state of backface culling.
int viewers()
Get the number of viewers.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void snapshotBaseFileName(const QString &_fname)
void hide()
Hide Node: set status to HideNode.
void snapshotCounter(const int _counter)
ACG::Vec4f backgroundColor()
Get current background color.
void multisampling(bool _state)
set multisampling on/off
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
MultiViewMode mode() const
Retruns current layout modes.
void allowRotation(bool _mode, int _viewer)
ChildIter find(BaseNode *_node)
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
ProjectionMode getProjectionMode() const
get current projection mode