/**************************************************************************** ** ** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmlscenereader.h" #include "testarbiter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Qt3DRender { QVector getNodesForCreation(Qt3DCore::QNode *root) { using namespace Qt3DCore; QVector nodes; Qt3DCore::QNodeVisitor visitor; visitor.traverse(root, [&nodes](QNode *node) { nodes.append(node); // Store the metaobject of the node in the QNode so that we have it available // to us during destruction in the QNode destructor. This allows us to send // the QNodeId and the metaobject as typeinfo to the backend aspects so they // in turn can find the correct QBackendNodeMapper object to handle the destruction // of the corresponding backend nodes. QNodePrivate *d = QNodePrivate::get(node); d->m_typeInfo = const_cast(QNodePrivate::findStaticMetaObject(node->metaObject())); // Mark this node as having been handled for creation so that it is picked up d->m_hasBackendNode = true; }); return nodes; } QVector nodeTreeChangesForNodes(const QVector nodes) { QVector nodeTreeChanges; nodeTreeChanges.reserve(nodes.size()); for (Qt3DCore::QNode *n : nodes) { nodeTreeChanges.push_back({ n->id(), Qt3DCore::QNodePrivate::get(n)->m_typeInfo, Qt3DCore::NodeTreeChange::Added, n }); } return nodeTreeChanges; } class TestAspect : public Qt3DRender::QRenderAspect { public: TestAspect(Qt3DCore::QNode *root) : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) , m_sceneRoot(nullptr) { 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(root), [](Qt3DCore::QEntity *) { }); Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine); aed->m_root = proot; aed->initialize(); aed->initNodeTree(root); const QVector nodes = getNodesForCreation(root); aed->m_aspectManager->setRootEntity(proot.data(), nodes); Render::Entity *rootEntity = nodeManagers()->lookupResource(rootEntityId()); Q_ASSERT(rootEntity); m_sceneRoot = rootEntity; } ~TestAspect() { 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(); } void onUnregistered() { QRenderAspect::onUnregistered(); } Qt3DRender::Render::NodeManagers *nodeManagers() const { return d_func()->m_renderer->nodeManagers(); } 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; }; } // namespace Qt3DRender QT_END_NAMESPACE namespace { void runRequiredJobs(Qt3DRender::TestAspect *test) { Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; updateWorldTransform.setRoot(test->sceneRoot()); updateWorldTransform.setManagers(test->nodeManagers()); updateWorldTransform.run(); Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; calcBVolume.setManagers(test->nodeManagers()); calcBVolume.setRoot(test->sceneRoot()); calcBVolume.run(); Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; updateWorldBVolume.setManager(test->nodeManagers()->renderNodesManager()); updateWorldBVolume.run(); Qt3DRender::Render::ExpandBoundingVolumeJob expandBVolume; expandBVolume.setRoot(test->sceneRoot()); expandBVolume.setManagers(test->nodeManagers()); expandBVolume.run(); Qt3DRender::Render::UpdateMeshTriangleListJob updateTriangleList; updateTriangleList.setManagers(test->nodeManagers()); updateTriangleList.run(); } void initializePickBoundingVolumeJob(Qt3DRender::Render::PickBoundingVolumeJob *job, Qt3DRender::TestAspect *test) { job->setFrameGraphRoot(test->frameGraphRoot()); job->setRoot(test->sceneRoot()); job->setManagers(test->nodeManagers()); job->setRenderSettings(test->renderSettings()); } } // anonymous class tst_PickBoundingVolumeJob : public QObject { Q_OBJECT private: void generateAllPickingSettingsCombinations() { QTest::addColumn("pickMethod"); QTest::addColumn("pickResultMode"); QTest::addColumn("faceOrientationPickingMode"); QTest::newRow("volume, nearest, front") << Qt3DRender::QPickingSettings::BoundingVolumePicking << Qt3DRender::QPickingSettings::NearestPick << Qt3DRender::QPickingSettings::FrontFace; QTest::newRow("volume, nearest, back") << Qt3DRender::QPickingSettings::BoundingVolumePicking << Qt3DRender::QPickingSettings::NearestPick << Qt3DRender::QPickingSettings::BackFace; QTest::newRow("volume, nearest, front+back") << Qt3DRender::QPickingSettings::BoundingVolumePicking << Qt3DRender::QPickingSettings::NearestPick << Qt3DRender::QPickingSettings::FrontAndBackFace; QTest::newRow("volume, all, front") << Qt3DRender::QPickingSettings::BoundingVolumePicking << Qt3DRender::QPickingSettings::AllPicks << Qt3DRender::QPickingSettings::FrontFace; QTest::newRow("volume, all, back") << Qt3DRender::QPickingSettings::BoundingVolumePicking << Qt3DRender::QPickingSettings::AllPicks << Qt3DRender::QPickingSettings::BackFace; QTest::newRow("volume, all, front+back") << Qt3DRender::QPickingSettings::BoundingVolumePicking << Qt3DRender::QPickingSettings::AllPicks << Qt3DRender::QPickingSettings::FrontAndBackFace; QTest::newRow("triangle, nearest, front") << Qt3DRender::QPickingSettings::TrianglePicking << Qt3DRender::QPickingSettings::NearestPick << Qt3DRender::QPickingSettings::FrontFace; QTest::newRow("triangle, nearest, back") << Qt3DRender::QPickingSettings::TrianglePicking << Qt3DRender::QPickingSettings::NearestPick << Qt3DRender::QPickingSettings::BackFace; QTest::newRow("triangle, nearest, front+back") << Qt3DRender::QPickingSettings::TrianglePicking << Qt3DRender::QPickingSettings::NearestPick << Qt3DRender::QPickingSettings::FrontAndBackFace; QTest::newRow("triangle, all, front") << Qt3DRender::QPickingSettings::TrianglePicking << Qt3DRender::QPickingSettings::AllPicks << Qt3DRender::QPickingSettings::FrontFace; QTest::newRow("triangle, all, back") << Qt3DRender::QPickingSettings::TrianglePicking << Qt3DRender::QPickingSettings::AllPicks << Qt3DRender::QPickingSettings::BackFace; QTest::newRow("triangle, all, front+back") << Qt3DRender::QPickingSettings::TrianglePicking << Qt3DRender::QPickingSettings::AllPicks << Qt3DRender::QPickingSettings::FrontAndBackFace; } private Q_SLOTS: void viewportCameraAreaGather() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // THEN QVERIFY(test->frameGraphRoot() != nullptr); Qt3DRender::QCamera *camera = root->findChild(); QVERIFY(camera != nullptr); QQuickWindow *window = root->findChild(); QVERIFY(camera != nullptr); QCOMPARE(window->size(), QSize(600, 600)); // WHEN Qt3DRender::Render::PickingUtils::ViewportCameraAreaGatherer gatherer; QVector results = gatherer.gather(test->frameGraphRoot()); // THEN QCOMPARE(results.size(), 1); auto vca = results.first(); QCOMPARE(vca.area, QSize(600, 600)); QCOMPARE(vca.cameraId, camera->id()); QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.)); } void checkCurrentPickerChange_data() { generateAllPickingSettingsCombinations(); } void checkCurrentPickerChange() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker1 = nullptr; Qt3DRender::QObjectPicker *picker2 = nullptr; if (pickers.first()->objectName() == QLatin1String("Picker1")) { picker1 = pickers.first(); picker2 = pickers.last(); } else { picker1 = pickers.last(); picker2 = pickers.first(); } QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); // THEN QVERIFY(pickBVJob.currentPicker().isNull()); // WHEN QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!earlyReturn); QVERIFY(!pickBVJob.currentPicker().isNull()); Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->data(pickBVJob.currentPicker()); QVERIFY(backendPicker != nullptr); QCOMPARE(backendPicker->peerId(), picker1->id()); // WHEN events.clear(); events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!earlyReturn); QVERIFY(pickBVJob.currentPicker().isNull()); // WHEN events.clear(); events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!earlyReturn); QVERIFY(!pickBVJob.currentPicker().isNull()); backendPicker = test->nodeManagers()->data(pickBVJob.currentPicker()); QVERIFY(backendPicker != nullptr); QCOMPARE(backendPicker->peerId(), picker2->id()); // WHEN events.clear(); events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!earlyReturn); QVERIFY(pickBVJob.currentPicker().isNull()); } void checkEarlyReturnWhenNoMouseEvents_data() { generateAllPickingSettingsCombinations(); } void checkEarlyReturnWhenNoMouseEvents() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); // THEN QVERIFY(pickBVJob.currentPicker().isNull()); // WHEN bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(earlyReturn); // WHEN QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 440.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!earlyReturn); } void checkEarlyReturnWhenMoveEventsAndNoCurrentPickers_data() { generateAllPickingSettingsCombinations(); } void checkEarlyReturnWhenMoveEventsAndNoCurrentPickers() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); // THEN QVERIFY(pickBVJob.currentPicker().isNull()); // WHEN const bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(earlyReturn); } void checkEarlyReturnWhenAllPickersDisabled_data() { generateAllPickingSettingsCombinations(); } void checkEarlyReturnWhenAllPickersDisabled() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_pickersdisabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(earlyReturn); } void checkEarlyReturnWhenMoveEventsAndDragDisabledPickers_data() { generateAllPickingSettingsCombinations(); } void checkEarlyReturnWhenMoveEventsAndDragDisabledPickers() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragdisabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!pickBVJob.currentPicker().isNull()); QVERIFY(!earlyReturn); // WHEN events.clear(); events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(earlyReturn); } void checkNoEarlyReturnWhenMoveEventsAndDragEnabledPickers_data() { generateAllPickingSettingsCombinations(); } void checkNoEarlyReturnWhenMoveEventsAndDragEnabledPickers() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!pickBVJob.currentPicker().isNull()); QVERIFY(!earlyReturn); // WHEN events.clear(); events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(!earlyReturn); } void checkEarlyReturnWhenNoProperFrameGraph_data() { generateAllPickingSettingsCombinations(); } void checkEarlyReturnWhenNoProperFrameGraph() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_improperframegraph.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); // WHEN Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); QList> events; events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); const bool earlyReturn = !pickBVJob.runHelper(); // THEN QVERIFY(pickBVJob.currentPicker().isNull()); QVERIFY(earlyReturn); } void checkDispatchMouseEvent_data() { generateAllPickingSettingsCombinations(); } void checkDispatchMouseEvent() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); test->renderSettings()->syncFromFrontEnd(renderSettings.first(), false); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker1 = nullptr; if (pickers.first()->objectName() == QLatin1String("Picker1")) picker1 = pickers.first(); else picker1 = pickers.last(); Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id()); QVERIFY(backendPicker1); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); const bool backAndFrontPicking = (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) && (pickResultMode == Qt3DRender::QPickingSettings::AllPicks) && (faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace); // WHEN -> Pressed on object 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> events; 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()); 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.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()); 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.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()); 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.0, 303.0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); 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()); QVERIFY(!picker1->isPressed()); QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); QCOMPARE(mouseMovedSpy.count(), 0); QCOMPARE(mouseButtonReleasedSpy.count(), 1); } void checkDispatchReleaseEventOnLastPickerWhenMovingOutOfViewport() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); settings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); settings->setPickResultMode(Qt3DRender::QPickingSettings::NearestPick); settings->setFaceOrientationPickingMode(Qt3DRender::QPickingSettings::FrontAndBackFace); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter; // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker1 = nullptr; if (pickers.first()->objectName() == QLatin1String("Picker1")) picker1 = pickers.first(); else picker1 = pickers.last(); Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id()); QVERIFY(backendPicker1); 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> events; 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()); 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.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()); QVERIFY(!picker1->isPressed()); QCOMPARE(mouseButtonPressedSpy.count(), 1); QCOMPARE(mouseMovedSpy.count(), 0); QCOMPARE(mouseButtonReleasedSpy.count(), 1); // WHEN -> Releasing out of the viewport mouseButtonPressedSpy.clear(); mouseMovedSpy.clear(); mouseButtonReleasedSpy.clear(); events.clear(); 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 QVERIFY(!backendPicker1->isPressed()); QVERIFY(!picker1->isPressed()); QCOMPARE(mouseButtonPressedSpy.count(), 0); QCOMPARE(mouseMovedSpy.count(), 0); QCOMPARE(mouseButtonReleasedSpy.count(), 0); } void checkDispatchHoverEvent_data() { generateAllPickingSettingsCombinations(); } void checkDispatchHoverEvent() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabledhoverenabled.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter; // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker1 = nullptr; if (pickers.first()->objectName() == QLatin1String("Picker1")) picker1 = pickers.first(); else picker1 = pickers.last(); Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id()); QVERIFY(backendPicker1); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); 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> events; 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()); 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.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()); QVERIFY(!picker1->isPressed()); QCOMPARE(mouseEntered.count(), 1); QCOMPARE(mouseExited.count(), 1); mouseEntered.clear(); mouseExited.clear(); // WHEN -> HoverMove In + Pressed other events.clear(); 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.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()); QVERIFY(!picker1->isPressed()); QCOMPARE(mouseEntered.count(), 1); QCOMPARE(mouseExited.count(), 1); } void shouldDispatchMouseEventFromChildren_data() { generateAllPickingSettingsCombinations(); } void shouldDispatchMouseEventFromChildren() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_childentity.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter; // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 1); Qt3DRender::QObjectPicker *picker = pickers.first(); QCOMPARE(pickers.first()->objectName(), QLatin1String("Picker")); Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->objectPickerManager()->lookupResource(picker->id()); QVERIFY(backendPicker); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode); QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode); const bool backAndFrontPicking = (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) && (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> events; 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()); 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.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()); 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.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()); 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(); 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., 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()); QVERIFY(!picker->isPressed()); QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1); QCOMPARE(mouseMovedSpy.count(), 0); QCOMPARE(mouseButtonReleasedSpy.count(), 1); QCOMPARE(mouseClickedSpy.count(), 1); } void checkPickerGrabbing_data() { generateAllPickingSettingsCombinations(); } void checkPickerGrabbing() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabledoverlapping.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); QFETCH(Qt3DRender::QPickingSettings::PickMethod, pickMethod); QFETCH(Qt3DRender::QPickingSettings::PickResultMode, pickResultMode); QFETCH(Qt3DRender::QPickingSettings::FaceOrientationPickingMode, faceOrientationPickingMode); settings->setPickMethod(pickMethod); settings->setPickResultMode(pickResultMode); settings->setFaceOrientationPickingMode(faceOrientationPickingMode); const bool backAndFrontPicking = (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) && (pickResultMode == Qt3DRender::QPickingSettings::AllPicks) && (faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter1; TestArbiter arbiter2; // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker1 = nullptr; Qt3DRender::QObjectPicker *picker2 = nullptr; if (pickers.first()->objectName() == QLatin1String("Picker1")) { picker1 = pickers.first(); picker2 = pickers.last(); } else { picker1 = pickers.last(); picker2 = pickers.first(); } Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id()); QVERIFY(backendPicker1); Qt3DRender::Render::ObjectPicker *backendPicker2 = test->nodeManagers()->objectPickerManager()->lookupResource(picker2->id()); QVERIFY(backendPicker2); QCOMPARE(test->renderSettings()->pickMethod(), pickMethod); 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> events; 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()); QVERIFY(picker1->isPressed()); 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., 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()); 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(!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); } } void checkParentNoPickerChildPicker() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_parententity.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); settings->setPickMethod(Qt3DRender::QPickingSettings::BoundingVolumePicking); settings->setPickResultMode(Qt3DRender::QPickingSettings::NearestPick); settings->setFaceOrientationPickingMode(Qt3DRender::QPickingSettings::FrontFace); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter; // Runs Required jobs runRequiredJobs(test.data()); // THEN // large no pickable object encapsing child and camera should not interfere with smaller picking object QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 1); Qt3DRender::QObjectPicker *picker = pickers.first(); QCOMPARE(pickers.first()->objectName(), QLatin1String("Picker")); Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->objectPickerManager()->lookupResource(picker->id()); QVERIFY(backendPicker); 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> events; 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()); 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() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_viewports.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); settings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); settings->setPickResultMode(Qt3DRender::QPickingSettings::NearestPick); settings->setFaceOrientationPickingMode(Qt3DRender::QPickingSettings::FrontFace); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter; // Runs Required jobs runRequiredJobs(test.data()); // THEN // object partially obscured by another viewport, make sure only visible portion is pickable QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker = pickers.last(); QCOMPARE(picker->objectName(), QLatin1String("Picker2")); Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->objectPickerManager()->lookupResource(picker->id()); QVERIFY(backendPicker); 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> events; 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()); 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(); 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()); 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() { QTest::addColumn("cameraOrigin"); QTest::addColumn("cameraUpVector"); int k = 0; const int n = 10; for (int j=0; j root(qobject_cast(sceneReader.root())); QVERIFY(root); QList renderSettings = root->findChildren(); QCOMPARE(renderSettings.size(), 1); Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); settings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter; QList cameras = root->findChildren(); QCOMPARE(cameras.size(), 1); Qt3DRender::QCamera *camera = cameras.first(); QFETCH(QVector3D, cameraUpVector); camera->setUpVector(cameraUpVector); QFETCH(QVector3D, cameraOrigin); camera->setPosition(cameraOrigin); // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 1); Qt3DRender::QObjectPicker *picker = pickers.front(); Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->objectPickerManager()->lookupResource(picker->id()); QVERIFY(backendPicker); 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> events; 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()); 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() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_priorityoverlapping.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); TestArbiter arbiter1; TestArbiter arbiter2; // Runs Required jobs runRequiredJobs(test.data()); // THEN QList pickers = root->findChildren(); QCOMPARE(pickers.size(), 2); Qt3DRender::QObjectPicker *picker1 = nullptr; Qt3DRender::QObjectPicker *picker2 = nullptr; if (pickers.first()->objectName() == QLatin1String("Picker1")) { picker1 = pickers.first(); picker2 = pickers.last(); } else { picker1 = pickers.last(); picker2 = pickers.first(); } Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id()); QVERIFY(backendPicker1); Qt3DRender::Render::ObjectPicker *backendPicker2 = test->nodeManagers()->objectPickerManager()->lookupResource(picker2->id()); QVERIFY(backendPicker2); 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 { Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); // WHEN -> Pressed on object QList> events; 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()); 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(!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(); 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); QCOMPARE(backendPicker2->priority(), 1000); Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); // WHEN -> Pressed on object QList> events; 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()); 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(), 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(); 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); } } void checkNoPickingFGPicking() { // GIVEN QmlSceneReader sceneReader(QUrl("qrc:/testscene_nopicking.qml")); QScopedPointer root(qobject_cast(sceneReader.root())); QVERIFY(root); QScopedPointer test(new Qt3DRender::TestAspect(root.data())); // THEN QVERIFY(test->frameGraphRoot() != nullptr); Qt3DRender::QNoPicking *noPicking = root->findChild(); QVERIFY(noPicking != nullptr); Qt3DRender::QCamera *camera = root->findChild(); QVERIFY(camera != nullptr); QQuickWindow *window = root->findChild(); QVERIFY(camera != nullptr); QCOMPARE(window->size(), QSize(600, 600)); // WHEN Qt3DRender::Render::PickingUtils::ViewportCameraAreaGatherer gatherer; QVector results = gatherer.gather(test->frameGraphRoot()); // THEN QCOMPARE(results.size(), 0); // WHEN Qt3DRender::Render::FrameGraphNode *backendFGNode = test->nodeManagers()->frameGraphManager()->lookupNode(noPicking->id()); QVERIFY(backendFGNode); QCOMPARE(backendFGNode->nodeType(), Qt3DRender::Render::FrameGraphNode::NoPicking); Qt3DRender::Render::NoPicking * backendNoPicking = static_cast(backendFGNode); backendNoPicking->setEnabled(false); // THEN QVERIFY(!backendNoPicking->isEnabled()); // WHEN results = gatherer.gather(test->frameGraphRoot()); // THEN QCOMPARE(results.size(), 1); auto vca = results.first(); QCOMPARE(vca.area, QSize(600, 600)); QCOMPARE(vca.cameraId, camera->id()); QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.)); } }; QTEST_MAIN(tst_PickBoundingVolumeJob) #include "tst_pickboundingvolumejob.moc"