diff --git a/include/gepetto/gui/osgwidget.hh b/include/gepetto/gui/osgwidget.hh index d4769c0fb7e1af5b9eedd026911eceada8bc0407..6583b465ee82447c527735bc00e3530207f7e51e 100644 --- a/include/gepetto/gui/osgwidget.hh +++ b/include/gepetto/gui/osgwidget.hh @@ -30,6 +30,9 @@ #include <gepetto/gui/fwd.hh> #include <gepetto/gui/windows-manager.hh> +class QProcess; +class QTextBrowser; + namespace gepetto { namespace gui { /// Widget that displays scenes. @@ -57,9 +60,14 @@ namespace gepetto { void addFloor(); + void toggleCapture (bool active); + protected: virtual void paintEvent(QPaintEvent* event); + private slots: + void readyReadProcessOutput (); + private: osg::ref_ptr<osgQt::GraphicsWindowQt> graphicsWindow_; WindowsManagerPtr_t wsm_; @@ -70,6 +78,11 @@ namespace gepetto { osgViewer::ViewerRefPtr viewer_; osg::ref_ptr <osgViewer::ScreenCaptureHandler> screenCapture_; + // To record movies. + QProcess* process_; + QDialog* showPOutput_; + QTextBrowser* pOutput_; + friend class PickHandler; }; } // namespace gui diff --git a/include/gepetto/gui/ui/mainwindow.ui b/include/gepetto/gui/ui/mainwindow.ui index 6ac572e4806309e7e1f1eddbb6c90b365e1f5328..5fafe64aa9fac7900688789b1ddc309af7a3aa32 100644 --- a/include/gepetto/gui/ui/mainwindow.ui +++ b/include/gepetto/gui/ui/mainwindow.ui @@ -208,6 +208,7 @@ <addaction name="actionSelection"/> <addaction name="actionHome"/> <addaction name="actionAdd_floor"/> + <addaction name="actionRecordMovie"/> </widget> <widget class="QDockWidget" name="dockWidget_log"> <property name="windowIcon"> @@ -398,6 +399,22 @@ <string>Add a floor</string> </property> </action> + <action name="actionRecordMovie"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset theme="media-record"> + <normaloff/> + </iconset> + </property> + <property name="text"> + <string>Scene capture.</string> + </property> + <property name="toolTip"> + <string><html><head/><body><p>Record the central widget as a sequence of images. You can find the images in /tmp/gepetto-gui/record/img_%d.jpeg</p></body></html></string> + </property> + </action> <action name="actionAbout"> <property name="text"> <string>&About...</string> @@ -433,7 +450,9 @@ </action> <action name="actionClose_connections"> <property name="icon"> - <iconset theme="network-disconnect"/> + <iconset theme="network-disconnect"> + <normaloff/> + </iconset> </property> <property name="text"> <string>Close connections</string> diff --git a/src/gui/mainwindow.cc b/src/gui/mainwindow.cc index 9ab2306cee7496501f5a45b3bf0d835e6fbb8cdf..74be4901911bd84ac11738418f923c19a41985cd 100644 --- a/src/gui/mainwindow.cc +++ b/src/gui/mainwindow.cc @@ -270,6 +270,7 @@ namespace gepetto { osg()->addSceneToWindow("hpp-gui", centralWidget_->windowID()); connect(ui_->actionAdd_floor, SIGNAL (triggered()), centralWidget_, SLOT (addFloor())); + connect(ui_->actionRecordMovie, SIGNAL (toggled(bool)), centralWidget_, SLOT (toggleCapture(bool))); } actionSearchBar_->addAction(new NodeAction("Attach camera " + osgWidget->objectName() + " to selected node", osgWidget, this)); osgWidget->addAction(actionSearchBar_->showAction()); diff --git a/src/gui/osgwidget.cc b/src/gui/osgwidget.cc index d5ce8e90f96d39c245efaa1022727b4a1de8c849..e5311951812661709a68509ab641c18fe44c96b8 100644 --- a/src/gui/osgwidget.cc +++ b/src/gui/osgwidget.cc @@ -20,6 +20,9 @@ #include <boost/regex.hpp> +#include <QProcess> +#include <QTextBrowser> + #include <osg/Camera> #include <osg/DisplaySettings> @@ -103,6 +106,9 @@ namespace gepetto { , wm_ () , viewer_ (new osgViewer::Viewer) , screenCapture_ () + , process_ (new QProcess (this)) + , showPOutput_ (new QDialog (this, Qt::Dialog | Qt::WindowCloseButtonHint | Qt::WindowMinMaxButtonsHint)) + , pOutput_ (new QTextBrowser()) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::ref_ptr <osg::GraphicsContext::Traits> traits_ptr (new osg::GraphicsContext::Traits(ds)); @@ -158,6 +164,13 @@ namespace gepetto { connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) ); timer_.start(parent->settings_->refreshRate); + + // Setup widgets to record movies. + process_->setProcessChannelMode(QProcess::MergedChannels); + connect (process_, SIGNAL (readyReadStandardOutput ()), SLOT (readyReadProcessOutput())); + showPOutput_->setModal(false); + showPOutput_->setLayout(new QHBoxLayout ()); + showPOutput_->layout()->addWidget(pOutput_); } OSGWidget::~OSGWidget() @@ -200,5 +213,49 @@ namespace gepetto { { wsm_->addFloor("hpp-gui/floor"); } + + void OSGWidget::toggleCapture (bool active) + { + MainWindow* main = MainWindow::instance(); + if (active) { + QDir tmp ("/tmp"); + tmp.mkpath ("gepetto-gui/record"); tmp.cd("gepetto-gui/record"); + foreach (QString f, tmp.entryList(QStringList() << "img_0_*.jpeg", QDir::Files)) + tmp.remove(f); + QString path = tmp.absoluteFilePath("img"); + const char* ext = "jpeg"; + osg ()->startCapture(windowID(), path.toLocal8Bit().data(), ext); + main->log("Saving images to " + path + "_*." + ext); + } else { + osg()->stopCapture(windowID()); + QString outputFile = QFileDialog::getSaveFileName(this, tr("Save video to"), "untitled.mp4"); + if (!outputFile.isNull()) { + if (QFile::exists(outputFile)) + QFile::remove(outputFile); + QString avconv = "avconv"; + + QStringList args; + QString input = "/tmp/gepetto-gui/record/img_0_%d.jpeg"; + args << "-r" << "50" + << "-i" << input + << "-vf" << "scale=trunc(iw/2)*2:trunc(ih/2)*2" + << "-r" << "25" + << "-vcodec" << "libx264" + << outputFile; + qDebug () << args; + + showPOutput_->setWindowTitle(avconv + " " + args.join(" ")); + pOutput_->clear(); + showPOutput_->resize(main->size() / 2); + showPOutput_->show(); + process_->start(avconv, args); + } + } + } + + void OSGWidget::readyReadProcessOutput() + { + pOutput_->append(process_->readAll()); + } } // namespace gui } // namespace gepetto