From 61a7a44b4f2ea88ee4451dbc0faedbd5efd11558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4=C3=A4tt=C3=A4?= Date: Tue, 25 Oct 2016 13:51:37 +0300 Subject: Update pickboundingvolumejob with event forwarding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I6d14d4ad1bf78bf3e6d6e8b2415137a94d833c9e Reviewed-by: Tomi Korpipää Reviewed-by: Sean Harmer --- src/render/backend/renderer.cpp | 7 ++- src/render/backend/renderer_p.h | 2 +- src/render/jobs/pickboundingvolumejob.cpp | 77 +++++++++++++++++++++++++++++-- src/render/jobs/pickboundingvolumejob_p.h | 6 ++- src/render/picking/pickeventfilter.cpp | 21 +++++++-- src/render/picking/pickeventfilter_p.h | 7 ++- 6 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 191e70392..c82ae7ec6 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -1576,7 +1576,12 @@ void Renderer::cleanGraphicsResources() QList Renderer::pendingPickingEvents() const { - return m_pickEventFilter->pendingEvents(); + return m_pickEventFilter->pendingMouseEvents(); +} + +QList Renderer::pendingKeyEvents() const +{ + return m_pickEventFilter->pendingKeyEvents(); } const GraphicsApiFilterData *Renderer::contextInfo() const diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index 344565173..690ce8584 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -227,8 +227,8 @@ public: inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; } - QList pendingPickingEvents() const; + QList pendingKeyEvents() const; void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId); const QVector takePendingRenderCaptureSendRequests(); diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 2ce6eb92e..a7df5270f 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -58,6 +58,8 @@ namespace Render { namespace { +typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList; + void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers) { switch (event.button()) { @@ -118,6 +120,11 @@ void PickBoundingVolumeJob::setMouseEvents(const QList &pendingEven m_pendingMouseEvents = pendingEvents; } +void PickBoundingVolumeJob::setKeyEvents(const QList &pendingEvents) +{ + m_pendingKeyEvents = pendingEvents; +} + void PickBoundingVolumeJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) { m_frameGraphRoot = frameGraphRoot; @@ -145,9 +152,10 @@ bool PickBoundingVolumeJob::runHelper() // Move to clear the events so that we don't process them several times // if run is called several times const auto mouseEvents = std::move(m_pendingMouseEvents); + const auto keyEvents = std::move(m_pendingKeyEvents); // If we have no events return early - if (mouseEvents.empty()) + if (mouseEvents.empty() && keyEvents.empty()) return false; // bail out early if no picker is enabled @@ -178,6 +186,23 @@ bool PickBoundingVolumeJob::runHelper() // that the tree structure has changed PickingUtils::EntityGatherer entitiesGatherer(m_node); + // Forward keyboard events + if (keyEvents.size() > 0) { + for (Entity *e : entitiesGatherer.entities()) { + ObjectPicker *picker = e->renderComponent(); + if (picker != nullptr) { + if (picker->isEventForwardingEnabled()) { + EventForward *eventForward + = m_manager->eventForwardManager()->lookupResource(picker->eventForward()); + if (eventForward->focus() && eventForward->forwardKeyboardEvents()) { + eventForward->forward(keyEvents); + break; + } + } + } + } + } + // Store the reducer function which varies depending on the picking settings set on the renderer using ReducerFunction = PickingUtils::CollisionVisitor::HitList (*)(PickingUtils::CollisionVisitor::HitList &results, const PickingUtils::CollisionVisitor::HitList &intermediate); @@ -203,7 +228,6 @@ bool PickBoundingVolumeJob::runHelper() // For each triplet of Viewport / Camera and Area for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) { - typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList; HitList sphereHits; QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId); if (trianglePickingRequested) { @@ -221,7 +245,8 @@ bool PickBoundingVolumeJob::runHelper() } // Dispatch events based on hit results - dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, trianglePickingRequested); + dispatchPickEvents(event, sphereHits, eventButton, eventButtons, + eventModifiers, trianglePickingRequested, ray); } } @@ -249,7 +274,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, QPickEvent::Buttons eventButton, int eventButtons, int eventModifiers, - bool trianglePickingRequested) + bool trianglePickingRequested, + const QRay3D &ray) { ObjectPicker *lastCurrentPicker = m_manager->objectPickerManager()->data(m_currentPicker); // If we have hits @@ -337,6 +363,49 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, default: break; } + if (objectPicker->isEventForwardingEnabled()) { + EventForward *eventForward + = m_manager->eventForwardManager()->lookupResource(objectPicker->eventForward()); + QCollisionQueryResult::Hit triangleHit = hit; + bool valid = true; + if (eventForward->isEnabled() && eventForward->forwardMouseEvents()) { + if (!trianglePickingRequested) { + // Triangle picking is not enables so the triangle is not already in the + // query results. We need to redo the picking to get the triangle. + Qt3DRender::QRayCastingService rayCasting; + PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; + const bool frontFaceRequested = + m_renderSettings->faceOrientationPickingMode() != QPickingSettings::BackFace; + const bool backFaceRequested = + m_renderSettings->faceOrientationPickingMode() != QPickingSettings::FrontFace; + gathererFunctor.m_frontFaceRequested = frontFaceRequested; + gathererFunctor.m_backFaceRequested = backFaceRequested; + gathererFunctor.m_manager = m_manager; + gathererFunctor.m_ray = ray; + + // The bounding method is inaccurate so the triangle picking doesn't + // necessarely produce any results + HitList hitlist = gathererFunctor.pick(&rayCasting, entity); + if (hitlist.size() > 0) + triangleHit = hitlist.at(0); + else + valid = false; + } + if (valid) { + CoordinateReader reader(m_manager); + if (reader.setGeometry(entity->renderComponent(), + eventForward->coordinateAttribute())) { + QVector4D c0 = reader.getCoordinate(triangleHit.m_vertexIndex[0]); + QVector4D c1 = reader.getCoordinate(triangleHit.m_vertexIndex[1]); + QVector4D c2 = reader.getCoordinate(triangleHit.m_vertexIndex[2]); + QVector4D ci = c2 * triangleHit.m_uvw.x() + + c1 * triangleHit.m_uvw.y() + c0 * triangleHit.m_uvw.z(); + ci.setW(1.0f); + eventForward->forward(event, ci); + } + } + } + } } // The ObjectPicker was hit -> it is still being hovered diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h index 913a5ace0..90a0bdbda 100644 --- a/src/render/jobs/pickboundingvolumejob_p.h +++ b/src/render/jobs/pickboundingvolumejob_p.h @@ -59,6 +59,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -85,6 +86,7 @@ public: void setRoot(Entity *root); void setMouseEvents(const QList &pendingEvents); + void setKeyEvents(const QList &pendingEvents); void setFrameGraphRoot(FrameGraphNode *frameGraphRoot); void setRenderSettings(RenderSettings *settings); void setManagers(NodeManagers *manager); @@ -104,7 +106,8 @@ protected: void dispatchPickEvents(const QMouseEvent &event, const PickingUtils::CollisionVisitor::HitList &sphereHits, QPickEvent::Buttons eventButton, int eventButtons, - int eventModifiers, bool trianglePickingRequested); + int eventModifiers, bool trianglePickingRequested, + const QRay3D &ray); private: NodeManagers *m_manager; @@ -112,6 +115,7 @@ private: FrameGraphNode *m_frameGraphRoot; RenderSettings *m_renderSettings; QList m_pendingMouseEvents; + QList m_pendingKeyEvents; void viewMatrixForCamera(Qt3DCore::QNodeId cameraId, QMatrix4x4 &viewMatrix, diff --git a/src/render/picking/pickeventfilter.cpp b/src/render/picking/pickeventfilter.cpp index a1ae52068..19d3b6b6e 100644 --- a/src/render/picking/pickeventfilter.cpp +++ b/src/render/picking/pickeventfilter.cpp @@ -61,11 +61,19 @@ PickEventFilter::~PickEventFilter() Called from a worker thread in the thread pool so be sure to mutex protect the data. */ -QList PickEventFilter::pendingEvents() +QList PickEventFilter::pendingMouseEvents() { QMutexLocker locker(&m_mutex); - QList pendingEvents(m_pendingEvents); - m_pendingEvents.clear(); + QList pendingEvents(m_pendingMouseEvents); + m_pendingMouseEvents.clear(); + return pendingEvents; +} + +QList PickEventFilter::pendingKeyEvents() +{ + QMutexLocker locker(&m_mutex); + QList pendingEvents(m_pendingKeyEvents); + m_pendingKeyEvents.clear(); return pendingEvents; } @@ -82,7 +90,12 @@ bool PickEventFilter::eventFilter(QObject *obj, QEvent *e) case QEvent::MouseMove: case QEvent::HoverMove: { QMutexLocker locker(&m_mutex); - m_pendingEvents.push_back(QMouseEvent(*static_cast(e))); + m_pendingMouseEvents.push_back(QMouseEvent(*static_cast(e))); + } break; + case QEvent::KeyPress: + case QEvent::KeyRelease: { + QMutexLocker locker(&m_mutex); + m_pendingKeyEvents.push_back(QKeyEvent(*static_cast(e))); } default: break; diff --git a/src/render/picking/pickeventfilter_p.h b/src/render/picking/pickeventfilter_p.h index df94a3085..fc4b00ddc 100644 --- a/src/render/picking/pickeventfilter_p.h +++ b/src/render/picking/pickeventfilter_p.h @@ -53,6 +53,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -68,13 +69,15 @@ public: explicit PickEventFilter(QObject *parent = nullptr); ~PickEventFilter(); - QList pendingEvents(); + QList pendingMouseEvents(); + QList pendingKeyEvents(); protected: bool eventFilter(QObject *obj, QEvent *e) Q_DECL_FINAL; private: - QList m_pendingEvents; + QList m_pendingMouseEvents; + QList m_pendingKeyEvents; QMutex m_mutex; }; -- cgit v1.2.3