Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag and drop mesh into scene #939

Merged
merged 11 commits into from
Aug 10, 2021
24 changes: 23 additions & 1 deletion src/gui/plugins/scene3d/GzScene3D.qml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*
*/
import QtQuick 2.9
import QtQuick.Controls 2.0
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.0
import RenderWindow 1.0
import QtGraphicalEffects 1.0
import IgnGazebo 1.0 as IgnGazebo
Expand Down Expand Up @@ -98,4 +99,25 @@ Rectangle {
GzScene3D.OnDropped(drop.text, drag.x, drag.y)
}
}

// pop error
Connections {
target: GzScene3D
onPopupError: errorPopup.open()
}

Dialog {
id: errorPopup
parent: ApplicationWindow.overlay
modal: true
focus: true
x: (parent.width - width) / 2
y: (parent.height - height) / 2
title: "Error"
Text {
text: GzScene3D.errorPopupText
}
standardButtons: Dialog.Ok
}

}
71 changes: 69 additions & 2 deletions src/gui/plugins/scene3d/Scene3D.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <ignition/common/KeyFrame.hh>
#include <ignition/common/MeshManager.hh>
#include <ignition/common/Profiler.hh>
#include <ignition/common/StringUtils.hh>
#include <ignition/common/Uuid.hh>
#include <ignition/common/VideoEncoder.hh>

Expand Down Expand Up @@ -373,6 +374,9 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {

/// \brief View collisions service
public: std::string viewCollisionsService;

/// \brief Text for popup error message
public: QString errorPopupText;
};
}
}
Expand Down Expand Up @@ -2793,7 +2797,7 @@ void Scene3D::OnDropped(const QString &_drop, int _mouseX, int _mouseY)
{
if (_drop.toStdString().empty())
{
ignwarn << "Dropped empty entity URI." << std::endl;
this->SetErrorPopupText("Dropped empty entity URI.");
return;
}

Expand All @@ -2808,7 +2812,56 @@ void Scene3D::OnDropped(const QString &_drop, int _mouseX, int _mouseY)
math::Vector3d pos = renderWindow->ScreenToScene({_mouseX, _mouseY});

msgs::EntityFactory req;
req.set_sdf_filename(_drop.toStdString());
std::string dropStr = _drop.toStdString();
if (QUrl(_drop).isLocalFile())
{
// mesh to sdf model
common::rtrim(dropStr);

if (!common::MeshManager::Instance()->IsValidFilename(dropStr))
{
QString errTxt = QString::fromStdString("Invalid URI: " + dropStr +
"\nOnly Fuel URLs or mesh file types DAE, OBJ, and STL are supported.");
this->SetErrorPopupText(errTxt);
return;
}

// Fixes whitespace
dropStr = common::replaceAll(dropStr, "%20", " ");

std::string filename = common::basename(dropStr);
std::vector<std::string> splitName = common::split(filename, ".");

std::string sdf = "<?xml version='1.0'?>"
"<sdf version='" + std::string(SDF_PROTOCOL_VERSION) + "'>"
"<model name='" + splitName[0] + "'>"
"<link name='link'>"
"<visual name='visual'>"
"<geometry>"
"<mesh>"
"<uri>" + dropStr + "</uri>"
"</mesh>"
"</geometry>"
"</visual>"
"<collision name='collision'>"
"<geometry>"
"<mesh>"
"<uri>" + dropStr + "</uri>"
"</mesh>"
"</geometry>"
"</collision>"
"</link>"
"</model>"
"</sdf>";

req.set_sdf(sdf);
}
else
{
// model from fuel
req.set_sdf_filename(dropStr);
}

req.set_allow_renaming(true);
msgs::Set(req.mutable_pose(),
math::Pose3d(pos.X(), pos.Y(), pos.Z(), 1, 0, 0, 0));
Expand All @@ -2817,6 +2870,20 @@ void Scene3D::OnDropped(const QString &_drop, int _mouseX, int _mouseY)
req, cb);
}

/////////////////////////////////////////////////
QString Scene3D::ErrorPopupText() const
{
return this->dataPtr->errorPopupText;
}

/////////////////////////////////////////////////
void Scene3D::SetErrorPopupText(const QString &_errorTxt)
{
this->dataPtr->errorPopupText = _errorTxt;
this->ErrorPopupTextChanged();
this->popupError();
chapulina marked this conversation as resolved.
Show resolved Hide resolved
}

/////////////////////////////////////////////////
void Scene3D::OnFocusWindow()
{
Expand Down
24 changes: 24 additions & 0 deletions src/gui/plugins/scene3d/Scene3D.hh
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
{
Q_OBJECT

/// \brief Text for popup error
Q_PROPERTY(
QString errorPopupText
READ ErrorPopupText
WRITE SetErrorPopupText
NOTIFY ErrorPopupTextChanged
)

/// \brief Constructor
public: Scene3D();

Expand Down Expand Up @@ -161,6 +169,22 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
private: bool OnViewCollisions(const msgs::StringMsg &_msg,
msgs::Boolean &_res);

/// \brief Get the text for the popup error message
/// \return The error text
public: Q_INVOKABLE QString ErrorPopupText() const;

/// \brief Set the text for the popup error message
/// \param[in] _errorTxt The error text
public: Q_INVOKABLE void SetErrorPopupText(const QString &_errorTxt);

/// \brief Notify the popup error text has changed
signals: void ErrorPopupTextChanged();

/// \brief Notify that an error has occurred (opens popup)
/// Note that the function name needs to start with lowercase in order for
/// the connection to work on the QML side
signals: void popupError();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
signals: void popupError();
signals: void PopupError();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/// \internal
/// \brief Pointer to private data.
private: std::unique_ptr<Scene3DPrivate> dataPtr;
Expand Down