diff options
-rw-r--r-- | src/render/jobs/pickboundingvolumejob.cpp | 118 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumejob_p.h | 3 | ||||
-rw-r--r-- | src/render/picking/objectpicker.cpp | 55 | ||||
-rw-r--r-- | src/render/picking/objectpicker_p.h | 7 | ||||
-rw-r--r-- | src/render/picking/qobjectpicker.cpp | 36 | ||||
-rw-r--r-- | src/render/picking/qobjectpicker.h | 3 | ||||
-rw-r--r-- | src/render/picking/qobjectpicker_p.h | 1 | ||||
-rw-r--r-- | src/render/picking/qpickevent_p.h | 4 | ||||
-rw-r--r-- | tests/auto/render/objectpicker/tst_objectpicker.cpp | 59 | ||||
-rw-r--r-- | tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp | 626 | ||||
-rw-r--r-- | tests/auto/render/picking/tst_picking.cpp | 50 | ||||
-rw-r--r-- | tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp | 80 |
12 files changed, 570 insertions, 472 deletions
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index a88e861b6..9d8d3e491 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -41,7 +41,11 @@ #include "qpicktriangleevent.h" #include "qpicklineevent.h" #include "qpickpointevent.h" +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DRender/qobjectpicker.h> +#include <Qt3DRender/qviewport.h> #include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DRender/private/qobjectpicker_p.h> #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/entity_p.h> @@ -65,6 +69,82 @@ using namespace Qt3DRender::RayCasting; namespace Render { +class PickBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + PickBoundingVolumeJobPrivate() = default; + ~PickBoundingVolumeJobPrivate() override = default; + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + enum CustomEventType { + MouseButtonClick = QEvent::User, + }; + + struct EventDetails { + Qt3DCore::QNodeId pickerId; + int sourceEventType; + QPickEventPtr resultingEvent; + Qt3DCore::QNodeId viewportNodeId; + }; + + QVector<EventDetails> dispatches; +}; + + +void PickBoundingVolumeJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + using namespace Qt3DCore; + QNodeId previousId; + QObjectPicker *node = nullptr; + + for (auto res: qAsConst(dispatches)) { + if (previousId != res.pickerId) { + node = qobject_cast<QObjectPicker *>(manager->lookupNode(res.pickerId)); + previousId = res.pickerId; + } + if (!node) + continue; + + QObjectPickerPrivate *dnode = static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node)); + + // resolve front end details + QPickEvent *pickEvent = res.resultingEvent.data(); + if (pickEvent) { + QPickEventPrivate *dpickEvent = QPickEventPrivate::get(pickEvent); + dpickEvent->m_viewport = static_cast<QViewport *>(manager->lookupNode(res.viewportNodeId)); + dpickEvent->m_entityPtr = static_cast<QEntity *>(manager->lookupNode(dpickEvent->m_entity)); + } + + // dispatch event + switch (res.sourceEventType) { + case QEvent::MouseButtonPress: + dnode->pressedEvent(pickEvent); + break; + case QEvent::MouseButtonRelease: + dnode->releasedEvent(pickEvent); + break; + case MouseButtonClick: + dnode->clickedEvent(pickEvent); + break; + case QEvent::MouseMove: + dnode->movedEvent(pickEvent); + break; + case QEvent::Enter: + emit node->entered(); + dnode->setContainsMouse(true); + break; + case QEvent::Leave: + dnode->setContainsMouse(false); + emit node->exited(); + break; + default: Q_UNREACHABLE(); + } + } + + dispatches.clear(); +} + namespace { void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers) @@ -109,10 +189,10 @@ void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &e } // anonymous PickBoundingVolumeJob::PickBoundingVolumeJob() - : AbstractPickingJob() + : AbstractPickingJob(*new PickBoundingVolumeJobPrivate) , m_pickersDirty(true) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0) } void PickBoundingVolumeJob::setRoot(Entity *root) @@ -300,6 +380,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, bool allHitsRequested, Qt3DCore::QNodeId viewportNodeId) { + Q_D(PickBoundingVolumeJob); + ObjectPicker *lastCurrentPicker = m_manager->objectPickerManager()->data(m_currentPicker); // If we have hits if (!sphereHits.isEmpty()) { @@ -383,37 +465,43 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, // Store pressed object handle m_currentPicker = objectPickerHandle; // Send pressed event to m_currentPicker - objectPicker->onPressed(pickEvent, viewportNodeId); + d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId}); + objectPicker->setPressed(true); break; } case QEvent::MouseButtonRelease: { // Only send the release event if it was pressed - if (objectPicker->isPressed()) - objectPicker->onReleased(pickEvent, viewportNodeId); + if (objectPicker->isPressed()) { + d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId}); + objectPicker->setPressed(false); + } if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) { - objectPicker->onClicked(pickEvent, viewportNodeId); + d->dispatches.push_back({objectPicker->peerId(), + PickBoundingVolumeJobPrivate::MouseButtonClick, + pickEvent, viewportNodeId}); m_currentPicker = HObjectPicker(); } break; } #if QT_CONFIG(gestures) case QEvent::Gesture: { - objectPicker->onClicked(pickEvent, viewportNodeId); + d->dispatches.push_back({objectPicker->peerId(), + PickBoundingVolumeJobPrivate::MouseButtonClick, + pickEvent, viewportNodeId}); break; } #endif case QEvent::MouseMove: { - if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) { - objectPicker->onMoved(pickEvent, viewportNodeId); - } + if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) + d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId}); Q_FALLTHROUGH(); // fallthrough } case QEvent::HoverMove: { if (!m_hoveredPickers.contains(objectPickerHandle)) { if (objectPicker->isHoverEnabled()) { // Send entered event to objectPicker - objectPicker->onEntered(); + d->dispatches.push_back({objectPicker->peerId(), QEvent::Enter, pickEvent, viewportNodeId}); // and save it in the hoveredPickers m_hoveredPickers.push_back(objectPickerHandle); } @@ -440,7 +528,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, if (lastCurrentPicker != nullptr) { m_currentPicker = HObjectPicker(); QPickEventPtr pickEvent(new QPickEvent); - lastCurrentPicker->onReleased(pickEvent, viewportNodeId); + lastCurrentPicker->setPressed(false); + d->dispatches.push_back({lastCurrentPicker->peerId(), event.type(), pickEvent, viewportNodeId}); } break; } @@ -452,12 +541,15 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, void PickBoundingVolumeJob::clearPreviouslyHoveredPickers() { + Q_D(PickBoundingVolumeJob); + for (const HObjectPicker &pickHandle : qAsConst(m_hoveredPickersToClear)) { ObjectPicker *pick = m_manager->objectPickerManager()->data(pickHandle); if (pick) - pick->onExited(); + d->dispatches.push_back({pick->peerId(), QEvent::Leave, {}, {}}); m_hoveredPickers.removeAll(pickHandle); } + m_hoveredPickersToClear.clear(); } diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h index e3d847916..49b11b775 100644 --- a/src/render/jobs/pickboundingvolumejob_p.h +++ b/src/render/jobs/pickboundingvolumejob_p.h @@ -70,6 +70,7 @@ namespace Qt3DRender { class QViewport; namespace Render { +class PickBoundingVolumeJobPrivate; namespace PickingUtils { typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList; @@ -101,6 +102,8 @@ protected: Qt3DCore::QNodeId viewportNodeId); private: + Q_DECLARE_PRIVATE(PickBoundingVolumeJob) + void clearPreviouslyHoveredPickers(); QList<QPair<QObject*, QMouseEvent>> m_pendingMouseEvents; diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp index e278d6b6f..84169586e 100644 --- a/src/render/picking/objectpicker.cpp +++ b/src/render/picking/objectpicker.cpp @@ -43,7 +43,6 @@ #include <Qt3DRender/private/qobjectpicker_p.h> #include <Qt3DRender/qattribute.h> #include <Qt3DRender/private/pickboundingvolumejob_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -100,7 +99,6 @@ void ObjectPicker::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstT markDirty(AbstractRenderer::AllDirty); notifyJob(); } - } void ObjectPicker::notifyJob() @@ -124,58 +122,9 @@ bool ObjectPicker::isDragEnabled() const return m_dragEnabled; } -void ObjectPicker::onClicked(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("clicked"); - e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId })); - notifyObservers(e); -} - -void ObjectPicker::onMoved(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("moved"); - e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId })); - notifyObservers(e); -} - -void ObjectPicker::onPressed(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("pressed"); - e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId })); - m_isPressed = true; - notifyObservers(e); -} - -void ObjectPicker::onReleased(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("released"); - e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId })); - m_isPressed = false; - notifyObservers(e); -} - -void ObjectPicker::onEntered() -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("entered"); - notifyObservers(e); -} - -void ObjectPicker::onExited() +void ObjectPicker::setPressed(bool pressed) { - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("exited"); - notifyObservers(e); + m_isPressed = pressed; } void ObjectPicker::setPriority(int priority) diff --git a/src/render/picking/objectpicker_p.h b/src/render/picking/objectpicker_p.h index b4f7d073c..49c8de770 100644 --- a/src/render/picking/objectpicker_p.h +++ b/src/render/picking/objectpicker_p.h @@ -74,12 +74,7 @@ public: bool isHoverEnabled() const; bool isDragEnabled() const; - void onClicked(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId); - void onMoved(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId); - void onPressed(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId); - void onReleased(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId); - void onEntered(); - void onExited(); + void setPressed(bool pressed); // Needed for unit tests void setPriority(int priority); diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp index 9537d4982..0c667806c 100644 --- a/src/render/picking/qobjectpicker.cpp +++ b/src/render/picking/qobjectpicker.cpp @@ -352,33 +352,6 @@ int QObjectPicker::priority() const return d->m_priority; } -/*! \internal */ -void QObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QObjectPicker); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - // TO DO: Complete this part - // to emit the correct signals - const QByteArray propertyName = e->propertyName(); - if (propertyName == QByteArrayLiteral("pressed")) { - d->pressedEvent(d->resolvePickEvent(e)); - } else if (propertyName == QByteArrayLiteral("released")) { - d->releasedEvent(d->resolvePickEvent(e)); - } else if (propertyName == QByteArrayLiteral("clicked")) { - d->clickedEvent(d->resolvePickEvent(e)); - } else if (propertyName == QByteArrayLiteral("moved")) { - d->movedEvent(d->resolvePickEvent(e)); - } else if (propertyName == QByteArrayLiteral("entered")) { - emit entered(); - d->setContainsMouse(true); - } else if (propertyName == QByteArrayLiteral("exited")) { - d->setContainsMouse(false); - emit exited(); - } - } -} - /*! \internal */ @@ -407,15 +380,6 @@ void QObjectPickerPrivate::setContainsMouse(bool containsMouse) } } -QPickEvent *QObjectPickerPrivate::resolvePickEvent(Qt3DCore::QPropertyUpdatedChangePtr e) -{ - QObjectPickerEvent ev = e->value().value<QObjectPickerEvent>(); - QPickEvent *pickEvent = ev.event.data(); - pickEvent->d_func()->m_viewport = static_cast<QViewport *>(scene()->lookupNode(ev.viewportNodeId)); - pickEvent->d_func()->m_entityPtr = static_cast<Qt3DCore::QEntity *>(scene()->lookupNode(pickEvent->d_func()->m_entity)); - return pickEvent; -} - void QObjectPickerPrivate::propagateEvent(QPickEvent *event, EventType type) { if (!m_entities.isEmpty()) { diff --git a/src/render/picking/qobjectpicker.h b/src/render/picking/qobjectpicker.h index 8866c99a9..ee63c9418 100644 --- a/src/render/picking/qobjectpicker.h +++ b/src/render/picking/qobjectpicker.h @@ -90,9 +90,6 @@ Q_SIGNALS: void containsMouseChanged(bool containsMouse); Q_REVISION(13) void priorityChanged(int priority); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - private: Q_DECLARE_PRIVATE(QObjectPicker) Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; diff --git a/src/render/picking/qobjectpicker_p.h b/src/render/picking/qobjectpicker_p.h index fb83912b0..69cee529d 100644 --- a/src/render/picking/qobjectpicker_p.h +++ b/src/render/picking/qobjectpicker_p.h @@ -91,7 +91,6 @@ public: Moved }; - QPickEvent *resolvePickEvent(Qt3DCore::QPropertyUpdatedChangePtr e); void propagateEvent(QPickEvent *event, EventType type); void pressedEvent(QPickEvent *event); diff --git a/src/render/picking/qpickevent_p.h b/src/render/picking/qpickevent_p.h index 4d2f1e2d4..15eeb04b8 100644 --- a/src/render/picking/qpickevent_p.h +++ b/src/render/picking/qpickevent_p.h @@ -37,6 +37,9 @@ ** ****************************************************************************/ +#ifndef QT3DRENDER_QPICKEVENT_P_H +#define QT3DRENDER_QPICKEVENT_P_H + // // W A R N I N G // ------------- @@ -95,3 +98,4 @@ public: QT_END_NAMESPACE +#endif // QT3DRENDER_QPICKEVENT_P_H diff --git a/tests/auto/render/objectpicker/tst_objectpicker.cpp b/tests/auto/render/objectpicker/tst_objectpicker.cpp index a8d9bd010..5fc988d47 100644 --- a/tests/auto/render/objectpicker/tst_objectpicker.cpp +++ b/tests/auto/render/objectpicker/tst_objectpicker.cpp @@ -137,65 +137,6 @@ private Q_SLOTS: QVERIFY(renderer.dirtyBits() != 0); } } - - void checkBackendPropertyNotifications() - { - // GIVEN - TestArbiter arbiter; - Qt3DRender::Render::ObjectPicker objectPicker; - Qt3DCore::QBackendNodePrivate::get(&objectPicker)->setArbiter(&arbiter); - Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent); - - // WHEN - objectPicker.onPressed(event, Qt3DCore::QNodeId()); - - // THEN - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - - arbiter.events.clear(); - - // WHEN - objectPicker.onReleased(event, Qt3DCore::QNodeId()); - - // THEN - QCOMPARE(arbiter.events.count(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); - - arbiter.events.clear(); - - // WHEN - objectPicker.onClicked(event, Qt3DCore::QNodeId()); - - // THEN - QCOMPARE(arbiter.events.count(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "clicked"); - - arbiter.events.clear(); - - // WHEN - objectPicker.onEntered(); - - // THEN - QCOMPARE(arbiter.events.count(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "entered"); - - arbiter.events.clear(); - - // WHEN - objectPicker.onExited(); - - // THEN - QCOMPARE(arbiter.events.count(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "exited"); - - arbiter.events.clear(); - } }; diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index 1fbdc4d04..5191b1a36 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -34,6 +34,10 @@ #include <Qt3DCore/qtransform.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qaspectengine_p.h> +#include <Qt3DCore/private/qaspectjob_p.h> #include <QtQuick/qquickwindow.h> #include <Qt3DRender/QCamera> @@ -60,6 +64,8 @@ #include <Qt3DRender/private/qobjectpicker_p.h> #include <Qt3DRender/private/nopicking_p.h> +#include <QSignalSpy> + #include <private/qpickevent_p.h> QT_BEGIN_NAMESPACE @@ -114,10 +120,18 @@ public: : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) , m_sceneRoot(nullptr) { - QRenderAspect::onRegistered(); - + m_engine = new Qt3DCore::QAspectEngine(this); + m_engine->registerAspect(this); + Q_ASSERT(d_func()->m_aspectManager); + + // do what QAspectEngine::setRootEntity does since we don't want to enter the simulation loop + Qt3DCore::QEntityPtr proot(qobject_cast<Qt3DCore::QEntity *>(root), [](Qt3DCore::QEntity *) { }); + Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine); + aed->m_root = proot; + aed->initialize(); + aed->initNodeTree(root); const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root); - d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChangesForNodes(nodes)); + aed->m_aspectManager->setRootEntity(proot.data(), nodes); Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); Q_ASSERT(rootEntity); @@ -126,7 +140,17 @@ public: ~TestAspect() { - QRenderAspect::onUnregistered(); + using namespace Qt3DCore; + QNodeVisitor visitor; + visitor.traverse(m_engine->rootEntity().data(), [](QNode *node) { + QNodePrivate *d = QNodePrivate::get(node); + d->m_scene = nullptr; + d->m_changeArbiter = nullptr; + }); + + m_engine->unregisterAspect(this); + delete m_engine; + m_engine = nullptr; } void onRegistered() { QRenderAspect::onRegistered(); } @@ -136,8 +160,10 @@ public: Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); } Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); } Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; } - + Qt3DCore::QAspectManager *aspectManager() const { return d_func()->m_aspectManager; } + Qt3DCore::QChangeArbiter *arbiter() const { return d_func()->m_arbiter; } private: + Qt3DCore::QAspectEngine *m_engine; Render::Entity *m_sceneRoot; }; @@ -285,7 +311,7 @@ private Q_SLOTS: auto vca = results.first(); QCOMPARE(vca.area, QSize(600, 600)); QCOMPARE(vca.cameraId, camera->id()); - QCOMPARE(vca.viewport, QRectF(0.0f, 0.0f, 1.0f, 1.0f)); + QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.)); } void checkCurrentPickerChange_data() @@ -344,7 +370,7 @@ private Q_SLOTS: // WHEN QList<QPair<QObject *,QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -357,7 +383,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -367,7 +393,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -380,7 +406,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -440,7 +466,7 @@ private Q_SLOTS: // WHEN QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 440.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 440.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -490,7 +516,7 @@ private Q_SLOTS: initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); @@ -547,7 +573,7 @@ private Q_SLOTS: initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -597,7 +623,7 @@ private Q_SLOTS: initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -608,7 +634,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -658,7 +684,7 @@ private Q_SLOTS: initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -669,7 +695,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -719,7 +745,7 @@ private Q_SLOTS: initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); const bool earlyReturn = !pickBVJob.runHelper(); @@ -740,6 +766,7 @@ private Q_SLOTS: QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root())); QVERIFY(root); + QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); QList<Qt3DRender::QRenderSettings *> renderSettings = root->findChildren<Qt3DRender::QRenderSettings *>(); QCOMPARE(renderSettings.size(), 1); @@ -751,9 +778,7 @@ private Q_SLOTS: settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); - - QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); - TestArbiter arbiter; + test->renderSettings()->syncFromFrontEnd(renderSettings.first(), false); // Runs Required jobs runRequiredJobs(test.data()); @@ -770,7 +795,7 @@ private Q_SLOTS: Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id()); QVERIFY(backendPicker1); - Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(&arbiter); + Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(test->arbiter()); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); @@ -785,94 +810,88 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); + QSignalSpy mouseButtonPressedSpy(picker1, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy(picker1, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy(picker1, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy(picker1, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy.isValid()); + QVERIFY(mouseMovedSpy.isValid()); + QVERIFY(mouseButtonReleasedSpy.isValid()); + QVERIFY(mouseClickedSpy.isValid()); + QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - Qt3DRender::QObjectPickerEvent pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull()); - if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) - QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>()); - - arbiter.events.clear(); + QVERIFY(picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); // WHEN -> Move on same object events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Moved QVERIFY(!earlyReturn); QVERIFY(backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "moved"); - pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull()); - if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) - QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>()); - - arbiter.events.clear(); + QVERIFY(picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); // WHEN -> Release on object events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Released + Clicked QVERIFY(!earlyReturn); QVERIFY(!backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), 2); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); - pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull()); - if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) - QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>()); - change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "clicked"); - pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull()); - if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) - QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>()); - - arbiter.events.clear(); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseButtonReleasedSpy.count(), /*backAndFrontPicking ? 2 :*/ 1); + QCOMPARE(mouseClickedSpy.count(), 1); + + mouseButtonPressedSpy.clear(); + mouseMovedSpy.clear(); + mouseButtonReleasedSpy.clear(); + mouseClickedSpy.clear(); // WHEN -> Release outside of object events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0, 0.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Released QVERIFY(!earlyReturn); QVERIFY(!backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 3 : 2); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); - - arbiter.events.clear(); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 1); } void checkDispatchReleaseEventOnLastPickerWhenMovingOutOfViewport() @@ -910,57 +929,70 @@ private Q_SLOTS: QVERIFY(backendPicker1); Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(&arbiter); + QSignalSpy mouseButtonPressedSpy(picker1, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy(picker1, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy(picker1, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy(picker1, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy.isValid()); + QVERIFY(mouseMovedSpy.isValid()); + QVERIFY(mouseButtonReleasedSpy.isValid()); + QVERIFY(mouseClickedSpy.isValid()); + + // WHEN -> Pressed on object Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - Qt3DRender::QObjectPickerEvent pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull()); - QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>()); - - arbiter.events.clear(); + QVERIFY(picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); // WHEN -> Releasing out of the viewport events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0f, 10000.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0, 10000.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Should have received released event QVERIFY(!earlyReturn); QVERIFY(!backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); - pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - QVERIFY(Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull()); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 1); - arbiter.events.clear(); // WHEN -> Releasing out of the viewport + mouseButtonPressedSpy.clear(); + mouseMovedSpy.clear(); + mouseButtonReleasedSpy.clear(); events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0f, 10000.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0, 10000.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Should have received nothing - QCOMPARE(arbiter.events.count(), 0); + QVERIFY(!backendPicker1->isPressed()); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 0); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); } void checkDispatchHoverEvent_data() @@ -1010,60 +1042,64 @@ private Q_SLOTS: QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); + QSignalSpy mouseEntered(picker1, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited(picker1, &Qt3DRender::QObjectPicker::exited); + + QVERIFY(mouseEntered.isValid()); + QVERIFY(mouseExited.isValid()); + // WHEN -> Hover on object Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Entered QVERIFY(!earlyReturn); QVERIFY(!backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "entered"); - - arbiter.events.clear(); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseEntered.count(), 1); + QCOMPARE(mouseExited.count(), 0); // WHEN -> HoverMove Out events.clear(); - events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0f, 40.0f), + events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0, 40.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN - Exited QVERIFY(!earlyReturn); QVERIFY(!backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "exited"); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseEntered.count(), 1); + QCOMPARE(mouseExited.count(), 1); - arbiter.events.clear(); + mouseEntered.clear(); + mouseExited.clear(); // WHEN -> HoverMove In + Pressed other events.clear(); - events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); - events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f), + events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0, 0.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN - Entered, Exited QVERIFY(!earlyReturn); QVERIFY(!backendPicker1->isPressed()); - QCOMPARE(arbiter.events.count(), 2); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "entered"); - change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "exited"); - - arbiter.events.clear(); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseEntered.count(), 1); + QCOMPARE(mouseExited.count(), 1); } void shouldDispatchMouseEventFromChildren_data() @@ -1115,78 +1151,94 @@ private Q_SLOTS: (pickResultMode == Qt3DRender::QPickingSettings::AllPicks) && (faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace); + QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy.isValid()); + QVERIFY(mouseMovedSpy.isValid()); + QVERIFY(mouseButtonReleasedSpy.isValid()); + QVERIFY(mouseClickedSpy.isValid()); + // WHEN -> Pressed on object Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0, 300.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - - arbiter.events.clear(); + QVERIFY(picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); // WHEN -> Move on same object + mouseButtonPressedSpy.clear(); events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0, 300.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Moved QVERIFY(!earlyReturn); QVERIFY(backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "moved"); - - arbiter.events.clear(); + QVERIFY(picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 0); + QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); // WHEN -> Release on object + mouseMovedSpy.clear(); events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0, 300.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Released + Clicked QVERIFY(!earlyReturn); QVERIFY(!backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), 2); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); - change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "clicked"); - - arbiter.events.clear(); + QVERIFY(!picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 0); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 1); + QCOMPARE(mouseClickedSpy.count(), 1); // WHEN -> Release outside of object events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), + mouseButtonPressedSpy.clear(); + mouseMovedSpy.clear(); + mouseButtonReleasedSpy.clear(); + + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0., 0.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Released QVERIFY(!earlyReturn); QVERIFY(!backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 3 : 2); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); - - arbiter.events.clear(); + QVERIFY(!picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 1); + QCOMPARE(mouseClickedSpy.count(), 1); } void checkPickerGrabbing_data() @@ -1212,6 +1264,11 @@ private Q_SLOTS: settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); + const bool backAndFrontPicking = + (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) && + (pickResultMode == Qt3DRender::QPickingSettings::AllPicks) && + (faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace); + QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter1; TestArbiter arbiter2; @@ -1245,47 +1302,85 @@ private Q_SLOTS: QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); + QSignalSpy mouseEntered1(picker1, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited1(picker1, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy1(picker1, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy1(picker1, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy1(picker1, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy1(picker1, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy1.isValid()); + QVERIFY(mouseMovedSpy1.isValid()); + QVERIFY(mouseButtonReleasedSpy1.isValid()); + QVERIFY(mouseClickedSpy1.isValid()); + QVERIFY(mouseEntered1.isValid()); + QVERIFY(mouseExited1.isValid()); + + QSignalSpy mouseEntered2(picker2, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited2(picker2, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy2(picker2, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy2(picker2, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy2(picker2, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy2(picker2, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy2.isValid()); + QVERIFY(mouseMovedSpy2.isValid()); + QVERIFY(mouseButtonReleasedSpy2.isValid()); + QVERIFY(mouseClickedSpy2.isValid()); + QVERIFY(mouseEntered2.isValid()); + QVERIFY(mouseExited2.isValid()); + // WHEN -> Pressed on object Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker1->isPressed()); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); + QVERIFY(picker1->isPressed()); - arbiter1.events.clear(); + QCOMPARE(mouseButtonPressedSpy1.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseMovedSpy1.count(), 0); + QCOMPARE(mouseButtonReleasedSpy1.count(), 0); + QCOMPARE(mouseClickedSpy1.count(), 0); + QCOMPARE(mouseEntered1.count(), 0); + QCOMPARE(mouseExited1.count(), 0); // WHEN -> Move on next object, show stay on previous picker unless all picks are requested events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Moved over the second picker, is the first one still pressed QVERIFY(!earlyReturn); if (pickResultMode != Qt3DRender::QPickingSettings::AllPicks) { QVERIFY(backendPicker1->isPressed()); - change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "moved"); + QVERIFY(picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy1.count(), 1); + QCOMPARE(mouseMovedSpy1.count(), 1); + QCOMPARE(mouseButtonReleasedSpy1.count(), 0); + QCOMPARE(mouseClickedSpy1.count(), 0); + QCOMPARE(mouseEntered1.count(), 0); + QCOMPARE(mouseExited1.count(), 0); } else { - QVERIFY(arbiter2.events.size() > 1); - change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "moved"); - change = arbiter2.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "entered"); + QVERIFY(!picker2->isPressed()); + QCOMPARE(mouseButtonPressedSpy2.count(), 0); + QCOMPARE(mouseMovedSpy2.count(), backAndFrontPicking ? 2 : 1); + QCOMPARE(mouseButtonReleasedSpy2.count(), 0); + QCOMPARE(mouseClickedSpy2.count(), 0); + QCOMPARE(mouseEntered2.count(), 1); + QCOMPARE(mouseExited2.count(), 0); } - - arbiter1.events.clear(); - arbiter2.events.clear(); } void checkParentNoPickerChildPicker() @@ -1321,22 +1416,41 @@ private Q_SLOTS: QVERIFY(backendPicker); Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter); + QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy.isValid()); + QVERIFY(mouseMovedSpy.isValid()); + QVERIFY(mouseButtonReleasedSpy.isValid()); + QVERIFY(mouseClickedSpy.isValid()); + QVERIFY(mouseEntered.isValid()); + QVERIFY(mouseExited.isValid()); + // WHEN -> Pressed on object Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); + QVERIFY(picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); + QCOMPARE(mouseEntered.count(), 0); + QCOMPARE(mouseExited.count(), 0); } void checkPickerAndViewports() @@ -1372,38 +1486,63 @@ private Q_SLOTS: QVERIFY(backendPicker); Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter); + QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy.isValid()); + QVERIFY(mouseMovedSpy.isValid()); + QVERIFY(mouseButtonReleasedSpy.isValid()); + QVERIFY(mouseClickedSpy.isValid()); + QVERIFY(mouseEntered.isValid()); + QVERIFY(mouseExited.isValid()); + // WHEN -> Pressed on object in vp1 Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); + QVERIFY(picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); + QCOMPARE(mouseEntered.count(), 0); + QCOMPARE(mouseExited.count(), 0); // WHEN reset -> Presset on object in vp2 backendPicker->cleanup(); backendPicker->setEnabled(true); events.clear(); - arbiter.events.clear(); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Nothing happened QVERIFY(!earlyReturn); QVERIFY(!backendPicker->isPressed()); - QCOMPARE(arbiter.events.count(), 0); + QVERIFY(picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); + QCOMPARE(mouseEntered.count(), 0); + QCOMPARE(mouseExited.count(), 0); } void checkMultipleRayDirections_data() @@ -1420,8 +1559,8 @@ private Q_SLOTS: const double angle = M_PI * 2. / (double)n * i; const double x = std::sin(angle) * 10.; const double z = std::cos(angle) * 10.; - QVector3D pos(x, 0, z); - QVector3D up(0, 1, 0); + QVector3D pos(x, 0.f, z); + QVector3D up(0.f, 1.f, 0.f); QTest::newRow(QString::number(k++).toLatin1().data()) << m * pos << m * up; } } @@ -1466,25 +1605,41 @@ private Q_SLOTS: QVERIFY(backendPicker); Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter); + QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy.isValid()); + QVERIFY(mouseMovedSpy.isValid()); + QVERIFY(mouseButtonReleasedSpy.isValid()); + QVERIFY(mouseClickedSpy.isValid()); + QVERIFY(mouseEntered.isValid()); + QVERIFY(mouseExited.isValid()); + // WHEN -> Pressed on object Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303.0f, 303.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Pressed QVERIFY(!earlyReturn); QVERIFY(backendPicker->isPressed()); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - Qt3DRender::QObjectPickerEvent pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>(); - QVERIFY(pickEvent.event); - - arbiter.events.clear(); + QVERIFY(picker->isPressed()); + QCOMPARE(mouseButtonPressedSpy.count(), 1); + QCOMPARE(mouseMovedSpy.count(), 0); + QCOMPARE(mouseButtonReleasedSpy.count(), 0); + QCOMPARE(mouseClickedSpy.count(), 0); + QCOMPARE(mouseEntered.count(), 0); + QCOMPARE(mouseExited.count(), 0); } void checkPriorityPicking() @@ -1523,6 +1678,33 @@ private Q_SLOTS: QVERIFY(backendPicker2); Qt3DCore::QBackendNodePrivate::get(backendPicker2)->setArbiter(&arbiter2); + QSignalSpy mouseEntered1(picker1, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited1(picker1, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy1(picker1, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy1(picker1, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy1(picker1, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy1(picker1, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy1.isValid()); + QVERIFY(mouseMovedSpy1.isValid()); + QVERIFY(mouseButtonReleasedSpy1.isValid()); + QVERIFY(mouseClickedSpy1.isValid()); + QVERIFY(mouseEntered1.isValid()); + QVERIFY(mouseExited1.isValid()); + + QSignalSpy mouseEntered2(picker2, &Qt3DRender::QObjectPicker::entered); + QSignalSpy mouseExited2(picker2, &Qt3DRender::QObjectPicker::exited); + QSignalSpy mouseButtonPressedSpy2(picker2, &Qt3DRender::QObjectPicker::pressed); + QSignalSpy mouseMovedSpy2(picker2, &Qt3DRender::QObjectPicker::moved); + QSignalSpy mouseButtonReleasedSpy2(picker2, &Qt3DRender::QObjectPicker::released); + QSignalSpy mouseClickedSpy2(picker2, &Qt3DRender::QObjectPicker::clicked); + + QVERIFY(mouseButtonPressedSpy2.isValid()); + QVERIFY(mouseMovedSpy2.isValid()); + QVERIFY(mouseButtonReleasedSpy2.isValid()); + QVERIFY(mouseClickedSpy2.isValid()); + QVERIFY(mouseEntered2.isValid()); + QVERIFY(mouseExited2.isValid()); // WHEN both have priority == 0, select closest { @@ -1531,31 +1713,62 @@ private Q_SLOTS: // WHEN -> Pressed on object QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Select picker with highest priority QVERIFY(!earlyReturn); QVERIFY(backendPicker1->isPressed()); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); + QVERIFY(picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy1.count(), 1); + QCOMPARE(mouseMovedSpy1.count(), 0); + QCOMPARE(mouseButtonReleasedSpy1.count(), 0); + QCOMPARE(mouseClickedSpy1.count(), 0); + QCOMPARE(mouseEntered1.count(), 0); + QCOMPARE(mouseExited1.count(), 0); QVERIFY(!backendPicker2->isPressed()); - QVERIFY(arbiter2.events.isEmpty()); - - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300.0f, 300.0f), + QVERIFY(!picker2->isPressed()); + QCOMPARE(mouseButtonPressedSpy2.count(), 0); + QCOMPARE(mouseMovedSpy2.count(), 0); + QCOMPARE(mouseButtonReleasedSpy2.count(), 0); + QCOMPARE(mouseClickedSpy2.count(), 0); + QCOMPARE(mouseEntered2.count(), 0); + QCOMPARE(mouseExited2.count(), 0); + + events.clear(); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); pickBVJob.runHelper(); - arbiter1.events.clear(); - arbiter2.events.clear(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); QVERIFY(!backendPicker1->isPressed()); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy1.count(), 1); + QCOMPARE(mouseMovedSpy1.count(), 0); + QCOMPARE(mouseButtonReleasedSpy1.count(), 1); + QCOMPARE(mouseClickedSpy1.count(), 1); + QCOMPARE(mouseEntered1.count(), 0); + QCOMPARE(mouseExited1.count(), 0); + QVERIFY(!backendPicker2->isPressed()); + QVERIFY(!picker2->isPressed()); + QCOMPARE(mouseButtonPressedSpy2.count(), 0); + QCOMPARE(mouseMovedSpy2.count(), 0); + QCOMPARE(mouseButtonReleasedSpy2.count(), 0); + QCOMPARE(mouseClickedSpy2.count(), 0); + QCOMPARE(mouseEntered2.count(), 0); + QCOMPARE(mouseExited2.count(), 0); } + mouseButtonPressedSpy1.clear(); + mouseButtonReleasedSpy1.clear(); + mouseClickedSpy1.clear(); + // WHEN furthest one has higher priority, select furthest one { backendPicker2->setPriority(1000); @@ -1566,29 +1779,56 @@ private Q_SLOTS: // WHEN -> Pressed on object QList<QPair<QObject *, QMouseEvent>> events; - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300.0f, 300.0f), + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); // THEN -> Select picker with highest priority QVERIFY(!earlyReturn); - QVERIFY(backendPicker2->isPressed()); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "pressed"); - QVERIFY(!backendPicker1->isPressed()); - QVERIFY(arbiter1.events.isEmpty()); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy1.count(), 0); + QCOMPARE(mouseMovedSpy1.count(), 0); + QCOMPARE(mouseButtonReleasedSpy1.count(), 0); + QCOMPARE(mouseClickedSpy1.count(), 0); + QCOMPARE(mouseEntered1.count(), 0); + QCOMPARE(mouseExited1.count(), 0); - events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300.0f, 300.0f), + QVERIFY(backendPicker2->isPressed()); + QVERIFY(picker2->isPressed()); + QCOMPARE(mouseButtonPressedSpy2.count(), 1); + QCOMPARE(mouseMovedSpy2.count(), 0); + QCOMPARE(mouseButtonReleasedSpy2.count(), 0); + QCOMPARE(mouseClickedSpy2.count(), 0); + QCOMPARE(mouseEntered2.count(), 0); + QCOMPARE(mouseExited2.count(), 0); + + events.clear(); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); pickBVJob.runHelper(); - arbiter1.events.clear(); - arbiter2.events.clear(); + Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager()); QVERIFY(!backendPicker1->isPressed()); + QVERIFY(!picker1->isPressed()); + QCOMPARE(mouseButtonPressedSpy1.count(), 0); + QCOMPARE(mouseMovedSpy1.count(), 0); + QCOMPARE(mouseButtonReleasedSpy1.count(), 0); + QCOMPARE(mouseClickedSpy1.count(), 0); + QCOMPARE(mouseEntered1.count(), 0); + QCOMPARE(mouseExited1.count(), 0); + QVERIFY(!backendPicker2->isPressed()); + QVERIFY(!picker2->isPressed()); + QCOMPARE(mouseButtonPressedSpy2.count(), 1); + QCOMPARE(mouseMovedSpy2.count(), 0); + QCOMPARE(mouseButtonReleasedSpy2.count(), 1); + QCOMPARE(mouseClickedSpy2.count(), 1); + QCOMPARE(mouseEntered2.count(), 0); + QCOMPARE(mouseExited2.count(), 0); } } @@ -1635,7 +1875,7 @@ private Q_SLOTS: auto vca = results.first(); QCOMPARE(vca.area, QSize(600, 600)); QCOMPARE(vca.cameraId, camera->id()); - QCOMPARE(vca.viewport, QRectF(0.0f, 0.0f, 1.0f, 1.0f)); + QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.)); } }; diff --git a/tests/auto/render/picking/tst_picking.cpp b/tests/auto/render/picking/tst_picking.cpp index 4f4201e07..d0e6512d5 100644 --- a/tests/auto/render/picking/tst_picking.cpp +++ b/tests/auto/render/picking/tst_picking.cpp @@ -153,14 +153,13 @@ private Q_SLOTS: QCoreApplication::processEvents(); + auto dpicker = [](QObjectPicker *node) { + return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node)); + }; + // WHEN Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent()); - QVariant v; - v.setValue<Qt3DRender::QObjectPickerEvent>({event, Qt3DCore::QNodeId()}); - Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id())); - e->setPropertyName("pressed"); - e->setValue(v); - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->pressedEvent(event.data()); // THEN QCOMPARE(root.pressedCalled, 0); @@ -171,7 +170,7 @@ private Q_SLOTS: // WHEN child11.pressedCalled = 0; child11.acceptsEvents = false; - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->pressedEvent(event.data()); // THEN QCOMPARE(root.pressedCalled, 0); @@ -184,7 +183,7 @@ private Q_SLOTS: child1.pressedCalled = 0; child11.acceptsEvents = false; child11.pressedCalled = 0; - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->pressedEvent(event.data()); // THEN QCOMPARE(root.pressedCalled, 1); @@ -208,16 +207,14 @@ private Q_SLOTS: QCoreApplication::processEvents(); + auto dpicker = [](QObjectPicker *node) { + return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node)); + }; + // WHEN Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent()); - QVariant v; - v.setValue<Qt3DRender::QObjectPickerEvent>({event, Qt3DCore::QNodeId()}); - Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id())); - e->setPropertyName("pressed"); - e->setValue(v); - child11.picker->sceneChangeEvent(e); - e->setPropertyName("released"); - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->pressedEvent(event.data()); + dpicker(child11.picker)->releasedEvent(event.data()); // THEN QCOMPARE(root.releasedCalled, 0); @@ -229,10 +226,8 @@ private Q_SLOTS: child11.releasedCalled = 0; child11.pressedCalled = 0; child11.acceptsEvents = false; - e->setPropertyName("pressed"); - child11.picker->sceneChangeEvent(e); - e->setPropertyName("released"); - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->pressedEvent(event.data()); + dpicker(child11.picker)->releasedEvent(event.data()); // THEN QCOMPARE(child1.pressedCalled, 1); @@ -259,14 +254,13 @@ private Q_SLOTS: QCoreApplication::processEvents(); + auto dpicker = [](QObjectPicker *node) { + return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node)); + }; + // WHEN Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent()); - QVariant v; - v.setValue<Qt3DRender::QObjectPickerEvent>({event, Qt3DCore::QNodeId()}); - Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id())); - e->setPropertyName("clicked"); - e->setValue(v); - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->clickedEvent(event.data()); // THEN QCOMPARE(root.clickedCalled, 0); @@ -277,7 +271,7 @@ private Q_SLOTS: // WHEN child11.clickedCalled = 0; child11.acceptsEvents = false; - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->clickedEvent(event.data()); // THEN QCOMPARE(root.clickedCalled, 0); @@ -290,7 +284,7 @@ private Q_SLOTS: child1.clickedCalled = 0; child11.acceptsEvents = false; child11.clickedCalled = 0; - child11.picker->sceneChangeEvent(e); + dpicker(child11.picker)->clickedEvent(event.data()); // THEN QCOMPARE(root.clickedCalled, 1); diff --git a/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp b/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp index 53c0ec939..5977829a6 100644 --- a/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp +++ b/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp @@ -234,24 +234,6 @@ private Q_SLOTS: QTest::newRow("objectPicker_all_true") << objectPicker; } - // TODO: Avoid cloning here -// void checkCloning() -// { -// // GIVEN -// QFETCH(Qt3DRender::QObjectPicker *, objectPicker); - -// // WHEN -// Qt3DRender::QObjectPicker *clone = static_cast<Qt3DRender::QObjectPicker *>(QNode::clone(objectPicker)); -// QCoreApplication::processEvents(); - -// // THEN -// QVERIFY(clone != nullptr); -// QCOMPARE(objectPicker->id(), clone->id()); -// QCOMPARE(objectPicker->isHoverEnabled(), clone->isHoverEnabled()); -// QCOMPARE(objectPicker->isPressed(), clone->isPressed()); -// QCOMPARE(objectPicker->containsMouse(), clone->containsMouse()); -// } - void checkPropertyUpdates() { // GIVEN @@ -272,68 +254,6 @@ private Q_SLOTS: arbiter.dirtyNodes.clear(); } - - void checkBackendUpdates_data() - { - QTest::addColumn<QByteArray>("signalPrototype"); - QTest::addColumn<QByteArray>("propertyName"); - QTest::addColumn<bool>("requiresEvent"); - - QTest::newRow("clicked") - << QByteArray(SIGNAL(clicked(Qt3DRender::QPickEvent *))) - << QByteArrayLiteral("clicked") - << true; - - QTest::newRow("pressed") - << QByteArray(SIGNAL(pressed(Qt3DRender::QPickEvent *))) - << QByteArrayLiteral("pressed") - << true; - - QTest::newRow("released") - << QByteArray(SIGNAL(released(Qt3DRender::QPickEvent *))) - << QByteArrayLiteral("released") - << true; - - QTest::newRow("entered") - << QByteArray(SIGNAL(entered())) - << QByteArrayLiteral("entered") - << false; - - QTest::newRow("exited") - << QByteArray(SIGNAL(exited())) - << QByteArrayLiteral("exited") - << false; - } - - void checkBackendUpdates() - { - // GIVEN - QFETCH(QByteArray, signalPrototype); - QFETCH(QByteArray, propertyName); - QFETCH(bool, requiresEvent); - Qt3DCore::QScene scene; - QScopedPointer<MyObjectPicker> objectPicker(new MyObjectPicker()); - Qt3DCore::QNodePrivate::get(objectPicker.data())->setScene(&scene); - - QSignalSpy spy(objectPicker.data(), signalPrototype.constData()); - Qt3DRender::QObjectPickerEvent event {Qt3DRender::QPickEventPtr::create(), Qt3DCore::QNodeId()}; - - // WHEN - // Create Backend Change and distribute it to frontend node - Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(objectPicker->id())); - e->setPropertyName(propertyName.constData()); - if (requiresEvent) - { - QVariant v; - v.setValue<Qt3DRender::QObjectPickerEvent>(event); - e->setValue(v); - } - objectPicker->sceneChangeEvent(e); - - // THEN - // Check that the QObjectPicker triggers the expected signal - QCOMPARE(spy.count(), 1); - } }; QTEST_MAIN(tst_QObjectPicker) |