From 8b00026769f72277676f1f02b7221e1f5c076f7a Mon Sep 17 00:00:00 2001 From: "Matias N. Goldberg" Date: Mon, 20 Sep 2021 13:56:06 -0300 Subject: [PATCH 01/11] Fix memory leak (#287) Fixes ignitionrobotics/ign-gazebo#1011 Signed-off-by: Matias N. Goldberg --- src/plugins/image_display/ImageDisplay.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/image_display/ImageDisplay.cc b/src/plugins/image_display/ImageDisplay.cc index 93a2ab9b6..0c736a139 100644 --- a/src/plugins/image_display/ImageDisplay.cc +++ b/src/plugins/image_display/ImageDisplay.cc @@ -212,6 +212,8 @@ void ImageDisplay::ProcessImage() image.setPixel(i, j, value); } } + + delete [] data; } this->dataPtr->provider->SetImage(image); From 2630a94c3b1c49bfa33447cd47b1d39528cfb3ec Mon Sep 17 00:00:00 2001 From: Louise Poubel Date: Thu, 30 Sep 2021 21:41:09 -0700 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=8E=88=206.0.0=20=20(#296)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Louise Poubel --- CMakeLists.txt | 2 +- Changelog.md | 11 +++++++++-- README.md | 8 ++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d4b323ea..855baa6fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ find_package(ignition-cmake2 2.8.0 REQUIRED) #============================================================================ # Configure the project #============================================================================ -ign_configure_project(VERSION_SUFFIX pre1) +ign_configure_project(VERSION_SUFFIX) #============================================================================ # Set project-specific options diff --git a/Changelog.md b/Changelog.md index 8ae1fa057..de0d86559 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,8 +4,8 @@ ### Ignition Gui 6.0.0 (2021-09-XX) -1. Render engine GUI name argument to be set in the minimal scene - * [Pull request #286](https://github.com/ignitionrobotics/ign-gui/pull/286) +1. Add a filter to the plugin menu + * [Pull request #277](https://github.com/ignitionrobotics/ign-gui/pull/277) 1. New events @@ -35,6 +35,9 @@ 1. PIMPL GUI events * [Pull request #253](https://github.com/ignitionrobotics/ign-gui/pull/253) +1. Added winID to fix second windows in OGRE2.2 + * [Pull request #292](https://github.com/ignitionrobotics/ign-gui/pull/292) + 1. Added camera tracking * [Pull request #226](https://github.com/ignitionrobotics/ign-gui/pull/226) * [Pull request #254](https://github.com/ignitionrobotics/ign-gui/pull/254) @@ -45,6 +48,10 @@ * [Pull request #285](https://github.com/ignitionrobotics/ign-gui/pull/285) * [Pull request #268](https://github.com/ignitionrobotics/ign-gui/pull/268) * [Pull request #224](https://github.com/ignitionrobotics/ign-gui/pull/224) + * [Pull request #282](https://github.com/ignitionrobotics/ign-gui/pull/282) + * [Pull request #273](https://github.com/ignitionrobotics/ign-gui/pull/273) + * [Pull request #286](https://github.com/ignitionrobotics/ign-gui/pull/286) + * [Pull request #295](https://github.com/ignitionrobotics/ign-gui/pull/295) 1. Remove deprecations: tock * [Pull request #243](https://github.com/ignitionrobotics/ign-gui/pull/243) diff --git a/README.md b/README.md index 33372aa85..ad13ba222 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Build | Status -- | -- -Test coverage | [![codecov](https://codecov.io/gh/ignitionrobotics/ign-gui/branch/main/graph/badge.svg)](https://codecov.io/gh/ignitionrobotics/ign-gui/branch/main) -Ubuntu Bionic | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_gui-ci-main-bionic-amd64)](https://build.osrfoundation.org/job/ignition_gui-ci-main-bionic-amd64) -Homebrew | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_gui-ci-main-homebrew-amd64)](https://build.osrfoundation.org/job/ignition_gui-ci-main-homebrew-amd64) -Windows | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ign_gui-ci-win)](https://build.osrfoundation.org/job/ign_gui-ci-win) +Test coverage | [![codecov](https://codecov.io/gh/ignitionrobotics/ign-gui/branch/ign-gui6/graph/badge.svg)](https://codecov.io/gh/ignitionrobotics/ign-gui/branch/ign-gui6) +Ubuntu Bionic | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_gui-ci-ign-gui6-bionic-amd64)](https://build.osrfoundation.org/job/ignition_gui-ci-ign-gui6-bionic-amd64) +Homebrew | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ignition_gui-ci-ign-gui6-homebrew-amd64)](https://build.osrfoundation.org/job/ignition_gui-ci-ign-gui6-homebrew-amd64) +Windows | [![Build Status](https://build.osrfoundation.org/buildStatus/icon?job=ign_gui-ign-6-win)](https://build.osrfoundation.org/job/ign_gui-ign-6-win) Ignition GUI builds on top of [Qt](https://www.qt.io/) to provide widgets which are useful when developing robotics applications, such as a 3D view, plots, dashboard, etc, From 443bfac97f6d214bbcc01dc2af7a573e4bba7ea6 Mon Sep 17 00:00:00 2001 From: Nate Koenig Date: Wed, 6 Oct 2021 12:13:09 -0700 Subject: [PATCH 03/11] Fix mimimal scene deadlock on shutdown (#300) Signed-off-by: Nate Koenig Co-authored-by: Nate Koenig --- src/plugins/minimal_scene/MinimalScene.cc | 26 +++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/plugins/minimal_scene/MinimalScene.cc b/src/plugins/minimal_scene/MinimalScene.cc index 3e7fe3174..913bf08b1 100644 --- a/src/plugins/minimal_scene/MinimalScene.cc +++ b/src/plugins/minimal_scene/MinimalScene.cc @@ -189,8 +189,11 @@ class ignition::gui::plugins::RenderWindowItem::Implementation /// \brief See RenderSync public: RenderSync renderSync; - //// \brief List of threads + /// \brief List of threads public: static QList threads; + + /// \brief List of our QT connections. + public: QList connections; }; /// \brief Private data class for MinimalScene @@ -236,6 +239,7 @@ void RenderSync::WaitForWorkerThread() // Worker thread asked us to wait! this->renderStallState = RenderStallState::WorkerCanProceed; + lock.unlock(); // Wake up worker thread this->cv.notify_one(); @@ -804,6 +808,10 @@ RenderWindowItem::RenderWindowItem(QQuickItem *_parent) ///////////////////////////////////////////////// RenderWindowItem::~RenderWindowItem() { + // Disconnect our QT connections. + for(auto conn : this->dataPtr->connections) + QObject::disconnect(conn); + this->dataPtr->renderSync.Shutdown(); QMetaObject::invokeMethod(this->dataPtr->renderThread, "ShutDown", @@ -882,13 +890,17 @@ QSGNode *RenderWindowItem::updatePaintNode(QSGNode *_node, // This rendering pipeline is throttled by vsync on the scene graph // rendering thread. - this->connect(this->dataPtr->renderThread, &RenderThread::TextureReady, - node, &TextureNode::NewTexture, Qt::DirectConnection); - this->connect(node, &TextureNode::PendingNewTexture, this->window(), + this->dataPtr->connections << this->connect(this->dataPtr->renderThread, + &RenderThread::TextureReady, node, &TextureNode::NewTexture, + Qt::DirectConnection); + this->dataPtr->connections << this->connect(node, + &TextureNode::PendingNewTexture, this->window(), &QQuickWindow::update, Qt::QueuedConnection); - this->connect(this->window(), &QQuickWindow::beforeRendering, node, - &TextureNode::PrepareNode, Qt::DirectConnection); - this->connect(node, &TextureNode::TextureInUse, this->dataPtr->renderThread, + this->dataPtr->connections << this->connect(this->window(), + &QQuickWindow::beforeRendering, node, &TextureNode::PrepareNode, + Qt::DirectConnection); + this->dataPtr->connections << this->connect(node, + &TextureNode::TextureInUse, this->dataPtr->renderThread, &RenderThread::RenderNext, Qt::QueuedConnection); // Get the production of FBO textures started.. From 89febb7494ab47723790382e127b75875dff49df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Tue, 12 Oct 2021 00:54:09 +0200 Subject: [PATCH 04/11] Improved doxygen (#275) Signed-off-by: ahcorde --- .github/workflows/ci.yml | 1 + CMakeLists.txt | 13 +++++++------ include/ignition/gui/Application.hh | 4 ++-- include/ignition/gui/GuiEvents.hh | 2 +- include/ignition/gui/Plugin.hh | 5 ++++- src/plugins/key_publisher/KeyPublisher.hh | 3 ++- tutorials/03_plugins.md | 10 +++++----- 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e36175c3a..53e67b817 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,7 @@ jobs: uses: ignition-tooling/action-ignition-ci@bionic with: codecov-enabled: true + doxygen-enabled: true focal-ci: runs-on: ubuntu-latest name: Ubuntu Focal CI diff --git a/CMakeLists.txt b/CMakeLists.txt index a387f1732..2001626e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,12 +108,13 @@ ign_create_docs( API_MAINPAGE_MD "${CMAKE_BINARY_DIR}/api.md" TUTORIALS_MAINPAGE_MD "${CMAKE_BINARY_DIR}/tutorials.md" ADDITIONAL_INPUT_DIRS "${CMAKE_SOURCE_DIR}/src/plugins" + IMAGE_PATH_DIRS "${CMAKE_SOURCE_DIR}/tutorials/images" TAGFILES - "\"${CMAKE_SOURCE_DIR}/doc/qt.tag.xml=http://doc.qt.io/qt-5/\" \ - \"${IGNITION-MATH_DOXYGEN_TAGFILE} = ${IGNITION-MATH_API_URL}\" \ - \"${IGNITION-MSGS_DOXYGEN_TAGFILE} = ${IGNITION-MSGS_API_URL}\" \ - \"${IGNITION-TRANSPORT_DOXYGEN_TAGFILE} = ${IGNITION-TRANSPORT_API_URL}\" \ - \"${IGNITION-COMMON_DOXYGEN_TAGFILE} = ${IGNITION-COMMON_API_URL}\"" - ) + "${CMAKE_SOURCE_DIR}/doc/qt.tag.xml=http://doc.qt.io/qt-5/" + "${IGNITION-MATH_DOXYGEN_TAGFILE} = ${IGNITION-MATH_API_URL}" + "${IGNITION-MSGS_DOXYGEN_TAGFILE} = ${IGNITION-MSGS_API_URL}" + "${IGNITION-TRANSPORT_DOXYGEN_TAGFILE} = ${IGNITION-TRANSPORT_API_URL}" + "${IGNITION-COMMON_DOXYGEN_TAGFILE} = ${IGNITION-COMMON_API_URL}" +) file(COPY ${CMAKE_SOURCE_DIR}/tutorials/images/ DESTINATION ${CMAKE_BINARY_DIR}/doxygen/html/images/) diff --git a/include/ignition/gui/Application.hh b/include/ignition/gui/Application.hh index cf8f170d9..b0813a8fc 100644 --- a/include/ignition/gui/Application.hh +++ b/include/ignition/gui/Application.hh @@ -96,11 +96,11 @@ namespace ignition /// and plugins. This function doesn't instantiate the plugins, it just /// keeps them in memory and they can be applied later by either /// instantiating a window or several dialogs. - /// \param[in] _config Full path to configuration file. + /// \param[in] _path Full path to configuration file. /// \return True if successful /// \sa InitializeMainWindow /// \sa InitializeDialogs - public: bool LoadConfig(const std::string &_config); + public: bool LoadConfig(const std::string &_path); /// \brief Load the configuration from the default config file. /// \return True if successful diff --git a/include/ignition/gui/GuiEvents.hh b/include/ignition/gui/GuiEvents.hh index 8ef8ea819..78f8a0cbf 100644 --- a/include/ignition/gui/GuiEvents.hh +++ b/include/ignition/gui/GuiEvents.hh @@ -103,7 +103,7 @@ namespace ignition class SpawnFromDescription : public QEvent { /// \brief Constructor - /// \param[in] _string The resource's description as a string, such + /// \param[in] _description The resource's description as a string, such /// as an SDF file. public: explicit SpawnFromDescription(const std::string &_description) : QEvent(kType), description(_description) diff --git a/include/ignition/gui/Plugin.hh b/include/ignition/gui/Plugin.hh index 07c69d600..b943b1e0d 100644 --- a/include/ignition/gui/Plugin.hh +++ b/include/ignition/gui/Plugin.hh @@ -102,7 +102,10 @@ namespace ignition /// \sa Load /// \param[in] _pluginElem Element containing configuration protected: virtual void LoadConfig( - const tinyxml2::XMLElement * /*_pluginElem*/) {} + const tinyxml2::XMLElement *_pluginElem) + { + (void)_pluginElem; + } /// \brief Get title /// \return Plugin title. diff --git a/src/plugins/key_publisher/KeyPublisher.hh b/src/plugins/key_publisher/KeyPublisher.hh index 759248882..38ecdd2e5 100644 --- a/src/plugins/key_publisher/KeyPublisher.hh +++ b/src/plugins/key_publisher/KeyPublisher.hh @@ -46,7 +46,8 @@ namespace gui public: virtual ~KeyPublisher(); // Documentation inherited - public: virtual void LoadConfig(const tinyxml2::XMLElement *) override; + public: virtual void LoadConfig( + const tinyxml2::XMLElement *_pluginElem) override; /// \brief Filter events in Qt /// \param[in] _obj The watched object diff --git a/tutorials/03_plugins.md b/tutorials/03_plugins.md index 15a4df333..53ced108c 100644 --- a/tutorials/03_plugins.md +++ b/tutorials/03_plugins.md @@ -48,11 +48,11 @@ Publish messages on an Ignition Transport topic. ign topic -e -t /echo -1. On a new terminal, open the publisher GUI: +2. On a new terminal, open the publisher GUI: ign gui -s Publisher -1. The GUI is pre-filled to publish "Hello" messages on the `/echo` topic. +3. The GUI is pre-filled to publish "Hello" messages on the `/echo` topic. Click "Publish" to publish a message and see it on the terminal. ### World stats and control @@ -101,7 +101,7 @@ plugins. ign gui -c examples/config/reqres.config -### Displays {#display-plugins} +### Displays **Not ported to versions 1 or higher yet** @@ -119,5 +119,5 @@ Ignition GUI will look for display plugins on the following paths, in this order: 1. All paths set on the `IGN_GUI_DISPLAY_PLUGIN_PATH` environment variable -1. `~/.ignition/gui/display_plugins` -1. [Display plugins that are installed with Ignition GUI](https://ignitionrobotics.org/api/gui/0.1/namespaceignition_1_1gui_1_1display_plugins.html) +2. `~/.ignition/gui/display_plugins` +3. [Display plugins that are installed with Ignition GUI](https://ignitionrobotics.org/api/gui/0.1/namespaceignition_1_1gui_1_1display_plugins.html) From 07a71e16ff09d34f71385288eedb8e767d15338f Mon Sep 17 00:00:00 2001 From: Jenn Nguyen Date: Tue, 12 Oct 2021 10:41:11 -0700 Subject: [PATCH 05/11] =?UTF-8?q?=F0=9F=8E=883.8.0=20(#302)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jenn Nguyen --- CMakeLists.txt | 2 +- Changelog.md | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2001626e5..9aebd23a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(ignition-gui3 VERSION 3.7.0) +project(ignition-gui3 VERSION 3.8.0) #============================================================================ # Find ignition-cmake diff --git a/Changelog.md b/Changelog.md index d17bbe236..b1ac85fd0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,23 @@ ### Ignition Gui 3.X.X (202X-XX-XX) +### Ignition Gui 3.8.0 (2021-10-12) + +1. Improved doxygen + * [Pull request #275](https://github.com/ignitionrobotics/ign-gui/pull/275) + +1. Add a filter to the plugin menu + * [Pull request #277](https://github.com/ignitionrobotics/ign-gui/pull/277) + +1. 👩‍🌾 Remove bitbucket-pipelines.yml + * [Pull request #274](https://github.com/ignitionrobotics/ign-gui/pull/274) + +1. Require ign-rendering 3.5 + * [Pull request #264](https://github.com/ignitionrobotics/ign-gui/pull/264) + +1. New teleop plugin implementation. + * [Pull request #245](https://github.com/ignitionrobotics/ign-gui/pull/245) + ### Ignition Gui 3.7.0 (2021-07-14) 1. Fix codeowners From e0039506622369e54fe371f055814e024eab4a88 Mon Sep 17 00:00:00 2001 From: Jenn Nguyen Date: Tue, 12 Oct 2021 19:24:52 -0700 Subject: [PATCH 06/11] fixed docs Signed-off-by: Jenn Nguyen --- include/ignition/gui/PlottingInterface.hh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/ignition/gui/PlottingInterface.hh b/include/ignition/gui/PlottingInterface.hh index 9e0a2ed17..9f463202f 100644 --- a/include/ignition/gui/PlottingInterface.hh +++ b/include/ignition/gui/PlottingInterface.hh @@ -63,7 +63,7 @@ class IGNITION_GUI_VISIBLE PlotData public: double Value() const; /// \brief Set the field arrival time - /// \param[in] _value arrival time to set it + /// \param[in] _time arrival time to set it public: void SetTime(const double _time); /// \brief Get the arrival time @@ -273,7 +273,6 @@ class IGNITION_GUI_VISIBLE PlottingInterface : public QObject /// \brief called by Qml to remove a chart from a component attribute /// \param[in] _entity entity id which has the component /// \param[in] _typeId component type id - /// \param[in] _type component data type /// \param[in] _attribute component specefice attribte /// \param[in] _chart chart id public slots: void onComponentUnSubscribe(QString _entity, @@ -296,7 +295,6 @@ class IGNITION_GUI_VISIBLE PlottingInterface : public QObject /// \brief Notify the gazebo plugin to unsubscribe a component data /// \param[in] _entity entity id which has the component /// \param[in] _typeId component type id - /// \param[in] _type component data type /// \param[in] _attribute component specefice attribte /// \param[in] _chart chart id signals: void ComponentUnSubscribe(uint64_t _entity, @@ -338,4 +336,3 @@ class IGNITION_GUI_VISIBLE PlottingInterface : public QObject } #endif - From 0361d322bc0f3e0ef46e18c7b41af1daa0b3d3d7 Mon Sep 17 00:00:00 2001 From: Jenn Nguyen Date: Wed, 13 Oct 2021 18:43:14 -0700 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=8E=885.3.0=20(#305)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🎈5.3.0 Signed-off-by: Jenn Nguyen * removed entry Signed-off-by: Jenn Nguyen --- CMakeLists.txt | 2 +- Changelog.md | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b24955f59..898012154 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(ignition-gui5 VERSION 5.2.0) +project(ignition-gui5 VERSION 5.3.0) #============================================================================ # Find ignition-cmake diff --git a/Changelog.md b/Changelog.md index e1ac3286e..8d9b5b357 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,23 @@ ### Ignition Gui 5.X.X (20XX-XX-XX) +### Ignition Gui 5.3.0 (2021-10-13) + +1. Improved doxygen + * [Pull request #275](https://github.com/ignitionrobotics/ign-gui/pull/275) + +1. Fix memory leak + * [Pull request #287](https://github.com/ignitionrobotics/ign-gui/pull/287) + +1. Add a filter to the plugin menu + * [Pull request #277](https://github.com/ignitionrobotics/ign-gui/pull/277) + +1. 👩‍🌾 Remove bitbucket-pipelines.yml + * [Pull request #274](https://github.com/ignitionrobotics/ign-gui/pull/274) + +1. Fix doc build error + * [Pull request #266](https://github.com/ignitionrobotics/ign-gui/pull/266) + ### Ignition Gui 5.2.0 (2021-07-27) 1. New teleop plugin implementation. From a8e18abb6ae28be80ede33c214eb667fb30d4542 Mon Sep 17 00:00:00 2001 From: Jenn Nguyen Date: Wed, 3 Nov 2021 15:01:00 -0700 Subject: [PATCH 08/11] Set near/far camera clipping distance (#309) Signed-off-by: Jenn Nguyen --- src/plugins/minimal_scene/MinimalScene.cc | 54 +++++++++++++++++++++++ src/plugins/minimal_scene/MinimalScene.hh | 19 +++++++- test/integration/minimal_scene.cc | 7 ++- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/plugins/minimal_scene/MinimalScene.cc b/src/plugins/minimal_scene/MinimalScene.cc index 913bf08b1..5b167094f 100644 --- a/src/plugins/minimal_scene/MinimalScene.cc +++ b/src/plugins/minimal_scene/MinimalScene.cc @@ -542,6 +542,8 @@ void IgnRenderer::Initialize() this->dataPtr->camera->SetUserData("user-camera", true); root->AddChild(this->dataPtr->camera); this->dataPtr->camera->SetLocalPose(this->cameraPose); + this->dataPtr->camera->SetNearClipPlane(this->cameraNearClip); + this->dataPtr->camera->SetFarClipPlane(this->cameraFarClip); this->dataPtr->camera->SetImageWidth(this->textureSize.width()); this->dataPtr->camera->SetImageHeight(this->textureSize.height()); this->dataPtr->camera->SetAntiAliasing(8); @@ -944,6 +946,18 @@ void RenderWindowItem::SetCameraPose(const math::Pose3d &_pose) this->dataPtr->renderThread->ignRenderer.cameraPose = _pose; } +///////////////////////////////////////////////// +void RenderWindowItem::SetCameraNearClip(double _near) +{ + this->dataPtr->renderThread->ignRenderer.cameraNearClip = _near; +} + +///////////////////////////////////////////////// +void RenderWindowItem::SetCameraFarClip(double _far) +{ + this->dataPtr->renderThread->ignRenderer.cameraFarClip = _far; +} + ///////////////////////////////////////////////// void RenderWindowItem::SetSceneService(const std::string &_service) { @@ -1044,6 +1058,46 @@ void MinimalScene::LoadConfig(const tinyxml2::XMLElement *_pluginElem) renderWindow->SetCameraPose(pose); } + elem = _pluginElem->FirstChildElement("camera_clip"); + if (nullptr != elem && !elem->NoChildren()) + { + auto child = elem->FirstChildElement("near"); + if (nullptr != child && nullptr != child->GetText()) + { + double n; + std::stringstream nearStr; + nearStr << std::string(child->GetText()); + nearStr >> n; + if (nearStr.fail()) + { + ignerr << "Unable to set to '" << nearStr.str() + << "' using default near clip distance" << std::endl; + } + else + { + renderWindow->SetCameraNearClip(n); + } + } + + child = elem->FirstChildElement("far"); + if (nullptr != child && nullptr != child->GetText()) + { + double f; + std::stringstream farStr; + farStr << std::string(child->GetText()); + farStr >> f; + if (farStr.fail()) + { + ignerr << "Unable to set to '" << farStr.str() + << "' using default far clip distance" << std::endl; + } + else + { + renderWindow->SetCameraFarClip(f); + } + } + } + elem = _pluginElem->FirstChildElement("service"); if (nullptr != elem && nullptr != elem->GetText()) { diff --git a/src/plugins/minimal_scene/MinimalScene.hh b/src/plugins/minimal_scene/MinimalScene.hh index c1c02a6f9..5dcb1f929 100644 --- a/src/plugins/minimal_scene/MinimalScene.hh +++ b/src/plugins/minimal_scene/MinimalScene.hh @@ -52,6 +52,9 @@ namespace plugins /// (0.3, 0.3, 0.3, 1.0) /// * \ : Optional starting pose for the camera, defaults to /// (0, 0, 5, 0, 0, 0) + /// * \ : Optional near/far clipping distance for camera + /// * \ : Camera's near clipping plane distance, defaults to 0.01 + /// * \ : Camera's far clipping plane distance, defaults to 1000.0 /// * \ : If present, sky is enabled. class MinimalScene : public Plugin { @@ -181,6 +184,12 @@ namespace plugins /// \brief Initial Camera pose public: math::Pose3d cameraPose = math::Pose3d(0, 0, 2, 0, 0.4, 0); + /// \brief Default camera near clipping plane distance + public: double cameraNearClip = 0.01; + + /// \brief Default camera far clipping plane distance + public: double cameraFarClip = 1000.0; + /// \brief Scene background color public: math::Color backgroundColor = math::Color::Black; @@ -283,9 +292,17 @@ namespace plugins public: void SetSceneName(const std::string &_name); /// \brief Set the initial pose the render window camera - /// \param[in] _pose Initical camera pose + /// \param[in] _pose Initial camera pose public: void SetCameraPose(const math::Pose3d &_pose); + /// \brief Set the render window camera's near clipping plane distance + /// \param[in] _near Near clipping plane distance + public: void SetCameraNearClip(double _near); + + /// \brief Set the render window camera's far clipping plane distance + /// \param[in] _far Far clipping plane distance + public: void SetCameraFarClip(double _far); + /// \brief Set scene service to use in this render window /// A service call will be made using ign-transport to get scene /// data using this service diff --git a/test/integration/minimal_scene.cc b/test/integration/minimal_scene.cc index fc291050f..728be48c9 100644 --- a/test/integration/minimal_scene.cc +++ b/test/integration/minimal_scene.cc @@ -82,6 +82,10 @@ TEST(MinimalSceneTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Config)) "1.0 0 0" "0 1 0" "1 2 3 0 0 1.57" + "" + " 0.1" + " 5000" + "" ""; tinyxml2::XMLDocument pluginDoc; @@ -126,6 +130,8 @@ TEST(MinimalSceneTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Config)) ASSERT_NE(nullptr, camera); EXPECT_EQ(math::Pose3d(1, 2, 3, 0, 0, 1.57), camera->WorldPose()); + EXPECT_DOUBLE_EQ(0.1, camera->NearClipPlane()); + EXPECT_DOUBLE_EQ(5000.0, camera->FarClipPlane()); // Cleanup auto plugins = win->findChildren(); @@ -139,4 +145,3 @@ TEST(MinimalSceneTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Config)) engine->DestroyScene(scene); EXPECT_TRUE(rendering::unloadEngine(engine->Name())); } - From d790029d17f7ea826bd1e9b3d101978a8247aad7 Mon Sep 17 00:00:00 2001 From: Louise Poubel Date: Fri, 5 Nov 2021 08:47:21 -0700 Subject: [PATCH 09/11] Fix doxygen (#311) Signed-off-by: Louise Poubel --- src/plugins/grid_config/GridConfig.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/grid_config/GridConfig.hh b/src/plugins/grid_config/GridConfig.hh index 48a357d46..859e8f4a5 100644 --- a/src/plugins/grid_config/GridConfig.hh +++ b/src/plugins/grid_config/GridConfig.hh @@ -49,7 +49,6 @@ namespace gui public: void UpdateGrid(); /// \brief Callback to retrieve existing grid or create a new one. - /// \param[in] _scene Scene to look for grid. public: void LoadGrid(); /// \brief Callback to update vertical cell count From 58987161ce462f2c978394ace6e80e333749454a Mon Sep 17 00:00:00 2001 From: Ashton Larkin <42042756+adlarkin@users.noreply.github.com> Date: Fri, 5 Nov 2021 11:19:11 -0600 Subject: [PATCH 10/11] Support emitting an event on play/pause/step (#306) * share updated GUI ECM info with server on play Signed-off-by: Ashton Larkin * clarify docs and fix service request type Signed-off-by: Ashton Larkin * send event on play/pause/step Signed-off-by: Ashton Larkin * support service and event Signed-off-by: Ashton Larkin * fix tests Signed-off-by: Ashton Larkin * Flip the default settng of usEvent in order to maintain current behavior by default Signed-off-by: Nate Koenig * ignore stats msgs triggered by a step Signed-off-by: Ashton Larkin * explicit constructor for new gui event Signed-off-by: Ashton Larkin * remove deprecation notes (support both event and service) Signed-off-by: Ashton Larkin * test event behavior Signed-off-by: Ashton Larkin * add missing helper test class Signed-off-by: Ashton Larkin * Disable tests on windows Signed-off-by: Nate Koenig * Address PR feedback Signed-off-by: Nate Koenig Co-authored-by: Nate Koenig Co-authored-by: Louise Poubel --- include/ignition/gui/GuiEvents.hh | 20 ++++ src/GuiEvents.cc | 19 ++++ src/GuiEvents_TEST.cc | 29 +++++ src/plugins/world_control/CMakeLists.txt | 28 +++-- src/plugins/world_control/WorldControl.cc | 103 +++++++++++++----- .../WorldControlEventListener.cc | 48 ++++++++ .../WorldControlEventListener.hh | 58 ++++++++++ .../world_control/WorldControl_TEST.cc | 78 +++++++++++-- 8 files changed, 337 insertions(+), 46 deletions(-) create mode 100644 src/plugins/world_control/WorldControlEventListener.cc create mode 100644 src/plugins/world_control/WorldControlEventListener.hh diff --git a/include/ignition/gui/GuiEvents.hh b/include/ignition/gui/GuiEvents.hh index 86fac1fad..f61972ae0 100644 --- a/include/ignition/gui/GuiEvents.hh +++ b/include/ignition/gui/GuiEvents.hh @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "ignition/gui/Export.hh" @@ -449,6 +450,25 @@ namespace ignition /// \brief Private data pointer IGN_UTILS_IMPL_PTR(dataPtr) }; + + /// \brief Event which is called to share WorldControl information. + class IGNITION_GUI_VISIBLE WorldControl : public QEvent + { + /// \brief Constructor + /// \param[in] _worldControl The WorldControl information + public: explicit WorldControl(const msgs::WorldControl &_worldControl); + + /// \brief Unique type for this event. + static const QEvent::Type kType = QEvent::Type(QEvent::MaxUser - 19); + + /// \brief Get the WorldControl information + /// \return The WorldControl information + public: const msgs::WorldControl &WorldControlInfo() const; + + /// \internal + /// \brief Private data pointer + IGN_UTILS_IMPL_PTR(dataPtr) + }; } } } diff --git a/src/GuiEvents.cc b/src/GuiEvents.cc index 16cacc25b..32185bfea 100644 --- a/src/GuiEvents.cc +++ b/src/GuiEvents.cc @@ -136,6 +136,12 @@ class ignition::gui::events::MousePressOnScene::Implementation public: common::MouseEvent mouse; }; +class ignition::gui::events::WorldControl::Implementation +{ + /// \brief WorldControl information. + public: msgs::WorldControl worldControl; +}; + using namespace ignition; using namespace gui; using namespace events; @@ -401,3 +407,16 @@ const common::MouseEvent &MousePressOnScene::Mouse() const { return this->dataPtr->mouse; } + +///////////////////////////////////////////////// +WorldControl::WorldControl(const msgs::WorldControl &_worldControl) + : QEvent(kType), dataPtr(utils::MakeImpl()) +{ + this->dataPtr->worldControl = _worldControl; +} + +///////////////////////////////////////////////// +const msgs::WorldControl &WorldControl::WorldControlInfo() const +{ + return this->dataPtr->worldControl; +} diff --git a/src/GuiEvents_TEST.cc b/src/GuiEvents_TEST.cc index a72e23864..253fa67d4 100644 --- a/src/GuiEvents_TEST.cc +++ b/src/GuiEvents_TEST.cc @@ -254,3 +254,32 @@ TEST(GuiEventsTest, MousePressOnScene) EXPECT_TRUE(event.Mouse().Alt()); EXPECT_FALSE(event.Mouse().Shift()); } + +///////////////////////////////////////////////// +TEST(GuiEventsTest, WorldControl) +{ + ignition::msgs::WorldControl worldControl; + worldControl.set_pause(true); + worldControl.set_step(true); + worldControl.set_multi_step(5u); + worldControl.mutable_reset()->set_all(true); + worldControl.mutable_reset()->set_time_only(true); + worldControl.mutable_reset()->set_model_only(false); + worldControl.set_seed(10u); + worldControl.mutable_run_to_sim_time()->set_sec(2); + worldControl.mutable_run_to_sim_time()->set_nsec(3); + events::WorldControl playEvent(worldControl); + + EXPECT_LT(QEvent::User, playEvent.type()); + EXPECT_FALSE(playEvent.WorldControlInfo().has_header()); + EXPECT_TRUE(playEvent.WorldControlInfo().pause()); + EXPECT_TRUE(playEvent.WorldControlInfo().step()); + EXPECT_EQ(5u, playEvent.WorldControlInfo().multi_step()); + EXPECT_FALSE(playEvent.WorldControlInfo().reset().has_header()); + EXPECT_TRUE(playEvent.WorldControlInfo().reset().all()); + EXPECT_TRUE(playEvent.WorldControlInfo().reset().time_only()); + EXPECT_FALSE(playEvent.WorldControlInfo().reset().model_only()); + EXPECT_EQ(10u, playEvent.WorldControlInfo().seed()); + EXPECT_EQ(2, playEvent.WorldControlInfo().run_to_sim_time().sec()); + EXPECT_EQ(3, playEvent.WorldControlInfo().run_to_sim_time().nsec()); +} diff --git a/src/plugins/world_control/CMakeLists.txt b/src/plugins/world_control/CMakeLists.txt index 7da2a0a0c..036f2ea61 100644 --- a/src/plugins/world_control/CMakeLists.txt +++ b/src/plugins/world_control/CMakeLists.txt @@ -1,9 +1,19 @@ -ign_gui_add_plugin(WorldControl - SOURCES - WorldControl.cc - QT_HEADERS - WorldControl.hh - TEST_SOURCES - WorldControl_TEST.cc -) - +if (NOT MSVC) + ign_gui_add_plugin(WorldControl + SOURCES + WorldControl.cc + WorldControlEventListener.cc + QT_HEADERS + WorldControl.hh + WorldControlEventListener.hh + TEST_SOURCES + WorldControl_TEST.cc + ) +else() + ign_gui_add_plugin(WorldControl + SOURCES + WorldControl.cc + QT_HEADERS + WorldControl.hh + ) +endif() diff --git a/src/plugins/world_control/WorldControl.cc b/src/plugins/world_control/WorldControl.cc index cbbe77bc1..91f32ee80 100644 --- a/src/plugins/world_control/WorldControl.cc +++ b/src/plugins/world_control/WorldControl.cc @@ -24,7 +24,10 @@ #include #include +#include "ignition/gui/Application.hh" #include "ignition/gui/Helpers.hh" +#include "ignition/gui/GuiEvents.hh" +#include "ignition/gui/MainWindow.hh" namespace ignition { @@ -34,6 +37,10 @@ namespace plugins { class WorldControlPrivate { + /// \brief Send the world control event or call the control service. + /// \param[in] _msg Message to send. + public: void SendEventMsg(const ignition::msgs::WorldControl &_msg); + /// \brief Message holding latest world statistics public: ignition::msgs::WorldStatistics msg; @@ -51,6 +58,15 @@ namespace plugins /// \brief True for paused public: bool pause{true}; + + /// \brief The paused state of the most recently received world stats msg + /// (true for paused) + public: bool lastStatsMsgPaused{true}; + + /// \brief Whether server communication should occur through an event (true) + /// or service (false). The service option is used by default for + /// ign-gui6, and should be changed to use the event by default in ign-gui7. + public: bool useEvent{false}; }; } } @@ -151,6 +167,7 @@ void WorldControl::LoadConfig(const tinyxml2::XMLElement *_pluginElem) pausedElem->QueryBoolText(&startPaused); } this->dataPtr->pause = startPaused; + this->dataPtr->lastStatsMsgPaused = startPaused; if (startPaused) this->paused(); else @@ -212,6 +229,14 @@ void WorldControl::LoadConfig(const tinyxml2::XMLElement *_pluginElem) ignerr << "Failed to create valid topic for world [" << worldName << "]" << std::endl; } + + if (auto elem = _pluginElem->FirstChildElement("use_event")) + elem->QueryBoolText(&this->dataPtr->useEvent); + + if (this->dataPtr->useEvent) + igndbg << "Using an event to share WorldControl msgs with the server\n"; + else + igndbg << "Using a service to share WorldControl msgs with the server\n"; } ///////////////////////////////////////////////// @@ -219,11 +244,26 @@ void WorldControl::ProcessMsg() { std::lock_guard lock(this->dataPtr->mutex); - if (!this->dataPtr->pause && this->dataPtr->msg.paused()) + // ignore the message if it's associated with a step + const auto &header = this->dataPtr->msg.header(); + if ((header.data_size() > 0) && (header.data(0).key() == "step")) + return; + + // If the pause state of the message doesn't match the pause state of this + // plugin, then play/pause must have occurred elsewhere (for example, the + // command line). If the pause state of the message matches the pause state + // of this plugin, but the pause state of the message differs from the + // previous message's pause state, this means that a pause/play request from + // this plugin has been registered by the server + if (this->dataPtr->msg.paused() && + (!this->dataPtr->pause || !this->dataPtr->lastStatsMsgPaused)) this->paused(); - else if (this->dataPtr->pause && !this->dataPtr->msg.paused()) + else if (!this->dataPtr->msg.paused() && + (this->dataPtr->pause || this->dataPtr->lastStatsMsgPaused)) this->playing(); + this->dataPtr->pause = this->dataPtr->msg.paused(); + this->dataPtr->lastStatsMsgPaused = this->dataPtr->msg.paused(); } ///////////////////////////////////////////////// @@ -238,33 +278,20 @@ void WorldControl::OnWorldStatsMsg(const ignition::msgs::WorldStatistics &_msg) ///////////////////////////////////////////////// void WorldControl::OnPlay() { - std::function cb = - [this](const ignition::msgs::Boolean &/*_rep*/, const bool _result) - { - if (_result) - QMetaObject::invokeMethod(this, "playing"); - }; - - ignition::msgs::WorldControl req; - req.set_pause(false); + ignition::msgs::WorldControl msg; + msg.set_pause(false); this->dataPtr->pause = false; - this->dataPtr->node.Request(this->dataPtr->controlService, req, cb); + this->dataPtr->SendEventMsg(msg); } ///////////////////////////////////////////////// void WorldControl::OnPause() { - std::function cb = - [this](const ignition::msgs::Boolean &/*_rep*/, const bool _result) - { - if (_result) - QMetaObject::invokeMethod(this, "paused"); - }; - - ignition::msgs::WorldControl req; - req.set_pause(true); + ignition::msgs::WorldControl msg; + msg.set_pause(true); this->dataPtr->pause = true; - this->dataPtr->node.Request(this->dataPtr->controlService, req, cb); + + this->dataPtr->SendEventMsg(msg); } ///////////////////////////////////////////////// @@ -276,15 +303,31 @@ void WorldControl::OnStepCount(const unsigned int _steps) ///////////////////////////////////////////////// void WorldControl::OnStep() { - std::function cb = - [](const ignition::msgs::Boolean &/*_rep*/, const bool /*_result*/) - { - }; + ignition::msgs::WorldControl msg; + msg.set_pause(this->dataPtr->pause); + msg.set_multi_step(this->dataPtr->multiStep); - ignition::msgs::WorldControl req; - req.set_pause(this->dataPtr->pause); - req.set_multi_step(this->dataPtr->multiStep); - this->dataPtr->node.Request(this->dataPtr->controlService, req, cb); + this->dataPtr->SendEventMsg(msg); +} + +///////////////////////////////////////////////// +void WorldControlPrivate::SendEventMsg(const ignition::msgs::WorldControl &_msg) +{ + if (this->useEvent) + { + gui::events::WorldControl event(_msg); + App()->sendEvent(App()->findChild(), &event); + } + else + { + std::function cb = + [](const ignition::msgs::Boolean &/*_rep*/, const bool /*_result*/) + { + // the service CB is empty because updates are handled in + // WorldControl::ProcessMsg + }; + this->node.Request(this->controlService, _msg, cb); + } } // Register this plugin diff --git a/src/plugins/world_control/WorldControlEventListener.cc b/src/plugins/world_control/WorldControlEventListener.cc new file mode 100644 index 000000000..c076748c1 --- /dev/null +++ b/src/plugins/world_control/WorldControlEventListener.cc @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +#include "WorldControlEventListener.hh" + +using namespace ignition; +using namespace gui; + +WorldControlEventListener::WorldControlEventListener() +{ + ignition::gui::App()->findChild< + ignition::gui::MainWindow *>()->installEventFilter(this); +} + +WorldControlEventListener::~WorldControlEventListener() = default; + +bool WorldControlEventListener::eventFilter(QObject *_obj, QEvent *_event) +{ + if (_event->type() == ignition::gui::events::WorldControl::kType) + { + auto worldControlEvent = + reinterpret_cast(_event); + if (worldControlEvent) + { + this->listenedToPlay = !worldControlEvent->WorldControlInfo().pause(); + this->listenedToPause = worldControlEvent->WorldControlInfo().pause(); + this->listenedToStep = + worldControlEvent->WorldControlInfo().multi_step() > 0u; + } + } + + // Standard event processing + return QObject::eventFilter(_obj, _event); +} diff --git a/src/plugins/world_control/WorldControlEventListener.hh b/src/plugins/world_control/WorldControlEventListener.hh new file mode 100644 index 000000000..8b4d34a8b --- /dev/null +++ b/src/plugins/world_control/WorldControlEventListener.hh @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ +#ifndef IGNITION_GUI_WORLDCONTROLEVENTLISTENER_HH_ +#define IGNITION_GUI_WORLDCONTROLEVENTLISTENER_HH_ + +#include "ignition/gui/Application.hh" +#include "ignition/gui/Export.hh" +#include "ignition/gui/GuiEvents.hh" +#include "ignition/gui/MainWindow.hh" +#include "ignition/gui/qt.h" + +namespace ignition +{ +namespace gui +{ + /// \brief Helper class for testing listening to events emitted by the + /// WorldControl plugin. This is used for testing the event behavior of + /// the WorldControl plugin. + class WorldControlEventListener : public QObject + { + Q_OBJECT + + /// \brief Constructor + public: WorldControlEventListener(); + + /// \brief Destructor + public: virtual ~WorldControlEventListener() override; + + // Documentation inherited + protected: bool eventFilter(QObject *_obj, QEvent *_event) override; + + /// \brief Whether a play event has been received (true) or not (false) + public: bool listenedToPlay{false}; + + /// \brief Whether a pause event has been received (true) or not (false) + public: bool listenedToPause{false}; + + /// \brief Whether a pause event has been received (true) or not (false) + public: bool listenedToStep{false}; + }; +} +} + +#endif diff --git a/src/plugins/world_control/WorldControl_TEST.cc b/src/plugins/world_control/WorldControl_TEST.cc index 809a934d0..4c8be21db 100644 --- a/src/plugins/world_control/WorldControl_TEST.cc +++ b/src/plugins/world_control/WorldControl_TEST.cc @@ -23,9 +23,10 @@ #include "test_config.h" // NOLINT(build/include) #include "ignition/gui/Application.hh" -#include "ignition/gui/Plugin.hh" #include "ignition/gui/MainWindow.hh" +#include "ignition/gui/Plugin.hh" #include "WorldControl.hh" +#include "WorldControlEventListener.hh" int g_argc = 1; char* g_argv[] = @@ -53,7 +54,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Load)) // Get plugin auto plugins = win->findChildren(); - EXPECT_EQ(plugins.size(), 1); + ASSERT_EQ(plugins.size(), 1); auto plugin = plugins[0]; EXPECT_EQ(plugin->Title(), "World control"); @@ -78,6 +79,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldControl)) "" "true" "/world_control_test" + "false" ""; tinyxml2::XMLDocument pluginDoc; @@ -94,7 +96,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldControl)) // Get plugin auto plugins = win->findChildren(); - EXPECT_EQ(plugins.size(), 1); + ASSERT_EQ(plugins.size(), 1); auto plugin = plugins[0]; EXPECT_EQ(plugin->Title(), "World Control!"); @@ -148,6 +150,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldNameNoService)) // Load plugin const char *pluginStr = "" + " false" ""; tinyxml2::XMLDocument pluginDoc; @@ -160,7 +163,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldNameNoService)) // Get plugin auto plugins = win->findChildren(); - EXPECT_EQ(plugins.size(), 1); + ASSERT_EQ(plugins.size(), 1); // World control service bool pauseCalled = false; @@ -201,6 +204,7 @@ TEST(WorldControlTest, const char *pluginStr = "" " /world/watermelon/control" + " false" ""; tinyxml2::XMLDocument pluginDoc; @@ -213,7 +217,7 @@ TEST(WorldControlTest, // Get plugin auto plugins = win->findChildren(); - EXPECT_EQ(plugins.size(), 1); + ASSERT_EQ(plugins.size(), 1); // World control service bool pauseCalled = false; @@ -252,6 +256,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldNameNoProp)) const char *pluginStr = "" " /world/watermelon/control" + " false" ""; tinyxml2::XMLDocument pluginDoc; @@ -264,7 +269,7 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldNameNoProp)) // Get plugin auto plugins = win->findChildren(); - EXPECT_EQ(plugins.size(), 1); + ASSERT_EQ(plugins.size(), 1); // World control service bool pauseCalled = false; @@ -276,7 +281,6 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldNameNoProp)) }; transport::Node node; - // banana, not watermelon node.Advertise("/world/watermelon/control", cb); // Pause @@ -286,3 +290,63 @@ TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldNameNoProp)) // Cleanup plugins.clear(); } + +///////////////////////////////////////////////// +TEST(WorldControlTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(WorldControlEvent)) +{ + common::Console::SetVerbosity(4); + + Application app(g_argc, g_argv); + app.AddPluginPath(std::string(PROJECT_BINARY_PATH) + "/lib"); + + // Load plugin + const char *pluginStr = + "" + "" + "World Control!" + "" + "true" + "/world_control_test" + "true" + ""; + + tinyxml2::XMLDocument pluginDoc; + EXPECT_EQ(tinyxml2::XML_SUCCESS, pluginDoc.Parse(pluginStr)); + EXPECT_TRUE(app.LoadPlugin("WorldControl", + pluginDoc.FirstChildElement("plugin"))); + + // Get main window + auto win = app.findChild(); + ASSERT_NE(nullptr, win); + + // Show, but don't exec, so we don't block + win->QuickWindow()->show(); + + // Get plugin + auto plugins = win->findChildren(); + ASSERT_EQ(plugins.size(), 1); + + auto plugin = plugins[0]; + EXPECT_EQ(plugin->Title(), "World Control!"); + + // World control event listener + ignition::gui::WorldControlEventListener eventListener; + EXPECT_FALSE(eventListener.listenedToPause); + EXPECT_FALSE(eventListener.listenedToStep); + EXPECT_FALSE(eventListener.listenedToPlay); + + // Pause + plugin->OnPause(); + EXPECT_TRUE(eventListener.listenedToPause); + + // Step + plugin->OnStep(); + EXPECT_TRUE(eventListener.listenedToStep); + + // Play + plugin->OnPlay(); + EXPECT_TRUE(eventListener.listenedToPlay); + + // Cleanup + plugins.clear(); +} From 195cec577f63cfd200b0c9a28299e700f3e709a2 Mon Sep 17 00:00:00 2001 From: Nate Koenig Date: Fri, 5 Nov 2021 10:58:12 -0700 Subject: [PATCH 11/11] Prepare for 6.1.0 release (#312) Signed-off-by: Nate Koenig Co-authored-by: Nate Koenig --- CMakeLists.txt | 2 +- Changelog.md | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b018e0cb..fc5c94242 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) #============================================================================ # Initialize the project #============================================================================ -project(ignition-gui6 VERSION 6.0.0) +project(ignition-gui6 VERSION 6.1.0) #============================================================================ # Find ignition-cmake diff --git a/Changelog.md b/Changelog.md index 0267e7f02..7638975f8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,21 @@ ## Ignition Gui 6 -### Ignition Gui 6.X.X +### Ignition Gui 6.1.0 (2021-11-05) + +1. Improved doxygen + * [Pull request #275](https://github.com/ignitionrobotics/ign-gui/pull/275) + +1. Fix mimimal scene deadlock on shutdown + * [Pull request #300](https://github.com/ignitionrobotics/ign-gui/pull/300) + +1. Fix memory leak + * [Pull request #287](https://github.com/ignitionrobotics/ign-gui/pull/287) + +1. Set near/far camera clipping distance + * [Pull request #309](https://github.com/ignitionrobotics/ign-gui/pull/309) + +1. Support emitting an event on play/pause/step + * [Pull request #306](https://github.com/ignitionrobotics/ign-gui/pull/306) ### Ignition Gui 6.0.0 (2021-09-XX)