diff --git a/idl/gepetto/viewer/graphical-interface.idl b/idl/gepetto/viewer/graphical-interface.idl index 782ec99d7c914fd235f79616b6d74fc9ffae5f3a..2fc2306e103bea3d64cf901c7d3880307d3d4041 100644 --- a/idl/gepetto/viewer/graphical-interface.idl +++ b/idl/gepetto/viewer/graphical-interface.idl @@ -351,6 +351,11 @@ typedef sequence<Transform> TransformSeq; /// Change configurations according to the last applyConfigurations.d void refresh() raises (Error); + + /// Set to false if you do not want refresh to be synchronized + /// with the rendering loop. + /// \note This is an experimental features. + void setRefreshIsSynchronous (in boolean synchonous) raises (Error); /// Return the Position + Quaternion orientation of an object in the global frame /// \param input nodeName : name of the node. diff --git a/include/gepetto/gui/windows-manager.hh b/include/gepetto/gui/windows-manager.hh index 1b3eaf62729c3acd0edd9666cc912beae9adcb00..080e4065549b01e17e9a1529c3f3392567c44bf3 100644 --- a/include/gepetto/gui/windows-manager.hh +++ b/include/gepetto/gui/windows-manager.hh @@ -54,8 +54,13 @@ namespace gepetto { const std::string& extension); bool stopCapture (const WindowID windowId); - public slots: - int createWindow(QString windowName); + void refresh (); + void setRefreshIsSynchronous (bool synchonous); + + public slots: + int createWindow(QString windowName); + void asyncRefresh (); + protected: WindowsManager (BodyTreeWidget* bodyTree); @@ -75,6 +80,10 @@ namespace gepetto { void deleteBodyItem(const std::string& nodeName); std::vector<OSGWidget*> widgets_; + + bool refreshIsSynchronous_; + graphics::Mutex configsAsyncMtx_; + NodeConfigurations_t configsAsync_; }; } // namespace gui } // namespace gepetto diff --git a/src/graphical-interface.impl.cpp b/src/graphical-interface.impl.cpp index 6ee2959c6f7a298ef5772ca58d7d00a7fb51deb2..eb1b01c47ef5146d3cab1060c30da244078a7054 100644 --- a/src/graphical-interface.impl.cpp +++ b/src/graphical-interface.impl.cpp @@ -292,6 +292,8 @@ namespace graphics { BIND_TO_WINDOWS_MANAGER_0(VOID, refresh) + BIND_TO_WINDOWS_MANAGER_1(VOID, setRefreshIsSynchronous, BOOL) + BIND_TO_WINDOWS_MANAGER_1(VOID, createScene, STRING) BIND_TO_WINDOWS_MANAGER_1(VOID, createSceneWithFloor, STRING) diff --git a/src/graphical-interface.impl.hh b/src/graphical-interface.impl.hh index 68968faed913217e763af726a66c478b313c106e..3b70e61de84610ebdd2c0e52b7ed693a0bd386f7 100644 --- a/src/graphical-interface.impl.hh +++ b/src/graphical-interface.impl.hh @@ -56,6 +56,7 @@ public: virtual Names_t* getWindowList() throw (Error); virtual void refresh() throw (Error); + virtual void setRefreshIsSynchronous(bool synchronous) throw (Error); virtual WindowID createWindow(const char* windowNameCorba) throw (Error); virtual WindowID getWindowID (const char* windowNameCorba) throw (Error); diff --git a/src/gui/windows-manager.cc b/src/gui/windows-manager.cc index b0fffacdaa28b489b090c17fd7275b3c9de08ec3..1589747b250de3991bcd16335b45a51cf565a0a4 100644 --- a/src/gui/windows-manager.cc +++ b/src/gui/windows-manager.cc @@ -26,6 +26,8 @@ namespace gepetto { namespace gui { + using graphics::ScopedLock; + Qt::ConnectionType connectionType (QObject* o, int blocking) { if (o->thread() == QThread::currentThread()) @@ -72,6 +74,7 @@ namespace gepetto { WindowsManager::WindowsManager(BodyTreeWidget* bodyTree) : Parent_t () , bodyTree_ (bodyTree) + , refreshIsSynchronous_ (true) { } @@ -244,5 +247,65 @@ namespace gepetto { Q_RETURN_ARG (bool, res)); return res; } + + struct ApplyConfigurationFunctor + { + void operator() (const graphics::NodeConfiguration& nc) const + { + nc.node->applyConfiguration ( nc.position, nc.quat); + } + }; + + void WindowsManager::refresh () + { + if (refreshIsSynchronous_) { + { + ScopedLock lock(configListMtx_); + { + ScopedLock lock(osgFrameMutex()); + //refresh scene with the new configuration + std::for_each(newNodeConfigurations_.begin(), + newNodeConfigurations_.end(), ApplyConfigurationFunctor()); + } + newNodeConfigurations_.resize (0); + } + if (autoCaptureTransform_) captureTransform (); + } else { + { + ScopedLock lock1(configsAsyncMtx_); + ScopedLock lock2(configListMtx_); + if (configsAsync_.size() == 0) { + configsAsync_.swap (newNodeConfigurations_); + QMetaObject::invokeMethod (this, "asyncRefresh", Qt::QueuedConnection); + } else { + configsAsync_.insert (configsAsync_.end(), + newNodeConfigurations_.begin(), + newNodeConfigurations_.end()); + newNodeConfigurations_.resize(0); + // No need to reinvoke asyncRefresh as it hasn't been ran yet. + } + } + } + } + + void WindowsManager::asyncRefresh () + { + NodeConfigurations_t& cfgs = configsAsync_; + { + ScopedLock lock(configsAsyncMtx_); + { + ScopedLock lock(osgFrameMutex()); + //refresh scene with the new configuration + std::for_each(cfgs.begin(), cfgs.end(), ApplyConfigurationFunctor()); + } + cfgs.resize (0); + } + if (autoCaptureTransform_) captureTransform (); + } + + void WindowsManager::setRefreshIsSynchronous (bool synchonous) + { + refreshIsSynchronous_ = synchonous; + } } // namespace gui } // namespace gepetto