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.setConfirmOverwrite(
true);
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;
418 return QString::null;
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;
434 return QString::null;
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;
487 return QString::null;
497 connect(&dialog, SIGNAL(resizeApplication(
int,
int)),
this, SIGNAL(resizeApplication(
int,
int)) );
499 bool ok = dialog.exec();
502 QString newName = dialog.filename->text();
510 QPixmap pic = QPixmap::grabWindow( winId() );
512 QPainter painter (&pic);
521 (*iter)->snapshot(fillImage, (*iter)->glWidth() , (*iter)->glHeight());
523 QPoint localPos = QPoint((*iter)->pos().x(),(*iter)->pos().y());
524 QPointF pos =
glView_->mapTo(
this,localPos);
525 painter.drawImage(pos,fillImage);
532 emit resizeApplication(w,h);
538 QImage* pic =
new QImage(QPixmap::grabWindow( winId() ).toImage());
539 writeImageAsynchronously(pic, suggestSnapshotFilename(
snapshotName_));
543 bool comments_visible_only,
bool comments_targeted_only,
544 bool store_material_info,
int snapshot_width,
int snapshot_height,
545 bool snapshot_transparent,
bool hide_coord_sys,
546 int snapshot_multisampling,
bool store_view) {
548 if (snapshot_height < 0) {
551 snapshot_height =
static_cast<int>(round(
552 static_cast<double>(snapshot_width) / w * h));
556 if (store_comments) {
558 comments_visible_only,
559 comments_targeted_only).join(
"\n");
563 if (ACG::SceneGraph::Material::support_json_serialization() &&
565 store_material_info) {
567 comments_visible_only,
568 comments_targeted_only).join(
"\n");
574 case QtMultiViewLayout::SingleView:
579 snapshot_width, snapshot_height,
580 snapshot_transparent, hide_coord_sys,
581 snapshot_multisampling);
583 if (!comments.isEmpty())
584 finalImage.setText(
"Mesh Comments", comments);
585 if (!materials.isEmpty())
586 finalImage.setText(
"Mesh Materials", materials);
590 window_size = QSize(-width(), -height());
592 window_size = QSize (width(), height());
594 int splitter_size = 0;
602 finalImage.setText(
"View", view);
604 finalImage.save(file_name);
608 case QtMultiViewLayout::DoubleView:
610 int w = snapshot_height;
617 img[0], static_cast<int>(relSizeW * w),
618 snapshot_width, snapshot_transparent,
621 img[1], static_cast<int>(relSizeW * w),
622 snapshot_width, snapshot_transparent,
625 QImage finalImage(img[0].width() + img[1].width() +2, img[0].height(),
626 QImage::Format_ARGB32_Premultiplied);
628 QPainter painter(&finalImage);
630 painter.fillRect(0,0,finalImage.width(),
631 finalImage.height(), QBrush(Qt::gray));
633 painter.drawImage(QRectF( 0, 0, img[0].width(), img[0].height()),img[0],
634 QRectF( 0, 0, img[0].width(), img[0].height()) );
635 painter.drawImage(QRectF(img[0].width()+2, 0, img[1].width(), img[1].height()),img[1],
636 QRectF( 0, 0, img[1].width(), img[1].height()) );
638 if (!comments.isEmpty())
639 finalImage.setText(
"Mesh Comments", comments);
640 finalImage.save(file_name);
645 case QtMultiViewLayout::Grid:
651 QImage img0,img1,img2,img3;
654 (
int)((
double)snapshot_width * relSizeW),
655 (
int)((
double)snapshot_height * relSizeH),
656 snapshot_transparent, hide_coord_sys);
658 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
659 (
int)((
double)snapshot_height * relSizeH),
660 snapshot_transparent, hide_coord_sys);
662 (
int)((
double)snapshot_width * relSizeW),
663 (
int)((
double)snapshot_height * (1.0 - relSizeH)),
664 snapshot_transparent, hide_coord_sys);
666 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
667 (
int)((
double)snapshot_height * (1.0 - relSizeH)),
668 snapshot_transparent, hide_coord_sys);
670 QImage finalImage(img0.width() + img1.width()+2,
671 img0.height() + img2.height()+2,
672 QImage::Format_ARGB32_Premultiplied);
674 QPainter painter(&finalImage);
676 painter.fillRect(0,0,finalImage.width(), finalImage.height(), QBrush(Qt::gray));
678 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
679 QRectF( 0, 0, img0.width(), img0.height()) );
680 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
681 QRectF( 0, 0, img1.width(), img1.height()) );
682 painter.drawImage(QRectF( 0,img0.height()+2, img2.width(), img2.height()),img2,
683 QRectF( 0, 0, img2.width(), img2.height()) );
684 painter.drawImage(QRectF(img0.width()+2, img0.height()+2, img3.width(), img3.height()),img3,
685 QRectF( 0, 0, img3.width(), img3.height()) );
687 if (!comments.isEmpty())
688 finalImage.setText(
"Mesh Comments", comments);
689 finalImage.save(file_name);
693 case QtMultiViewLayout::HSplit:
701 QImage img0,img1,img2,img3;
704 (
int)((
double)snapshot_width * relSizeW), snapshot_height,
705 snapshot_transparent, hide_coord_sys);
707 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
708 relSizeH1 * (
double)snapshot_height,
709 snapshot_transparent, hide_coord_sys);
711 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
712 relSizeH2 * (
double)snapshot_height,
713 snapshot_transparent, hide_coord_sys);
715 (
int)((
double)snapshot_width * (1.0 - relSizeW)),
716 relSizeH3 * (
double)snapshot_height,
717 snapshot_transparent, hide_coord_sys);
719 QImage finalImage(img0.width() + img1.width() +2, img0.height(), QImage::Format_ARGB32_Premultiplied);
721 QPainter painter(&finalImage);
723 painter.fillRect(0,0,finalImage.width(), finalImage.height(), QBrush(Qt::gray));
725 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
726 QRectF( 0, 0, img0.width(), img0.height()) );
727 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
728 QRectF( 0, 0, img1.width(), img1.height()) );
729 painter.drawImage(QRectF(img0.width()+2, img1.height()+2, img2.width(), img2.height()),img2,
730 QRectF( 0, 0, img2.width(), img2.height()) );
731 painter.drawImage(QRectF(img0.width()+2, img1.height()+img2.height()+4, img3.width(),img3.height()),img3,
732 QRectF( 0, 0, img3.width(), img3.height()) );
734 if (!comments.isEmpty())
735 finalImage.setText(
"Mesh Comments", comments);
736 finalImage.save(file_name);
752 if (!ACG::SceneGraph::Material::support_json_serialization())
753 dialog.metaData_storeMatInfo_cb->setVisible(
false);
755 bool ok = dialog.exec();
758 QString newName = dialog.filename->text();
764 const bool storeComments = dialog.metaData_storeComments_cb->isChecked();
765 const bool comments_visible_only =
766 dialog.metaData_comments_visibleOnly_cb->isChecked();
767 const bool comments_targeted_only =
768 dialog.metaData_comments_targetedOnly_cb->isChecked();
769 const bool store_material_info =
770 dialog.metaData_storeMatInfo_cb->isChecked();
771 const int snapshot_width = dialog.snapWidth->value();
772 const int snapshot_height = dialog.snapHeight->value();
773 const bool snapshot_transparent = dialog.transparent->isChecked();
774 const bool hide_coord_sys = dialog.hideCoordsys->isChecked();
775 const int snapshot_multisampling =
776 dialog.multisampling->isChecked() ?
777 dialog.num_samples->value() : 1;
778 const bool store_view = dialog.metaData_storeView_cb->isChecked();
781 comments_targeted_only, store_material_info, snapshot_width,
782 snapshot_height, snapshot_transparent, hide_coord_sys,
783 snapshot_multisampling, store_view);
793 case QtMultiViewLayout::SingleView:
795 QImage* finalImage =
new QImage();
799 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
803 case QtMultiViewLayout::DoubleView:
810 QImage* finalImage =
new QImage(img[0].width() + img[1].width() +2, img[0].height(), QImage::Format_ARGB32_Premultiplied);
812 QPainter painter(finalImage);
814 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
816 painter.drawImage(QRectF( 0, 0, img[0].width(), img[0].height()),img[0],
817 QRectF( 0, 0, img[0].width(), img[0].height()) );
818 painter.drawImage(QRectF(img[0].width()+2, 0, img[1].width(), img[1].height()),img[1],
819 QRectF( 0, 0, img[1].width(), img[1].height()) );
821 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
826 case QtMultiViewLayout::Grid:
828 QImage img0,img1,img2,img3;
835 QImage* finalImage =
new QImage(img0.width() + img1.width() + 2, img0.height() + img2.height() + 2, QImage::Format_ARGB32_Premultiplied);
837 QPainter painter(finalImage);
839 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
841 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
842 QRectF( 0, 0, img0.width(), img0.height()) );
843 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
844 QRectF( 0, 0, img1.width(), img1.height()) );
845 painter.drawImage(QRectF( 0, img0.height()+2, img2.width(), img2.height()),img2,
846 QRectF( 0, 0, img2.width(), img2.height()) );
847 painter.drawImage(QRectF(img0.width()+2, img0.height()+2, img3.width(), img3.height()),img3,
848 QRectF( 0, 0, img3.width(), img3.height()) );
850 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
854 case QtMultiViewLayout::HSplit:
856 QImage img0,img1,img2,img3;
863 QImage* finalImage =
new QImage(img0.width() + img1.width() + 2, img0.height(), QImage::Format_ARGB32_Premultiplied);
865 QPainter painter(finalImage);
867 painter.fillRect(0,0,finalImage->width(), finalImage->height(), QBrush(Qt::gray));
869 painter.drawImage(QRectF( 0, 0, img0.width(), img0.height()),img0,
870 QRectF( 0, 0, img0.width(), img0.height()) );
871 painter.drawImage(QRectF(img0.width()+2, 0, img1.width(), img1.height()),img1,
872 QRectF( 0, 0, img1.width(), img1.height()) );
873 painter.drawImage(QRectF(img0.width()+2, img1.height()+2, img2.width(), img2.height()),img2,
874 QRectF( 0, 0, img2.width(), img2.height()) );
875 painter.drawImage(QRectF(img0.width()+2, img1.height()+img2.height()+4, img3.width(),img3.height()),img3,
876 QRectF( 0, 0, img3.width(), img3.height()) );
878 writeImageAsynchronously(finalImage, suggestSnapshotFilename(
snapshotName_));
892 void writeImageQImage(QImage* _image,
const QString _name) {
898 void CoreWidget::writeImageAsynchronously(QImage* _image,
const QString _name) {
900 QFuture<void>* future =
new QFuture<void>();
901 *future = QtConcurrent::run(writeImageQImage, _image, _name);
902 QFutureWatcher<void>* watcher =
new QFutureWatcher<void>();
903 watcher->setFuture(*future);
905 watcher_garbage_.insert(std::pair<QFutureWatcher<void>*,QFuture<void>*>(watcher, future));
907 connect(watcher, SIGNAL(finished()),
this, SLOT(delete_garbage()));
912 void CoreWidget::delete_garbage() {
914 QObject* obj = QObject::sender();
915 QFutureWatcher<void>* watcher =
dynamic_cast<QFutureWatcher<void>*
>(obj);
922 std::map<QFutureWatcher<void>*,QFuture<void>*>::iterator f;
923 f = watcher_garbage_.find(watcher);
924 if(f != watcher_garbage_.end()) {
927 watcher_garbage_.erase(f);
944 QSize windowSize(0, 0);
945 int splitterWidth = 0;
946 QSize viewportSize(0, 0);
948 view, &windowSize, &splitterWidth, &viewportSize);
950 if (windowSize.height() != 0 && windowSize.width() != 0) {
951 if (windowSize.width() < 0) {
962 if (splitterWidth > 0) {
964 if (splitter_sizes.size() < 2) {
965 std::cerr <<
"The tool splitter has less than two children. This " 966 "shouldn't happen." << std::endl;
969 "Core/Gui/ToolBoxes/ToolBoxOnTheRight",
true).toBool()
972 const int diff = splitterWidth - splitter_sizes[primary_idx];
973 splitter_sizes[primary_idx] += diff;
974 splitter_sizes[1-primary_idx] -= diff;
983 if (viewportSize.width() > 0 && viewportSize.height() > 0) {
988 for (
int i = 0; i < 2; ++i) {
990 if (cur_viewport_size != viewportSize) {
991 std::cout <<
"Stored viewport size is " << viewportSize.width()
992 <<
" x " << viewportSize.height() <<
". Actual size is " 993 << cur_viewport_size.width() <<
" x " 994 << cur_viewport_size.height() <<
". Resizing window." 998 QSize diff = viewportSize - cur_viewport_size;
999 resize(size() + diff);
1000 const QSize new_viewport_size =
1002 diff = viewportSize - new_viewport_size;
1003 if (diff.width() != 0) {
1004 std::cout <<
"New viewport size is " 1005 << new_viewport_size.width()
1006 <<
" x " << new_viewport_size.height() <<
"." 1007 <<
" Moving splitter by " << diff.width() <<
"." 1011 if (splitter_sizes.size() < 2) {
1012 std::cerr <<
"The tool splitter has less than two children. This " 1013 "shouldn't happen." << std::endl;
1016 "Core/Gui/ToolBoxes/ToolBoxOnTheRight",
true).toBool()
1019 splitter_sizes[primary_idx] += diff.width();
1020 splitter_sizes[1-primary_idx] -= diff.width();
1039 if (splitterWidth != -1)
1048 sizes.push_back(size.width() - splitterWidth);
1049 sizes.push_back(splitterWidth);
1053 sizes.push_back(splitterWidth);
1054 sizes.push_back(size.width() - splitterWidth);
1063 if (size == QSize(0,0))
1070 resizeApplication(size.width(),size.height());
1080 size = QSize (width(),height());
1082 int splitter_size = 0;
1088 const bool make_c_string = (QApplication::keyboardModifiers() & Qt::ControlModifier);
1090 size, splitter_size, make_c_string);
1099 emit log(
LOGERR, tr(
"CoordSys Node not found"));
1108 for (
unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
1116 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