Skip to content

Commit

Permalink
Emit key events from Scene3D
Browse files Browse the repository at this point in the history
Signed-off-by: ahcorde <ahcorde@gmail.com>
  • Loading branch information
ahcorde committed May 27, 2021
1 parent 4a0159b commit 9d42483
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
50 changes: 50 additions & 0 deletions include/ignition/gui/GuiEvents.hh
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,56 @@ namespace ignition
/// for this event.
private: bool menuEnabled;
};

/// \brief Event which is called to broadcast the key release within
/// the scene.
class KeyRelease : public QEvent
{
/// \brief Constructor
/// \param[in] _key The released key within the scene
public: explicit KeyRelease(const int &_key)
: QEvent(kType), key(_key)
{
}

/// \brief Unique type for this event.
static const QEvent::Type kType = QEvent::Type(QEvent::MaxUser - 8);

/// \brief Get the released key within the scene that the user released.
/// \return The key code.
public: int Key() const
{
return this->key;
}

/// \brief The key that the user released within the scene.
private: int key;
};

/// \brief Event which is called to broadcast the key press within
/// the scene.
class KeyPress : public QEvent
{
/// \brief Constructor
/// \param[in] _key The pressed key within the scene
public: explicit KeyPress(const int &_key)
: QEvent(kType), key(_key)
{
}

/// \brief Unique type for this event.
static const QEvent::Type kType = QEvent::Type(QEvent::MaxUser - 9);

/// \brief Get the released key within the scene that the user pressed.
/// \return The key code.
public: int Key() const
{
return this->key;
}

/// \brief The key that the user pressed within the scene.
private: int key;
};
}
}
}
Expand Down
48 changes: 47 additions & 1 deletion src/plugins/scene3d/Scene3D.cc
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,8 @@ void IgnRenderer::HandleMouseEvent()
this->BroadcastHoverPos();
this->BroadcastLeftClick();
this->BroadcastRightClick();
this->BroadcastKeyPress();
this->BroadcastKeyRelease();
this->HandleMouseViewControl();
}

Expand Down Expand Up @@ -990,7 +992,7 @@ void IgnRenderer::HandleKeyRelease(QKeyEvent *_e)

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

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

this->dataPtr->keyEvent.SetControl(
(_e->modifiers() & Qt::ControlModifier)
Expand Down Expand Up @@ -1058,6 +1060,30 @@ void IgnRenderer::BroadcastRightClick()
App()->sendEvent(App()->findChild<MainWindow *>(), &rightClickToSceneEvent);
}

/////////////////////////////////////////////////
void IgnRenderer::BroadcastKeyRelease()
{
events::KeyRelease keyRelease(this->dataPtr->keyEvent.Key());

if (this->dataPtr->keyEvent.Type() == common::KeyEvent::RELEASE)
{
App()->sendEvent(App()->findChild<MainWindow *>(), &keyRelease);
this->dataPtr->keyEvent.SetType(common::KeyEvent::NO_EVENT);
}
}

/////////////////////////////////////////////////
void IgnRenderer::BroadcastKeyPress()
{
events::KeyPress keyPress(this->dataPtr->keyEvent.Key());

if (this->dataPtr->keyEvent.Type() == common::KeyEvent::PRESS)
{
App()->sendEvent(App()->findChild<MainWindow *>(), &keyPress);
this->dataPtr->keyEvent.SetType(common::KeyEvent::NO_EVENT);
}
}

/////////////////////////////////////////////////
void IgnRenderer::Initialize()
{
Expand Down Expand Up @@ -1638,6 +1664,26 @@ void RenderWindowItem::wheelEvent(QWheelEvent *_e)
this->dataPtr->mouseEvent, math::Vector2d(scroll, scroll));
}

////////////////////////////////////////////////
void RenderWindowItem::keyPressEvent(QKeyEvent *_event)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(_event);
if (keyEvent)
{
this->HandleKeyPress(keyEvent);
}
}

