From d79fe8e864d816257e6aaedca4d0a861bcb5ed8a Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Mon, 26 Apr 2021 12:38:52 -0700 Subject: [PATCH 01/18] enable scale mode Signed-off-by: Ian Chen --- .../plugins/transform_control/TransformControl.cc | 4 ++++ .../plugins/transform_control/TransformControl.hh | 3 +++ .../transform_control/TransformControl.qml | 15 +++++++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/gui/plugins/transform_control/TransformControl.cc b/src/gui/plugins/transform_control/TransformControl.cc index d4b1d8c94e..8c589731fe 100644 --- a/src/gui/plugins/transform_control/TransformControl.cc +++ b/src/gui/plugins/transform_control/TransformControl.cc @@ -245,6 +245,10 @@ bool TransformControl::eventFilter(QObject *_obj, QEvent *_event) { this->activateRotate(); } + else if (keyEvent->key() == Qt::Key_S) + { + this->activateScale(); + } } else if (_event->type() == QEvent::KeyRelease) { diff --git a/src/gui/plugins/transform_control/TransformControl.hh b/src/gui/plugins/transform_control/TransformControl.hh index 3c8a4e5dd5..3d1ffa3b3b 100644 --- a/src/gui/plugins/transform_control/TransformControl.hh +++ b/src/gui/plugins/transform_control/TransformControl.hh @@ -142,6 +142,9 @@ namespace gazebo /// \brief Notify that rotation has been activated signals: void activateRotate(); + /// \brief Notify that scale has been activated + signals: void activateScale(); + /// \internal /// \brief Pointer to private data. private: std::unique_ptr dataPtr; diff --git a/src/gui/plugins/transform_control/TransformControl.qml b/src/gui/plugins/transform_control/TransformControl.qml index 2563902daa..d046e63dc8 100644 --- a/src/gui/plugins/transform_control/TransformControl.qml +++ b/src/gui/plugins/transform_control/TransformControl.qml @@ -29,10 +29,10 @@ ToolBar { Layout.minimumHeight: 100 // TODO(anyone) enable scale button when support is added in ign-physics - // function activateScale() { - // scale.checked = true; - // TransformControl.OnMode("scale"); - // } + function activateScale() { + scale.checked = true; + TransformControl.OnMode("scale"); + } property color snapTitle: (Material.theme == Material.Light) ? Material.color(Material.Grey, Material.Shade900) : @@ -106,6 +106,11 @@ ToolBar { onActivateRotate: activateRotate(); } + Connections { + target: TransformControl + onActivateScale: activateScale(); + } + RowLayout { spacing: 2 ToolButton { @@ -222,7 +227,6 @@ ToolBar { // TODO(anyone) enable scale snap values below when support is added in ign-physics // Also be sure to replace the placeholder 0's in all of the `OnSnapUpdate` calls in // this file to xScaleEntry.value, yScaleEntry.value, and zScaleEntry.value, respectively - /* ToolButton { id: scale text: "S" @@ -260,7 +264,6 @@ ToolBar { TransformControl.OnMode("scale") } } - */ ToolButton { id: snap From fdb7341a20eeea3700fc9255c395a706aba5994b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 30 Apr 2021 18:43:07 +0200 Subject: [PATCH 02/18] Visual scaling enabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- .../ignition/gazebo/rendering/RenderUtil.hh | 5 ++ src/gui/plugins/scene3d/Scene3D.cc | 85 ++++++++++++++++++- src/rendering/RenderUtil.cc | 20 +++++ src/rendering/SceneManager.cc | 5 ++ 4 files changed, 114 insertions(+), 1 deletion(-) diff --git a/include/ignition/gazebo/rendering/RenderUtil.hh b/include/ignition/gazebo/rendering/RenderUtil.hh index 5d64553867..55ecdc4600 100644 --- a/include/ignition/gazebo/rendering/RenderUtil.hh +++ b/include/ignition/gazebo/rendering/RenderUtil.hh @@ -158,6 +158,11 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { /// \param[in] _active True if active. public: void SetTransformActive(bool _active); + /// Scale a given wirebox. + /// \param[in] _entityId The entity Id. + /// \param[in] _scale Scale vector. + public: void ScaleWireBox(int _entityId, const math::Vector3d &_scale); + /// \brief Private data pointer. private: std::unique_ptr dataPtr; }; diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index ab85034298..0361167bae 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1607,10 +1607,53 @@ void IgnRenderer::HandleMouseTransformControl() else if (this->dataPtr->transformControl.Mode() == rendering::TransformMode::TM_SCALE) { + // Check if the model that we're trying to scale looks like a simple shape + // It will need to have only two children nodes: one for the visual gizmo + // and another one for the link. + auto node = this->dataPtr->transformControl.Node(); + auto v = std::dynamic_pointer_cast(node); + if (!v) + return; + + if (v->ChildCount() != 2) + return; + + auto c1 = v->ChildByIndex(0); + auto c2 = v->ChildByIndex(1); + ignition::rendering::VisualPtr leafNode; + + if (c1->Name().find("scene::Visual") != std::string::npos) + { + if (c2->ChildCount() != 1) + return; + + leafNode = std::dynamic_pointer_cast( + c2->ChildByIndex(0)); + } + else + { + if (c1->ChildCount() != 1) + return; + + leafNode = std::dynamic_pointer_cast( + c1->ChildByIndex(0)); + } + + int userData = std::get(leafNode->UserData("geometry-type")); + sdf::GeometryType geomType = static_cast(userData); + + // We only support scaling of simple shapes. + if (userData != static_cast(sdf::GeometryType::BOX) && + userData != static_cast(sdf::GeometryType::CYLINDER) && + userData != static_cast(sdf::GeometryType::SPHERE)) + { + return; + } + this->XYZConstraint(axis); // note: scaling is limited to local space math::Vector3d scale = - this->dataPtr->transformControl.ScaleFrom2d(axis, start, end); + this->dataPtr->transformControl.ScaleFrom2d(axis, start, end); if (this->dataPtr->keyEvent.Control()) { math::Vector3d snapVals = this->ScaleSnap(); @@ -1624,7 +1667,47 @@ void IgnRenderer::HandleMouseTransformControl() SnapPoint(scale, snapVals); } + + // Apply geometry constaints to the scaling. + if (geomType == sdf::GeometryType::SPHERE) + { + if (axis.X() > 0) + { + scale.Y(scale.X()); + scale.Z(scale.X()); + } + else if (axis.Y() > 0) + { + scale.X(scale.Y()); + scale.Z(scale.Y()); + } + else if (axis.Z() > 0) + { + scale.X(scale.Z()); + scale.Y(scale.Z()); + } + } + else if (geomType == sdf::GeometryType::CYLINDER) + { + if (axis.X() > 0) + { + scale.Y(scale.X()); + } + else if (axis.Y() > 0) + { + scale.X(scale.Y()); + } + } + + // Scale. this->dataPtr->transformControl.Scale(scale); + + // Update the bounding box. + if (v) + { + Entity entityId = std::get(v->UserData("gazebo-entity")); + this->dataPtr->renderUtil.ScaleWireBox(entityId, scale); + } } this->dataPtr->drag = 0; this->dataPtr->mouseDirty = false; diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index 4d94e6532d..d173f5740d 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -2058,6 +2058,26 @@ void RenderUtilPrivate::LowlightNode(const rendering::NodePtr &_node) } } +///////////////////////////////////////////////// +void RenderUtil::ScaleWireBox(int _entityId, const math::Vector3d &_scale) +{ + if (this->dataPtr->wireBoxes.find(_entityId) == + this->dataPtr->wireBoxes.end()) + { + return; + } + + ignition::rendering::WireBoxPtr wireBox = this->dataPtr->wireBoxes[_entityId]; + if (!wireBox) + return; + + auto visParent = wireBox->Parent(); + if (!visParent) + return; + + visParent->SetLocalScale(_scale); +} + ///////////////////////////////////////////////// void RenderUtil::ViewCollisions(const Entity &_entity) { diff --git a/src/rendering/SceneManager.cc b/src/rendering/SceneManager.cc index 06219d9387..192d61812a 100644 --- a/src/rendering/SceneManager.cc +++ b/src/rendering/SceneManager.cc @@ -265,6 +265,11 @@ rendering::VisualPtr SceneManager::CreateVisual(Entity _id, rendering::VisualPtr visualVis = this->dataPtr->scene->CreateVisual(name); visualVis->SetUserData("gazebo-entity", static_cast(_id)); visualVis->SetUserData("pause-update", static_cast(0)); + + auto geometry = _visual.Geom(); + if (geometry) + visualVis->SetUserData("geometry-type", static_cast(geometry->Type())); + visualVis->SetLocalPose(_visual.RawPose()); if (_visual.HasLaserRetro()) From 3a711dda5d2e1a86f89d4f963e331208a93482b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 30 Apr 2021 22:00:44 +0200 Subject: [PATCH 03/18] Tweak signature. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- include/ignition/gazebo/rendering/RenderUtil.hh | 3 ++- src/rendering/RenderUtil.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/ignition/gazebo/rendering/RenderUtil.hh b/include/ignition/gazebo/rendering/RenderUtil.hh index 55ecdc4600..329420b137 100644 --- a/include/ignition/gazebo/rendering/RenderUtil.hh +++ b/include/ignition/gazebo/rendering/RenderUtil.hh @@ -161,7 +161,8 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { /// Scale a given wirebox. /// \param[in] _entityId The entity Id. /// \param[in] _scale Scale vector. - public: void ScaleWireBox(int _entityId, const math::Vector3d &_scale); + public: void ScaleWireBox(const Entity &_entityId, + const math::Vector3d &_scale); /// \brief Private data pointer. private: std::unique_ptr dataPtr; diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index d173f5740d..158b5dd5e7 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -2059,7 +2059,8 @@ void RenderUtilPrivate::LowlightNode(const rendering::NodePtr &_node) } ///////////////////////////////////////////////// -void RenderUtil::ScaleWireBox(int _entityId, const math::Vector3d &_scale) +void RenderUtil::ScaleWireBox(const Entity &_entityId, + const math::Vector3d &_scale) { if (this->dataPtr->wireBoxes.find(_entityId) == this->dataPtr->wireBoxes.end()) From 00b7d9386a740fa0fd69aba84f09fdcad42ef651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 7 May 2021 17:21:45 +0200 Subject: [PATCH 04/18] Check if simple mesh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/gui/plugins/scene3d/Scene3D.cc | 85 +++++++++++-------- src/gui/plugins/scene3d/Scene3D.hh | 10 +++ .../transform_control/TransformControl.qml | 3 - 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index 0361167bae..f4fc1713dc 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1341,6 +1341,51 @@ void IgnRenderer::XYZConstraint(math::Vector3d &_axis) } } +///////////////////////////////////////////////// +bool IgnRenderer::ContainsSimpleShape(const rendering::NodePtr &_node, + rendering::VisualPtr &_visual) const +{ + std::queue q; + + // Adding the root node. + q.push(_node); + + while (!q.empty()) + { + // Process the next node. + auto n = q.front(); + q.pop(); + if (n) + { + auto v = std::dynamic_pointer_cast(n); + if (v) + { + try + { + int userData = std::get(v->UserData("geometry-type")); + + if (userData == static_cast(sdf::GeometryType::BOX) || + userData == static_cast(sdf::GeometryType::CYLINDER) || + userData == static_cast(sdf::GeometryType::SPHERE)) + { + _visual = v; + return true; + } + } + catch (const std::bad_variant_access& ex) + { + } + } + + // Add all children to the queue to be considered. + for (auto i = 0u; i < n->ChildCount(); ++i) + q.push(n->ChildByIndex(i)); + } + } + + return false; +} + ///////////////////////////////////////////////// void IgnRenderer::HandleMouseTransformControl() { @@ -1608,48 +1653,16 @@ void IgnRenderer::HandleMouseTransformControl() rendering::TransformMode::TM_SCALE) { // Check if the model that we're trying to scale looks like a simple shape - // It will need to have only two children nodes: one for the visual gizmo - // and another one for the link. + rendering::VisualPtr visualSimple; auto node = this->dataPtr->transformControl.Node(); auto v = std::dynamic_pointer_cast(node); - if (!v) + bool found = this->ContainsSimpleShape(node, visualSimple); + if (!found) return; - if (v->ChildCount() != 2) - return; - - auto c1 = v->ChildByIndex(0); - auto c2 = v->ChildByIndex(1); - ignition::rendering::VisualPtr leafNode; - - if (c1->Name().find("scene::Visual") != std::string::npos) - { - if (c2->ChildCount() != 1) - return; - - leafNode = std::dynamic_pointer_cast( - c2->ChildByIndex(0)); - } - else - { - if (c1->ChildCount() != 1) - return; - - leafNode = std::dynamic_pointer_cast( - c1->ChildByIndex(0)); - } - - int userData = std::get(leafNode->UserData("geometry-type")); + int userData = std::get(v->UserData("geometry-type")); sdf::GeometryType geomType = static_cast(userData); - // We only support scaling of simple shapes. - if (userData != static_cast(sdf::GeometryType::BOX) && - userData != static_cast(sdf::GeometryType::CYLINDER) && - userData != static_cast(sdf::GeometryType::SPHERE)) - { - return; - } - this->XYZConstraint(axis); // note: scaling is limited to local space math::Vector3d scale = diff --git a/src/gui/plugins/scene3d/Scene3D.hh b/src/gui/plugins/scene3d/Scene3D.hh index 3f51fde8dc..6bfeef590b 100644 --- a/src/gui/plugins/scene3d/Scene3D.hh +++ b/src/gui/plugins/scene3d/Scene3D.hh @@ -439,6 +439,16 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { /// when the deselection is initiated from this plugin. private: void DeselectAllEntities(bool _sendEvent); + /// \brief Helper function that traverses the node tree looking for any + /// child with the "geometry-type" user data. If found, the function also + /// checks if the value is a simple shape (box, cylinder or sphere). + /// \param[in] _node Root node. + /// \param[out] _visual The visual pointer to the simple shape if found. + /// \return True if any simple shape was found in the tree or false + /// otherwise. + private: bool ContainsSimpleShape(const rendering::NodePtr &_node, + rendering::VisualPtr &_visual) const; + /// \brief Signal fired when context menu event is triggered signals: void ContextMenuRequested(QString _entity); diff --git a/src/gui/plugins/transform_control/TransformControl.qml b/src/gui/plugins/transform_control/TransformControl.qml index d046e63dc8..2dd7d2a1a7 100644 --- a/src/gui/plugins/transform_control/TransformControl.qml +++ b/src/gui/plugins/transform_control/TransformControl.qml @@ -224,9 +224,6 @@ ToolBar { TransformControl.OnMode("rotate") } } - // TODO(anyone) enable scale snap values below when support is added in ign-physics - // Also be sure to replace the placeholder 0's in all of the `OnSnapUpdate` calls in - // this file to xScaleEntry.value, yScaleEntry.value, and zScaleEntry.value, respectively ToolButton { id: scale text: "S" From 241066820463ea700291c8d193100cb76446a21d Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Fri, 7 May 2021 11:34:47 -0700 Subject: [PATCH 05/18] fix scaling wirebox Signed-off-by: Ian Chen --- include/ignition/gazebo/rendering/RenderUtil.hh | 4 ++-- src/gui/plugins/scene3d/Scene3D.cc | 3 ++- src/rendering/RenderUtil.cc | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/ignition/gazebo/rendering/RenderUtil.hh b/include/ignition/gazebo/rendering/RenderUtil.hh index 329420b137..da210532eb 100644 --- a/include/ignition/gazebo/rendering/RenderUtil.hh +++ b/include/ignition/gazebo/rendering/RenderUtil.hh @@ -158,10 +158,10 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { /// \param[in] _active True if active. public: void SetTransformActive(bool _active); - /// Scale a given wirebox. + /// Set the scale of a given wirebox. /// \param[in] _entityId The entity Id. /// \param[in] _scale Scale vector. - public: void ScaleWireBox(const Entity &_entityId, + public: void SetWireBoxScale(const Entity &_entityId, const math::Vector3d &_scale); /// \brief Private data pointer. diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index f4fc1713dc..a991855c50 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1719,7 +1719,8 @@ void IgnRenderer::HandleMouseTransformControl() if (v) { Entity entityId = std::get(v->UserData("gazebo-entity")); - this->dataPtr->renderUtil.ScaleWireBox(entityId, scale); + auto s = this->dataPtr->transformControl.Node()->LocalScale(); + this->dataPtr->renderUtil.SetWireBoxScale(entityId, s); } } this->dataPtr->drag = 0; diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index 158b5dd5e7..34f674282f 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -2059,7 +2059,7 @@ void RenderUtilPrivate::LowlightNode(const rendering::NodePtr &_node) } ///////////////////////////////////////////////// -void RenderUtil::ScaleWireBox(const Entity &_entityId, +void RenderUtil::SetWireBoxScale(const Entity &_entityId, const math::Vector3d &_scale) { if (this->dataPtr->wireBoxes.find(_entityId) == From 99a47234191fd2369d3d57163e7f42c6918fd289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 7 May 2021 21:46:15 +0200 Subject: [PATCH 06/18] Tweaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- include/ignition/gazebo/rendering/RenderUtil.hh | 2 +- src/gui/plugins/scene3d/Scene3D.cc | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/ignition/gazebo/rendering/RenderUtil.hh b/include/ignition/gazebo/rendering/RenderUtil.hh index da210532eb..e14fa3bf51 100644 --- a/include/ignition/gazebo/rendering/RenderUtil.hh +++ b/include/ignition/gazebo/rendering/RenderUtil.hh @@ -160,7 +160,7 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { /// Set the scale of a given wirebox. /// \param[in] _entityId The entity Id. - /// \param[in] _scale Scale vector. + /// \param[in] _scale Scale vector in absolute coordinates. public: void SetWireBoxScale(const Entity &_entityId, const math::Vector3d &_scale); diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index a991855c50..7dc76f241e 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1728,7 +1728,6 @@ void IgnRenderer::HandleMouseTransformControl() } } - ///////////////////////////////////////////////// void IgnRenderer::HandleMouseViewControl() { From 5e8910d100907e1482e46931f2e202129cbbc955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 7 May 2021 21:51:25 +0200 Subject: [PATCH 07/18] Add TODO note. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/rendering/RenderUtil.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index 34f674282f..5fec14cf3f 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -2062,6 +2062,8 @@ void RenderUtilPrivate::LowlightNode(const rendering::NodePtr &_node) void RenderUtil::SetWireBoxScale(const Entity &_entityId, const math::Vector3d &_scale) { + /// \TODO(anyone) Consider to use this->dataPtr->sceneManager.NodeById() + /// when WireBox are tracked in the scene manager. if (this->dataPtr->wireBoxes.find(_entityId) == this->dataPtr->wireBoxes.end()) { From ff9b35fab39948ad90e75f5266bdcd65dce2d535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Fri, 7 May 2021 21:51:39 +0200 Subject: [PATCH 08/18] Add TODO note. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/rendering/RenderUtil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index 5fec14cf3f..9d7b77c93b 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -2063,7 +2063,7 @@ void RenderUtil::SetWireBoxScale(const Entity &_entityId, const math::Vector3d &_scale) { /// \TODO(anyone) Consider to use this->dataPtr->sceneManager.NodeById() - /// when WireBox are tracked in the scene manager. + /// when WireBoxes are tracked in the scene manager. if (this->dataPtr->wireBoxes.find(_entityId) == this->dataPtr->wireBoxes.end()) { From 7d0728af45f193a2ad28b8d3b689ca0765f58c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Thu, 27 May 2021 19:00:41 +0200 Subject: [PATCH 09/18] Adding error messages and ToDos. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/gui/plugins/scene3d/Scene3D.cc | 1 + src/rendering/RenderUtil.cc | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index 7dc76f241e..9c72999359 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1364,6 +1364,7 @@ bool IgnRenderer::ContainsSimpleShape(const rendering::NodePtr &_node, { int userData = std::get(v->UserData("geometry-type")); + /// \TODO(anyone) Consider sdf::GeometryType::CAPSULE in Edifice. if (userData == static_cast(sdf::GeometryType::BOX) || userData == static_cast(sdf::GeometryType::CYLINDER) || userData == static_cast(sdf::GeometryType::SPHERE)) diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc index 9d7b77c93b..d5140a47b7 100644 --- a/src/rendering/RenderUtil.cc +++ b/src/rendering/RenderUtil.cc @@ -2067,16 +2067,26 @@ void RenderUtil::SetWireBoxScale(const Entity &_entityId, if (this->dataPtr->wireBoxes.find(_entityId) == this->dataPtr->wireBoxes.end()) { + ignerr << "Trying to scale a wirebox with unknown id [" << _entityId + << "]" << std::endl; return; } ignition::rendering::WireBoxPtr wireBox = this->dataPtr->wireBoxes[_entityId]; if (!wireBox) + { + ignerr << "Null wirebox associated to id [" << _entityId + << "]" << std::endl; return; + } auto visParent = wireBox->Parent(); if (!visParent) + { + ignerr << "Trying to scale a wirebox with null parent [" << _entityId + << "]" << std::endl; return; + } visParent->SetLocalScale(_scale); } From 3b857a95eabebb641e77e02298b1d916d0aa5d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Thu, 27 May 2021 20:37:36 +0200 Subject: [PATCH 10/18] Expand TODO with ellipsoid. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/gui/plugins/scene3d/Scene3D.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index 9c72999359..e283c5a382 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1364,7 +1364,8 @@ bool IgnRenderer::ContainsSimpleShape(const rendering::NodePtr &_node, { int userData = std::get(v->UserData("geometry-type")); - /// \TODO(anyone) Consider sdf::GeometryType::CAPSULE in Edifice. + /// \TODO(anyone) Consider sdf::GeometryType::CAPSULE and + /// sdf::GeometryType::ELLIPSOID in Edifice. if (userData == static_cast(sdf::GeometryType::BOX) || userData == static_cast(sdf::GeometryType::CYLINDER) || userData == static_cast(sdf::GeometryType::SPHERE)) From 124772c06471b0de54e4ed8a4cc2bd2920fc302e Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Fri, 28 May 2021 10:01:09 -0500 Subject: [PATCH 11/18] Lint Signed-off-by: Michael Carroll --- src/gui/plugins/scene3d/Scene3D.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index e283c5a382..dd4834095a 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include From d449365a6b933a18dd95b19664d889e03b897751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 21 Jun 2021 16:20:42 +0200 Subject: [PATCH 12/18] Tweak ContainsSimpleShape() signature. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/gui/plugins/scene3d/Scene3D.cc | 14 ++++++-------- src/gui/plugins/scene3d/Scene3D.hh | 7 +++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index dd4834095a..760763d5b8 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1343,8 +1343,8 @@ void IgnRenderer::XYZConstraint(math::Vector3d &_axis) } ///////////////////////////////////////////////// -bool IgnRenderer::ContainsSimpleShape(const rendering::NodePtr &_node, - rendering::VisualPtr &_visual) const +rendering::VisualPtr IgnRenderer::ContainsSimpleShape( + const rendering::NodePtr) const { std::queue q; @@ -1371,8 +1371,7 @@ bool IgnRenderer::ContainsSimpleShape(const rendering::NodePtr &_node, userData == static_cast(sdf::GeometryType::CYLINDER) || userData == static_cast(sdf::GeometryType::SPHERE)) { - _visual = v; - return true; + return v; } } catch (const std::bad_variant_access& ex) @@ -1386,7 +1385,7 @@ bool IgnRenderer::ContainsSimpleShape(const rendering::NodePtr &_node, } } - return false; + return nullptr; } ///////////////////////////////////////////////// @@ -1656,11 +1655,10 @@ void IgnRenderer::HandleMouseTransformControl() rendering::TransformMode::TM_SCALE) { // Check if the model that we're trying to scale looks like a simple shape - rendering::VisualPtr visualSimple; auto node = this->dataPtr->transformControl.Node(); auto v = std::dynamic_pointer_cast(node); - bool found = this->ContainsSimpleShape(node, visualSimple); - if (!found) + rendering::VisualPtr visualSimple = this->ContainsSimpleShape(node); + if (!visualSimple) return; int userData = std::get(v->UserData("geometry-type")); diff --git a/src/gui/plugins/scene3d/Scene3D.hh b/src/gui/plugins/scene3d/Scene3D.hh index 6bfeef590b..2f454acc96 100644 --- a/src/gui/plugins/scene3d/Scene3D.hh +++ b/src/gui/plugins/scene3d/Scene3D.hh @@ -443,11 +443,10 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { /// child with the "geometry-type" user data. If found, the function also /// checks if the value is a simple shape (box, cylinder or sphere). /// \param[in] _node Root node. - /// \param[out] _visual The visual pointer to the simple shape if found. - /// \return True if any simple shape was found in the tree or false + /// \return The visual pointer to the simple shape if found or nullptr /// otherwise. - private: bool ContainsSimpleShape(const rendering::NodePtr &_node, - rendering::VisualPtr &_visual) const; + private: rendering::VisualPtr ContainsSimpleShape( + const rendering::NodePtr &_node) const; /// \brief Signal fired when context menu event is triggered signals: void ContextMenuRequested(QString _entity); From c37424bdfbadc937b8e9eb1f45ce6f82f860d6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 21 Jun 2021 16:26:43 +0200 Subject: [PATCH 13/18] Tweak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/gui/plugins/scene3d/Scene3D.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index 760763d5b8..211dfd0bc3 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1344,7 +1344,7 @@ void IgnRenderer::XYZConstraint(math::Vector3d &_axis) ///////////////////////////////////////////////// rendering::VisualPtr IgnRenderer::ContainsSimpleShape( - const rendering::NodePtr) const + const rendering::NodePtr &_node) const { std::queue q; From 01ec14146d4da2b118fcf923ca1133b56d384c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Thu, 24 Jun 2021 23:08:23 +0200 Subject: [PATCH 14/18] Add ModelSDF serializer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- include/ignition/gazebo/components/Model.hh | 55 ++++++++++++++++++- test/integration/components.cc | 61 +++++++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/include/ignition/gazebo/components/Model.hh b/include/ignition/gazebo/components/Model.hh index 7fdc7014ce..651e295ef1 100644 --- a/include/ignition/gazebo/components/Model.hh +++ b/include/ignition/gazebo/components/Model.hh @@ -17,7 +17,10 @@ #ifndef IGNITION_GAZEBO_COMPONENTS_MODEL_HH_ #define IGNITION_GAZEBO_COMPONENTS_MODEL_HH_ +#include + #include +#include #include #include @@ -29,6 +32,54 @@ namespace gazebo { // Inline bracket to help doxygen filtering. inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE { +namespace serializers +{ + class SdfModelSerializer + { + /// \brief Serialization for `sdf::Model`. + /// \param[in] _out Output stream. + /// \param[in] _time Model to stream + /// \return The stream. + public: static std::ostream &Serialize(std::ostream &_out, + const sdf::Model &_model) + { + sdf::ElementPtr modelElem = _model.Element(); + if (!modelElem) + { + ignerr << "Unable to serialize sdf::Model" << std::endl; + return _out; + } + + _out << "" + << "" + << modelElem->ToString("") + << ""; + return _out; + } + + /// \brief Deserialization for `sdf::Model`. + /// \param[in] _in Input stream. + /// \param[out] _model Model to populate + /// \return The stream. + public: static std::istream &Deserialize(std::istream &_in, + sdf::Model &_model) + { + sdf::Root root; + std::string sdf(std::istreambuf_iterator(_in), {}); + + sdf::Errors errors = root.LoadSdfString(sdf); + if (!errors.empty()) + { + ignerr << "Unable to unserialize sdf::Model" << std::endl; + return _in; + } + + _model.Load(root.Element()->GetElement("model")); + return _in; + } + }; +} + namespace components { /// \brief A component that identifies an entity as being a model. @@ -36,7 +87,9 @@ namespace components IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.Model", Model) /// \brief A component that holds the model's SDF DOM - using ModelSdf = Component; + using ModelSdf = Component; IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.ModelSdf", ModelSdf) } } diff --git a/test/integration/components.cc b/test/integration/components.cc index c341dfcc0d..c306ca18c1 100644 --- a/test/integration/components.cc +++ b/test/integration/components.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "ignition/gazebo/components/Actor.hh" @@ -1098,6 +1099,66 @@ TEST_F(ComponentsTest, Model) comp3.Deserialize(istr); } +///////////////////////////////////////////////// +TEST_F(ComponentsTest, ModelSdf) +{ + std::ostringstream stream; + std::string version = SDF_VERSION; + stream + << "" + << "" + << " " + << " " + << " 0.001" + << " 1.0" + << " " + << " " + << " " + << " " + << " " + << " " + << " 0.1 0 0 0 0 0" + << " 0.2 0.3 0.4 1" + << " 0.3 0.4 0.5 1" + << " " + << " " + << " " + << " " + << ""; + + sdf::SDFPtr sdfParsed(new sdf::SDF()); + sdf::init(sdfParsed); + ASSERT_TRUE(sdf::readString(stream.str(), sdfParsed)); + + // model + EXPECT_TRUE(sdfParsed->Root()->HasElement("world")); + sdf::ElementPtr worldElem = sdfParsed->Root()->GetElement("world"); + EXPECT_TRUE(worldElem->HasElement("model")); + sdf::ElementPtr modelElem = worldElem->GetElement("model"); + EXPECT_TRUE(modelElem->HasAttribute("name")); + EXPECT_EQ(modelElem->Get("name"), "my_model"); + + sdf::Model model; + model.Load(modelElem); + EXPECT_EQ("my_model", model.Name()); + + // Create components + auto comp1 = components::ModelSdf(model); + components::ModelSdf comp2; + + // Stream operators + std::ostringstream ostr; + comp1.Serialize(ostr); + + std::istringstream istr(ostr.str()); + comp2.Deserialize(istr); + + EXPECT_EQ("my_model", comp2.Data().Name()); + EXPECT_EQ(1u, comp2.Data().LinkCount()); +} + ///////////////////////////////////////////////// TEST_F(ComponentsTest, Name) { From 556b16b4eb4693616f4755cb62a45480a519ce7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Thu, 24 Jun 2021 23:09:35 +0200 Subject: [PATCH 15/18] Use SDF_PROTOCOL_VERSION instead. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- include/ignition/gazebo/components/Model.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ignition/gazebo/components/Model.hh b/include/ignition/gazebo/components/Model.hh index 651e295ef1..6655cca652 100644 --- a/include/ignition/gazebo/components/Model.hh +++ b/include/ignition/gazebo/components/Model.hh @@ -51,7 +51,7 @@ namespace serializers } _out << "" - << "" + << "" << modelElem->ToString("") << ""; return _out; From bbfb28bac1fe451ac77763097597eb567ad9de9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 26 Jul 2021 17:53:58 +0200 Subject: [PATCH 16/18] Print warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- src/gui/plugins/scene3d/Scene3D.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/plugins/scene3d/Scene3D.cc b/src/gui/plugins/scene3d/Scene3D.cc index 211dfd0bc3..a6078de2b6 100644 --- a/src/gui/plugins/scene3d/Scene3D.cc +++ b/src/gui/plugins/scene3d/Scene3D.cc @@ -1659,7 +1659,10 @@ void IgnRenderer::HandleMouseTransformControl() auto v = std::dynamic_pointer_cast(node); rendering::VisualPtr visualSimple = this->ContainsSimpleShape(node); if (!visualSimple) + { + ignwarn << "Scaling not supported for this visual type." << std::endl; return; + } int userData = std::get(v->UserData("geometry-type")); sdf::GeometryType geomType = static_cast(userData); From f9e262684e07eae73fc2339e8a7513cf1826c419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 26 Jul 2021 18:16:25 +0200 Subject: [PATCH 17/18] Tweak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- include/ignition/gazebo/components/Model.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ignition/gazebo/components/Model.hh b/include/ignition/gazebo/components/Model.hh index 6655cca652..5131bbb7ce 100644 --- a/include/ignition/gazebo/components/Model.hh +++ b/include/ignition/gazebo/components/Model.hh @@ -68,7 +68,7 @@ namespace serializers std::string sdf(std::istreambuf_iterator(_in), {}); sdf::Errors errors = root.LoadSdfString(sdf); - if (!errors.empty()) + if (!root.Element()->GetElement("model")) { ignerr << "Unable to unserialize sdf::Model" << std::endl; return _in; From 0dd2af31376b5cb0ff49b977ae3d350d05b0f062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 9 Aug 2021 15:19:40 +0200 Subject: [PATCH 18/18] Use HasElement() instead. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Agüero --- include/ignition/gazebo/components/Model.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ignition/gazebo/components/Model.hh b/include/ignition/gazebo/components/Model.hh index 5131bbb7ce..b1dd9f9f96 100644 --- a/include/ignition/gazebo/components/Model.hh +++ b/include/ignition/gazebo/components/Model.hh @@ -68,7 +68,7 @@ namespace serializers std::string sdf(std::istreambuf_iterator(_in), {}); sdf::Errors errors = root.LoadSdfString(sdf); - if (!root.Element()->GetElement("model")) + if (!root.Element()->HasElement("model")) { ignerr << "Unable to unserialize sdf::Model" << std::endl; return _in;