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

Emit more events from Scene3D #213

Merged
merged 17 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/plugins/grid_3d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ ign_gui_add_plugin(Grid3D
TEST_SOURCES
# Grid3D_TEST.cc
PUBLIC_LINK_LIBS
${IGNITION-RENDERING_LIBRARIES}
ignition-rendering${IGN_RENDERING_VER}::ignition-rendering${IGN_RENDERING_VER}
)

4 changes: 1 addition & 3 deletions src/plugins/scene3d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ ign_gui_add_plugin(Scene3D
Scene3D.cc
QT_HEADERS
Scene3D.hh
TEST_SOURCES
# Scene3D_TEST.cc
PUBLIC_LINK_LIBS
${IGNITION-RENDERING_LIBRARIES}
ignition-rendering${IGN_RENDERING_VER}::ignition-rendering${IGN_RENDERING_VER}
)

201 changes: 184 additions & 17 deletions src/plugins/scene3d/Scene3D.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <vector>

#include <ignition/common/Console.hh>
#include <ignition/common/KeyEvent.hh>
#include <ignition/common/MouseEvent.hh>
#include <ignition/plugin/Register.hh>
#include <ignition/common/MeshManager.hh>
Expand Down Expand Up @@ -207,9 +208,15 @@ namespace plugins
/// \brief Flag to indicate if mouse event is dirty
public: bool mouseDirty = false;

/// \brief Flag to indicate if hover event is dirty
public: bool hoverDirty = false;

/// \brief Mouse event
public: common::MouseEvent mouseEvent;

/// \brief Key event
public: common::KeyEvent keyEvent;

/// \brief Mouse move distance since last event.
public: math::Vector2d drag;

Expand All @@ -222,6 +229,9 @@ namespace plugins
/// \brief Camera orbit controller
public: rendering::OrbitViewController viewControl;

/// \brief The currently hovered mouse position in screen coordinates
public: math::Vector2i mouseHoverPos{math::Vector2i::Zero};

/// \brief Ray query for mouse clicks
public: rendering::RayQueryPtr rayQuery;

Expand Down Expand Up @@ -885,6 +895,15 @@ void IgnRenderer::Render()
void IgnRenderer::HandleMouseEvent()
{
std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
this->BroadcastHoverPos();
this->BroadcastLeftClick();
this->BroadcastRightClick();
this->HandleMouseViewControl();
}

/////////////////////////////////////////////////
void IgnRenderer::HandleMouseViewControl()
{
if (!this->dataPtr->mouseDirty)
return;

Expand Down Expand Up @@ -939,6 +958,106 @@ void IgnRenderer::HandleMouseEvent()
this->dataPtr->mouseDirty = false;
}

////////////////////////////////////////////////
void IgnRenderer::HandleKeyPress(QKeyEvent *_e)
{
if (_e->isAutoRepeat())
return;

std::lock_guard<std::mutex> lock(this->dataPtr->mutex);

this->dataPtr->keyEvent.SetKey(_e->key());
this->dataPtr->keyEvent.SetText(_e->text().toStdString());

this->dataPtr->keyEvent.SetControl(
(_e->modifiers() & Qt::ControlModifier));
this->dataPtr->keyEvent.SetShift(
(_e->modifiers() & Qt::ShiftModifier));
this->dataPtr->keyEvent.SetAlt(
(_e->modifiers() & Qt::AltModifier));

this->dataPtr->mouseEvent.SetControl(this->dataPtr->keyEvent.Control());
this->dataPtr->mouseEvent.SetShift(this->dataPtr->keyEvent.Shift());
this->dataPtr->mouseEvent.SetAlt(this->dataPtr->keyEvent.Alt());
this->dataPtr->keyEvent.SetType(common::KeyEvent::PRESS);
}

////////////////////////////////////////////////
void IgnRenderer::HandleKeyRelease(QKeyEvent *_e)
{
if (_e->isAutoRepeat())
return;

std::lock_guard<std::mutex> lock(this->dataPtr->mutex);

this->dataPtr->keyEvent.SetKey(0);

this->dataPtr->keyEvent.SetControl(
(_e->modifiers() & Qt::ControlModifier)
&& (_e->key() != Qt::Key_Control));
this->dataPtr->keyEvent.SetShift(
(_e->modifiers() & Qt::ShiftModifier)
&& (_e->key() != Qt::Key_Shift));
this->dataPtr->keyEvent.SetAlt(
(_e->modifiers() & Qt::AltModifier)
&& (_e->key() != Qt::Key_Alt));

this->dataPtr->mouseEvent.SetControl(this->dataPtr->keyEvent.Control());
this->dataPtr->mouseEvent.SetShift(this->dataPtr->keyEvent.Shift());
this->dataPtr->mouseEvent.SetAlt(this->dataPtr->keyEvent.Alt());
this->dataPtr->keyEvent.SetType(common::KeyEvent::RELEASE);
}

