From 726d2deddb80cb73a3de18f1726e3ad9a67ecfc1 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 4 Nov 2015 15:37:15 +0100 Subject: PickBoundingVolumeJob: few fixes - properly handle click events - fix hover events when using multiple viewports - handle picking on parent Entities that have no geometry Change-Id: Ie44cc4278a4dacf36f2ad6e4f77aea0eb2977d51 Reviewed-by: Paul Lemire Reviewed-by: Andy Nichols --- src/render/jobs/pickboundingvolumejob.cpp | 47 ++++++++++++++++++++----------- src/render/jobs/pickboundingvolumejob_p.h | 1 + 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'src/render/jobs') diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 02d620b33..2140d5cd3 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -172,18 +172,28 @@ void PickBoundingVolumeJob::run() if (!vcPairs.empty()) { Q_FOREACH (const QMouseEvent &event, m_mouseEvents) { + m_hoveredPickersToClear = m_hoveredPickers; + ObjectPicker *lastCurrentPicker = m_renderer->objectPickerManager()->data(m_currentPicker); Q_FOREACH (const ViewportCameraPair &vc, vcPairs) { const QVector hits = hitsForViewportAndCamera(event.pos(), vc.viewport, vc.cameraId, rayCasting); - ObjectPicker *lastCurrentPicker = m_renderer->objectPickerManager()->data(m_currentPicker); // If we have hits if (!hits.isEmpty()) { Q_FOREACH (const Qt3DCore::QNodeId &entityId, hits) { Entity *entity = m_renderer->renderNodesManager()->lookupResource(entityId); HObjectPicker objectPickerHandle = entity->componentHandle(); + + // If the Entity which actually received the hit doesn't have + // an object picker component, we need to check the parent if it has one ... + while (objectPickerHandle.isNull() && entity != Q_NULLPTR) { + entity = entity->parent(); + if (entity != Q_NULLPTR) + objectPickerHandle = entity->componentHandle(); + } + ObjectPicker *objectPicker = m_renderer->objectPickerManager()->data(objectPickerHandle); if (objectPicker != Q_NULLPTR) { @@ -199,8 +209,10 @@ void PickBoundingVolumeJob::run() case QEvent::MouseButtonRelease: { // Send release event to m_currentPicker - if (lastCurrentPicker != Q_NULLPTR) + if (lastCurrentPicker != Q_NULLPTR) { + lastCurrentPicker->onClicked(); lastCurrentPicker->onReleased(); + } break; } @@ -209,12 +221,9 @@ void PickBoundingVolumeJob::run() break; } + case QEvent::HoverMove: case QEvent::MouseMove: { if (!m_hoveredPickers.contains(objectPickerHandle)) { - // Send exited event to object pickers on which we - // had set the hovered flag - clearPreviouslyHoveredPickers(); - if (objectPicker->hoverEnabled()) { // Send entered event to objectPicker objectPicker->onEntered(); @@ -229,10 +238,14 @@ void PickBoundingVolumeJob::run() break; } } + + // The ObjectPicker was hit -> it is still being hovered + m_hoveredPickersToClear.removeAll(objectPickerHandle); + lastCurrentPicker = m_renderer->objectPickerManager()->data(m_currentPicker); } - // Otherwise + // Otherwise no hits } else { switch (event.type()) { case QEvent::MouseButtonRelease: { @@ -241,18 +254,19 @@ void PickBoundingVolumeJob::run() lastCurrentPicker->onReleased(); break; } - case QEvent::MouseMove: { - // Send exited event to object pickers on which we - // had set the hovered flag - clearPreviouslyHoveredPickers(); - break; - } default: break; } } } } + + // Clear Hovered elements that needs to be cleared + // Send exit event to object pickers on which we + // had set the hovered flag for a previous frame + // and that aren't being hovered any longer + clearPreviouslyHoveredPickers(); + } } @@ -318,19 +332,20 @@ QVector PickBoundingVolumeJob::hitsForViewportAndCamera(const // In GL the y is inverted compared to Qt const QPoint glCorrectPos = s ? QPoint(pos.x(), s->size().height() - pos.y()) : pos; const Qt3DCore::QRay3D ray = intersectionRay(glCorrectPos, viewMatrix, projectionMatrix, viewport); - const Qt3DCore::QQueryHandle rayCastingHandle = rayCasting->query(ray, Qt3DCore::QAbstractCollisionQueryService::FirstHit); + const Qt3DCore::QQueryHandle rayCastingHandle = rayCasting->query(ray, Qt3DCore::QAbstractCollisionQueryService::AllHits); const Qt3DCore::QCollisionQueryResult queryResult = rayCasting->fetchResult(rayCastingHandle); return queryResult.entitiesHit(); } void PickBoundingVolumeJob::clearPreviouslyHoveredPickers() { - Q_FOREACH (const HObjectPicker &pickHandle, m_hoveredPickers) { + Q_FOREACH (const HObjectPicker &pickHandle, m_hoveredPickersToClear) { ObjectPicker *pick = m_renderer->objectPickerManager()->data(pickHandle); if (pick) pick->onExited(); + m_hoveredPickers.removeAll(pickHandle); } - m_hoveredPickers.clear(); + m_hoveredPickersToClear.clear(); } } // namespace Render diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h index c3b190f67..e52fcccf4 100644 --- a/src/render/jobs/pickboundingvolumejob_p.h +++ b/src/render/jobs/pickboundingvolumejob_p.h @@ -101,6 +101,7 @@ private: void clearPreviouslyHoveredPickers(); HObjectPicker m_currentPicker; QVector m_hoveredPickers; + QVector m_hoveredPickersToClear; }; typedef QSharedPointer PickBoundingVolumeJobPtr; -- cgit v1.2.3