/**************************************************************************** ** ** Copyright (C) 2015 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 #include #include #include #include #include #include #include #include #include #include #include #include #include "testpostmanarbiter.h" class TestFactory : public Qt3DRender::QGeometryFactory { public: explicit TestFactory(int size) : m_size(size) {} Qt3DRender::QGeometry *operator ()() final { return nullptr; } bool operator ==(const Qt3DRender::QGeometryFactory &other) const final { const TestFactory *otherFactory = Qt3DRender::functor_cast(&other); if (otherFactory != nullptr) return otherFactory->m_size == m_size; return false; } QT3D_FUNCTOR(TestFactory) private: int m_size; }; class tst_QGeometryRenderer: public QObject { Q_OBJECT private Q_SLOTS: void checkCloning_data() { QTest::addColumn("geometryRenderer"); Qt3DRender::QGeometryRenderer *defaultConstructed = new Qt3DRender::QGeometryRenderer(); QTest::newRow("defaultConstructed") << defaultConstructed ; Qt3DRender::QGeometryRenderer *geometry1 = new Qt3DRender::QGeometryRenderer(); geometry1->setGeometry(new Qt3DRender::QGeometry()); geometry1->setInstanceCount(1); geometry1->setIndexOffset(0); geometry1->setFirstInstance(55); geometry1->setIndexBufferByteOffset(48); geometry1->setRestartIndexValue(-1); geometry1->setPrimitiveRestartEnabled(false); geometry1->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); geometry1->setVertexCount(15); geometry1->setVerticesPerPatch(2); geometry1->setGeometryFactory(Qt3DRender::QGeometryFactoryPtr(new TestFactory(383))); QTest::newRow("triangle") << geometry1; Qt3DRender::QGeometryRenderer *geometry2 = new Qt3DRender::QGeometryRenderer(); geometry2->setGeometry(new Qt3DRender::QGeometry()); geometry2->setInstanceCount(200); geometry2->setIndexOffset(58); geometry2->setFirstInstance(10); geometry2->setIndexBufferByteOffset(96); geometry2->setRestartIndexValue(65535); geometry2->setVertexCount(2056); geometry2->setPrimitiveRestartEnabled(true); geometry2->setVerticesPerPatch(3); geometry2->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); geometry2->setGeometryFactory(Qt3DRender::QGeometryFactoryPtr(new TestFactory(305))); QTest::newRow("lines with restart") << geometry2; } void checkCloning() { // GIVEN QFETCH(Qt3DRender::QGeometryRenderer *, geometryRenderer); // WHEN Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(geometryRenderer); QVector creationChanges = creationChangeGenerator.creationChanges(); // THEN QCOMPARE(creationChanges.size(), 1 + (geometryRenderer->geometry() ? 1 : 0)); const Qt3DCore::QNodeCreatedChangePtr creationChangeData = qSharedPointerCast>(creationChanges.first()); const Qt3DRender::QGeometryRendererData &cloneData = creationChangeData->data; QCOMPARE(geometryRenderer->id(), creationChangeData->subjectId()); QCOMPARE(geometryRenderer->isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(geometryRenderer->metaObject(), creationChangeData->metaObject()); QCOMPARE(cloneData.instanceCount, geometryRenderer->instanceCount()); QCOMPARE(cloneData.vertexCount, geometryRenderer->vertexCount()); QCOMPARE(cloneData.indexOffset, geometryRenderer->indexOffset()); QCOMPARE(cloneData.firstInstance, geometryRenderer->firstInstance()); QCOMPARE(cloneData.indexBufferByteOffset, geometryRenderer->indexBufferByteOffset()); QCOMPARE(cloneData.restartIndexValue, geometryRenderer->restartIndexValue()); QCOMPARE(cloneData.primitiveRestart, geometryRenderer->primitiveRestartEnabled()); QCOMPARE(cloneData.primitiveType, geometryRenderer->primitiveType()); QCOMPARE(cloneData.verticesPerPatch, geometryRenderer->verticesPerPatch()); if (geometryRenderer->geometry() != nullptr) QCOMPARE(cloneData.geometryId, geometryRenderer->geometry()->id()); QCOMPARE(cloneData.geometryFactory, geometryRenderer->geometryFactory()); if (geometryRenderer->geometryFactory()) QVERIFY(*cloneData.geometryFactory == *geometryRenderer->geometryFactory()); } void checkPropertyUpdates() { // GIVEN TestArbiter arbiter; QScopedPointer geometryRenderer(new Qt3DRender::QGeometryRenderer()); arbiter.setArbiterOnNode(geometryRenderer.data()); // WHEN geometryRenderer->setInstanceCount(256); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setVertexCount(1340); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setIndexOffset(883); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setFirstInstance(1200); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setIndexBufferByteOffset(91); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setRestartIndexValue(65535); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setVerticesPerPatch(2); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setPrimitiveRestartEnabled(true); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(555)); geometryRenderer->setGeometryFactory(factory); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 1); auto change = arbiter.events.first().staticCast(); QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->value().value(), factory); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); arbiter.events.clear(); // WHEN Qt3DRender::QGeometry geom; geometryRenderer->setGeometry(&geom); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); // WHEN Qt3DRender::QGeometry geom2; geometryRenderer->setGeometry(&geom2); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 0); QCOMPARE(arbiter.dirtyNodes.size(), 1); QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data()); arbiter.dirtyNodes.clear(); } void checkGeometryBookkeeping() { // GIVEN QScopedPointer geometryRenderer(new Qt3DRender::QGeometryRenderer); { // WHEN Qt3DRender::QGeometry geometry; geometryRenderer->setGeometry(&geometry); // THEN QCOMPARE(geometry.parent(), geometryRenderer.data()); QCOMPARE(geometryRenderer->geometry(), &geometry); } // THEN (Should not crash and parameter be unset) QVERIFY(geometryRenderer->geometry() == nullptr); { // WHEN Qt3DRender::QGeometryRenderer someOtherGeometryRenderer; QScopedPointer geometry(new Qt3DRender::QGeometry(&someOtherGeometryRenderer)); geometryRenderer->setGeometry(geometry.data()); // THEN QCOMPARE(geometry->parent(), &someOtherGeometryRenderer); QCOMPARE(geometryRenderer->geometry(), geometry.data()); // WHEN geometryRenderer.reset(); geometry.reset(); // THEN Should not crash when the geometry is destroyed (tests for failed removal of destruction helper) } } }; QTEST_MAIN(tst_QGeometryRenderer) #include "tst_qgeometryrenderer.moc"