/////////////////////////////////////////////////
void IgnRenderer::BroadcastHoverPos()
{
if (!this->dataPtr->hoverDirty)
return;

auto pos = this->ScreenToScene(this->dataPtr->mouseHoverPos);

events::HoverToScene hoverToSceneEvent(pos);
App()->sendEvent(App()->findChild<MainWindow *>(), &hoverToSceneEvent);
}

/////////////////////////////////////////////////
void IgnRenderer::BroadcastLeftClick()
{
if (!this->dataPtr->mouseDirty)
return;

if (this->dataPtr->mouseEvent.Dragging())
return;

if (this->dataPtr->mouseEvent.Button() != common::MouseEvent::LEFT ||
this->dataPtr->mouseEvent.Type() != common::MouseEvent::RELEASE)
return;

auto pos = this->ScreenToScene(this->dataPtr->mouseEvent.Pos());

events::LeftClickToScene leftClickToSceneEvent(pos);
App()->sendEvent(App()->findChild<MainWindow *>(), &leftClickToSceneEvent);
}

/////////////////////////////////////////////////
void IgnRenderer::BroadcastRightClick()
{
if (!this->dataPtr->mouseDirty)
return;

if (this->dataPtr->mouseEvent.Dragging())
return;

if (this->dataPtr->mouseEvent.Button() != common::MouseEvent::RIGHT ||
this->dataPtr->mouseEvent.Type() != common::MouseEvent::RELEASE)
return;

auto pos = this->ScreenToScene(this->dataPtr->mouseEvent.Pos());

events::RightClickToScene rightClickToSceneEvent(pos);
App()->sendEvent(App()->findChild<MainWindow *>(), &rightClickToSceneEvent);
}

/////////////////////////////////////////////////
void IgnRenderer::Initialize()
{
Expand Down Expand Up @@ -1016,6 +1135,14 @@ void IgnRenderer::Destroy()
}
}

/////////////////////////////////////////////////
void IgnRenderer::NewHoverEvent(const math::Vector2i &_hoverPos)
{
std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
this->dataPtr->mouseHoverPos = _hoverPos;
this->dataPtr->hoverDirty = true;
}

/////////////////////////////////////////////////
void IgnRenderer::NewMouseEvent(const common::MouseEvent &_e,
const math::Vector2d &_drag)
Expand Down Expand Up @@ -1455,6 +1582,12 @@ void Scene3D::LoadConfig(const tinyxml2::XMLElement *_pluginElem)
}
}

/////////////////////////////////////////////////
void RenderWindowItem::OnHovered(const ignition::math::Vector2i &_hoverPos)
{
this->dataPtr->renderThread->ignRenderer.NewHoverEvent(_hoverPos);
}

/////////////////////////////////////////////////
void RenderWindowItem::mousePressEvent(QMouseEvent *_e)
{
Expand Down Expand Up @@ -1505,23 +1638,57 @@ void RenderWindowItem::wheelEvent(QWheelEvent *_e)
this->dataPtr->mouseEvent, math::Vector2d(scroll, scroll));
}

///////////////////////////////////////////////////
// void Scene3D::resizeEvent(QResizeEvent *_e)
// {
// if (this->dataPtr->renderWindow)
// {
// this->dataPtr->renderWindow->OnResize(_e->size().width(),
// _e->size().height());
// }
//
// if (this->dataPtr->camera)
// {
// this->dataPtr->camera->SetAspectRatio(
// static_cast<double>(this->width()) / this->height());
// this->dataPtr->camera->SetHFOV(M_PI * 0.5);
// }
// }
//
////////////////////////////////////////////////
void RenderWindowItem::HandleKeyPress(QKeyEvent *_e)
{
this->dataPtr->renderThread->ignRenderer.HandleKeyPress(_e);
}

////////////////////////////////////////////////
void RenderWindowItem::HandleKeyRelease(QKeyEvent *_e)
{
this->dataPtr->renderThread->ignRenderer.HandleKeyRelease(_e);
}

/////////////////////////////////////////////////
bool Scene3D::eventFilter(QObject *_obj, QEvent *_event)
{
if (_event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(_event);
if (keyEvent)
{
auto renderWindow = this->PluginItem()->findChild<RenderWindowItem *>();
renderWindow->HandleKeyPress(keyEvent);
}
}
else if (_event->type() == QEvent::KeyRelease)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(_event);
if (keyEvent)
{
auto renderWindow = this->PluginItem()->findChild<RenderWindowItem *>();
renderWindow->HandleKeyRelease(keyEvent);
}
}

