diff --git a/include/ignition/gui/GuiEvents.hh b/include/ignition/gui/GuiEvents.hh index 817bccab5..2219e3acb 100644 --- a/include/ignition/gui/GuiEvents.hh +++ b/include/ignition/gui/GuiEvents.hh @@ -364,6 +364,32 @@ namespace ignition /// \brief Private data pointer IGN_UTILS_IMPL_PTR(dataPtr) }; + + /// \brief Event called to clone a resource, given its name as a string. + class IGNITION_GUI_VISIBLE DropOnScene : public QEvent + { + /// \brief Constructor + /// \param[in] _drop Dropped string. + /// \param[in] _dropMouse x and y coordinate of mouse position. + public: explicit DropOnScene( + const std::string &_dropText, + const ignition::math::Vector2i &_dropMouse); + + /// \brief Get the text of the dropped thing on the scene + /// \return The name of the dropped thing on the scene + public: const std::string &DropText() const; + + /// \brief Get X and Y position + /// \return Get X and Y position + public: const ignition::math::Vector2i &Mouse() const; + + /// \brief Unique type for this event. + static const QEvent::Type kType = QEvent::Type(QEvent::MaxUser - 15); + + /// \internal + /// \brief Private data pointer + IGN_UTILS_IMPL_PTR(dataPtr) + }; } } } diff --git a/src/GuiEvents.cc b/src/GuiEvents.cc index ca7b1711b..4664d70e4 100644 --- a/src/GuiEvents.cc +++ b/src/GuiEvents.cc @@ -109,6 +109,15 @@ class ignition::gui::events::SpawnCloneFromName::Implementation public: std::string name; }; +class ignition::gui::events::DropOnScene::Implementation +{ + /// \brief The name of the dropped thing + public: std::string dropText; + + /// \brief X and Y position of the mouse + public: ignition::math::Vector2i mouse; +}; + using namespace ignition; using namespace gui; using namespace events; @@ -314,3 +323,24 @@ const std::string &SpawnCloneFromName::Name() const { return this->dataPtr->name; } + +///////////////////////////////////////////////// +DropOnScene::DropOnScene( + const std::string &_dropText, const ignition::math::Vector2i &_dropMouse) + : QEvent(kType), dataPtr(utils::MakeImpl()) +{ + this->dataPtr->dropText = _dropText; + this->dataPtr->mouse = _dropMouse; +} + +///////////////////////////////////////////////// +const std::string &DropOnScene::DropText() const +{ + return this->dataPtr->dropText; +} + +///////////////////////////////////////////////// +const ignition::math::Vector2i &DropOnScene::Mouse() const +{ + return this->dataPtr->mouse; +} diff --git a/src/GuiEvents_TEST.cc b/src/GuiEvents_TEST.cc index 80379750f..3342523ce 100644 --- a/src/GuiEvents_TEST.cc +++ b/src/GuiEvents_TEST.cc @@ -202,3 +202,13 @@ TEST(GuiEventsTest, SpawnCloneFromName) EXPECT_LT(QEvent::User, toCloneName.type()); EXPECT_EQ("thingToClone", toCloneName.Name()); } + +///////////////////////////////////////////////// +TEST(GuiEventsTest, DropOnScene) +{ + events::DropOnScene dropOnScene("text", ignition::math::Vector2i(3, 100)); + + EXPECT_LT(QEvent::User, dropOnScene.type()); + EXPECT_EQ(ignition::math::Vector2i(3, 100), dropOnScene.Mouse()); + EXPECT_EQ("text", dropOnScene.DropText()); +} diff --git a/src/plugins/minimal_scene/MinimalScene.cc b/src/plugins/minimal_scene/MinimalScene.cc index c68585fba..aadee1a38 100644 --- a/src/plugins/minimal_scene/MinimalScene.cc +++ b/src/plugins/minimal_scene/MinimalScene.cc @@ -62,6 +62,9 @@ class ignition::gui::plugins::IgnRenderer::Implementation /// \brief Flag to indicate if hover event is dirty public: bool hoverDirty{false}; + /// \brief Flag to indicate if drop event is dirty + public: bool dropDirty{false}; + /// \brief Mouse event public: common::MouseEvent mouseEvent; @@ -77,6 +80,12 @@ class ignition::gui::plugins::IgnRenderer::Implementation /// \brief The currently hovered mouse position in screen coordinates public: math::Vector2i mouseHoverPos{math::Vector2i::Zero}; + /// \brief The currently drop mouse position in screen coordinates + public: math::Vector2i mouseDropPos{math::Vector2i::Zero}; + + /// \brief The dropped text in the scene + public: std::string dropText{""}; + /// \brief Ray query for mouse clicks public: rendering::RayQueryPtr rayQuery{nullptr}; @@ -312,6 +321,7 @@ void IgnRenderer::HandleMouseEvent() this->BroadcastRightClick(); this->BroadcastKeyPress(); this->BroadcastKeyRelease(); + this->BroadcastDrop(); this->HandleMouseViewControl(); this->dataPtr->mouseDirty = false; } @@ -354,6 +364,17 @@ void IgnRenderer::HandleKeyRelease(const common::KeyEvent &_e) this->dataPtr->mouseEvent.SetAlt(this->dataPtr->keyEvent.Alt()); } +///////////////////////////////////////////////// +void IgnRenderer::BroadcastDrop() +{ + if (!this->dataPtr->dropDirty) + return; + events::DropOnScene dropOnSceneEvent( + this->dataPtr->dropText, this->dataPtr->mouseDropPos); + App()->sendEvent(App()->findChild(), &dropOnSceneEvent); + this->dataPtr->dropDirty = false; +} + ///////////////////////////////////////////////// void IgnRenderer::BroadcastHoverPos() { @@ -516,6 +537,16 @@ void IgnRenderer::NewHoverEvent(const math::Vector2i &_hoverPos) this->dataPtr->hoverDirty = true; } +///////////////////////////////////////////////// +void IgnRenderer::NewDropEvent(const std::string &_dropText, + const math::Vector2i &_dropPos) +{ + std::lock_guard lock(this->dataPtr->mutex); + this->dataPtr->dropText = _dropText; + this->dataPtr->mouseDropPos = _dropPos; + this->dataPtr->dropDirty = true; +} + ///////////////////////////////////////////////// void IgnRenderer::NewMouseEvent(const common::MouseEvent &_e) { @@ -1000,6 +1031,14 @@ void RenderWindowItem::OnHovered(const ignition::math::Vector2i &_hoverPos) this->dataPtr->renderThread->ignRenderer.NewHoverEvent(_hoverPos); } +///////////////////////////////////////////////// +void RenderWindowItem::OnDropped(const QString &_drop, + const ignition::math::Vector2i &_dropPos) +{ + this->dataPtr->renderThread->ignRenderer.NewDropEvent( + _drop.toStdString(), _dropPos); +} + ///////////////////////////////////////////////// void RenderWindowItem::mousePressEvent(QMouseEvent *_e) { @@ -1087,6 +1126,13 @@ void MinimalScene::OnHovered(int _mouseX, int _mouseY) renderWindow->OnHovered({_mouseX, _mouseY}); } +///////////////////////////////////////////////// +void MinimalScene::OnDropped(const QString &_drop, int _mouseX, int _mouseY) +{ + auto renderWindow = this->PluginItem()->findChild(); + renderWindow->OnDropped(_drop, {_mouseX, _mouseY}); +} + ///////////////////////////////////////////////// void MinimalScene::OnFocusWindow() { diff --git a/src/plugins/minimal_scene/MinimalScene.hh b/src/plugins/minimal_scene/MinimalScene.hh index 640072b3f..f56ae2095 100644 --- a/src/plugins/minimal_scene/MinimalScene.hh +++ b/src/plugins/minimal_scene/MinimalScene.hh @@ -69,6 +69,13 @@ namespace plugins /// focus the window for mouse/key events public slots: void OnFocusWindow(); + /// \brief Callback when receives a drop event. + /// \param[in] _drop Dropped string. + /// \param[in] _mouseX x coordinate of mouse position. + /// \param[in] _mouseY y coordinate of mouse position. + public slots: void OnDropped(const QString &_drop, + int _mouseX, int _mouseY); + // Documentation inherited public: virtual void LoadConfig(const tinyxml2::XMLElement *_pluginElem) override; @@ -109,6 +116,12 @@ namespace plugins /// \param[in] _hoverPos Mouse hover screen position public: void NewHoverEvent(const math::Vector2i &_hoverPos); + /// \brief New hover event triggered. + /// \param[in] _dropText Text dropped on the scene + /// \param[in] _dropPos Mouse drop screen position + public: void NewDropEvent(const std::string &_dropText, + const math::Vector2i &_dropPos); + /// \brief Handle key press event for snapping /// \param[in] _e The key event to process. public: void HandleKeyPress(const common::KeyEvent &_e); @@ -135,6 +148,9 @@ namespace plugins /// \brief Broadcasts a key release event within the scene private: void BroadcastKeyRelease(); + /// \brief Broadcasts a drop event within the scene + private: void BroadcastDrop(); + /// \brief Broadcasts a key press event within the scene private: void BroadcastKeyPress(); @@ -292,6 +308,12 @@ namespace plugins /// the render window. public: void OnHovered(const ignition::math::Vector2i &_hoverPos); + /// \brief Callback when receives a drop event. + /// \param[in] _drop Dropped string. + /// \param[in] _dropPos x coordinate of mouse position. + public: void OnDropped(const QString &_drop, + const ignition::math::Vector2i &_dropPos); + /// \brief Set if sky is enabled /// \param[in] _sky True to enable the sky, false otherwise. public: void SetSkyEnabled(const bool &_sky); diff --git a/src/plugins/minimal_scene/MinimalScene.qml b/src/plugins/minimal_scene/MinimalScene.qml index bab4a5d16..5a960f9fe 100644 --- a/src/plugins/minimal_scene/MinimalScene.qml +++ b/src/plugins/minimal_scene/MinimalScene.qml @@ -68,4 +68,12 @@ Rectangle { width = Qt.binding(function() {return parent.parent.width}) height = Qt.binding(function() {return parent.parent.height}) } + + DropArea { + anchors.fill: renderWindow + + onDropped: { + MinimalScene.OnDropped(drop.text, drag.x, drag.y) + } +} }