////////////////////////////////////////////////
void RenderWindowItem::keyReleaseEvent(QKeyEvent *_event)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(_event);
if (keyEvent)
{
this->HandleKeyRelease(keyEvent);
}
}

////////////////////////////////////////////////
void RenderWindowItem::HandleKeyPress(QKeyEvent *_e)
{
Expand Down
12 changes: 12 additions & 0 deletions src/plugins/scene3d/Scene3D.hh
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ namespace plugins
/// \brief Broadcasts a right click within the scene
private: void BroadcastRightClick();

/// \brief Broadcasts the currently key release
private: void BroadcastKeyRelease();

/// \brief Broadcasts the currently key release
private: void BroadcastKeyPress();

/// \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 @@ -318,6 +324,12 @@ namespace plugins
// Documentation inherited
protected: virtual void wheelEvent(QWheelEvent *_e) override;

// Documentation inherited
protected: virtual void keyPressEvent(QKeyEvent *_event) override;

// Documentation inherited
protected: virtual void keyReleaseEvent(QKeyEvent *_event) override;

/// \brief Overrides the paint event to render the render engine
/// camera view
/// \param[in] _oldNode The node passed in previous updatePaintNode
Expand Down
32 changes: 30 additions & 2 deletions test/integration/scene3d.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,13 @@ TEST(Scene3DTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Events))
bool receivedRightEvent{false};
bool receivedLeftEvent{false};
bool receivedHoverEvent{false};
bool receivedKeyPressEvent{false};
bool receivedKeyReleaseEvent{false};

// Position vectors reported by click events
math::Vector3d leftClickPoint, rightClickPoint;
// key pressed or released
int keyPressedValue, keyReleasedValue;

// Helper to filter events
auto testHelper = std::make_unique<TestHelper>();
Expand All @@ -189,12 +193,25 @@ TEST(Scene3DTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Events))
{
receivedHoverEvent = true;
}
else if (_event->type() == events::KeyRelease::kType)
{
receivedKeyReleaseEvent = true;
auto keyReleased = static_cast<events::KeyRelease*>(_event);
keyReleasedValue = keyReleased->Key();
}
else if (_event->type() == events::KeyPress::kType)
{
receivedKeyPressEvent = true;
auto keyPress = static_cast<events::KeyPress*>(_event);
keyPressedValue = keyPress->Key();
}
};

int sleep = 0;
int maxSleep = 30;
while ((!receivedRenderEvent || !receivedRightEvent ||
!receivedLeftEvent || !receivedHoverEvent) && sleep < maxSleep)
!receivedLeftEvent || !receivedHoverEvent || !receivedKeyReleaseEvent ||
!receivedKeyPressEvent) && sleep < maxSleep)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
QCoreApplication::processEvents();
Expand All @@ -211,16 +228,27 @@ TEST(Scene3DTest, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(Events))
std::this_thread::sleep_for(std::chrono::milliseconds(100));
QCoreApplication::processEvents();

QTest::keyPress(win->QuickWindow(), Qt::Key_Tab, Qt::NoModifier);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
QCoreApplication::processEvents();

QTest::keyRelease(win->QuickWindow(), Qt::Key_Escape, Qt::NoModifier);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
QCoreApplication::processEvents();

sleep++;
}

EXPECT_TRUE(receivedRenderEvent);
EXPECT_TRUE(receivedLeftEvent);
EXPECT_TRUE(receivedRightEvent);
EXPECT_TRUE(receivedHoverEvent);

EXPECT_EQ(leftClickPoint, rightClickPoint);
EXPECT_NEAR(1.0, leftClickPoint.X(), 1e-4);
EXPECT_NEAR(11.942695, leftClickPoint.Y(), 1e-4);
EXPECT_NEAR(4.159424, leftClickPoint.Z(), 1e-4);
EXPECT_TRUE(receivedKeyReleaseEvent);
EXPECT_EQ(Qt::Key_Escape, keyReleasedValue);
EXPECT_TRUE(receivedKeyPressEvent);
EXPECT_EQ(Qt::Key_Tab, keyPressedValue);
}

0 comments on commit 9d42483

Please sign in to comment.