// Standard event processing
return QObject::eventFilter(_obj, _event);
}

/////////////////////////////////////////////////
void Scene3D::OnHovered(int _mouseX, int _mouseY)
{
auto renderWindow = this->PluginItem()->findChild<RenderWindowItem *>();
renderWindow->OnHovered({_mouseX, _mouseY});
}

/////////////////////////////////////////////////
void Scene3D::OnFocusWindow()
{
auto renderWindow = this->PluginItem()->findChild<RenderWindowItem *>();
renderWindow->forceActiveFocus();
}

// Register this plugin
IGNITION_ADD_PLUGIN(ignition::gui::plugins::Scene3D,
Expand Down
51 changes: 50 additions & 1 deletion src/plugins/scene3d/Scene3D.hh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ namespace plugins
/// \brief Destructor
public: virtual ~Scene3D();

/// \brief Callback when the mouse hovers to a new position.
/// \param[in] _mouseX x coordinate of the hovered mouse position.
/// \param[in] _mouseY y coordinate of the hovered mouse position.
public slots: void OnHovered(int _mouseX, int _mouseY);

/// \brief Callback when the mouse enters the render window to
/// focus the window for mouse/key events
public slots: void OnFocusWindow();

// Documentation inherited
protected: bool eventFilter(QObject *_obj, QEvent *_event) override;

// Documentation inherited
public: virtual void LoadConfig(const tinyxml2::XMLElement *_pluginElem)
override;
Expand Down Expand Up @@ -106,9 +118,33 @@ namespace plugins
public: void NewMouseEvent(const common::MouseEvent &_e,
const math::Vector2d &_drag = math::Vector2d::Zero);

/// \brief New hover event triggered.
/// \param[in] _hoverPos Mouse hover screen position
public: void NewHoverEvent(const math::Vector2i &_hoverPos);

/// \brief Handle key press event for snapping
/// \param[in] _e The key event to process.
public: void HandleKeyPress(QKeyEvent *_e);

/// \brief Handle key release event for snapping
/// \param[in] _e The key event to process.
public: void HandleKeyRelease(QKeyEvent *_e);

/// \brief Handle mouse event for view control
private: void HandleMouseEvent();

/// \brief Handle mouse event for view control
private: void HandleMouseViewControl();

/// \brief Broadcasts the currently hovered 3d scene location.
private: void BroadcastHoverPos();

/// \brief Broadcasts a left click within the scene
private: void BroadcastLeftClick();

/// \brief Broadcasts a right click within the scene
private: void BroadcastRightClick();

/// \brief Retrieve the first point on a surface in the 3D scene hit by a
/// ray cast from the given 2D screen coordinates.
/// \param[in] _screenPos 2D coordinates on the screen, in pixels.
Expand Down Expand Up @@ -254,9 +290,22 @@ namespace plugins
/// \param[in] _topic Scene topic
public: void SetSceneTopic(const std::string &_topic);

/// \brief Called when the mouse hovers to a new position.
/// \param[in] _hoverPos 2D coordinates of the hovered mouse position on
/// the render window.
public: void OnHovered(const ignition::math::Vector2i &_hoverPos);

/// \brief Slot called when thread is ready to be started
public Q_SLOTS: void Ready();

/// \brief Handle key press event for snapping
/// \param[in] _e The key event to process.
public: void HandleKeyPress(QKeyEvent *_e);

/// \brief Handle key release event for snapping
/// \param[in] _e The key event to process.
public: void HandleKeyRelease(QKeyEvent *_e);

// Documentation inherited
protected: virtual void mousePressEvent(QMouseEvent *_e) override;

Expand All @@ -276,7 +325,7 @@ namespace plugins
/// \param[in] _data The node transformation data.
/// \return Updated node.
private: QSGNode *updatePaintNode(QSGNode *_oldNode,
QQuickItem::UpdatePaintNodeData *_data) override;
QQuickItem::UpdatePaintNodeData *_data) override;

/// \internal
/// \brief Pointer to private data.
Expand Down
17 changes: 16 additions & 1 deletion src/plugins/scene3d/Scene3D.qml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*
*/
import QtQuick 2.0
import QtQuick 2.9
import QtQuick.Controls 2.0
import RenderWindow 1.0
import QtGraphicalEffects 1.0
Expand All @@ -28,6 +28,21 @@ Rectangle {
*/
property bool gammaCorrect: false

/**
* Get mouse position on 3D widget
*/
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
onEntered: {
Scene3D.OnFocusWindow()
}
onPositionChanged: {
Scene3D.OnHovered(mouseArea.mouseX, mouseArea.mouseY);
}
}

RenderWindow {
id: renderWindow
Expand Down
Loading