diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:09:44 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:10:02 +0100 |
commit | 77d294db076dac19e8b549b445ffede9f7260c84 (patch) | |
tree | 828ee7a6862ec5c0bd24f97cb540625a2c647376 /tests | |
parent | 59f8fec8a41606b3185fe3a4e276978e3e1ed5ef (diff) | |
parent | 939b9b4b7591e8a421cf048a0a84ed3e75d81d21 (diff) |
Merge branch 'dev' into wip/animationwip/animation
Change-Id: I6e770609c90a7745d08fa4e2f424e865678c5d6f
Diffstat (limited to 'tests')
198 files changed, 15626 insertions, 1494 deletions
diff --git a/tests/auto/animation/qconductedclipanimator/qconductedclipanimator.pro b/tests/auto/animation/additiveclipblend/additiveclipblend.pro index ef04bb54c..09b2e1156 100644 --- a/tests/auto/animation/qconductedclipanimator/qconductedclipanimator.pro +++ b/tests/auto/animation/additiveclipblend/additiveclipblend.pro @@ -1,12 +1,12 @@ TEMPLATE = app -TARGET = tst_qconductedclipanimator +TARGET = tst_additiveclipblend QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib CONFIG += testcase SOURCES += \ - tst_qconductedclipanimator.cpp + tst_additiveclipblend.cpp include(../../core/common/common.pri) diff --git a/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp b/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp new file mode 100644 index 000000000..28ab8917a --- /dev/null +++ b/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp @@ -0,0 +1,433 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qadditiveclipblend.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qadditiveclipblend_p.h> +#include <Qt3DAnimation/private/additiveclipblend_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(Handler *) +Q_DECLARE_METATYPE(AdditiveClipBlend *) + +namespace { + +class TestClipBlendNode : public ClipBlendNode +{ +public: + TestClipBlendNode(double duration) + : ClipBlendNode(ClipBlendNode::LerpBlendType) + , m_duration(duration) + {} + + inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE + { + return currentDependencyIds(); + } + + QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_FINAL + { + return QVector<Qt3DCore::QNodeId>(); + } + + using ClipBlendNode::setClipResults; + + double duration() const Q_DECL_FINAL { return m_duration; } + +protected: + ClipResults doBlend(const QVector<ClipResults> &) const Q_DECL_FINAL { return ClipResults(); } + +private: + double m_duration; +}; + +} // anonymous + +class tst_AdditiveClipBlend : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +public: + TestClipBlendNode *createTestBlendNode(Handler *handler, + double duration) + { + auto id = Qt3DCore::QNodeId::createId(); + TestClipBlendNode *node = new TestClipBlendNode(duration); + setPeerId(node, id); + node->setHandler(handler); + node->setClipBlendNodeManager(handler->clipBlendNodeManager()); + handler->clipBlendNodeManager()->appendNode(id, node); + return node; + } + + AdditiveClipBlend *createAdditiveClipBlendNode(Handler *handler, const float &blendFactor) + { + auto id = Qt3DCore::QNodeId::createId(); + AdditiveClipBlend *node = new AdditiveClipBlend(); + node->setAdditiveFactor(blendFactor); + setPeerId(node, id); + node->setHandler(handler); + node->setClipBlendNodeManager(handler->clipBlendNodeManager()); + handler->clipBlendNodeManager()->appendNode(id, node); + return node; + } + + BlendedClipAnimator *createBlendedClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + BlendedClipAnimator *animator = handler->blendedClipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + AdditiveClipBlend backendAdditiveBlend; + + // THEN + QCOMPARE(backendAdditiveBlend.isEnabled(), false); + QVERIFY(backendAdditiveBlend.peerId().isNull()); + QCOMPARE(backendAdditiveBlend.baseClipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendAdditiveBlend.additiveClipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendAdditiveBlend.additiveFactor(), 0.0f); + QCOMPARE(backendAdditiveBlend.blendType(), ClipBlendNode::AdditiveBlendType); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DAnimation::QAdditiveClipBlend additiveBlend; + Qt3DAnimation::QAdditiveClipBlend baseClip; + Qt3DAnimation::QAdditiveClipBlend additiveClip; + Qt3DAnimation::QAnimationClipLoader clip; + additiveBlend.setBaseClip(&baseClip); + additiveBlend.setAdditiveClip(&additiveClip); + additiveBlend.setAdditiveFactor(0.8f); + + { + // WHEN + AdditiveClipBlend backendAdditiveBlend; + simulateInitialization(&additiveBlend, &backendAdditiveBlend); + + // THEN + QCOMPARE(backendAdditiveBlend.isEnabled(), true); + QCOMPARE(backendAdditiveBlend.peerId(), additiveBlend.id()); + QCOMPARE(backendAdditiveBlend.baseClipId(), baseClip.id()); + QCOMPARE(backendAdditiveBlend.additiveClipId(), additiveClip.id()); + QCOMPARE(backendAdditiveBlend.additiveFactor(), 0.8f); + } + { + // WHEN + AdditiveClipBlend backendAdditiveBlend; + additiveBlend.setEnabled(false); + simulateInitialization(&additiveBlend, &backendAdditiveBlend); + + // THEN + QCOMPARE(backendAdditiveBlend.peerId(), additiveBlend.id()); + QCOMPARE(backendAdditiveBlend.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + AdditiveClipBlend backendAdditiveBlend; + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendAdditiveBlend.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendAdditiveBlend.isEnabled(), newValue); + } + { + // WHEN + const float newValue = 0.883f; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("additiveFactor"); + change->setValue(QVariant::fromValue(newValue)); + backendAdditiveBlend.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendAdditiveBlend.additiveFactor(), newValue); + } + { + // WHEN + const Qt3DAnimation::QAdditiveClipBlend newValue; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("baseClip"); + change->setValue(QVariant::fromValue(newValue.id())); + backendAdditiveBlend.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendAdditiveBlend.baseClipId(), newValue.id()); + } + { + // WHEN + const Qt3DAnimation::QAdditiveClipBlend newValue; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("additiveClip"); + change->setValue(QVariant::fromValue(newValue.id())); + backendAdditiveBlend.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendAdditiveBlend.additiveClipId(), newValue.id()); + } + } + + void checkDependencyIds() + { + // GIVEN + AdditiveClipBlend addBlend; + auto baseClipId = Qt3DCore::QNodeId::createId(); + auto additiveClipId = Qt3DCore::QNodeId::createId(); + + // WHEN + addBlend.setBaseClipId(baseClipId); + addBlend.setAdditiveClipId(additiveClipId); + QVector<Qt3DCore::QNodeId> actualIds = addBlend.currentDependencyIds(); + + // THEN + QCOMPARE(actualIds.size(), 2); + QCOMPARE(actualIds[0], baseClipId); + QCOMPARE(actualIds[1], additiveClipId); + + // WHEN + auto anotherAdditiveClipId = Qt3DCore::QNodeId::createId(); + addBlend.setAdditiveClipId(anotherAdditiveClipId); + actualIds = addBlend.currentDependencyIds(); + + // THEN + QCOMPARE(actualIds.size(), 2); + QCOMPARE(actualIds[0], baseClipId); + QCOMPARE(actualIds[1], anotherAdditiveClipId); + } + + void checkDuration() + { + // GIVEN + auto handler = new Handler(); + const double expectedDuration = 123.5; + const double baseNodeDuration = expectedDuration; + const double additiveNodeDuration = 5.0; + + auto baseNode = createTestBlendNode(handler, baseNodeDuration); + auto additiveNode = createTestBlendNode(handler, additiveNodeDuration); + + AdditiveClipBlend blendNode; + blendNode.setHandler(handler); + blendNode.setClipBlendNodeManager(handler->clipBlendNodeManager()); + blendNode.setBaseClipId(baseNode->peerId()); + blendNode.setAdditiveClipId(additiveNode->peerId()); + + // WHEN + double actualDuration = blendNode.duration(); + + // THEN + QCOMPARE(actualDuration, expectedDuration); + } + + void checkDoBlend_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<AdditiveClipBlend *>("blendNode"); + QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); + QTest::addColumn<ClipResults>("expectedResults"); + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto baseNode = createTestBlendNode(handler, duration); + baseNode->setClipResults(animator->peerId(), { 0.0f, 0.0f, 0.0f }); + auto additiveNode = createTestBlendNode(handler, duration); + additiveNode->setClipResults(animator->peerId(), { 1.0f, 1.0f, 1.0f }); + + const float additiveFactor = 0.0f; + auto blendNode = createAdditiveClipBlendNode(handler, additiveFactor); + blendNode->setBaseClipId(baseNode->peerId()); + blendNode->setAdditiveClipId(additiveNode->peerId()); + blendNode->setAdditiveFactor(additiveFactor); + + ClipResults expectedResults = { 0.0f, 0.0f, 0.0f }; + + QTest::addRow("unit additive, beta = 0.0") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto baseNode = createTestBlendNode(handler, duration); + baseNode->setClipResults(animator->peerId(), { 0.0f, 0.0f, 0.0f }); + auto additiveNode = createTestBlendNode(handler, duration); + additiveNode->setClipResults(animator->peerId(), { 1.0f, 1.0f, 1.0f }); + + const float additiveFactor = 0.5f; + auto blendNode = createAdditiveClipBlendNode(handler, additiveFactor); + blendNode->setBaseClipId(baseNode->peerId()); + blendNode->setAdditiveClipId(additiveNode->peerId()); + blendNode->setAdditiveFactor(additiveFactor); + + ClipResults expectedResults = { 0.5f, 0.5f, 0.5f }; + + QTest::addRow("unit additive, beta = 0.5") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto baseNode = createTestBlendNode(handler, duration); + baseNode->setClipResults(animator->peerId(), { 0.0f, 0.0f, 0.0f }); + auto additiveNode = createTestBlendNode(handler, duration); + additiveNode->setClipResults(animator->peerId(), { 1.0f, 1.0f, 1.0f }); + + const float additiveFactor = 1.0f; + auto blendNode = createAdditiveClipBlendNode(handler, additiveFactor); + blendNode->setBaseClipId(baseNode->peerId()); + blendNode->setAdditiveClipId(additiveNode->peerId()); + blendNode->setAdditiveFactor(additiveFactor); + + ClipResults expectedResults = { 1.0f, 1.0f, 1.0f }; + + QTest::addRow("unit additive, beta = 1.0") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto baseNode = createTestBlendNode(handler, duration); + baseNode->setClipResults(animator->peerId(), { 0.0f, 1.0f, 2.0f }); + auto additiveNode = createTestBlendNode(handler, duration); + additiveNode->setClipResults(animator->peerId(), { 1.0f, 2.0f, 3.0f }); + + const float blendFactor = 0.5f; + auto blendNode = createAdditiveClipBlendNode(handler, blendFactor); + blendNode->setBaseClipId(baseNode->peerId()); + blendNode->setAdditiveClipId(additiveNode->peerId()); + blendNode->setAdditiveFactor(blendFactor); + + ClipResults expectedResults = { 0.5f, 2.0f, 3.5f }; + + QTest::addRow("lerp varying data, beta = 0.5") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + const int dataCount = 1000; + ClipResults baseData(dataCount); + ClipResults additiveData(dataCount); + ClipResults expectedResults(dataCount); + for (int i = 0; i < dataCount; ++i) { + baseData[i] = float(i); + additiveData[i] = 2.0f * float(i); + expectedResults[i] = 2.0f * float(i); + } + auto baseNode = createTestBlendNode(handler, duration); + baseNode->setClipResults(animator->peerId(), baseData); + auto additiveNode = createTestBlendNode(handler, duration); + additiveNode->setClipResults(animator->peerId(), additiveData); + + const float blendFactor = 0.5f; + auto blendNode = createAdditiveClipBlendNode(handler, blendFactor); + blendNode->setBaseClipId(baseNode->peerId()); + blendNode->setAdditiveClipId(additiveNode->peerId()); + blendNode->setAdditiveFactor(blendFactor); + + QTest::addRow("lerp lots of data, beta = 0.5") + << handler << blendNode << animator->peerId() << expectedResults; + } + } + + void checkDoBlend() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(AdditiveClipBlend *, blendNode); + QFETCH(Qt3DCore::QNodeId, animatorId); + QFETCH(ClipResults, expectedResults); + + // WHEN + blendNode->blend(animatorId); + + // THEN + const ClipResults actualResults = blendNode->clipResults(animatorId); + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); + + // Cleanup + delete handler; + } +}; + +QTEST_MAIN(tst_AdditiveClipBlend) + +#include "tst_additiveclipblend.moc" diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index 43844ed88..b48fd347b 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -2,28 +2,37 @@ TEMPLATE = subdirs SUBDIRS += \ qanimationaspect \ - qanimationclip \ + qanimationcliploader \ qclipanimator \ qblendedclipanimator \ - qconductedclipanimator \ qchannelmapping \ - qchannelmapper + qchannelmapper \ + qclipblendvalue \ + qanimationcontroller \ + qanimationgroup \ + qkeyframeanimation \ + qmorphinganimation \ + qmorphtarget \ + qvertexblendanimation qtConfig(private_tests) { SUBDIRS += \ animationclip \ - qabstractclipblendnode \ fcurve \ functionrangefinder \ bezierevaluator \ clipanimator \ blendedclipanimator \ - conductedclipanimator \ channelmapper \ channelmapping \ - qlerpblend \ + qlerpclipblend \ clipblendnodemanager \ clipblendnode \ - lerpblend \ - clipblendnodevisitor + lerpclipblend \ + clipblendnodevisitor \ + qadditiveclipblend \ + additiveclipblend \ + clipblendvalue \ + animationutils \ + qabstractanimation } diff --git a/tests/auto/animation/animationclip/tst_animationclip.cpp b/tests/auto/animation/animationclip/tst_animationclip.cpp index f0b45bfeb..61c55d36e 100644 --- a/tests/auto/animation/animationclip/tst_animationclip.cpp +++ b/tests/auto/animation/animationclip/tst_animationclip.cpp @@ -28,7 +28,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/private/animationclip_p.h> -#include <Qt3DAnimation/qanimationclip.h> +#include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -37,7 +37,9 @@ #include <qbackendnodetester.h> #include <testpostmanarbiter.h> -class tst_AnimationClip: public Qt3DCore::QBackendNodeTester +using namespace Qt3DAnimation::Animation; + +class tst_AnimationClip : public Qt3DCore::QBackendNodeTester { Q_OBJECT @@ -45,10 +47,10 @@ private Q_SLOTS: void checkPeerPropertyMirroring() { // GIVEN - Qt3DAnimation::Animation::AnimationClip backendClip; - Qt3DAnimation::Animation::Handler handler; + AnimationClip backendClip; + Handler handler; backendClip.setHandler(&handler); - Qt3DAnimation::QAnimationClip clip; + Qt3DAnimation::QAnimationClipLoader clip; clip.setSource(QUrl::fromLocalFile("walk.qlip")); @@ -64,8 +66,8 @@ private Q_SLOTS: void checkInitialAndCleanedUpState() { // GIVEN - Qt3DAnimation::Animation::AnimationClip backendClip; - Qt3DAnimation::Animation::Handler handler; + AnimationClip backendClip; + Handler handler; backendClip.setHandler(&handler); // THEN @@ -73,9 +75,10 @@ private Q_SLOTS: QCOMPARE(backendClip.isEnabled(), false); QCOMPARE(backendClip.source(), QUrl()); QCOMPARE(backendClip.duration(), 0.0f); + QCOMPARE(backendClip.status(), Qt3DAnimation::QAnimationClipLoader::NotReady); // GIVEN - Qt3DAnimation::QAnimationClip clip; + Qt3DAnimation::QAnimationClipLoader clip; clip.setSource(QUrl::fromLocalFile("walk.qlip")); // WHEN @@ -87,14 +90,16 @@ private Q_SLOTS: QCOMPARE(backendClip.source(), QUrl()); QCOMPARE(backendClip.isEnabled(), false); QCOMPARE(backendClip.duration(), 0.0f); + QCOMPARE(backendClip.status(), Qt3DAnimation::QAnimationClipLoader::NotReady); } void checkPropertyChanges() { // GIVEN - Qt3DAnimation::Animation::AnimationClip backendClip; - Qt3DAnimation::Animation::Handler handler; + AnimationClip backendClip; + Handler handler; backendClip.setHandler(&handler); + backendClip.setDataType(Qt3DAnimation::Animation::AnimationClip::File); Qt3DCore::QPropertyUpdatedChangePtr updateChange; // WHEN @@ -121,7 +126,7 @@ private Q_SLOTS: { // GIVEN TestArbiter arbiter; - Qt3DAnimation::Animation::AnimationClip backendClip; + AnimationClip backendClip; backendClip.setEnabled(true); Qt3DCore::QBackendNodePrivate::get(&backendClip)->setArbiter(&arbiter); @@ -134,7 +139,8 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "duration"); QCOMPARE(change->value().toFloat(), backendClip.duration()); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); + QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate, + false); arbiter.events.clear(); @@ -147,6 +153,38 @@ private Q_SLOTS: arbiter.events.clear(); } + + void checkStatusPropertyBackendNotification() + { + // GIVEN + TestArbiter arbiter; + AnimationClip backendClip; + backendClip.setEnabled(true); + Qt3DCore::QBackendNodePrivate::get(&backendClip)->setArbiter(&arbiter); + + // WHEN + backendClip.setStatus(Qt3DAnimation::QAnimationClipLoader::Error); + + // THEN + QCOMPARE(backendClip.status(), Qt3DAnimation::QAnimationClipLoader::Error); + QCOMPARE(arbiter.events.count(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "status"); + QCOMPARE(change->value().value<Qt3DAnimation::QAnimationClipLoader::Status>(), backendClip.status()); + QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate, + false); + + arbiter.events.clear(); + + // WHEN + backendClip.setStatus(Qt3DAnimation::QAnimationClipLoader::Error); + + // THEN + QCOMPARE(backendClip.status(), Qt3DAnimation::QAnimationClipLoader::Error); + QCOMPARE(arbiter.events.count(), 0); + + arbiter.events.clear(); + } }; QTEST_APPLESS_MAIN(tst_AnimationClip) diff --git a/tests/auto/animation/qabstractclipblendnode/qabstractclipblendnode.pro b/tests/auto/animation/animationutils/animationutils.pro index 9dff8e7bd..5c7e3c510 100644 --- a/tests/auto/animation/qabstractclipblendnode/qabstractclipblendnode.pro +++ b/tests/auto/animation/animationutils/animationutils.pro @@ -1,11 +1,15 @@ TEMPLATE = app -TARGET = tst_qabstractclipblendnode +TARGET = tst_animationutils QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib CONFIG += testcase -SOURCES += tst_qabstractclipblendnode.cpp +SOURCES += \ + tst_animationutils.cpp include(../../core/common/common.pri) + +RESOURCES += \ + animationutils.qrc diff --git a/tests/auto/animation/animationutils/animationutils.qrc b/tests/auto/animation/animationutils/animationutils.qrc new file mode 100644 index 000000000..bbcd96524 --- /dev/null +++ b/tests/auto/animation/animationutils/animationutils.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>clip1.json</file> + <file>clip2.json</file> + <file>clip3.json</file> + </qresource> +</RCC> diff --git a/tests/auto/animation/animationutils/clip1.json b/tests/auto/animation/animationutils/clip1.json new file mode 100644 index 000000000..8fa382589 --- /dev/null +++ b/tests/auto/animation/animationutils/clip1.json @@ -0,0 +1,113 @@ +{ + "animations": [ + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/auto/animation/animationutils/clip2.json b/tests/auto/animation/animationutils/clip2.json new file mode 100644 index 000000000..3faff409c --- /dev/null +++ b/tests/auto/animation/animationutils/clip2.json @@ -0,0 +1,250 @@ +{ + "animations": [ + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation" + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/auto/animation/animationutils/clip3.json b/tests/auto/animation/animationutils/clip3.json new file mode 100644 index 000000000..ae390590e --- /dev/null +++ b/tests/auto/animation/animationutils/clip3.json @@ -0,0 +1,430 @@ +{ + "animations": [ + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation" + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + }, + { + "channelComponents": [ + { + "channelComponentName": "Base Color X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Base Color Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Base Color Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Base Color" + }, + { + "channelComponents": [ + { + "channelComponentName": "Metalness X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + } + ], + "channelName": "Metalness" + }, + { + "channelComponents": [ + { + "channelComponentName": "Roughness X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + } + ], + "channelName": "Roughness" + } + ] + } + ] +} diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp new file mode 100644 index 000000000..ac4fb6fa0 --- /dev/null +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -0,0 +1,2501 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 <QtTest/QTest> +#include <Qt3DAnimation/private/animationclip_p.h> +#include <Qt3DAnimation/private/animationutils_p.h> +#include <Qt3DAnimation/private/blendedclipanimator_p.h> +#include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/clipblendvalue_p.h> +#include <Qt3DAnimation/private/handler_p.h> +#include <Qt3DAnimation/private/additiveclipblend_p.h> +#include <Qt3DAnimation/private/lerpclipblend_p.h> +#include <Qt3DAnimation/private/managers_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qvector4d.h> +#include <QtGui/qquaternion.h> + +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) +Q_DECLARE_METATYPE(QVector<ChannelMapping *>) +Q_DECLARE_METATYPE(ChannelMapper *) +Q_DECLARE_METATYPE(AnimationClip *) +Q_DECLARE_METATYPE(QVector<MappingData>) +Q_DECLARE_METATYPE(QVector<Qt3DCore::QPropertyUpdatedChangePtr>) +Q_DECLARE_METATYPE(Channel) +Q_DECLARE_METATYPE(AnimatorEvaluationData) +Q_DECLARE_METATYPE(ClipEvaluationData) +Q_DECLARE_METATYPE(ClipAnimator *) +Q_DECLARE_METATYPE(BlendedClipAnimator *) +Q_DECLARE_METATYPE(QVector<ChannelNameAndType>) + +namespace { + +class MeanBlendNode : public ClipBlendNode +{ +public: + MeanBlendNode() + : ClipBlendNode(ClipBlendNode::LerpBlendType) + {} + + void setValueNodeIds(Qt3DCore::QNodeId value1Id, + Qt3DCore::QNodeId value2Id) + { + m_value1Id = value1Id; + m_value2Id = value2Id; + } + + inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE + { + return currentDependencyIds(); + } + + QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_FINAL + { + return QVector<Qt3DCore::QNodeId>() << m_value1Id << m_value2Id; + } + + using ClipBlendNode::setClipResults; + + double duration() const Q_DECL_FINAL { return 0.0f; } + +protected: + ClipResults doBlend(const QVector<ClipResults> &blendData) const Q_DECL_FINAL + { + Q_ASSERT(blendData.size() == 2); + const int elementCount = blendData.first().size(); + ClipResults blendResults(elementCount); + + for (int i = 0; i < elementCount; ++i) + blendResults[i] = 0.5f * (blendData[0][i] + blendData[1][i]); + + return blendResults; + } + +private: + Qt3DCore::QNodeId m_value1Id; + Qt3DCore::QNodeId m_value2Id; +}; + +bool fuzzyCompare(float x1, float x2) +{ + if (qFuzzyIsNull(x1) && qFuzzyIsNull(x2)) { + return true; + } else if ((qFuzzyIsNull(x1) && !qFuzzyIsNull(x2)) || + (!qFuzzyIsNull(x1) && qFuzzyIsNull(x2))) { + return false; + } else { + return qFuzzyCompare(x1, x2); + } +} + +} // anonymous + + +class tst_AnimationUtils : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +public: + ChannelMapping *createChannelMapping(Handler *handler, + const QString &channelName, + const Qt3DCore::QNodeId targetId, + const QString &property, + const char *propertyName, + int type) + { + auto channelMappingId = Qt3DCore::QNodeId::createId(); + ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); + setPeerId(channelMapping, channelMappingId); + channelMapping->setTargetId(targetId); + channelMapping->setProperty(property); + channelMapping->setPropertyName(propertyName); + channelMapping->setChannelName(channelName); + channelMapping->setType(type); + return channelMapping; + } + + ChannelMapper *createChannelMapper(Handler *handler, + const QVector<Qt3DCore::QNodeId> &mappingIds) + { + auto channelMapperId = Qt3DCore::QNodeId::createId(); + ChannelMapper *channelMapper = handler->channelMapperManager()->getOrCreateResource(channelMapperId); + setPeerId(channelMapper, channelMapperId); + channelMapper->setMappingIds(mappingIds); + return channelMapper; + } + + AnimationClip *createAnimationClipLoader(Handler *handler, + const QUrl &source) + { + auto clipId = Qt3DCore::QNodeId::createId(); + AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(clipId); + setPeerId(clip, clipId); + clip->setDataType(AnimationClip::File); + clip->setSource(source); + clip->loadAnimation(); + return clip; + } + + ClipAnimator *createClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + ClipAnimator *animator = handler->clipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + + BlendedClipAnimator *createBlendedClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + BlendedClipAnimator *animator = handler->blendedClipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + + LerpClipBlend *createLerpClipBlend(Handler *handler) + { + auto lerpId = Qt3DCore::QNodeId::createId(); + LerpClipBlend *lerp = new LerpClipBlend(); + setPeerId(lerp, lerpId); + lerp->setClipBlendNodeManager(handler->clipBlendNodeManager()); + lerp->setHandler(handler); + handler->clipBlendNodeManager()->appendNode(lerpId, lerp); + return lerp; + } + + AdditiveClipBlend *createAdditiveClipBlend(Handler *handler) + { + auto additiveId = Qt3DCore::QNodeId::createId(); + AdditiveClipBlend *additive = new AdditiveClipBlend(); + setPeerId(additive, additiveId); + additive->setClipBlendNodeManager(handler->clipBlendNodeManager()); + additive->setHandler(handler); + handler->clipBlendNodeManager()->appendNode(additiveId, additive); + return additive; + } + + ClipBlendValue *createClipBlendValue(Handler *handler) + { + auto valueId = Qt3DCore::QNodeId::createId(); + ClipBlendValue *value = new ClipBlendValue(); + setPeerId(value, valueId); + value->setClipBlendNodeManager(handler->clipBlendNodeManager()); + value->setHandler(handler); + handler->clipBlendNodeManager()->appendNode(valueId, value); + return value; + } + + MeanBlendNode *createMeanBlendNode(Handler *handler) + { + auto id = Qt3DCore::QNodeId::createId(); + MeanBlendNode *node = new MeanBlendNode(); + setPeerId(node, id); + node->setClipBlendNodeManager(handler->clipBlendNodeManager()); + node->setHandler(handler); + handler->clipBlendNodeManager()->appendNode(id, node); + return node; + } + +private Q_SLOTS: + void checkBuildPropertyMappings_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); + QTest::addColumn<ChannelMapper *>("channelMapper"); + QTest::addColumn<AnimationClip *>("clip"); + QTest::addColumn<QVector<MappingData>>("expectedMappingData"); + + auto handler = new Handler; + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + // ... a channel mapper... + auto channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + + // ...and an animation clip + auto clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + + QVector<MappingData> mappingData; + MappingData mapping; + mapping.targetId = channelMapping->targetId(); + mapping.propertyName = channelMapping->propertyName(); // Location + mapping.type = channelMapping->type(); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2; // Location X, Y, Z + mappingData.push_back(mapping); + + QTest::newRow("clip1.json") << handler + << channelMappings + << channelMapper + << clip + << mappingData; + } + + void checkBuildPropertyMappings() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(QVector<ChannelMapping *>, channelMappings); + QFETCH(ChannelMapper *, channelMapper); + QFETCH(AnimationClip *, clip); + QFETCH(QVector<MappingData>, expectedMappingData); + + // WHEN + // Build the mapping data for the above configuration + QVector<MappingData> mappingData = buildPropertyMappings(handler, clip, channelMapper); + + // THEN + QCOMPARE(mappingData.size(), expectedMappingData.size()); + for (int i = 0; i < mappingData.size(); ++i) { + const auto mapping = mappingData[i]; + const auto expectedMapping = expectedMappingData[i]; + + QCOMPARE(mapping.targetId, expectedMapping.targetId); + QCOMPARE(mapping.propertyName, expectedMapping.propertyName); + QCOMPARE(mapping.type, expectedMapping.type); + QCOMPARE(mapping.channelIndices.size(), expectedMapping.channelIndices.size()); + for (int j = 0; j < mapping.channelIndices.size(); ++j) { + QCOMPARE(mapping.channelIndices[j], expectedMapping.channelIndices[j]); + } + } + + // Cleanup + delete handler; + } + + void checkBuildPropertyMappings2_data() + { + QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); + QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); + QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); + QTest::addColumn<QVector<MappingData>>("expectedResults"); + + // Single ChannelMapping + { + auto channelMapping = new ChannelMapping(); + channelMapping->setChannelName("Location"); + channelMapping->setTargetId(Qt3DCore::QNodeId::createId()); + channelMapping->setProperty(QLatin1String("translation")); + channelMapping->setPropertyName("translation"); + channelMapping->setType(static_cast<int>(QVariant::Vector3D)); + + QVector<ChannelMapping *> channelMappings = { channelMapping }; + + // Create a few channels in the format description + ChannelNameAndType rotation = { QLatin1String("Rotation"), + static_cast<int>(QVariant::Quaternion) }; + ChannelNameAndType location = { QLatin1String("Location"), + static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType baseColor = { QLatin1String("BaseColor"), + static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType metalness = { QLatin1String("Metalness"), + static_cast<int>(QVariant::Double) }; + ChannelNameAndType roughness = { QLatin1String("Roughness"), + static_cast<int>(QVariant::Double) }; + QVector<ChannelNameAndType> channelNamesAndTypes + = { rotation, location, baseColor, metalness, roughness }; + + // And the matching indices + ComponentIndices rotationIndices = { 0, 1, 2, 3 }; + ComponentIndices locationIndices = { 4, 5, 6 }; + ComponentIndices baseColorIndices = { 7, 8, 9 }; + ComponentIndices metalnessIndices = { 10 }; + ComponentIndices roughnessIndices = { 11 }; + QVector<ComponentIndices> channelComponentIndices + = { rotationIndices, locationIndices, baseColorIndices, + metalnessIndices, roughnessIndices }; + + MappingData expectedMapping; + expectedMapping.targetId = channelMapping->targetId(); + expectedMapping.propertyName = channelMapping->propertyName(); + expectedMapping.type = channelMapping->type(); + expectedMapping.channelIndices = locationIndices; + QVector<MappingData> expectedResults = { expectedMapping }; + + QTest::newRow("single mapping") + << channelMappings + << channelNamesAndTypes + << channelComponentIndices + << expectedResults; + } + + // Multiple ChannelMappings + { + auto locationMapping = new ChannelMapping(); + locationMapping->setChannelName("Location"); + locationMapping->setTargetId(Qt3DCore::QNodeId::createId()); + locationMapping->setProperty(QLatin1String("translation")); + locationMapping->setPropertyName("translation"); + locationMapping->setType(static_cast<int>(QVariant::Vector3D)); + + auto metalnessMapping = new ChannelMapping(); + metalnessMapping->setChannelName("Metalness"); + metalnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); + metalnessMapping->setProperty(QLatin1String("metalness")); + metalnessMapping->setPropertyName("metalness"); + metalnessMapping->setType(static_cast<int>(QVariant::Double)); + + auto baseColorMapping = new ChannelMapping(); + baseColorMapping->setChannelName("BaseColor"); + baseColorMapping->setTargetId(Qt3DCore::QNodeId::createId()); + baseColorMapping->setProperty(QLatin1String("baseColor")); + baseColorMapping->setPropertyName("baseColor"); + baseColorMapping->setType(static_cast<int>(QVariant::Vector3D)); + + auto roughnessMapping = new ChannelMapping(); + roughnessMapping->setChannelName("Roughness"); + roughnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); + roughnessMapping->setProperty(QLatin1String("roughness")); + roughnessMapping->setPropertyName("roughness"); + roughnessMapping->setType(static_cast<int>(QVariant::Double)); + + auto rotationMapping = new ChannelMapping(); + rotationMapping->setChannelName("Rotation"); + rotationMapping->setTargetId(Qt3DCore::QNodeId::createId()); + rotationMapping->setProperty(QLatin1String("rotation")); + rotationMapping->setPropertyName("rotation"); + rotationMapping->setType(static_cast<int>(QVariant::Quaternion)); + + QVector<ChannelMapping *> channelMappings + = { locationMapping, metalnessMapping, + baseColorMapping, roughnessMapping, + rotationMapping }; + + // Create a few channels in the format description + ChannelNameAndType rotation = { QLatin1String("Rotation"), + static_cast<int>(QVariant::Quaternion) }; + ChannelNameAndType location = { QLatin1String("Location"), + static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType baseColor = { QLatin1String("BaseColor"), + static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType metalness = { QLatin1String("Metalness"), + static_cast<int>(QVariant::Double) }; + ChannelNameAndType roughness = { QLatin1String("Roughness"), + static_cast<int>(QVariant::Double) }; + QVector<ChannelNameAndType> channelNamesAndTypes + = { rotation, location, baseColor, metalness, roughness }; + + // And the matching indices + ComponentIndices rotationIndices = { 0, 1, 2, 3 }; + ComponentIndices locationIndices = { 4, 5, 6 }; + ComponentIndices baseColorIndices = { 7, 8, 9 }; + ComponentIndices metalnessIndices = { 10 }; + ComponentIndices roughnessIndices = { 11 }; + QVector<ComponentIndices> channelComponentIndices + = { rotationIndices, locationIndices, baseColorIndices, + metalnessIndices, roughnessIndices }; + + MappingData expectedLocationMapping; + expectedLocationMapping.targetId = locationMapping->targetId(); + expectedLocationMapping.propertyName = locationMapping->propertyName(); + expectedLocationMapping.type = locationMapping->type(); + expectedLocationMapping.channelIndices = locationIndices; + + MappingData expectedMetalnessMapping; + expectedMetalnessMapping.targetId = metalnessMapping->targetId(); + expectedMetalnessMapping.propertyName = metalnessMapping->propertyName(); + expectedMetalnessMapping.type = metalnessMapping->type(); + expectedMetalnessMapping.channelIndices = metalnessIndices; + + MappingData expectedBaseColorMapping; + expectedBaseColorMapping.targetId = baseColorMapping->targetId(); + expectedBaseColorMapping.propertyName = baseColorMapping->propertyName(); + expectedBaseColorMapping.type = baseColorMapping->type(); + expectedBaseColorMapping.channelIndices = baseColorIndices; + + MappingData expectedRoughnessMapping; + expectedRoughnessMapping.targetId = roughnessMapping->targetId(); + expectedRoughnessMapping.propertyName = roughnessMapping->propertyName(); + expectedRoughnessMapping.type = roughnessMapping->type(); + expectedRoughnessMapping.channelIndices = roughnessIndices; + + MappingData expectedRotationMapping; + expectedRotationMapping.targetId = rotationMapping->targetId(); + expectedRotationMapping.propertyName = rotationMapping->propertyName(); + expectedRotationMapping.type = rotationMapping->type(); + expectedRotationMapping.channelIndices = rotationIndices; + + QVector<MappingData> expectedResults + = { expectedLocationMapping, + expectedMetalnessMapping, + expectedBaseColorMapping, + expectedRoughnessMapping, + expectedRotationMapping }; + + QTest::newRow("multiple mappings") + << channelMappings + << channelNamesAndTypes + << channelComponentIndices + << expectedResults; + } + } + + void checkBuildPropertyMappings2() + { + // GIVEN + QFETCH(QVector<ChannelMapping *>, channelMappings); + QFETCH(QVector<ChannelNameAndType>, channelNamesAndTypes); + QFETCH(QVector<ComponentIndices>, channelComponentIndices); + QFETCH(QVector<MappingData>, expectedResults); + + // WHEN + const QVector<MappingData> actualResults = buildPropertyMappings(channelMappings, + channelNamesAndTypes, + channelComponentIndices); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) { + const auto actualMapping = actualResults[i]; + const auto expectedMapping = expectedResults[i]; + + QCOMPARE(actualMapping.targetId, expectedMapping.targetId); + QCOMPARE(actualMapping.propertyName, expectedMapping.propertyName); + QCOMPARE(actualMapping.type, expectedMapping.type); + QCOMPARE(actualMapping.channelIndices.size(), expectedMapping.channelIndices.size()); + for (int j = 0; j < actualMapping.channelIndices.size(); ++j) { + QCOMPARE(actualMapping.channelIndices[j], expectedMapping.channelIndices[j]); + } + } + } + + void checkLocalTimeFromGlobalTime_data() + { + QTest::addColumn<double>("globalTime"); + QTest::addColumn<double>("globalStartTime"); + QTest::addColumn<double>("playbackRate"); + QTest::addColumn<double>("duration"); + QTest::addColumn<int>("loopCount"); + QTest::addColumn<double>("expectedLocalTime"); + QTest::addColumn<int>("expectedCurrentLoop"); + + double globalTime; + double globalStartTime; + double playbackRate; + double duration; + int loopCount; + double expectedLocalTime; + int expectedCurrentLoop; + + globalTime = 0.0; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedLocalTime = 0.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 0") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 0.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedLocalTime = 0.5; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 0.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 1.0; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedLocalTime = 1.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 1.0") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = -0.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedLocalTime = 0.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = -0.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 1.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedLocalTime = 1.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 1.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 0.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 2; + expectedLocalTime = 0.5; + expectedCurrentLoop = 0; + QTest::newRow("simple, loopCount = 2, t_global = 0.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 1.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 2; + expectedLocalTime = 0.5; + expectedCurrentLoop = 1; + QTest::newRow("simple, loopCount = 2, t_global = 1.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 3.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 2.0; + loopCount = 2; + expectedLocalTime = 1.5; + expectedCurrentLoop = 1; + QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 4.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 2.0; + loopCount = 2; + expectedLocalTime = 2.0; + expectedCurrentLoop = 1; + QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 1.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 0; + expectedLocalTime = 0.5; + expectedCurrentLoop = 1; + QTest::newRow("simple, loopCount = inf, t_global = 1.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + + globalTime = 10.2; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 0; + expectedLocalTime = 0.2; + expectedCurrentLoop = 10; + QTest::newRow("simple, loopCount = inf, t_global = 10.2") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedLocalTime << expectedCurrentLoop; + } + + void checkLocalTimeFromGlobalTime() + { + // GIVEN + QFETCH(double, globalTime); + QFETCH(double, globalStartTime); + QFETCH(double, playbackRate); + QFETCH(double, duration); + QFETCH(int, loopCount); + QFETCH(double, expectedLocalTime); + QFETCH(int, expectedCurrentLoop); + + // WHEN + int actualCurrentLoop = 0; + double actualLocalTime = localTimeFromGlobalTime(globalTime, + globalStartTime, + playbackRate, + duration, + loopCount, + actualCurrentLoop); + + // THEN + QCOMPARE(actualCurrentLoop, expectedCurrentLoop); + QCOMPARE(actualLocalTime, expectedLocalTime); + } + + void checkPhaseFromGlobalTime_data() + { + QTest::addColumn<double>("globalTime"); + QTest::addColumn<double>("globalStartTime"); + QTest::addColumn<double>("playbackRate"); + QTest::addColumn<double>("duration"); + QTest::addColumn<int>("loopCount"); + QTest::addColumn<double>("expectedPhase"); + QTest::addColumn<int>("expectedCurrentLoop"); + + double globalTime; + double globalStartTime; + double playbackRate; + double duration; + int loopCount; + double expectedPhase; + int expectedCurrentLoop; + + globalTime = 0.0; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedPhase = 0.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 0") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 0.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedPhase = 0.5; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 0.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 1.0; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedPhase = 1.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 1.0") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = -0.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedPhase = 0.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = -0.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 1.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 1; + expectedPhase = 1.0; + expectedCurrentLoop = 0; + QTest::newRow("simple, t_global = 1.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 0.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 2; + expectedPhase = 0.5; + expectedCurrentLoop = 0; + QTest::newRow("simple, loopCount = 2, t_global = 0.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 1.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 2; + expectedPhase = 0.5; + expectedCurrentLoop = 1; + QTest::newRow("simple, loopCount = 2, t_global = 1.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 3.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 2.0; + loopCount = 2; + expectedPhase = 0.75; + expectedCurrentLoop = 1; + QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 4.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 2.0; + loopCount = 2; + expectedPhase = 1.0; + expectedCurrentLoop = 1; + QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 1.5; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 0; + expectedPhase = 0.5; + expectedCurrentLoop = 1; + QTest::newRow("simple, loopCount = inf, t_global = 1.5") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + + globalTime = 10.2; + globalStartTime = 0.0; + playbackRate = 1.0; + duration = 1.0; + loopCount = 0; + expectedPhase = 0.2; + expectedCurrentLoop = 10; + QTest::newRow("simple, loopCount = inf, t_global = 10.2") + << globalTime << globalStartTime << playbackRate << duration << loopCount + << expectedPhase << expectedCurrentLoop; + } + + void checkPhaseFromGlobalTime() + { + // GIVEN + QFETCH(double, globalTime); + QFETCH(double, globalStartTime); + QFETCH(double, playbackRate); + QFETCH(double, duration); + QFETCH(int, loopCount); + QFETCH(double, expectedPhase); + QFETCH(int, expectedCurrentLoop); + + // WHEN + int actualCurrentLoop = 0; + double actualPhase = phaseFromGlobalTime(globalTime, + globalStartTime, + playbackRate, + duration, + loopCount, + actualCurrentLoop); + + // THEN + QCOMPARE(actualCurrentLoop, expectedCurrentLoop); + QCOMPARE(actualPhase, expectedPhase); + } + + void checkPreparePropertyChanges_data() + { + QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); + QTest::addColumn<QVector<MappingData>>("mappingData"); + QTest::addColumn<QVector<float>>("channelResults"); + QTest::addColumn<bool>("finalFrame"); + QTest::addColumn<QVector<Qt3DCore::QPropertyUpdatedChangePtr>>("expectedChanges"); + + Qt3DCore::QNodeId animatorId; + QVector<MappingData> mappingData; + QVector<float> channelResults; + bool finalFrame; + QVector<Qt3DCore::QPropertyUpdatedChangePtr> expectedChanges; + + // Single property, vec3 + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "translation"; + mapping.type = static_cast<int>(QVariant::Vector3D); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f; + finalFrame = false; + + auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId); + change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + change->setPropertyName(mapping.propertyName); + change->setValue(QVariant::fromValue(QVector3D(1.0f, 2.0f, 3.0f))); + expectedChanges.push_back(change); + + QTest::newRow("vec3 translation, final = false") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + finalFrame = true; + auto animatorChange = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId); + animatorChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + animatorChange->setPropertyName("running"); + animatorChange->setValue(false); + expectedChanges.push_back(animatorChange); + + QTest::newRow("vec3 translation, final = true") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + + // Multiple properties, all vec3 + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData translationMapping; + translationMapping.targetId = Qt3DCore::QNodeId::createId(); + translationMapping.propertyName = "translation"; + translationMapping.type = static_cast<int>(QVariant::Vector3D); + translationMapping.channelIndices = QVector<int>() << 0 << 1 << 2; + mappingData.push_back(translationMapping); + + MappingData scaleMapping; + scaleMapping.targetId = Qt3DCore::QNodeId::createId(); + scaleMapping.propertyName = "scale"; + scaleMapping.type = static_cast<int>(QVariant::Vector3D); + scaleMapping.channelIndices = QVector<int>() << 3 << 4 << 5; + mappingData.push_back(scaleMapping); + + channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f + << 4.0f << 5.0f << 6.0f; + finalFrame = false; + + auto translationChange = Qt3DCore::QPropertyUpdatedChangePtr::create(translationMapping.targetId); + translationChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + translationChange->setPropertyName(translationMapping.propertyName); + translationChange->setValue(QVariant::fromValue(QVector3D(1.0f, 2.0f, 3.0f))); + expectedChanges.push_back(translationChange); + + auto scaleChange = Qt3DCore::QPropertyUpdatedChangePtr::create(scaleMapping.targetId); + scaleChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + scaleChange->setPropertyName(scaleMapping.propertyName); + scaleChange->setValue(QVariant::fromValue(QVector3D(4.0f, 5.0f, 6.0f))); + expectedChanges.push_back(scaleChange); + + QTest::newRow("vec3 translation, vec3 scale, final = false") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + finalFrame = true; + auto animatorChange = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId); + animatorChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + animatorChange->setPropertyName("running"); + animatorChange->setValue(false); + expectedChanges.push_back(animatorChange); + + QTest::newRow("vec3 translation, vec3 scale, final = true") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + + // Single property, double + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "mass"; + mapping.type = static_cast<int>(QVariant::Double); + mapping.channelIndices = QVector<int>() << 0; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 3.5f; + finalFrame = false; + + auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId); + change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + change->setPropertyName(mapping.propertyName); + change->setValue(QVariant::fromValue(3.5f)); + expectedChanges.push_back(change); + + QTest::newRow("double mass") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + + // Single property, vec2 + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "pos"; + mapping.type = static_cast<int>(QVariant::Vector2D); + mapping.channelIndices = QVector<int>() << 0 << 1; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 2.0f << 1.0f; + finalFrame = false; + + auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId); + change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + change->setPropertyName(mapping.propertyName); + change->setValue(QVariant::fromValue(QVector2D(2.0f, 1.0f))); + expectedChanges.push_back(change); + + QTest::newRow("vec2 pos") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + + // Single property, vec4 + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "foo"; + mapping.type = static_cast<int>(QVariant::Vector2D); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2 << 3; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 4.0f << 3.0f << 2.0f << 1.0f; + finalFrame = false; + + auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId); + change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + change->setPropertyName(mapping.propertyName); + change->setValue(QVariant::fromValue(QVector4D(4.0f, 3.0f, 2.0f, 1.0f))); + expectedChanges.push_back(change); + + QTest::newRow("vec4 foo") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + + // Single property, quaternion + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "rotation"; + mapping.type = static_cast<int>(QVariant::Quaternion); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2 << 3; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 1.0f << 0.0f << 0.0f << 1.0f; + finalFrame = false; + + auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId); + change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + change->setPropertyName(mapping.propertyName); + change->setValue(QVariant::fromValue(QQuaternion(1.0f, 0.0f, 0.0f, 1.0f))); + expectedChanges.push_back(change); + + QTest::newRow("quaternion rotation") + << animatorId << mappingData << channelResults << finalFrame + << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + } + + void checkPreparePropertyChanges() + { + // GIVEN + QFETCH(Qt3DCore::QNodeId, animatorId); + QFETCH(QVector<MappingData>, mappingData); + QFETCH(QVector<float>, channelResults); + QFETCH(bool, finalFrame); + QFETCH(QVector<Qt3DCore::QPropertyUpdatedChangePtr>, expectedChanges); + + // WHEN + QVector<Qt3DCore::QSceneChangePtr> actualChanges + = preparePropertyChanges(animatorId, mappingData, channelResults, finalFrame); + + // THEN + QCOMPARE(actualChanges.size(), expectedChanges.size()); + for (int i = 0; i < actualChanges.size(); ++i) { + auto expectedChange = expectedChanges[i]; + auto actualChange + = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(expectedChanges[i]); + + QCOMPARE(actualChange->subjectId(), expectedChange->subjectId()); + QCOMPARE(actualChange->deliveryFlags(), expectedChange->deliveryFlags()); + QCOMPARE(actualChange->propertyName(), expectedChange->propertyName()); + QCOMPARE(actualChange->value(), expectedChange->value()); + } + } + + void checkEvaluateClipAtLocalTime_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<AnimationClip *>("clip"); + QTest::addColumn<float>("localTime"); + QTest::addColumn<ClipResults>("expectedResults"); + + Handler *handler; + AnimationClip *clip; + float localTime; + ClipResults expectedResults; + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + localTime = 0.0f; + expectedResults = QVector<float>() << 0.0f << 0.0f << 0.0f; + + QTest::newRow("clip1.json, t = 0.0") + << handler << clip << localTime << expectedResults; + expectedResults.clear(); + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + localTime = clip->duration(); + expectedResults = QVector<float>() << 5.0f << 0.0f << 0.0f; + + QTest::newRow("clip1.json, t = duration") + << handler << clip << localTime << expectedResults; + expectedResults.clear(); + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + localTime = clip->duration() / 2.0f; + expectedResults = QVector<float>() << 2.5f << 0.0f << 0.0f; + + QTest::newRow("clip1.json, t = duration/2") + << handler << clip << localTime << expectedResults; + expectedResults.clear(); + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip2.json")); + localTime = 0.0f; + expectedResults = QVector<float>() + << 0.0f << 0.0f << 0.0f // Translation + << 1.0f << 0.0f << 0.0f << 0.0f; // Rotation + + QTest::newRow("clip2.json, t = 0.0") + << handler << clip << localTime << expectedResults; + expectedResults.clear(); + } + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip2.json")); + localTime = clip->duration(); + expectedResults = QVector<float>() + << 5.0f << 0.0f << 0.0f // Translation + << 0.0f << 0.0f << -1.0f << 0.0f; // Rotation + + QTest::newRow("clip2.json, t = duration") + << handler << clip << localTime << expectedResults; + expectedResults.clear(); + } + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip2.json")); + localTime = clip->duration() / 2.0f; + expectedResults = QVector<float>() + << 2.5f << 0.0f << 0.0f // Translation + << 0.5f << 0.0f << -0.5f << 0.0f; // Rotation + + QTest::newRow("clip2.json, t = duration/2") + << handler << clip << localTime << expectedResults; + expectedResults.clear(); + } + } + + void checkEvaluateClipAtLocalTime() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(AnimationClip *, clip); + QFETCH(float, localTime); + QFETCH(ClipResults, expectedResults); + + // WHEN + ClipResults actualResults = evaluateClipAtLocalTime(clip, localTime); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) { + auto actual = actualResults[i]; + auto expected = expectedResults[i]; + + QVERIFY(fuzzyCompare(actual, expected) == true); + } + + // Cleanup + delete handler; + } + + void checkEvaluateClipAtPhase_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<AnimationClip *>("clip"); + QTest::addColumn<float>("phase"); + QTest::addColumn<ClipResults>("expectedResults"); + + Handler *handler; + AnimationClip *clip; + float phase; + ClipResults expectedResults; + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + phase = 0.0f; + expectedResults = QVector<float>() << 0.0f << 0.0f << 0.0f; + + QTest::newRow("clip1.json, phi = 0.0") + << handler << clip << phase << expectedResults; + expectedResults.clear(); + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + phase = 1.0f; + expectedResults = QVector<float>() << 5.0f << 0.0f << 0.0f; + + QTest::newRow("clip1.json, phi = 1.0") + << handler << clip << phase << expectedResults; + expectedResults.clear(); + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + phase = 0.5f; + expectedResults = QVector<float>() << 2.5f << 0.0f << 0.0f; + + QTest::newRow("clip1.json, phi = 0.5") + << handler << clip << phase << expectedResults; + expectedResults.clear(); + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip2.json")); + phase = 0.0f; + expectedResults = QVector<float>() + << 0.0f << 0.0f << 0.0f // Translation + << 1.0f << 0.0f << 0.0f << 0.0f; // Rotation + + QTest::newRow("clip2.json, phi = 0.0") + << handler << clip << phase << expectedResults; + expectedResults.clear(); + } + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip2.json")); + phase = 1.0f; + expectedResults = QVector<float>() + << 5.0f << 0.0f << 0.0f // Translation + << 0.0f << 0.0f << -1.0f << 0.0f; // Rotation + + QTest::newRow("clip2.json, t = 1.0") + << handler << clip << phase << expectedResults; + expectedResults.clear(); + } + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip2.json")); + phase = 0.5f; + expectedResults = QVector<float>() + << 2.5f << 0.0f << 0.0f // Translation + << 0.5f << 0.0f << -0.5f << 0.0f; // Rotation + + QTest::newRow("clip2.json, phi = 0.5") + << handler << clip << phase << expectedResults; + expectedResults.clear(); + } + } + + void checkEvaluateClipAtPhase() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(AnimationClip *, clip); + QFETCH(float, phase); + QFETCH(ClipResults, expectedResults); + + // WHEN + ClipResults actualResults = evaluateClipAtPhase(clip, phase); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) { + auto actual = actualResults[i]; + auto expected = expectedResults[i]; + + QVERIFY(fuzzyCompare(actual, expected) == true); + } + + // Cleanup + delete handler; + } + + void checkChannelComponentsToIndicesHelper_data() + { + QTest::addColumn<Channel>("channel"); + QTest::addColumn<int>("dataType"); + QTest::addColumn<int>("offset"); + QTest::addColumn<QVector<char>>("suffixes"); + QTest::addColumn<QVector<int>>("expectedResults"); + + Channel channel; + int dataType; + int offset; + QVector<char> suffixes; + QVector<int> expectedResults; + + // vec3 with and without offset + { + channel = Channel(); + channel.name = QLatin1String("Location"); + channel.channelComponents.resize(3); + channel.channelComponents[0].name = QLatin1String("Location X"); + channel.channelComponents[1].name = QLatin1String("Location Y"); + channel.channelComponents[2].name = QLatin1String("Location Z"); + + dataType = static_cast<int>(QVariant::Vector3D); + offset = 0; + suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); + expectedResults = (QVector<int>() << 0 << 1 << 2); + + QTest::newRow("vec3 location, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 4; + expectedResults = (QVector<int>() << 4 << 5 << 6); + QTest::newRow("vec3 location, offset = 4") + << channel << dataType << offset << suffixes << expectedResults; + + suffixes.clear(); + expectedResults.clear(); + } + + // vec2 with and without offset + { + channel = Channel(); + channel.name = QLatin1String("pos"); + channel.channelComponents.resize(2); + channel.channelComponents[0].name = QLatin1String("pos X"); + channel.channelComponents[1].name = QLatin1String("pos Y"); + + dataType = static_cast<int>(QVariant::Vector2D); + offset = 0; + suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); + expectedResults = (QVector<int>() << 0 << 1); + + QTest::newRow("vec2 pos, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 2; + expectedResults = (QVector<int>() << 2 << 3); + QTest::newRow("vec2 pos, offset = 2") + << channel << dataType << offset << suffixes << expectedResults; + + suffixes.clear(); + expectedResults.clear(); + } + + // vec4 with and without offset + { + channel = Channel(); + channel.name = QLatin1String("foo"); + channel.channelComponents.resize(4); + channel.channelComponents[0].name = QLatin1String("foo X"); + channel.channelComponents[1].name = QLatin1String("foo Y"); + channel.channelComponents[2].name = QLatin1String("foo Z"); + channel.channelComponents[3].name = QLatin1String("foo W"); + + dataType = static_cast<int>(QVariant::Vector4D); + offset = 0; + suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); + expectedResults = (QVector<int>() << 0 << 1 << 2 << 3); + + QTest::newRow("vec4 foo, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 10; + expectedResults = (QVector<int>() << 10 << 11 << 12 << 13); + QTest::newRow("vec4 foo, offset = 10") + << channel << dataType << offset << suffixes << expectedResults; + + suffixes.clear(); + expectedResults.clear(); + } + + // double with and without offset + { + channel = Channel(); + channel.name = QLatin1String("foo"); + channel.channelComponents.resize(1); + channel.channelComponents[0].name = QLatin1String("Mass X"); + + dataType = static_cast<int>(QVariant::Double); + offset = 0; + suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); + expectedResults = (QVector<int>() << 0); + + QTest::newRow("double Mass, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 5; + expectedResults = (QVector<int>() << 5); + QTest::newRow("double Mass, offset = 5") + << channel << dataType << offset << suffixes << expectedResults; + + suffixes.clear(); + expectedResults.clear(); + } + + // quaternion with and without offset + { + channel = Channel(); + channel.name = QLatin1String("Rotation"); + channel.channelComponents.resize(4); + channel.channelComponents[0].name = QLatin1String("Rotation W"); + channel.channelComponents[1].name = QLatin1String("Rotation X"); + channel.channelComponents[2].name = QLatin1String("Rotation Y"); + channel.channelComponents[3].name = QLatin1String("Rotation Z"); + + dataType = static_cast<int>(QVariant::Quaternion); + offset = 0; + suffixes = (QVector<char>() << 'W' << 'X' << 'Y' << 'Z'); + expectedResults = (QVector<int>() << 0 << 1 << 2 << 3); + + QTest::newRow("quaternion Rotation, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 10; + expectedResults = (QVector<int>() << 10 << 11 << 12 << 13); + QTest::newRow("quaternion Rotation, offset = 10") + << channel << dataType << offset << suffixes << expectedResults; + + suffixes.clear(); + expectedResults.clear(); + } + + // quaternion with and without offset, randomized + { + channel = Channel(); + channel.name = QLatin1String("Rotation"); + channel.channelComponents.resize(4); + channel.channelComponents[0].name = QLatin1String("Rotation X"); + channel.channelComponents[1].name = QLatin1String("Rotation W"); + channel.channelComponents[2].name = QLatin1String("Rotation Z"); + channel.channelComponents[3].name = QLatin1String("Rotation Y"); + + dataType = static_cast<int>(QVariant::Quaternion); + offset = 0; + suffixes = (QVector<char>() << 'W' << 'X' << 'Y' << 'Z'); + expectedResults = (QVector<int>() << 1 << 0 << 3 << 2); + + QTest::newRow("quaternion Rotation, offset = 0, randomized") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 10; + expectedResults = (QVector<int>() << 11 << 10 << 13 << 12); + QTest::newRow("quaternion Rotation, offset = 10, randomized") + << channel << dataType << offset << suffixes << expectedResults; + + suffixes.clear(); + expectedResults.clear(); + } + } + + void checkChannelComponentsToIndicesHelper() + { + // GIVEN + QFETCH(Channel, channel); + QFETCH(int, dataType); + QFETCH(int, offset); + QFETCH(QVector<char>, suffixes); + QFETCH(QVector<int>, expectedResults); + + // WHEN + QVector<int> actualResults + = channelComponentsToIndicesHelper(channel, dataType, offset, suffixes); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) { + QCOMPARE(actualResults[i], expectedResults[i]); + } + } + + void checkChannelComponentsToIndices_data() + { + QTest::addColumn<Channel>("channel"); + QTest::addColumn<int>("dataType"); + QTest::addColumn<int>("offset"); + QTest::addColumn<QVector<int>>("expectedResults"); + + Channel channel; + int dataType; + int offset; + QVector<int> expectedResults; + + // Quaternion + { + channel = Channel(); + channel.name = QLatin1String("Rotation"); + channel.channelComponents.resize(4); + channel.channelComponents[0].name = QLatin1String("Rotation W"); + channel.channelComponents[1].name = QLatin1String("Rotation X"); + channel.channelComponents[2].name = QLatin1String("Rotation Y"); + channel.channelComponents[3].name = QLatin1String("Rotation Z"); + + dataType = static_cast<int>(QVariant::Quaternion); + offset = 0; + expectedResults = (QVector<int>() << 0 << 1 << 2 << 3); + + QTest::newRow("quaternion Rotation, offset = 0") + << channel << dataType << offset << expectedResults; + + expectedResults.clear(); + + offset = 10; + expectedResults = (QVector<int>() << 10 << 11 << 12 << 13); + QTest::newRow("quaternion Rotation, offset = 10") + << channel << dataType << offset << expectedResults; + + expectedResults.clear(); + } + + // vec3 with and without offset + { + channel = Channel(); + channel.name = QLatin1String("Location"); + channel.channelComponents.resize(3); + channel.channelComponents[0].name = QLatin1String("Location X"); + channel.channelComponents[1].name = QLatin1String("Location Y"); + channel.channelComponents[2].name = QLatin1String("Location Z"); + + dataType = static_cast<int>(QVariant::Vector3D); + offset = 0; + expectedResults = (QVector<int>() << 0 << 1 << 2); + + QTest::newRow("vec3 location, offset = 0") + << channel << dataType << offset << expectedResults; + + expectedResults.clear(); + + offset = 4; + expectedResults = (QVector<int>() << 4 << 5 << 6); + QTest::newRow("vec3 location, offset = 4") + << channel << dataType << offset << expectedResults; + + expectedResults.clear(); + } + } + + void checkChannelComponentsToIndices() + { + QFETCH(Channel, channel); + QFETCH(int, dataType); + QFETCH(int, offset); + QFETCH(QVector<int>, expectedResults); + + // WHEN + QVector<int> actualResults + = channelComponentsToIndices(channel, dataType, offset); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) { + QCOMPARE(actualResults[i], expectedResults[i]); + } + } + + void checkEvaluationDataForClip_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<AnimationClip *>("clip"); + QTest::addColumn<AnimatorEvaluationData>("animatorData"); + QTest::addColumn<ClipEvaluationData>("expectedClipData"); + + Handler *handler; + AnimationClip *clip; + AnimatorEvaluationData animatorData; + ClipEvaluationData clipData; + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 1; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + const qint64 globalTimeNS = 0; + animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, + animatorData.startTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = false; + + QTest::newRow("clip1.json, globalTime = 0") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 1; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + const qint64 globalTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, + animatorData.startTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = true; + + QTest::newRow("clip1.json, globalTime = duration") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 0; // Infinite loops + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + const qint64 globalTimeNS = 2.0 * clip->duration() * 1.0e9; + animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, + animatorData.startTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = false; + + QTest::newRow("clip1.json, globalTime = 2 * duration, loops = infinite") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 2; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + const qint64 globalTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, + animatorData.startTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = true; + + QTest::newRow("clip1.json, globalTime = 2 * duration + 1, loops = 2") + << handler << clip << animatorData << clipData; + } + } + + void checkEvaluationDataForClip() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(AnimationClip *, clip); + QFETCH(AnimatorEvaluationData, animatorData); + QFETCH(ClipEvaluationData, expectedClipData); + + // WHEN + ClipEvaluationData actualClipData = evaluationDataForClip(clip, animatorData); + + // THEN + QCOMPARE(actualClipData.currentLoop, expectedClipData.currentLoop); + QVERIFY(fuzzyCompare(actualClipData.localTime, expectedClipData.localTime) == true); + QCOMPARE(actualClipData.isFinalFrame, expectedClipData.isFinalFrame); + + // Cleanup + delete handler; + } + + void checkEvaluationDataForAnimator_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<ClipAnimator *>("animator"); + QTest::addColumn<qint64>("globalTimeNS"); + QTest::addColumn<AnimatorEvaluationData>("expectedAnimatorData"); + + Handler *handler; + ClipAnimator *animator; + qint64 globalTimeNS; + AnimatorEvaluationData expectedAnimatorData; + + { + handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loops = 1; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + globalTimeNS = 0; + + expectedAnimatorData.loopCount = loops; + expectedAnimatorData.playbackRate = 1.0; // hard-wired for now + expectedAnimatorData.startTime = 0.0; + expectedAnimatorData.globalTime = 0.0; + + QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 1") + << handler << animator << globalTimeNS << expectedAnimatorData; + } + + { + handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loops = 5; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + globalTimeNS = 0; + + expectedAnimatorData.loopCount = loops; + expectedAnimatorData.playbackRate = 1.0; // hard-wired for now + expectedAnimatorData.startTime = 0.0; + expectedAnimatorData.globalTime = 0.0; + + QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 5") + << handler << animator << globalTimeNS << expectedAnimatorData; + } + + { + handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loops = 1; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + globalTimeNS = 5000000000; + + expectedAnimatorData.loopCount = loops; + expectedAnimatorData.playbackRate = 1.0; // hard-wired for now + expectedAnimatorData.startTime = 0.0; + expectedAnimatorData.globalTime = 5.0; + + QTest::newRow("globalStartTime = 0, globalTime = 5, loops = 1") + << handler << animator << globalTimeNS << expectedAnimatorData; + } + + { + handler = new Handler(); + const qint64 globalStartTimeNS = 3000000000; + const int loops = 1; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + globalTimeNS = 5000000000; + + expectedAnimatorData.loopCount = loops; + expectedAnimatorData.playbackRate = 1.0; // hard-wired for now + expectedAnimatorData.startTime = 3.0; + expectedAnimatorData.globalTime = 5.0; + + QTest::newRow("globalStartTime = 3, globalTime = 5, loops = 1") + << handler << animator << globalTimeNS << expectedAnimatorData; + } + } + + void checkEvaluationDataForAnimator() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(ClipAnimator *, animator); + QFETCH(qint64, globalTimeNS); + QFETCH(AnimatorEvaluationData, expectedAnimatorData); + + // WHEN + AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, globalTimeNS); + + // THEN + QCOMPARE(actualAnimatorData.loopCount, expectedAnimatorData.loopCount); + QVERIFY(fuzzyCompare(actualAnimatorData.playbackRate, expectedAnimatorData.playbackRate) == true); + QVERIFY(fuzzyCompare(actualAnimatorData.startTime, expectedAnimatorData.startTime) == true); + QVERIFY(fuzzyCompare(actualAnimatorData.globalTime, expectedAnimatorData.globalTime) == true); + + // Cleanup + delete handler; + } + + void checkGatherValueNodesToEvaluate_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<Qt3DCore::QNodeId>("blendTreeRootId"); + QTest::addColumn<QVector<Qt3DCore::QNodeId>>("expectedIds"); + + { + Handler *handler = new Handler; + + const auto lerp = createLerpClipBlend(handler); + const auto value1 = createClipBlendValue(handler); + const auto clip1Id = Qt3DCore::QNodeId::createId(); + value1->setClipId(clip1Id); + lerp->setStartClipId(value1->peerId()); + + const auto value2 = createClipBlendValue(handler); + const auto clip2Id = Qt3DCore::QNodeId::createId(); + value2->setClipId(clip2Id); + lerp->setEndClipId(value2->peerId()); + + QVector<Qt3DCore::QNodeId> expectedIds = { value1->peerId(), value2->peerId() }; + + QTest::newRow("simple lerp") << handler << lerp->peerId() << expectedIds; + } + } + + void checkGatherValueNodesToEvaluate() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(Qt3DCore::QNodeId, blendTreeRootId); + QFETCH(QVector<Qt3DCore::QNodeId>, expectedIds); + + // WHEN + QVector<Qt3DCore::QNodeId> actualIds = gatherValueNodesToEvaluate(handler, blendTreeRootId); + + // THEN + QCOMPARE(actualIds.size(), expectedIds.size()); + for (int i = 0; i < actualIds.size(); ++i) + QCOMPARE(actualIds[i], expectedIds[i]); + + // Cleanup + delete handler; + } + + void checkEvaluateBlendTree_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<BlendedClipAnimator *>("animator"); + QTest::addColumn<Qt3DCore::QNodeId>("blendNodeId"); + QTest::addColumn<ClipResults>("expectedResults"); + + { + /* + ValueNode1---- + | + MeanBlendNode + | + ValueNode2---- + */ + + auto handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + // Set up the blend node and dependencies (evaluated clip results of the + // dependent nodes in the animator indexed by their ids). + MeanBlendNode *blendNode = createMeanBlendNode(handler); + + // First clip to use in the mean + auto valueNode1 = createClipBlendValue(handler); + ClipResults valueNode1Results = { 0.0f, 0.0f, 0.0f }; + valueNode1->setClipResults(animator->peerId(), valueNode1Results); + + // Second clip to use in the mean + auto valueNode2 = createClipBlendValue(handler); + ClipResults valueNode2Results = { 1.0f, 1.0f, 1.0f }; + valueNode2->setClipResults(animator->peerId(), valueNode2Results); + + blendNode->setValueNodeIds(valueNode1->peerId(), valueNode2->peerId()); + + ClipResults expectedResults = { 0.5f, 0.5f, 0.5f }; + + QTest::newRow("mean node, 1 channel") + << handler << animator << blendNode->peerId() << expectedResults; + } + + { + /* + ValueNode1---- + | + MeanBlendNode + | + ValueNode2---- + */ + + auto handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + // Set up the blend node and dependencies (evaluated clip results of the + // dependent nodes in the animator indexed by their ids). + MeanBlendNode *blendNode = createMeanBlendNode(handler); + + // First clip to use in the mean + auto valueNode1 = createClipBlendValue(handler); + ClipResults valueNode1Results = { 0.0f, 0.0f, 0.0f, 1.0f, 2.0f, 3.0f }; + valueNode1->setClipResults(animator->peerId(), valueNode1Results); + + // Second clip to use in the mean + auto valueNode2 = createClipBlendValue(handler); + ClipResults valueNode2Results = { 1.0f, 1.0f, 1.0f, 2.0f, 4.0f, 6.0f }; + valueNode2->setClipResults(animator->peerId(), valueNode2Results); + + blendNode->setValueNodeIds(valueNode1->peerId(), valueNode2->peerId()); + + ClipResults expectedResults = { 0.5f, 0.5f, 0.5f, 1.5f, 3.0f, 4.5f }; + + QTest::newRow("mean node, 2 channels") + << handler << animator << blendNode->peerId() << expectedResults; + } + + { + /* + ValueNode1---- + | + MeanBlendNode1------ + | | + ValueNode2---- | + MeanBlendNode3 + ValueNode3---- | + | | + MeanBlendNode2------ + | + ValueNode4---- + */ + + auto handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + // Set up the blend node and dependencies (evaluated clip results of the + // dependent nodes in the animator indexed by their ids). + + // MeanBlendNode1 + MeanBlendNode *meanNode1 = createMeanBlendNode(handler); + + // First clip to use in mean1 + auto valueNode1 = createClipBlendValue(handler); + ClipResults valueNode1Results = { 0.0f, 0.0f, 0.0f }; + valueNode1->setClipResults(animator->peerId(), valueNode1Results); + + // Second clip to use in mean1 + auto valueNode2 = createClipBlendValue(handler); + ClipResults valueNode2Results = { 2.0f, 2.0f, 2.0f }; + valueNode2->setClipResults(animator->peerId(), valueNode2Results); + + meanNode1->setValueNodeIds(valueNode1->peerId(), valueNode2->peerId()); + + + // MeanBlendNode2 + MeanBlendNode *meanNode2 = createMeanBlendNode(handler); + + // First clip to use in mean1 + auto valueNode3 = createClipBlendValue(handler); + ClipResults valueNode3Results = { 10.0f, 10.0f, 10.0f }; + valueNode3->setClipResults(animator->peerId(), valueNode3Results); + + // Second clip to use in mean1 + auto valueNode4 = createClipBlendValue(handler); + ClipResults valueNode4Results = { 20.0f, 20.0f, 20.0f }; + valueNode4->setClipResults(animator->peerId(), valueNode4Results); + + meanNode2->setValueNodeIds(valueNode3->peerId(), valueNode4->peerId()); + + + // MeanBlendNode3 + MeanBlendNode *meanNode3 = createMeanBlendNode(handler); + meanNode3->setValueNodeIds(meanNode1->peerId(), meanNode2->peerId()); + + // Mean1 = 1 + // Mean2 = 15 + // Mean3 = (1 + 15 ) / 2 = 8 + ClipResults expectedResults = { 8.0f, 8.0f, 8.0f }; + + QTest::newRow("3 mean nodes, 1 channel") + << handler << animator << meanNode3->peerId() << expectedResults; + } + + { + /* + ValueNode1---- + | + MeanBlendNode1------ + | | + ValueNode2---- | + MeanBlendNode3--- + ValueNode3---- | | + | | | + MeanBlendNode2------ AdditiveBlendNode1 + | | + ValueNode4---- | + ValueNode5------- + */ + + auto handler = new Handler(); + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + // Set up the blend node and dependencies (evaluated clip results of the + // dependent nodes in the animator indexed by their ids). + + // MeanBlendNode1 + MeanBlendNode *meanNode1 = createMeanBlendNode(handler); + + // First clip to use in mean1 + auto valueNode1 = createClipBlendValue(handler); + ClipResults valueNode1Results = { 0.0f, 0.0f, 0.0f }; + valueNode1->setClipResults(animator->peerId(), valueNode1Results); + + // Second clip to use in mean1 + auto valueNode2 = createClipBlendValue(handler); + ClipResults valueNode2Results = { 2.0f, 2.0f, 2.0f }; + valueNode2->setClipResults(animator->peerId(), valueNode2Results); + + meanNode1->setValueNodeIds(valueNode1->peerId(), valueNode2->peerId()); + + + // MeanBlendNode2 + MeanBlendNode *meanNode2 = createMeanBlendNode(handler); + + // First clip to use in mean2 + auto valueNode3 = createClipBlendValue(handler); + ClipResults valueNode3Results = { 10.0f, 10.0f, 10.0f }; + valueNode3->setClipResults(animator->peerId(), valueNode3Results); + + // Second clip to use in mean2 + auto valueNode4 = createClipBlendValue(handler); + ClipResults valueNode4Results = { 20.0f, 20.0f, 20.0f }; + valueNode4->setClipResults(animator->peerId(), valueNode4Results); + + meanNode2->setValueNodeIds(valueNode3->peerId(), valueNode4->peerId()); + + + // MeanBlendNode3 + MeanBlendNode *meanNode3 = createMeanBlendNode(handler); + meanNode3->setValueNodeIds(meanNode1->peerId(), meanNode2->peerId()); + + + // AdditiveBlendNode1 + AdditiveClipBlend *additiveBlendNode1 = createAdditiveClipBlend(handler); + auto valueNode5 = createClipBlendValue(handler); + ClipResults valueNode5Results = { 1.0f, 2.0f, 3.0f }; + valueNode5->setClipResults(animator->peerId(), valueNode5Results); + + additiveBlendNode1->setBaseClipId(meanNode3->peerId()); + additiveBlendNode1->setAdditiveClipId(valueNode5->peerId()); + additiveBlendNode1->setAdditiveFactor(0.5); + + // Mean1 = 1 + // Mean2 = 15 + // Mean3 = (1 + 15 ) / 2 = 8 + // Additive1 = 8 + 0.5 * (1, 2, 3) = (8.5, 9, 9.5) + ClipResults expectedResults = { 8.5f, 9.0f, 9.5f }; + + QTest::newRow("3 mean nodes + additive, 1 channel") + << handler << animator << additiveBlendNode1->peerId() << expectedResults; + } + } + + void checkEvaluateBlendTree() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(BlendedClipAnimator *, animator); + QFETCH(Qt3DCore::QNodeId, blendNodeId); + QFETCH(ClipResults, expectedResults); + + // WHEN + const ClipResults actualResults = evaluateBlendTree(handler, animator, blendNodeId); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); + + // Cleanup + delete handler; + } + + void checkFormatClipResults_data() + { + QTest::addColumn<ClipResults>("rawClipResults"); + QTest::addColumn<ComponentIndices>("format"); + QTest::addColumn<ClipResults>("expectedResults"); + + { + ClipResults rawClipResults = { 1.0f, 2.0f, 3.0f }; + ComponentIndices format = { 0, 1, 2 }; + ClipResults expectedResults = { 1.0f, 2.0f, 3.0f }; + + QTest::newRow("identity") + << rawClipResults << format << expectedResults; + } + + { + ClipResults rawClipResults = { 1.0f, 2.0f }; + ComponentIndices format = { 1, 0 }; + ClipResults expectedResults = { 2.0f, 1.0f }; + + QTest::newRow("swap") + << rawClipResults << format << expectedResults; + } + + { + ClipResults rawClipResults = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; + ComponentIndices format = { 0, 2, 1, 3, 4 }; + ClipResults expectedResults = { 1.0f, 3.0f, 2.0f, 4.0f, 5.0f }; + + QTest::newRow("swap subset") + << rawClipResults << format << expectedResults; + } + + { + ClipResults rawClipResults = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; + ComponentIndices format = { 4, 3, 2, 1, 0 }; + ClipResults expectedResults = { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f }; + + QTest::newRow("reverse") + << rawClipResults << format << expectedResults; + } + + { + ClipResults rawClipResults = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; + ComponentIndices format = { 0, 1, -1, 3, 4 }; + ClipResults expectedResults = { 1.0f, 2.0f, 0.0f, 4.0f, 5.0f }; + + QTest::newRow("include missing") + << rawClipResults << format << expectedResults; + } + } + + void checkFormatClipResults() + { + // GIVEN + QFETCH(ClipResults, rawClipResults); + QFETCH(ComponentIndices, format); + QFETCH(ClipResults, expectedResults); + + // WHEN + const ClipResults actualResults = formatClipResults(rawClipResults, format); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); + } + + void checkBuildRequiredChannelsAndTypes_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<ChannelMapper *>("mapper"); + QTest::addColumn<QVector<ChannelNameAndType>>("expectedResults"); + + { + auto handler = new Handler(); + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + auto channelMapper = createChannelMapper(handler, + QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + + QVector<ChannelNameAndType> expectedResults; + expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + + QTest::addRow("Location, vec3") << handler << channelMapper << expectedResults; + } + + { + auto handler = new Handler(); + auto channelMapping1 = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + auto channelMapping2 = createChannelMapping(handler, + QLatin1String("Rotation"), + Qt3DCore::QNodeId::createId(), + QLatin1String("rotatrion"), + "rotation", + static_cast<int>(QVariant::Quaternion)); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping1); + channelMappings.push_back(channelMapping2); + + QVector<Qt3DCore::QNodeId> channelMappingIds + = (QVector<Qt3DCore::QNodeId>() + << channelMapping1->peerId() + << channelMapping2->peerId()); + auto channelMapper = createChannelMapper(handler, channelMappingIds); + + QVector<ChannelNameAndType> expectedResults; + expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + + QTest::addRow("Multiple unique channels") << handler << channelMapper << expectedResults; + } + + { + auto handler = new Handler(); + auto channelMapping1 = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + auto channelMapping2 = createChannelMapping(handler, + QLatin1String("Rotation"), + Qt3DCore::QNodeId::createId(), + QLatin1String("rotation"), + "rotation", + static_cast<int>(QVariant::Quaternion)); + auto channelMapping3 = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + auto channelMapping4 = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping1); + channelMappings.push_back(channelMapping2); + channelMappings.push_back(channelMapping3); + channelMappings.push_back(channelMapping4); + + QVector<Qt3DCore::QNodeId> channelMappingIds + = (QVector<Qt3DCore::QNodeId>() + << channelMapping1->peerId() + << channelMapping2->peerId() + << channelMapping3->peerId() + << channelMapping4->peerId()); + auto channelMapper = createChannelMapper(handler, channelMappingIds); + + QVector<ChannelNameAndType> expectedResults; + expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + + QTest::addRow("Multiple channels with repeats") << handler << channelMapper << expectedResults; + } + } + + void checkBuildRequiredChannelsAndTypes() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(ChannelMapper *, mapper); + QFETCH(QVector<ChannelNameAndType>, expectedResults); + + // WHEN + const QVector<ChannelNameAndType> actualResults = buildRequiredChannelsAndTypes(handler, mapper); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); + + // Cleanup + delete handler; + } + + void checkAssignChannelComponentIndices_data() + { + QTest::addColumn<QVector<ChannelNameAndType>>("allChannels"); + QTest::addColumn<QVector<ComponentIndices>>("expectedResults"); + + { + QVector<ChannelNameAndType> allChannels; + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + + QVector<ComponentIndices> expectedResults; + expectedResults.push_back({ 0, 1, 2 }); + + QTest::newRow("vec3 location") << allChannels << expectedResults; + } + + { + QVector<ChannelNameAndType> allChannels; + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + + QVector<ComponentIndices> expectedResults; + expectedResults.push_back({ 0, 1, 2 }); + expectedResults.push_back({ 3, 4, 5, 6 }); + + QTest::newRow("vec3 location, quaterion rotation") << allChannels << expectedResults; + } + + { + QVector<ChannelNameAndType> allChannels; + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + allChannels.push_back({ QLatin1String("BaseColor"), static_cast<int>(QVariant::Vector3D) }); + allChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); + allChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + + QVector<ComponentIndices> expectedResults; + expectedResults.push_back({ 0, 1, 2 }); + expectedResults.push_back({ 3, 4, 5, 6 }); + expectedResults.push_back({ 7, 8, 9 }); + expectedResults.push_back({ 10 }); + expectedResults.push_back({ 11 }); + + QTest::newRow("vec3 location, quaterion rotation, pbr metal-rough") << allChannels << expectedResults; + } + } + + void checkAssignChannelComponentIndices() + { + // GIVEN + QFETCH(QVector<ChannelNameAndType>, allChannels); + QFETCH(QVector<ComponentIndices>, expectedResults); + + // WHEN + const QVector<ComponentIndices> actualResults = assignChannelComponentIndices(allChannels); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) { + const ComponentIndices &actualResult = actualResults[i]; + const ComponentIndices &expectedResult = expectedResults[i]; + + for (int j = 0; j < actualResult.size(); ++j) + QCOMPARE(actualResult[j], expectedResult[j]); + } + } + + void checkGenerateClipFormatIndices_data() + { + QTest::addColumn<QVector<ChannelNameAndType>>("targetChannels"); + QTest::addColumn<QVector<ComponentIndices>>("targetIndices"); + QTest::addColumn<AnimationClip *>("clip"); + QTest::addColumn<ComponentIndices>("expectedResults"); + + { + QVector<ChannelNameAndType> targetChannels; + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Base Color"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + + QVector<ComponentIndices> targetIndices; + targetIndices.push_back({ 0, 1, 2, 3 }); + targetIndices.push_back({ 4, 5, 6 }); + targetIndices.push_back({ 7, 8, 9 }); + targetIndices.push_back({ 10 }); + targetIndices.push_back({ 11 }); + + auto *clip = new AnimationClip(); + clip->setDataType(AnimationClip::File); + clip->setSource(QUrl("qrc:/clip3.json")); + clip->loadAnimation(); + + ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation + 4, 5, 6, // Location + 7, 8, 9, // Base Color + 10, // Metalness + 11 }; // Roughness + + QTest::newRow("rotation, location, pbr metal-rough") + << targetChannels << targetIndices << clip << expectedResults; + } + + { + QVector<ChannelNameAndType> targetChannels; + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + targetChannels.push_back({ QLatin1String("Base Color"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + + QVector<ComponentIndices> targetIndices; + targetIndices.push_back({ 0, 1, 2 }); + targetIndices.push_back({ 3, 4, 5, 6 }); + targetIndices.push_back({ 7, 8, 9 }); + targetIndices.push_back({ 10 }); + targetIndices.push_back({ 11 }); + + auto *clip = new AnimationClip(); + clip->setDataType(AnimationClip::File); + clip->setSource(QUrl("qrc:/clip3.json")); + clip->loadAnimation(); + + ComponentIndices expectedResults = { 4, 5, 6, // Location + 0, 1, 2, 3, // Rotation + 7, 8, 9, // Base Color + 10, // Metalness + 11 }; // Roughness + + QTest::newRow("location, rotation, pbr metal-rough") + << targetChannels << targetIndices << clip << expectedResults; + } + + { + QVector<ChannelNameAndType> targetChannels; + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Albedo"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + + QVector<ComponentIndices> targetIndices; + targetIndices.push_back({ 0, 1, 2, 3 }); + targetIndices.push_back({ 4, 5, 6 }); + targetIndices.push_back({ 7, 8, 9 }); + targetIndices.push_back({ 10 }); + targetIndices.push_back({ 11 }); + + auto *clip = new AnimationClip(); + clip->setDataType(AnimationClip::File); + clip->setSource(QUrl("qrc:/clip3.json")); + clip->loadAnimation(); + + ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation + 4, 5, 6, // Location + -1, -1, -1, // Albedo (missing from clip) + 10, // Metalness + 11 }; // Roughness + + QTest::newRow("rotation, location, albedo (missing), metal-rough") + << targetChannels << targetIndices << clip << expectedResults; + } + + { + QVector<ChannelNameAndType> targetChannels; + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + targetChannels.push_back({ QLatin1String("Albedo"), static_cast<int>(QVariant::Vector3D) }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + + QVector<ComponentIndices> targetIndices; + targetIndices.push_back({ 0, 1, 2 }); + targetIndices.push_back({ 3, 4, 5, 6 }); + targetIndices.push_back({ 7, 8, 9 }); + targetIndices.push_back({ 10 }); + targetIndices.push_back({ 11 }); + + auto *clip = new AnimationClip(); + clip->setDataType(AnimationClip::File); + clip->setSource(QUrl("qrc:/clip3.json")); + clip->loadAnimation(); + + ComponentIndices expectedResults = { 4, 5, 6, // Location + 0, 1, 2, 3, // Rotation + -1, -1, -1, // Albedo (missing from clip) + 10, // Metalness + 11 }; // Roughness + + QTest::newRow("location, rotation, albedo (missing), metal-rough") + << targetChannels << targetIndices << clip << expectedResults; + } + } + + void checkGenerateClipFormatIndices() + { + // GIVEN + QFETCH(QVector<ChannelNameAndType>, targetChannels); + QFETCH(QVector<ComponentIndices>, targetIndices); + QFETCH(AnimationClip *, clip); + QFETCH(ComponentIndices, expectedResults); + + // WHEN + const ComponentIndices actualResults = generateClipFormatIndices(targetChannels, + targetIndices, + clip); + + // THEN + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); + + // Cleanup + delete clip; + } +}; + +QTEST_MAIN(tst_AnimationUtils) + +#include "tst_animationutils.moc" diff --git a/tests/auto/animation/bezierevaluator/tst_bezierevaluator.cpp b/tests/auto/animation/bezierevaluator/tst_bezierevaluator.cpp index 746af8d55..5dc971ab7 100644 --- a/tests/auto/animation/bezierevaluator/tst_bezierevaluator.cpp +++ b/tests/auto/animation/bezierevaluator/tst_bezierevaluator.cpp @@ -35,6 +35,7 @@ Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Keyframe) +using namespace Qt3DAnimation; using namespace Qt3DAnimation::Animation; class tst_BezierEvaluator : public QObject @@ -131,9 +132,9 @@ private Q_SLOTS: QTest::addColumn<QVector<float>>("bezierParamters"); float t0 = 0.0f; - Keyframe kf0{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, Keyframe::Bezier}; + Keyframe kf0{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, QKeyFrame::BezierInterpolation}; float t1 = 50.0f; - Keyframe kf1{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, Keyframe::Bezier}; + Keyframe kf1{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, QKeyFrame::BezierInterpolation}; const int count = 21; QVector<float> times = (QVector<float>() << 0.0f @@ -199,9 +200,9 @@ private Q_SLOTS: QTest::addColumn<QVector<float>>("values"); float t0 = 0.0f; - Keyframe kf0{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, Keyframe::Bezier}; + Keyframe kf0{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, QKeyFrame::BezierInterpolation}; float t1 = 50.0f; - Keyframe kf1{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, Keyframe::Bezier}; + Keyframe kf1{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, QKeyFrame::BezierInterpolation}; QVector<float> times = (QVector<float>() << 0.0f << 1.00375f diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp index c53f6ec62..3265de167 100644 --- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp +++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp @@ -28,7 +28,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/private/blendedclipanimator_p.h> -#include <Qt3DAnimation/qanimationclip.h> +#include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qblendedclipanimator.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> @@ -39,7 +39,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/qblendedclipanimator.h> -#include <Qt3DAnimation/qlerpblend.h> +#include <Qt3DAnimation/qlerpclipblend.h> #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/private/qblendedclipanimator_p.h> #include <Qt3DAnimation/private/blendedclipanimator_p.h> @@ -65,7 +65,6 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.isRunning(), false); QCOMPARE(backendBlendedClipAnimator.startTime(), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); - QCOMPARE(backendBlendedClipAnimator.mappingData().size(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); } @@ -83,9 +82,6 @@ private Q_SLOTS: backendBlendedClipAnimator.setMapperId(Qt3DCore::QNodeId::createId()); backendBlendedClipAnimator.setRunning(true); backendBlendedClipAnimator.setStartTime(28); - QVector<Qt3DAnimation::Animation::AnimationUtils::BlendingMappingData> mappingData; - mappingData.resize(5); - backendBlendedClipAnimator.setMappingData(mappingData); backendBlendedClipAnimator.cleanup(); // THEN @@ -95,7 +91,6 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.isRunning(), false); QCOMPARE(backendBlendedClipAnimator.startTime(), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); - QCOMPARE(backendBlendedClipAnimator.mappingData().size(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); } @@ -104,11 +99,11 @@ private Q_SLOTS: // GIVEN Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator; Qt3DAnimation::QChannelMapper mapper; - Qt3DAnimation::QLerpBlend blendTree; + Qt3DAnimation::QLerpClipBlend blendTree; blendedClipAnimator.setRunning(true); blendedClipAnimator.setBlendTree(&blendTree); blendedClipAnimator.setChannelMapper(&mapper); - blendedClipAnimator.setLoops(10); + blendedClipAnimator.setLoopCount(10); { // WHEN diff --git a/tests/auto/animation/clipanimator/tst_clipanimator.cpp b/tests/auto/animation/clipanimator/tst_clipanimator.cpp index 77f067973..615547405 100644 --- a/tests/auto/animation/clipanimator/tst_clipanimator.cpp +++ b/tests/auto/animation/clipanimator/tst_clipanimator.cpp @@ -28,7 +28,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/private/clipanimator_p.h> -#include <Qt3DAnimation/qanimationclip.h> +#include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qclipanimator.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> @@ -49,10 +49,10 @@ private Q_SLOTS: Qt3DAnimation::Animation::ClipAnimator backendAnimator; backendAnimator.setHandler(&handler); Qt3DAnimation::QClipAnimator animator; - auto clip = new Qt3DAnimation::QAnimationClip(); + auto clip = new Qt3DAnimation::QAnimationClipLoader(); animator.setClip(clip); - animator.setLoops(10); + animator.setLoopCount(10); // WHEN simulateInitialization(&animator, &backendAnimator); @@ -62,7 +62,7 @@ private Q_SLOTS: QCOMPARE(backendAnimator.isEnabled(), animator.isEnabled()); QCOMPARE(backendAnimator.clipId(), clip->id()); QCOMPARE(backendAnimator.isRunning(), animator.isRunning()); - QCOMPARE(backendAnimator.loops(), animator.loops()); + QCOMPARE(backendAnimator.loops(), animator.loopCount()); } void checkInitialAndCleanedUpState() @@ -81,10 +81,10 @@ private Q_SLOTS: // GIVEN Qt3DAnimation::QClipAnimator animator; - auto clip = new Qt3DAnimation::QAnimationClip(); + auto clip = new Qt3DAnimation::QAnimationClipLoader(); animator.setClip(clip); animator.setRunning(true); - animator.setLoops(25); + animator.setLoopCount(25); // WHEN simulateInitialization(&animator, &backendAnimator); @@ -116,7 +116,7 @@ private Q_SLOTS: QCOMPARE(backendAnimator.isEnabled(), true); // WHEN - auto newClip = new Qt3DAnimation::QAnimationClip(); + auto newClip = new Qt3DAnimation::QAnimationClipLoader(); updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); updateChange->setPropertyName("clip"); updateChange->setValue(QVariant::fromValue(newClip->id())); diff --git a/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp b/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp index c045c2112..b64e263bf 100644 --- a/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp +++ b/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp @@ -28,8 +28,8 @@ #include <QtTest/QTest> -#include <Qt3DAnimation/qlerpblend.h> -#include <Qt3DAnimation/qanimationclip.h> +#include <Qt3DAnimation/qlerpclipblend.h> +#include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/private/qabstractclipblendnode_p.h> #include <Qt3DAnimation/private/clipblendnode_p.h> #include <Qt3DAnimation/private/managers_p.h> @@ -39,21 +39,73 @@ #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> #include "qbackendnodetester.h" +#include <random> +#include <algorithm> + +using namespace Qt3DAnimation::Animation; + namespace { -class TestClipBlendNode : public Qt3DAnimation::Animation::ClipBlendNode +class TestClipBlendNode : public ClipBlendNode { public: - TestClipBlendNode() - : Qt3DAnimation::Animation::ClipBlendNode(Qt3DAnimation::Animation::ClipBlendNode::LerpBlendType) + TestClipBlendNode(const ClipResults &clipResults = ClipResults()) + : ClipBlendNode(ClipBlendNode::LerpBlendType) + , m_clipResults(clipResults) {} + + inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE + { + return currentDependencyIds(); + } + + QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_FINAL + { + return QVector<Qt3DCore::QNodeId>(); + } + + using ClipBlendNode::setClipResults; + + double duration() const Q_DECL_FINAL { return 0.0f; } + +protected: + ClipResults doBlend(const QVector<ClipResults> &) const Q_DECL_FINAL + { + return m_clipResults; + } + +private: + ClipResults m_clipResults; }; } // anonymous +Q_DECLARE_METATYPE(TestClipBlendNode *) + class tst_ClipBlendNode : public Qt3DCore::QBackendNodeTester { Q_OBJECT +public: + TestClipBlendNode *createTestClipBlendNode(Handler *handler, const ClipResults &clipResults) + { + auto id = Qt3DCore::QNodeId::createId(); + TestClipBlendNode *node = new TestClipBlendNode(clipResults); + setPeerId(node, id); + handler->clipBlendNodeManager()->appendNode(id, node); + return node; + } + + BlendedClipAnimator *createBlendedClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + BlendedClipAnimator *animator = handler->blendedClipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } private Q_SLOTS: @@ -65,25 +117,22 @@ private Q_SLOTS: // THEN QCOMPARE(backendClipBlendNode.isEnabled(), false); QVERIFY(backendClipBlendNode.peerId().isNull()); - QCOMPARE(backendClipBlendNode.clipIds(), Qt3DCore::QNodeIdVector()); - QCOMPARE(backendClipBlendNode.parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendClipBlendNode.childrenIds(), Qt3DCore::QNodeIdVector()); QVERIFY(backendClipBlendNode.clipBlendNodeManager() == nullptr); - QCOMPARE(backendClipBlendNode.blendType(), Qt3DAnimation::Animation::ClipBlendNode::LerpBlendType); + QCOMPARE(backendClipBlendNode.blendType(), ClipBlendNode::LerpBlendType); + QCOMPARE(backendClipBlendNode.clipResults(Qt3DCore::QNodeId()), ClipResults()); } void checkInitializeFromPeer() { // GIVEN - Qt3DAnimation::QLerpBlend clipBlendNode; - Qt3DAnimation::QAnimationClip clip; - clipBlendNode.addClip(&clip); + Qt3DAnimation::QLerpClipBlend clipBlendNode; + Qt3DAnimation::QAnimationClipLoader clip; QCoreApplication::processEvents(); { // WHEN - Qt3DAnimation::Animation::ClipBlendNodeManager manager; + ClipBlendNodeManager manager; TestClipBlendNode backendClipBlendNode; backendClipBlendNode.setClipBlendNodeManager(&manager); simulateInitialization(&clipBlendNode, &backendClipBlendNode); @@ -91,16 +140,13 @@ private Q_SLOTS: // THEN QCOMPARE(backendClipBlendNode.isEnabled(), true); QCOMPARE(backendClipBlendNode.peerId(), clipBlendNode.id()); - QCOMPARE(backendClipBlendNode.clipIds().size(), 1); - QCOMPARE(backendClipBlendNode.clipIds().first(), clip.id()); - QCOMPARE(backendClipBlendNode.parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendClipBlendNode.childrenIds().size(), 0); QCOMPARE(backendClipBlendNode.clipBlendNodeManager(), &manager); - QCOMPARE(backendClipBlendNode.blendType(), Qt3DAnimation::Animation::ClipBlendNode::LerpBlendType); + QCOMPARE(backendClipBlendNode.blendType(), ClipBlendNode::LerpBlendType); + QCOMPARE(backendClipBlendNode.clipResults(Qt3DCore::QNodeId()), ClipResults()); } { // WHEN - Qt3DAnimation::Animation::ClipBlendNodeManager manager; + ClipBlendNodeManager manager; TestClipBlendNode backendClipBlendNode; clipBlendNode.setEnabled(false); backendClipBlendNode.setClipBlendNodeManager(&manager); @@ -112,112 +158,152 @@ private Q_SLOTS: } } - void checkSceneChangeEvents() + void checkClipResults_data() { - // GIVEN - TestClipBlendNode backendClipBlendNode; - Qt3DAnimation::Animation::ClipBlendNodeManager manager; - backendClipBlendNode.setClipBlendNodeManager(&manager); + QTest::addColumn<TestClipBlendNode *>("blendNode"); + QTest::addColumn<QVector<int>>("indexes"); + QTest::addColumn<QVector<Qt3DCore::QNodeId>>("animatorIds"); + QTest::addColumn<QVector<ClipResults>>("expectedClipResults"); + + // Single entry { - // WHEN - const bool newValue = false; - const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); - change->setPropertyName("enabled"); - change->setValue(newValue); - backendClipBlendNode.sceneChangeEvent(change); + auto blendNode = new TestClipBlendNode; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ClipResults> expectedClipResults; - // THEN - QCOMPARE(backendClipBlendNode.isEnabled(), newValue); + const auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); + + ClipResults clipResults = { 0.0f, 1.0f, 2.0f }; + for (int i = 0; i < 3; ++i) + clipResults.push_back(float(i)); + expectedClipResults.push_back(clipResults); + + // Set data and indexes + blendNode->setClipResults(animatorId, clipResults); + QVector<int> indexes = QVector<int>() << 0; + + QTest::newRow("single entry") + << blendNode << indexes << animatorIds << expectedClipResults; } + + // No data { - // WHEN - Qt3DAnimation::QAnimationClip clip; - // To geneate the type_info in the QNodePrivate of clip - Qt3DCore::QNodeCreatedChangeGenerator generator(&clip); + auto blendNode = new TestClipBlendNode; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ClipResults> expectedClipResults; - const auto addedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &clip); - backendClipBlendNode.sceneChangeEvent(addedChange); + auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); - // THEN - QCOMPARE(backendClipBlendNode.clipIds().size(), 1); - QCOMPARE(backendClipBlendNode.clipIds().first(), clip.id()); + ClipResults clipResults; + expectedClipResults.push_back(clipResults); - // WHEN - const auto removedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &clip); - backendClipBlendNode.sceneChangeEvent(removedChange); + // Don't set any data + QVector<int> indexes = QVector<int>() << 0; - // THEN - QCOMPARE(backendClipBlendNode.clipIds().size(), 0); + QTest::newRow("no entries") + << blendNode << indexes << animatorIds << expectedClipResults; } + + // Multiple entries, ordered { - // WHEN - Qt3DAnimation::QLerpBlend clipBlendChild; - // Will be destroyed when manager is destroyed - TestClipBlendNode *backenChildClipBlendNode = new TestClipBlendNode(); - backendClipBlendNode.setClipBlendNodeManager(&manager); - manager.appendNode(clipBlendChild.id(), backenChildClipBlendNode); + auto blendNode = new TestClipBlendNode; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ClipResults> expectedClipResults; - // To geneate the type_info in the QNodePrivate of clipBlendChild - Qt3DCore::QNodeCreatedChangeGenerator generator(&clipBlendChild); - const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &clipBlendChild); - backendClipBlendNode.sceneChangeEvent(addChange); + const int animatorCount = 10; + for (int j = 0; j < animatorCount; ++j) { + auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); - // THEN - QCOMPARE(backendClipBlendNode.childrenIds().size(), 1); - QCOMPARE(backendClipBlendNode.childrenIds().first(), clipBlendChild.id()); + ClipResults clipResults; + for (int i = 0; i < j + 5; ++i) + clipResults.push_back(float(i + j)); + expectedClipResults.push_back(clipResults); - // WHEN - const auto removedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &clipBlendChild); - backendClipBlendNode.sceneChangeEvent(removedChange); + blendNode->setClipResults(animatorId, clipResults); + } - // THEN - QCOMPARE(backendClipBlendNode.childrenIds().size(), 0); + QVector<int> indexes(animatorCount); + std::iota(indexes.begin(), indexes.end(), 0); + + QTest::newRow("multiple entries, ordered") + << blendNode << indexes << animatorIds << expectedClipResults; + } + + // Multiple entries, unordered + { + auto blendNode = new TestClipBlendNode; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ClipResults> expectedClipResults; + + const int animatorCount = 10; + for (int j = 0; j < animatorCount; ++j) { + auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); + + ClipResults clipResults; + for (int i = 0; i < j + 5; ++i) + clipResults.push_back(float(i + j)); + expectedClipResults.push_back(clipResults); + + blendNode->setClipResults(animatorId, clipResults); + } + + // Shuffle the animatorIds to randomise the lookups + QVector<int> indexes(animatorCount); + std::iota(indexes.begin(), indexes.end(), 0); + std::random_device rd; + std::mt19937 generator(rd()); + std::shuffle(indexes.begin(), indexes.end(), generator); + + QTest::newRow("multiple entries, unordered") + << blendNode << indexes << animatorIds << expectedClipResults; } } - void checkParentInitialization() + void checkClipResults() { // GIVEN - TestClipBlendNode *backendClipBlendNode = new TestClipBlendNode(); - TestClipBlendNode *backendChildClipBlendNode = new TestClipBlendNode(); - Qt3DAnimation::QLerpBlend clipBlendParent; - Qt3DAnimation::QLerpBlend childClipBlend(&clipBlendParent); - Qt3DAnimation::Animation::ClipBlendNodeManager manager; - backendClipBlendNode->setClipBlendNodeManager(&manager); - backendChildClipBlendNode->setClipBlendNodeManager(&manager); + QFETCH(TestClipBlendNode *, blendNode); + QFETCH(QVector<int>, indexes); + QFETCH(QVector<Qt3DCore::QNodeId>, animatorIds); + QFETCH(QVector<ClipResults>, expectedClipResults); - // THEN - QCOMPARE(backendClipBlendNode->parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendClipBlendNode->childrenIds().size(), 0); - QCOMPARE(backendChildClipBlendNode->parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendChildClipBlendNode->childrenIds().size(), 0); + for (int i = 0; i < indexes.size(); ++i) { + // WHEN + const int index = indexes[i]; + const ClipResults actualClipResults = blendNode->clipResults(animatorIds[index]); - // WHEN - manager.appendNode(clipBlendParent.id(), backendClipBlendNode); - manager.appendNode(childClipBlend.id(), backendChildClipBlendNode); - simulateInitialization(&clipBlendParent, backendClipBlendNode); - simulateInitialization(&childClipBlend, backendChildClipBlendNode); + // THEN + QCOMPARE(actualClipResults.size(), expectedClipResults[index].size()); + for (int j = 0; j < actualClipResults.size(); ++j) + QCOMPARE(actualClipResults[j], expectedClipResults[index][j]); + } - // THEN - QCOMPARE(backendClipBlendNode->parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendClipBlendNode->childrenIds().size(), 1); - QCOMPARE(backendClipBlendNode->childrenIds().first(), childClipBlend.id()); - QCOMPARE(backendChildClipBlendNode->parentId(), clipBlendParent.id()); - QCOMPARE(backendChildClipBlendNode->childrenIds().size(), 0); + delete blendNode; + } + + void checkPerformBlend() + { + // GIVEN + auto handler = new Handler(); + ClipResults expectedResults = { 1.0f, 2.0f, 3.0f }; + auto blendNode = createTestClipBlendNode(handler, expectedResults); + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); // WHEN - // To geneate the type_info in the QNodePrivate of clipBlendChild - Qt3DCore::QNodeCreatedChangeGenerator generator(&childClipBlend); - const auto removedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &childClipBlend); - backendClipBlendNode->sceneChangeEvent(removedChange); + blendNode->blend(animator->peerId()); // THEN - QCOMPARE(backendClipBlendNode->parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendClipBlendNode->childrenIds().size(), 0); - QCOMPARE(backendChildClipBlendNode->parentId(), Qt3DCore::QNodeId()); - QCOMPARE(backendChildClipBlendNode->childrenIds().size(), 0); + const ClipResults actualResults = blendNode->clipResults(animator->peerId()); + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); } - }; QTEST_MAIN(tst_ClipBlendNode) diff --git a/tests/auto/animation/clipblendnodemanager/tst_clipblendnodemanager.cpp b/tests/auto/animation/clipblendnodemanager/tst_clipblendnodemanager.cpp index 2cf549f7e..7bcef28ae 100644 --- a/tests/auto/animation/clipblendnodemanager/tst_clipblendnodemanager.cpp +++ b/tests/auto/animation/clipblendnodemanager/tst_clipblendnodemanager.cpp @@ -48,6 +48,24 @@ public: { deadCount += 1; } + + inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE + { + return currentDependencyIds(); + } + + QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_FINAL + { + return QVector<Qt3DCore::QNodeId>(); + } + + double duration() const Q_DECL_FINAL { return 0.0f; } + +protected: + Qt3DAnimation::Animation::ClipResults doBlend(const QVector<Qt3DAnimation::Animation::ClipResults> &) const Q_DECL_FINAL + { + return Qt3DAnimation::Animation::ClipResults(); + } }; } // anonymous diff --git a/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp b/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp index 6c6723920..3f705e713 100644 --- a/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp +++ b/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp @@ -31,8 +31,8 @@ #include <QSignalSpy> #include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/private/clipblendnodevisitor_p.h> -#include <Qt3DAnimation/private/lerpblend_p.h> -#include <Qt3DAnimation/qlerpblend.h> +#include <Qt3DAnimation/private/lerpclipblend_p.h> +#include <Qt3DAnimation/qlerpclipblend.h> #include "qbackendnodetester.h" class tst_ClipBlendNodeVisitor : public Qt3DCore::QBackendNodeTester @@ -43,17 +43,21 @@ private Q_SLOTS: void checkVisitAllNodes() { // GIVEN - Qt3DAnimation::QLerpBlend rootBlendNode; - Qt3DAnimation::QLerpBlend childBlendNode1(&rootBlendNode); - Qt3DAnimation::QLerpBlend childBlendNode2(&rootBlendNode); - Qt3DAnimation::QLerpBlend childBlendNode11(&childBlendNode1); - Qt3DAnimation::QLerpBlend childBlendNode12(&childBlendNode1); - - Qt3DAnimation::Animation::LerpBlend *backendRootBlendNode = new Qt3DAnimation::Animation::LerpBlend(); - Qt3DAnimation::Animation::LerpBlend *backendChildBlendNode1 = new Qt3DAnimation::Animation::LerpBlend(); - Qt3DAnimation::Animation::LerpBlend *backendChildBlendNode2 = new Qt3DAnimation::Animation::LerpBlend(); - Qt3DAnimation::Animation::LerpBlend *backendChildBlendNode11 = new Qt3DAnimation::Animation::LerpBlend(); - Qt3DAnimation::Animation::LerpBlend *backendChildBlendNode12 = new Qt3DAnimation::Animation::LerpBlend(); + Qt3DAnimation::QLerpClipBlend rootBlendNode; + Qt3DAnimation::QLerpClipBlend childBlendNode1(&rootBlendNode); + Qt3DAnimation::QLerpClipBlend childBlendNode2(&rootBlendNode); + rootBlendNode.setStartClip(&childBlendNode1); + rootBlendNode.setEndClip(&childBlendNode2); + Qt3DAnimation::QLerpClipBlend childBlendNode11(&childBlendNode1); + Qt3DAnimation::QLerpClipBlend childBlendNode12(&childBlendNode1); + childBlendNode1.setStartClip(&childBlendNode11); + childBlendNode1.setEndClip(&childBlendNode12); + + Qt3DAnimation::Animation::LerpClipBlend *backendRootBlendNode = new Qt3DAnimation::Animation::LerpClipBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendChildBlendNode1 = new Qt3DAnimation::Animation::LerpClipBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendChildBlendNode2 = new Qt3DAnimation::Animation::LerpClipBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendChildBlendNode11 = new Qt3DAnimation::Animation::LerpClipBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendChildBlendNode12 = new Qt3DAnimation::Animation::LerpClipBlend(); Qt3DAnimation::Animation::ClipBlendNodeManager manager; backendRootBlendNode->setClipBlendNodeManager(&manager); @@ -76,30 +80,26 @@ private Q_SLOTS: simulateInitialization(&childBlendNode12, backendChildBlendNode12); // THEN - QVERIFY(backendRootBlendNode->parentId().isNull()); - QCOMPARE(backendRootBlendNode->childrenIds().size(), 2); - QCOMPARE(backendChildBlendNode1->parentId(), rootBlendNode.id()); - QCOMPARE(backendChildBlendNode1->childrenIds().size(), 2); - QCOMPARE(backendChildBlendNode2->parentId(), rootBlendNode.id()); - QCOMPARE(backendChildBlendNode2->childrenIds().size(), 0); - QCOMPARE(backendChildBlendNode11->parentId(), childBlendNode1.id()); - QCOMPARE(backendChildBlendNode11->childrenIds().size(), 0); - QCOMPARE(backendChildBlendNode12->parentId(), childBlendNode1.id()); - QCOMPARE(backendChildBlendNode12->childrenIds().size(), 0); + QCOMPARE(backendRootBlendNode->allDependencyIds().size(), 2); + QCOMPARE(backendChildBlendNode1->allDependencyIds().size(), 2); + QCOMPARE(backendChildBlendNode2->allDependencyIds().size(), 2); + QCOMPARE(backendChildBlendNode11->allDependencyIds().size(), 2); + QCOMPARE(backendChildBlendNode12->allDependencyIds().size(), 2); // WHEN int i = 0; + // Note: post-order traversal auto childCounter = [&] (Qt3DAnimation::Animation::ClipBlendNode *node) { if (i == 0) - QCOMPARE(node, backendRootBlendNode); + QCOMPARE(node, backendChildBlendNode11); else if (i == 1) - QCOMPARE(node, backendChildBlendNode1); + QCOMPARE(node, backendChildBlendNode12); else if (i == 2) - QCOMPARE(node, backendChildBlendNode11); + QCOMPARE(node, backendChildBlendNode1); else if (i == 3) - QCOMPARE(node, backendChildBlendNode12); - else if (i == 4) QCOMPARE(node, backendChildBlendNode2); + else if (i == 4) + QCOMPARE(node, backendRootBlendNode); ++i; }; @@ -111,9 +111,9 @@ private Q_SLOTS: void checkDoesntCrashIfRootNodeIsNotFound() { // GIVEN - Qt3DAnimation::QLerpBlend rootBlendNode; + Qt3DAnimation::QLerpClipBlend rootBlendNode; - Qt3DAnimation::Animation::LerpBlend *backendRootBlendNode = new Qt3DAnimation::Animation::LerpBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendRootBlendNode = new Qt3DAnimation::Animation::LerpClipBlend(); Qt3DAnimation::Animation::ClipBlendNodeManager manager; backendRootBlendNode->setClipBlendNodeManager(&manager); @@ -124,8 +124,7 @@ private Q_SLOTS: simulateInitialization(&rootBlendNode, backendRootBlendNode); // THEN - QVERIFY(backendRootBlendNode->parentId().isNull()); - QCOMPARE(backendRootBlendNode->childrenIds().size(), 0); + QCOMPARE(backendRootBlendNode->allDependencyIds().size(), 2); // WHEN auto childCounter = [] (Qt3DAnimation::Animation::ClipBlendNode *) {}; @@ -138,13 +137,15 @@ private Q_SLOTS: void checkDoesntCrashIfChildNodeIsNotFound() { // GIVEN - Qt3DAnimation::QLerpBlend rootBlendNode; - Qt3DAnimation::QLerpBlend childBlendNode1(&rootBlendNode); - Qt3DAnimation::QLerpBlend childBlendNode2(&rootBlendNode); + Qt3DAnimation::QLerpClipBlend rootBlendNode; + Qt3DAnimation::QLerpClipBlend childBlendNode1(&rootBlendNode); + Qt3DAnimation::QLerpClipBlend childBlendNode2(&rootBlendNode); + rootBlendNode.setStartClip(&childBlendNode1); + rootBlendNode.setEndClip(&childBlendNode2); - Qt3DAnimation::Animation::LerpBlend *backendRootBlendNode = new Qt3DAnimation::Animation::LerpBlend(); - Qt3DAnimation::Animation::LerpBlend *backendChildBlendNode1 = new Qt3DAnimation::Animation::LerpBlend(); - Qt3DAnimation::Animation::LerpBlend *backendChildBlendNode2 = new Qt3DAnimation::Animation::LerpBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendRootBlendNode = new Qt3DAnimation::Animation::LerpClipBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendChildBlendNode1 = new Qt3DAnimation::Animation::LerpClipBlend(); + Qt3DAnimation::Animation::LerpClipBlend *backendChildBlendNode2 = new Qt3DAnimation::Animation::LerpClipBlend(); Qt3DAnimation::Animation::ClipBlendNodeManager manager; backendRootBlendNode->setClipBlendNodeManager(&manager); @@ -163,12 +164,9 @@ private Q_SLOTS: simulateInitialization(&childBlendNode2, backendChildBlendNode2); // THEN - QVERIFY(backendRootBlendNode->parentId().isNull()); - QCOMPARE(backendRootBlendNode->childrenIds().size(), 2); - QCOMPARE(backendChildBlendNode1->parentId(), rootBlendNode.id()); - QCOMPARE(backendChildBlendNode1->childrenIds().size(), 0); - QCOMPARE(backendChildBlendNode2->parentId(), rootBlendNode.id()); - QCOMPARE(backendChildBlendNode2->childrenIds().size(), 0); + QCOMPARE(backendRootBlendNode->allDependencyIds().size(), 2); + QCOMPARE(backendChildBlendNode1->allDependencyIds().size(), 2); + QCOMPARE(backendChildBlendNode2->allDependencyIds().size(), 2); // WHEN int i = 0; diff --git a/tests/auto/animation/lerpblend/lerpblend.pro b/tests/auto/animation/clipblendvalue/clipblendvalue.pro index bc2cc383b..ff50f0bbd 100644 --- a/tests/auto/animation/lerpblend/lerpblend.pro +++ b/tests/auto/animation/clipblendvalue/clipblendvalue.pro @@ -1,11 +1,12 @@ TEMPLATE = app -TARGET = tst_lerpblend +TARGET = tst_clipblendvalue QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib CONFIG += testcase -SOURCES += tst_lerpblend.cpp +SOURCES += \ + tst_clipblendvalue.cpp include(../../core/common/common.pri) diff --git a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp new file mode 100644 index 000000000..6fe2846b8 --- /dev/null +++ b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp @@ -0,0 +1,299 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qclipblendvalue.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qclipblendvalue_p.h> +#include <Qt3DAnimation/private/clipblendvalue_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" + +#include <random> +#include <algorithm> + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(ClipBlendValue *) + +class tst_ClipBlendValue : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +public: + AnimationClip *createAnimationClipLoader(Handler *handler, + double duration) + { + auto clipId = Qt3DCore::QNodeId::createId(); + AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(clipId); + setPeerId(clip, clipId); + clip->setDuration(duration); + return clip; + } + +private Q_SLOTS: + void checkInitialState() + { + // GIVEN + ClipBlendValue backendClipBlendValue; + + // THEN + QCOMPARE(backendClipBlendValue.isEnabled(), false); + QVERIFY(backendClipBlendValue.peerId().isNull()); + QCOMPARE(backendClipBlendValue.clipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendClipBlendValue.blendType(), ClipBlendNode::ValueType); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DAnimation::QClipBlendValue clipBlendValue; + Qt3DAnimation::QAnimationClipLoader clip; + clipBlendValue.setClip(&clip); + + { + // WHEN + ClipBlendValue backendClipBlendValue; + simulateInitialization(&clipBlendValue, &backendClipBlendValue); + + // THEN + QCOMPARE(backendClipBlendValue.isEnabled(), true); + QCOMPARE(backendClipBlendValue.peerId(), clipBlendValue.id()); + QCOMPARE(backendClipBlendValue.clipId(), clip.id()); + } + { + // WHEN + ClipBlendValue backendClipBlendValue; + clipBlendValue.setEnabled(false); + simulateInitialization(&clipBlendValue, &backendClipBlendValue); + + // THEN + QCOMPARE(backendClipBlendValue.peerId(), clipBlendValue.id()); + QCOMPARE(backendClipBlendValue.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + ClipBlendValue backendClipBlendValue; + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendClipBlendValue.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendClipBlendValue.isEnabled(), newValue); + } + { + // WHEN + const Qt3DAnimation::QAnimationClipLoader newValue; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("clip"); + change->setValue(QVariant::fromValue(newValue.id())); + backendClipBlendValue.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendClipBlendValue.clipId(), newValue.id()); + } + } + + void checkDependencyIds() + { + // GIVEN + ClipBlendValue clipNode; + auto clipId = Qt3DCore::QNodeId::createId(); + + // WHEN + clipNode.setClipId(clipId); + QVector<Qt3DCore::QNodeId> actualIds = clipNode.currentDependencyIds(); + + // THEN + QCOMPARE(actualIds.size(), 1); + QCOMPARE(actualIds[0], clipId); + + // WHEN + auto anotherClipId = Qt3DCore::QNodeId::createId(); + clipNode.setClipId(anotherClipId); + actualIds = clipNode.currentDependencyIds(); + + // THEN + QCOMPARE(actualIds.size(), 1); + QCOMPARE(actualIds[0], anotherClipId); + } + + void checkDuration() + { + // GIVEN + auto handler = new Handler(); + const double expectedDuration = 123.5; + auto clip = createAnimationClipLoader(handler, expectedDuration); + ClipBlendValue clipNode; + clipNode.setHandler(handler); + clipNode.setClipBlendNodeManager(handler->clipBlendNodeManager()); + clipNode.setClipId(clip->peerId()); + + // WHEN + double actualDuration = clipNode.duration(); + + // THEN + QCOMPARE(actualDuration, expectedDuration); + } + + void checkFormatIndices_data() + { + QTest::addColumn<ClipBlendValue *>("blendNode"); + QTest::addColumn<QVector<int>>("indexes"); + QTest::addColumn<QVector<Qt3DCore::QNodeId>>("animatorIds"); + QTest::addColumn<QVector<ComponentIndices>>("expectedFormatIndices"); + + // Single entry + { + auto blendNode = new ClipBlendValue; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ComponentIndices> expectedFormatIndices; + + const auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); + + ComponentIndices formatIndices = { 0, 1, 2 }; + expectedFormatIndices.push_back(formatIndices); + + // Set data and indexes + blendNode->setFormatIndices(animatorId, formatIndices); + QVector<int> indexes = QVector<int>() << 0; + + QTest::newRow("single entry") + << blendNode << indexes << animatorIds << expectedFormatIndices; + } + + // No data + { + auto blendNode = new ClipBlendValue; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ComponentIndices> expectedFormatIndices; + + auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); + + ComponentIndices formatIndices; + expectedFormatIndices.push_back(formatIndices); + + // Don't set any data + QVector<int> indexes = QVector<int>() << 0; + + QTest::newRow("no entries") + << blendNode << indexes << animatorIds << expectedFormatIndices; + } + + // Multiple entries, ordered + { + auto blendNode = new ClipBlendValue; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ComponentIndices> expectedFormatIndices; + + const int animatorCount = 10; + for (int j = 0; j < animatorCount; ++j) { + auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); + + ComponentIndices formatIndices; + for (int i = 0; i < j + 5; ++i) + formatIndices.push_back(i + j); + expectedFormatIndices.push_back(formatIndices); + + blendNode->setFormatIndices(animatorId, formatIndices); + } + + QVector<int> indexes(animatorCount); + std::iota(indexes.begin(), indexes.end(), 0); + + QTest::newRow("multiple entries, ordered") + << blendNode << indexes << animatorIds << expectedFormatIndices; + } + + // Multiple entries, unordered + { + auto blendNode = new ClipBlendValue; + QVector<Qt3DCore::QNodeId> animatorIds; + QVector<ComponentIndices> expectedFormatIndices; + + const int animatorCount = 10; + for (int j = 0; j < animatorCount; ++j) { + auto animatorId = Qt3DCore::QNodeId::createId(); + animatorIds.push_back(animatorId); + + ComponentIndices formatIndices; + for (int i = 0; i < j + 5; ++i) + formatIndices.push_back(i + j); + expectedFormatIndices.push_back(formatIndices); + + blendNode->setFormatIndices(animatorId, formatIndices); + } + + // Shuffle the animatorIds to randomise the lookups + QVector<int> indexes(animatorCount); + std::iota(indexes.begin(), indexes.end(), 0); + std::random_device rd; + std::mt19937 generator(rd()); + std::shuffle(indexes.begin(), indexes.end(), generator); + + QTest::newRow("multiple entries, unordered") + << blendNode << indexes << animatorIds << expectedFormatIndices; + } + } + + void checkFormatIndices() + { + // GIVEN + QFETCH(ClipBlendValue *, blendNode); + QFETCH(QVector<int>, indexes); + QFETCH(QVector<Qt3DCore::QNodeId>, animatorIds); + QFETCH(QVector<ComponentIndices>, expectedFormatIndices); + + for (int i = 0; i < indexes.size(); ++i) { + // WHEN + const int index = indexes[i]; + const ComponentIndices actualFormatIndices = blendNode->formatIndices(animatorIds[index]); + + // THEN + QCOMPARE(actualFormatIndices.size(), expectedFormatIndices[index].size()); + for (int j = 0; j < actualFormatIndices.size(); ++j) + QCOMPARE(actualFormatIndices[j], expectedFormatIndices[index][j]); + } + + delete blendNode; + } +}; + +QTEST_MAIN(tst_ClipBlendValue) + +#include "tst_clipblendvalue.moc" diff --git a/tests/auto/animation/conductedclipanimator/conductedclipanimator.pro b/tests/auto/animation/conductedclipanimator/conductedclipanimator.pro deleted file mode 100644 index 61a1106d9..000000000 --- a/tests/auto/animation/conductedclipanimator/conductedclipanimator.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_conductedclipanimator - -QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib - -CONFIG += testcase - -SOURCES += \ - tst_conductedclipanimator.cpp - -include(../../core/common/common.pri) diff --git a/tests/auto/animation/conductedclipanimator/tst_conductedclipanimator.cpp b/tests/auto/animation/conductedclipanimator/tst_conductedclipanimator.cpp deleted file mode 100644 index 8536ab7e7..000000000 --- a/tests/auto/animation/conductedclipanimator/tst_conductedclipanimator.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 <QtTest/QTest> -#include <Qt3DAnimation/private/conductedclipanimator_p.h> -#include <Qt3DAnimation/qanimationclip.h> -#include <Qt3DAnimation/qconductedclipanimator.h> -#include <Qt3DCore/private/qnode_p.h> -#include <Qt3DCore/private/qscene_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/private/qbackendnode_p.h> -#include <qbackendnodetester.h> -#include <testpostmanarbiter.h> - -class tst_ConductedClipAnimator: public Qt3DCore::QBackendNodeTester -{ - Q_OBJECT - -private Q_SLOTS: - void checkPeerPropertyMirroring() - { - // GIVEN - Qt3DAnimation::Animation::ConductedClipAnimator backendAnimator; - Qt3DAnimation::QConductedClipAnimator animator; - - // WHEN - simulateInitialization(&animator, &backendAnimator); - - // THEN - QCOMPARE(backendAnimator.peerId(), animator.id()); - QCOMPARE(backendAnimator.isEnabled(), animator.isEnabled()); - } - - void checkInitialAndCleanedUpState() - { - // GIVEN - Qt3DAnimation::Animation::ConductedClipAnimator backendAnimator; - - // THEN - QVERIFY(backendAnimator.peerId().isNull()); - QCOMPARE(backendAnimator.isEnabled(), false); - - // GIVEN - Qt3DAnimation::QConductedClipAnimator animator; - - // WHEN - simulateInitialization(&animator, &backendAnimator); - backendAnimator.cleanup(); - - // THEN - QCOMPARE(backendAnimator.isEnabled(), false); - } - - void checkPropertyChanges() - { - // GIVEN - Qt3DAnimation::Animation::ConductedClipAnimator backendAnimator; - Qt3DCore::QPropertyUpdatedChangePtr updateChange; - - // WHEN - updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - updateChange->setPropertyName("enabled"); - updateChange->setValue(true); - backendAnimator.sceneChangeEvent(updateChange); - - // THEN - QCOMPARE(backendAnimator.isEnabled(), true); - } -}; - -QTEST_APPLESS_MAIN(tst_ConductedClipAnimator) - -#include "tst_conductedclipanimator.moc" diff --git a/tests/auto/animation/fcurve/tst_fcurve.cpp b/tests/auto/animation/fcurve/tst_fcurve.cpp index 8cd8b9537..e3e8db50d 100644 --- a/tests/auto/animation/fcurve/tst_fcurve.cpp +++ b/tests/auto/animation/fcurve/tst_fcurve.cpp @@ -29,6 +29,7 @@ #include <QtTest/QTest> #include <private/fcurve_p.h> +using namespace Qt3DAnimation; using namespace Qt3DAnimation::Animation; class tst_FCurve : public QObject @@ -53,7 +54,7 @@ private Q_SLOTS: FCurve fcurve; // WHEN - const Keyframe kf0{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, Keyframe::Bezier}; + const Keyframe kf0{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, QKeyFrame::BezierInterpolation}; fcurve.appendKeyframe(0.0f, kf0); // THEN @@ -62,7 +63,7 @@ private Q_SLOTS: QCOMPARE(fcurve.endTime(), 0.0f); // WHEN - const Keyframe kf1{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, Keyframe::Bezier}; + const Keyframe kf1{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, QKeyFrame::BezierInterpolation}; fcurve.appendKeyframe(50.0f, kf1); // THEN @@ -77,8 +78,8 @@ private Q_SLOTS: { // GIVEN FCurve fcurve; - fcurve.appendKeyframe(0.0f, Keyframe{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, Keyframe::Bezier}); - fcurve.appendKeyframe(50.0f, Keyframe{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, Keyframe::Bezier}); + fcurve.appendKeyframe(0.0f, Keyframe{0.0f, {-5.0f, 0.0f}, {5.0f, 0.0f}, QKeyFrame::BezierInterpolation}); + fcurve.appendKeyframe(50.0f, Keyframe{5.0f, {45.0f, 5.0f}, {55.0f, 5.0f}, QKeyFrame::BezierInterpolation}); // WHEN fcurve.clearKeyframes(); diff --git a/tests/auto/animation/lerpblend/tst_lerpblend.cpp b/tests/auto/animation/lerpblend/tst_lerpblend.cpp deleted file mode 100644 index 9d758e7c4..000000000 --- a/tests/auto/animation/lerpblend/tst_lerpblend.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> -** 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 <QtTest/QTest> -#include <Qt3DAnimation/qlerpblend.h> -#include <Qt3DAnimation/qanimationclip.h> -#include <Qt3DAnimation/private/qlerpblend_p.h> -#include <Qt3DAnimation/private/lerpblend_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include "qbackendnodetester.h" - -class tst_LerpBlend : public Qt3DCore::QBackendNodeTester -{ - Q_OBJECT - -private Q_SLOTS: - - void checkInitialState() - { - // GIVEN - Qt3DAnimation::Animation::LerpBlend backendLerpBlend; - - // THEN - QCOMPARE(backendLerpBlend.isEnabled(), false); - QVERIFY(backendLerpBlend.peerId().isNull()); - QCOMPARE(backendLerpBlend.blendFactor(), 0.0f); - } - - void checkInitializeFromPeer() - { - // GIVEN - Qt3DAnimation::QLerpBlend lerpBlend; - Qt3DAnimation::QAnimationClip clip; - lerpBlend.setBlendFactor(0.8f); - lerpBlend.addClip(&clip); - - { - // WHEN - Qt3DAnimation::Animation::LerpBlend backendLerpBlend; - simulateInitialization(&lerpBlend, &backendLerpBlend); - - // THEN - QCOMPARE(backendLerpBlend.isEnabled(), true); - QCOMPARE(backendLerpBlend.peerId(), lerpBlend.id()); - QCOMPARE(backendLerpBlend.blendFactor(), 0.8f); - QCOMPARE(backendLerpBlend.clipIds().size(), 1); - QCOMPARE(backendLerpBlend.clipIds().first(), clip.id()); - } - { - // WHEN - Qt3DAnimation::Animation::LerpBlend backendLerpBlend; - lerpBlend.setEnabled(false); - simulateInitialization(&lerpBlend, &backendLerpBlend); - - // THEN - QCOMPARE(backendLerpBlend.peerId(), lerpBlend.id()); - QCOMPARE(backendLerpBlend.isEnabled(), false); - } - } - - void checkSceneChangeEvents() - { - // GIVEN - Qt3DAnimation::Animation::LerpBlend backendLerpBlend; - { - // WHEN - const bool newValue = false; - const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); - change->setPropertyName("enabled"); - change->setValue(newValue); - backendLerpBlend.sceneChangeEvent(change); - - // THEN - QCOMPARE(backendLerpBlend.isEnabled(), newValue); - } - { - // WHEN - const float newValue = 0.883f; - const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); - change->setPropertyName("blendFactor"); - change->setValue(QVariant::fromValue(newValue)); - backendLerpBlend.sceneChangeEvent(change); - - // THEN - QCOMPARE(backendLerpBlend.blendFactor(), newValue); - } - } - -}; - -QTEST_MAIN(tst_LerpBlend) - -#include "tst_lerpblend.moc" diff --git a/tests/auto/animation/qlerpblend/qlerpblend.pro b/tests/auto/animation/lerpclipblend/lerpclipblend.pro index f5bdc848f..e5447cccf 100644 --- a/tests/auto/animation/qlerpblend/qlerpblend.pro +++ b/tests/auto/animation/lerpclipblend/lerpclipblend.pro @@ -1,11 +1,11 @@ TEMPLATE = app -TARGET = tst_qlerpblend +TARGET = tst_lerpclipblend QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib CONFIG += testcase -SOURCES += tst_qlerpblend.cpp +SOURCES += tst_lerpclipblend.cpp include(../../core/common/common.pri) diff --git a/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp b/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp new file mode 100644 index 000000000..003b1ef53 --- /dev/null +++ b/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qlerpclipblend.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qlerpclipblend_p.h> +#include <Qt3DAnimation/private/lerpclipblend_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(Handler *) +Q_DECLARE_METATYPE(LerpClipBlend *) + +namespace { + +class TestClipBlendNode : public ClipBlendNode +{ +public: + TestClipBlendNode(double duration) + : ClipBlendNode(ClipBlendNode::LerpBlendType) + , m_duration(duration) + {} + + inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE + { + return currentDependencyIds(); + } + + QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_FINAL + { + return QVector<Qt3DCore::QNodeId>(); + } + + using ClipBlendNode::setClipResults; + + double duration() const Q_DECL_FINAL { return m_duration; } + +protected: + ClipResults doBlend(const QVector<ClipResults> &) const Q_DECL_FINAL { return ClipResults(); } + +private: + double m_duration; +}; + +} // anonymous + +class tst_LerpClipBlend : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +public: + TestClipBlendNode *createTestBlendNode(Handler *handler, + double duration) + { + auto id = Qt3DCore::QNodeId::createId(); + TestClipBlendNode *node = new TestClipBlendNode(duration); + setPeerId(node, id); + node->setHandler(handler); + node->setClipBlendNodeManager(handler->clipBlendNodeManager()); + handler->clipBlendNodeManager()->appendNode(id, node); + return node; + } + + LerpClipBlend *createLerpClipBlendNode(Handler *handler, const float &blendFactor) + { + auto id = Qt3DCore::QNodeId::createId(); + LerpClipBlend *node = new LerpClipBlend(); + node->setBlendFactor(blendFactor); + setPeerId(node, id); + node->setHandler(handler); + node->setClipBlendNodeManager(handler->clipBlendNodeManager()); + handler->clipBlendNodeManager()->appendNode(id, node); + return node; + } + + BlendedClipAnimator *createBlendedClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + BlendedClipAnimator *animator = handler->blendedClipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + LerpClipBlend backendLerpBlend; + + // THEN + QCOMPARE(backendLerpBlend.isEnabled(), false); + QVERIFY(backendLerpBlend.peerId().isNull()); + QCOMPARE(backendLerpBlend.blendFactor(), 0.0f); + QCOMPARE(backendLerpBlend.blendType(), ClipBlendNode::LerpBlendType); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DAnimation::QLerpClipBlend lerpBlend; + Qt3DAnimation::QAnimationClipLoader clip; + lerpBlend.setBlendFactor(0.8f); + + { + // WHEN + LerpClipBlend backendLerpBlend; + simulateInitialization(&lerpBlend, &backendLerpBlend); + + // THEN + QCOMPARE(backendLerpBlend.isEnabled(), true); + QCOMPARE(backendLerpBlend.peerId(), lerpBlend.id()); + QCOMPARE(backendLerpBlend.blendFactor(), 0.8f); + } + { + // WHEN + LerpClipBlend backendLerpBlend; + lerpBlend.setEnabled(false); + simulateInitialization(&lerpBlend, &backendLerpBlend); + + // THEN + QCOMPARE(backendLerpBlend.peerId(), lerpBlend.id()); + QCOMPARE(backendLerpBlend.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + LerpClipBlend backendLerpBlend; + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendLerpBlend.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendLerpBlend.isEnabled(), newValue); + } + { + // WHEN + const float newValue = 0.883f; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("blendFactor"); + change->setValue(QVariant::fromValue(newValue)); + backendLerpBlend.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendLerpBlend.blendFactor(), newValue); + } + } + + void checkDependencyIds() + { + // GIVEN + LerpClipBlend lerpBlend; + auto startClipId = Qt3DCore::QNodeId::createId(); + auto endClipId = Qt3DCore::QNodeId::createId(); + + // WHEN + lerpBlend.setStartClipId(startClipId); + lerpBlend.setEndClipId(endClipId); + QVector<Qt3DCore::QNodeId> actualIds = lerpBlend.currentDependencyIds(); + + // THEN + QCOMPARE(actualIds.size(), 2); + QCOMPARE(actualIds[0], startClipId); + QCOMPARE(actualIds[1], endClipId); + + // WHEN + auto anotherEndClipId = Qt3DCore::QNodeId::createId(); + lerpBlend.setEndClipId(anotherEndClipId); + actualIds = lerpBlend.currentDependencyIds(); + + // THEN + QCOMPARE(actualIds.size(), 2); + QCOMPARE(actualIds[0], startClipId); + QCOMPARE(actualIds[1], anotherEndClipId); + } + + void checkDuration() + { + // GIVEN + auto handler = new Handler(); + const double startNodeDuration = 10.0; + const double endNodeDuration = 20.0; + const float blendFactor = 0.25f; + const double expectedDuration = 12.5; + + auto startNode = createTestBlendNode(handler, startNodeDuration); + auto endNode = createTestBlendNode(handler, endNodeDuration); + + LerpClipBlend blendNode; + blendNode.setHandler(handler); + blendNode.setClipBlendNodeManager(handler->clipBlendNodeManager()); + blendNode.setStartClipId(startNode->peerId()); + blendNode.setEndClipId(endNode->peerId()); + blendNode.setBlendFactor(blendFactor); + + // WHEN + double actualDuration = blendNode.duration(); + + // THEN + QCOMPARE(actualDuration, expectedDuration); + } + + void checkDoBlend_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<LerpClipBlend *>("blendNode"); + QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); + QTest::addColumn<ClipResults>("expectedResults"); + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto startNode = createTestBlendNode(handler, duration); + startNode->setClipResults(animator->peerId(), { 0.0f, 0.0f, 0.0f }); + auto endNode = createTestBlendNode(handler, duration); + endNode->setClipResults(animator->peerId(), { 1.0f, 1.0f, 1.0f }); + + const float blendFactor = 0.0f; + auto blendNode = createLerpClipBlendNode(handler, blendFactor); + blendNode->setStartClipId(startNode->peerId()); + blendNode->setEndClipId(endNode->peerId()); + blendNode->setBlendFactor(blendFactor); + + ClipResults expectedResults = { 0.0f, 0.0f, 0.0f }; + + QTest::addRow("unit lerp, beta = 0.0") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto startNode = createTestBlendNode(handler, duration); + startNode->setClipResults(animator->peerId(), { 0.0f, 0.0f, 0.0f }); + auto endNode = createTestBlendNode(handler, duration); + endNode->setClipResults(animator->peerId(), { 1.0f, 1.0f, 1.0f }); + + const float blendFactor = 0.5f; + auto blendNode = createLerpClipBlendNode(handler, blendFactor); + blendNode->setStartClipId(startNode->peerId()); + blendNode->setEndClipId(endNode->peerId()); + blendNode->setBlendFactor(blendFactor); + + ClipResults expectedResults = { 0.5f, 0.5f, 0.5f }; + + QTest::addRow("unit lerp, beta = 0.5") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto startNode = createTestBlendNode(handler, duration); + startNode->setClipResults(animator->peerId(), { 0.0f, 0.0f, 0.0f }); + auto endNode = createTestBlendNode(handler, duration); + endNode->setClipResults(animator->peerId(), { 1.0f, 1.0f, 1.0f }); + + const float blendFactor = 1.0f; + auto blendNode = createLerpClipBlendNode(handler, blendFactor); + blendNode->setStartClipId(startNode->peerId()); + blendNode->setEndClipId(endNode->peerId()); + blendNode->setBlendFactor(blendFactor); + + ClipResults expectedResults = { 1.0f, 1.0f, 1.0f }; + + QTest::addRow("unit lerp, beta = 1.0") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + auto startNode = createTestBlendNode(handler, duration); + startNode->setClipResults(animator->peerId(), { 0.0f, 1.0f, 2.0f }); + auto endNode = createTestBlendNode(handler, duration); + endNode->setClipResults(animator->peerId(), { 1.0f, 2.0f, 3.0f }); + + const float blendFactor = 0.5f; + auto blendNode = createLerpClipBlendNode(handler, blendFactor); + blendNode->setStartClipId(startNode->peerId()); + blendNode->setEndClipId(endNode->peerId()); + blendNode->setBlendFactor(blendFactor); + + ClipResults expectedResults = { 0.5f, 1.5f, 2.5f }; + + QTest::addRow("lerp varying data, beta = 0.5") + << handler << blendNode << animator->peerId() << expectedResults; + } + + { + auto handler = new Handler(); + + const qint64 globalStartTimeNS = 0; + const int loopCount = 1; + auto animator = createBlendedClipAnimator(handler, globalStartTimeNS, loopCount); + + const double duration = 1.0; + const int dataCount = 1000; + ClipResults startData(dataCount); + ClipResults endData(dataCount); + ClipResults expectedResults(dataCount); + for (int i = 0; i < dataCount; ++i) { + startData[i] = float(i); + endData[i] = 2.0f * float(i); + expectedResults[i] = 1.5f * float(i); + } + auto startNode = createTestBlendNode(handler, duration); + startNode->setClipResults(animator->peerId(), startData); + auto endNode = createTestBlendNode(handler, duration); + endNode->setClipResults(animator->peerId(), endData); + + const float blendFactor = 0.5f; + auto blendNode = createLerpClipBlendNode(handler, blendFactor); + blendNode->setStartClipId(startNode->peerId()); + blendNode->setEndClipId(endNode->peerId()); + blendNode->setBlendFactor(blendFactor); + + QTest::addRow("lerp lots of data, beta = 0.5") + << handler << blendNode << animator->peerId() << expectedResults; + } + } + + void checkDoBlend() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(LerpClipBlend *, blendNode); + QFETCH(Qt3DCore::QNodeId, animatorId); + QFETCH(ClipResults, expectedResults); + + // WHEN + blendNode->blend(animatorId); + + // THEN + const ClipResults actualResults = blendNode->clipResults(animatorId); + QCOMPARE(actualResults.size(), expectedResults.size()); + for (int i = 0; i < actualResults.size(); ++i) + QCOMPARE(actualResults[i], expectedResults[i]); + + // Cleanup + delete handler; + } +}; + +QTEST_MAIN(tst_LerpClipBlend) + +#include "tst_lerpclipblend.moc" diff --git a/tests/auto/animation/qabstractanimation/qabstractanimation.pro b/tests/auto/animation/qabstractanimation/qabstractanimation.pro new file mode 100644 index 000000000..be37677b6 --- /dev/null +++ b/tests/auto/animation/qabstractanimation/qabstractanimation.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qabstractanimation + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += tst_qabstractanimation.cpp + diff --git a/tests/auto/animation/qabstractanimation/tst_qabstractanimation.cpp b/tests/auto/animation/qabstractanimation/tst_qabstractanimation.cpp new file mode 100644 index 000000000..90349fb28 --- /dev/null +++ b/tests/auto/animation/qabstractanimation/tst_qabstractanimation.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** 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 <QtTest/qtest.h> +#include <Qt3DAnimation/qabstractanimation.h> +#include <Qt3DCore/qnode.h> +#include <qobject.h> +#include <qsignalspy.h> + +#include <private/qabstractanimation_p.h> + +class TestAnimation : public Qt3DAnimation::QAbstractAnimation +{ +public: + explicit TestAnimation(Qt3DCore::QNode *parent = nullptr) + : Qt3DAnimation::QAbstractAnimation( + *new Qt3DAnimation::QAbstractAnimationPrivate( + Qt3DAnimation::QAbstractAnimation::KeyframeAnimation), parent) + { + + } +}; + +class tst_QAbstractAnimation : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + TestAnimation abstractAnimation; + + // THEN + QCOMPARE(abstractAnimation.animationName(), QString()); + QCOMPARE(abstractAnimation.animationType(), + Qt3DAnimation::QAbstractAnimation::KeyframeAnimation); + QCOMPARE(abstractAnimation.position(), 0.0f); + QCOMPARE(abstractAnimation.duration(), 0.0f); + } + + void checkPropertyChanges() + { + // GIVEN + TestAnimation abstractAnimation; + + { + // WHEN + QSignalSpy spy(&abstractAnimation, SIGNAL(animationNameChanged(QString))); + const QString newValue = QString("test"); + abstractAnimation.setAnimationName(newValue); + + // THEN + QCOMPARE(abstractAnimation.animationName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + abstractAnimation.setAnimationName(newValue); + + // THEN + QCOMPARE(abstractAnimation.animationName(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&abstractAnimation, SIGNAL(positionChanged(float))); + const float newValue = 1.0f; + abstractAnimation.setPosition(newValue); + + // THEN + QCOMPARE(abstractAnimation.position(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + abstractAnimation.setPosition(newValue); + + // THEN + QCOMPARE(abstractAnimation.position(), newValue); + QCOMPARE(spy.count(), 0); + + } + } + +}; + +QTEST_APPLESS_MAIN(tst_QAbstractAnimation) + +#include "tst_qabstractanimation.moc" diff --git a/tests/auto/animation/qabstractclipblendnode/tst_qabstractclipblendnode.cpp b/tests/auto/animation/qabstractclipblendnode/tst_qabstractclipblendnode.cpp deleted file mode 100644 index e2d963310..000000000 --- a/tests/auto/animation/qabstractclipblendnode/tst_qabstractclipblendnode.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> -** 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 <QtTest/QTest> -#include <Qt3DAnimation/qabstractclipblendnode.h> -#include <Qt3DAnimation/qanimationclip.h> -#include <QObject> -#include <QSignalSpy> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> -#include <Qt3DCore/qnodecreatedchange.h> -#include "testpostmanarbiter.h" - -namespace { - -class TestClipBlendNode : public Qt3DAnimation::QAbstractClipBlendNode -{ -public: - TestClipBlendNode(Qt3DCore::QNode *parent = nullptr) - : Qt3DAnimation::QAbstractClipBlendNode(parent) - {} - - using Qt3DAnimation::QAbstractClipBlendNode::addClip; - using Qt3DAnimation::QAbstractClipBlendNode::removeClip; -}; - -} - -class tst_QAbstractClipBlendNode : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - - void checkDefaultConstruction() - { - // GIVEN - TestClipBlendNode abstractClipBlendNode; - - // THEN - QCOMPARE(abstractClipBlendNode.clips().size(), 0); - } - - void checkPropertyChanges() - { - // GIVEN - TestClipBlendNode abstractClipBlendNode; - - { - // WHEN - Qt3DAnimation::QAnimationClip newValue; - abstractClipBlendNode.addClip(&newValue); - - // THEN - QCOMPARE(abstractClipBlendNode.clips().size(), 1); - - // WHEN - abstractClipBlendNode.addClip(&newValue); - - // THEN - QCOMPARE(abstractClipBlendNode.clips().size(), 1); - - // WHEN - abstractClipBlendNode.removeClip(&newValue); - - // THEN - QCOMPARE(abstractClipBlendNode.clips().size(), 0); - } - } - - void checkClipBookkeeping() - { - // GIVEN - TestClipBlendNode abstractClipBlendNode; - - { - // WHEN - Qt3DAnimation::QAnimationClip clip; - abstractClipBlendNode.addClip(&clip); - - QCOMPARE(abstractClipBlendNode.clips().size(), 1); - } - - // THEN -> should not crash - QCOMPARE(abstractClipBlendNode.clips().size(), 0); - } - - void checkClipUpdate() - { - // GIVEN - TestArbiter arbiter; - TestClipBlendNode abstractClipBlendNode; - Qt3DAnimation::QAnimationClip clip; - arbiter.setArbiterOnNode(&abstractClipBlendNode); - - { - // WHEN - abstractClipBlendNode.addClip(&clip); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>(); - QCOMPARE(change->propertyName(), "clip"); - QCOMPARE(change->addedNodeId(), clip.id()); - QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded); - - arbiter.events.clear(); - } - - { - // WHEN - abstractClipBlendNode.removeClip(&clip); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>(); - QCOMPARE(change->propertyName(), "clip"); - QCOMPARE(change->removedNodeId(), clip.id()); - QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved); - - arbiter.events.clear(); - } - - } - - void checkParentClipBlendNode() - { - // GIVEN - TestClipBlendNode clipNodeLevel0; - TestClipBlendNode clipNodeLevel1_1(&clipNodeLevel0); - TestClipBlendNode clipNodeLevel1_2(&clipNodeLevel0); - TestClipBlendNode clipNodeLevel2_1(&clipNodeLevel1_1); - Qt3DCore::QNode fakeNodeLevel2_2(&clipNodeLevel1_2); - TestClipBlendNode clipNodeLeve3_1(&fakeNodeLevel2_2); - - // THEN - QVERIFY(clipNodeLevel0.parent() == nullptr); - QCOMPARE(clipNodeLevel1_1.parent(), &clipNodeLevel0); - QCOMPARE(clipNodeLevel1_2.parent(), &clipNodeLevel0); - QCOMPARE(clipNodeLevel2_1.parent(), &clipNodeLevel1_1); - QCOMPARE(fakeNodeLevel2_2.parent(), &clipNodeLevel1_2); - QCOMPARE(clipNodeLeve3_1.parent(), &fakeNodeLevel2_2); - - QVERIFY(clipNodeLevel0.parentClipBlendNode() == nullptr); - QCOMPARE(clipNodeLevel1_1.parentClipBlendNode(), &clipNodeLevel0); - QCOMPARE(clipNodeLevel1_2.parentClipBlendNode(), &clipNodeLevel0); - QCOMPARE(clipNodeLevel2_1.parentClipBlendNode(), &clipNodeLevel1_1); - QCOMPARE(clipNodeLeve3_1.parentClipBlendNode(), &clipNodeLevel1_2); - } -}; - -QTEST_MAIN(tst_QAbstractClipBlendNode) - -#include "tst_qabstractclipblendnode.moc" diff --git a/tests/auto/animation/qadditiveclipblend/qadditiveclipblend.pro b/tests/auto/animation/qadditiveclipblend/qadditiveclipblend.pro new file mode 100644 index 000000000..e5c6797ee --- /dev/null +++ b/tests/auto/animation/qadditiveclipblend/qadditiveclipblend.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qadditiveclipblend + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qadditiveclipblend.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp b/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp new file mode 100644 index 000000000..c1f01394f --- /dev/null +++ b/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qadditiveclipblend.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qadditiveclipblend_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DAnimation/qclipblendnodecreatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +class tst_QAdditiveClipBlend : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QAbstractClipBlendNode*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QAdditiveClipBlend addBlend; + + // THEN + QCOMPARE(addBlend.additiveFactor(), 0.0f); + QCOMPARE(addBlend.baseClip(), static_cast<Qt3DAnimation::QAbstractClipBlendNode *>(nullptr)); + QCOMPARE(addBlend.additiveClip(), static_cast<Qt3DAnimation::QAbstractClipBlendNode *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QAdditiveClipBlend addBlend; + + { + // WHEN + QSignalSpy spy(&addBlend, SIGNAL(additiveFactorChanged(float))); + const float newValue = 0.5f; + addBlend.setAdditiveFactor(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(addBlend.additiveFactor(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + addBlend.setAdditiveFactor(newValue); + + // THEN + QCOMPARE(addBlend.additiveFactor(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&addBlend, SIGNAL(baseClipChanged(Qt3DAnimation::QAbstractClipBlendNode*))); + auto newValue = new Qt3DAnimation::QAdditiveClipBlend(); + addBlend.setBaseClip(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(addBlend.baseClip(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + addBlend.setBaseClip(newValue); + + // THEN + QCOMPARE(addBlend.baseClip(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&addBlend, SIGNAL(additiveClipChanged(Qt3DAnimation::QAbstractClipBlendNode*))); + auto newValue = new Qt3DAnimation::QAdditiveClipBlend(); + addBlend.setAdditiveClip(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(addBlend.additiveClip(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + addBlend.setAdditiveClip(newValue); + + // THEN + QCOMPARE(addBlend.additiveClip(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QAdditiveClipBlend addBlend; + Qt3DAnimation::QAdditiveClipBlend baseClip; + Qt3DAnimation::QAdditiveClipBlend additiveClip; + + addBlend.setBaseClip(&baseClip); + addBlend.setAdditiveClip(&additiveClip); + addBlend.setAdditiveFactor(0.8f); + + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&addBlend); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 3); // 1 + 2 clips + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QAdditiveClipBlendData>>(creationChanges.first()); + const Qt3DAnimation::QAdditiveClipBlendData cloneData = creationChangeData->data; + + QCOMPARE(addBlend.additiveFactor(), cloneData.additiveFactor); + QCOMPARE(addBlend.id(), creationChangeData->subjectId()); + QCOMPARE(addBlend.isEnabled(), true); + QCOMPARE(addBlend.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(addBlend.metaObject(), creationChangeData->metaObject()); + QCOMPARE(cloneData.baseClipId, baseClip.id()); + QCOMPARE(cloneData.additiveClipId, additiveClip.id()); + } + + // WHEN + addBlend.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&addBlend); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 3); // 1 + 2 clips + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QAdditiveClipBlendData>>(creationChanges.first()); + const Qt3DAnimation::QAdditiveClipBlendData cloneData = creationChangeData->data; + + QCOMPARE(addBlend.additiveFactor(), cloneData.additiveFactor); + QCOMPARE(addBlend.id(), creationChangeData->subjectId()); + QCOMPARE(addBlend.isEnabled(), false); + QCOMPARE(addBlend.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(addBlend.metaObject(), creationChangeData->metaObject()); + QCOMPARE(cloneData.baseClipId, baseClip.id()); + QCOMPARE(cloneData.additiveClipId, additiveClip.id()); + } + } + + void checkAdditiveFactorUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QAdditiveClipBlend addBlend; + arbiter.setArbiterOnNode(&addBlend); + + { + // WHEN + addBlend.setAdditiveFactor(0.4f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "additiveFactor"); + QCOMPARE(change->value().value<float>(), addBlend.additiveFactor()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + addBlend.setAdditiveFactor(0.4f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkBaseClipUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QAdditiveClipBlend addBlend; + arbiter.setArbiterOnNode(&addBlend); + auto baseClip = new Qt3DAnimation::QAdditiveClipBlend(); + + { + // WHEN + addBlend.setBaseClip(baseClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "baseClip"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), addBlend.baseClip()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + addBlend.setBaseClip(baseClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkAdditiveClipUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QAdditiveClipBlend addBlend; + arbiter.setArbiterOnNode(&addBlend); + auto additiveClip = new Qt3DAnimation::QAdditiveClipBlend(); + + { + // WHEN + addBlend.setAdditiveClip(additiveClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "additiveClip"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), addBlend.additiveClip()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + addBlend.setAdditiveClip(additiveClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkBaseClipBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DAnimation::QAdditiveClipBlend> additiveBlend(new Qt3DAnimation::QAdditiveClipBlend); + { + // WHEN + Qt3DAnimation::QAdditiveClipBlend clip; + additiveBlend->setBaseClip(&clip); + + // THEN + QCOMPARE(clip.parent(), additiveBlend.data()); + QCOMPARE(additiveBlend->baseClip(), &clip); + } + // THEN (Should not crash and clip be unset) + QVERIFY(additiveBlend->baseClip() == nullptr); + + { + // WHEN + Qt3DAnimation::QAdditiveClipBlend someOtherAdditiveBlend; + QScopedPointer<Qt3DAnimation::QAdditiveClipBlend> clip(new Qt3DAnimation::QAdditiveClipBlend(&someOtherAdditiveBlend)); + additiveBlend->setBaseClip(clip.data()); + + // THEN + QCOMPARE(clip->parent(), &someOtherAdditiveBlend); + QCOMPARE(additiveBlend->baseClip(), clip.data()); + + // WHEN + additiveBlend.reset(); + clip.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } + + void checkAdditiveClipBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DAnimation::QAdditiveClipBlend> additiveBlend(new Qt3DAnimation::QAdditiveClipBlend); + { + // WHEN + Qt3DAnimation::QAdditiveClipBlend clip; + additiveBlend->setAdditiveClip(&clip); + + // THEN + QCOMPARE(clip.parent(), additiveBlend.data()); + QCOMPARE(additiveBlend->additiveClip(), &clip); + } + // THEN (Should not crash and clip be unset) + QVERIFY(additiveBlend->additiveClip() == nullptr); + + { + // WHEN + Qt3DAnimation::QAdditiveClipBlend someOtherAdditiveBlend; + QScopedPointer<Qt3DAnimation::QAdditiveClipBlend> clip(new Qt3DAnimation::QAdditiveClipBlend(&someOtherAdditiveBlend)); + additiveBlend->setAdditiveClip(clip.data()); + + // THEN + QCOMPARE(clip->parent(), &someOtherAdditiveBlend); + QCOMPARE(additiveBlend->additiveClip(), clip.data()); + + // WHEN + additiveBlend.reset(); + clip.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } +}; + +QTEST_MAIN(tst_QAdditiveClipBlend) + +#include "tst_qadditiveclipblend.moc" diff --git a/tests/auto/animation/qanimationclip/qanimationclip.pro b/tests/auto/animation/qanimationcliploader/qanimationcliploader.pro index 5a9678496..d6ef54df6 100644 --- a/tests/auto/animation/qanimationclip/qanimationclip.pro +++ b/tests/auto/animation/qanimationcliploader/qanimationcliploader.pro @@ -7,6 +7,6 @@ QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib CONFIG += testcase SOURCES += \ - tst_qanimationclip.cpp + tst_qanimationcliploader.cpp include(../../core/common/common.pri) diff --git a/tests/auto/animation/qanimationclip/tst_qanimationclip.cpp b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp index 8c83f6530..968ad8764 100644 --- a/tests/auto/animation/qanimationclip/tst_qanimationclip.cpp +++ b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp @@ -28,8 +28,8 @@ #include <QtTest/QTest> -#include <Qt3DAnimation/qanimationclip.h> -#include <Qt3DAnimation/private/qanimationclip_p.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qanimationcliploader_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qnodecreatedchange.h> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> @@ -37,7 +37,7 @@ #include <QSignalSpy> #include <testpostmanarbiter.h> -class tst_QAnimationClip : public QObject +class tst_QAnimationClipLoader : public Qt3DAnimation::QAnimationClipLoader { Q_OBJECT @@ -45,17 +45,18 @@ private Q_SLOTS: void checkDefaultConstruction() { // GIVEN - Qt3DAnimation::QAnimationClip clip; + Qt3DAnimation::QAnimationClipLoader clip; // THEN QCOMPARE(clip.source(), QUrl()); QCOMPARE(clip.duration(), 0.0f); + QCOMPARE(clip.status(), Qt3DAnimation::QAnimationClipLoader::NotReady); } void checkPropertyChanges() { // GIVEN - Qt3DAnimation::QAnimationClip clip; + Qt3DAnimation::QAnimationClipLoader clip; { // WHEN @@ -81,7 +82,7 @@ private Q_SLOTS: void checkCreationData() { // GIVEN - Qt3DAnimation::QAnimationClip clip; + Qt3DAnimation::QAnimationClipLoader clip; clip.setSource(QUrl(QStringLiteral("http://someRemoteURL.com"))); @@ -97,8 +98,8 @@ private Q_SLOTS: { QCOMPARE(creationChanges.size(), 1); - const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QAnimationClipData>>(creationChanges.first()); - const Qt3DAnimation::QAnimationClipData data = creationChangeData->data; + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QAnimationClipLoaderData>>(creationChanges.first()); + const Qt3DAnimation::QAnimationClipLoaderData data = creationChangeData->data; QCOMPARE(clip.id(), creationChangeData->subjectId()); QCOMPARE(clip.isEnabled(), true); @@ -119,7 +120,7 @@ private Q_SLOTS: { QCOMPARE(creationChanges.size(), 1); - const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QAnimationClipData>>(creationChanges.first()); + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QAnimationClipLoaderData>>(creationChanges.first()); QCOMPARE(clip.id(), creationChangeData->subjectId()); QCOMPARE(clip.isEnabled(), false); @@ -132,7 +133,7 @@ private Q_SLOTS: { // GIVEN TestArbiter arbiter; - Qt3DAnimation::QAnimationClip clip; + Qt3DAnimation::QAnimationClipLoader clip; arbiter.setArbiterOnNode(&clip); { @@ -159,8 +160,41 @@ private Q_SLOTS: } } + + void checkStatusPropertyUpdate() + { + // GIVEN + qRegisterMetaType<Qt3DAnimation::QAnimationClipLoader::Status>("Status"); + TestArbiter arbiter; + arbiter.setArbiterOnNode(this); + QSignalSpy spy(this, SIGNAL(statusChanged(Status))); + const Qt3DAnimation::QAnimationClipLoader::Status newStatus = Qt3DAnimation::QAnimationClipLoader::Error; + + // THEN + QVERIFY(spy.isValid()); + + // WHEN + Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + valueChange->setPropertyName("status"); + valueChange->setValue(QVariant::fromValue(newStatus)); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(status(), newStatus); + + // WHEN + spy.clear(); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 0); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(status(), newStatus); + } }; -QTEST_MAIN(tst_QAnimationClip) +QTEST_MAIN(tst_QAnimationClipLoader) -#include "tst_qanimationclip.moc" +#include "tst_qanimationcliploader.moc" diff --git a/tests/auto/animation/qanimationcontroller/qanimationcontroller.pro b/tests/auto/animation/qanimationcontroller/qanimationcontroller.pro new file mode 100644 index 000000000..ff5348d47 --- /dev/null +++ b/tests/auto/animation/qanimationcontroller/qanimationcontroller.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qanimationcontroller + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation testlib + +CONFIG += testcase + +SOURCES += tst_qanimationcontroller.cpp + diff --git a/tests/auto/animation/qanimationcontroller/tst_qanimationcontroller.cpp b/tests/auto/animation/qanimationcontroller/tst_qanimationcontroller.cpp new file mode 100644 index 000000000..4774dc8ba --- /dev/null +++ b/tests/auto/animation/qanimationcontroller/tst_qanimationcontroller.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** 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 <QtTest/qtest.h> +#include <Qt3DAnimation/qanimationcontroller.h> +#include <Qt3DAnimation/qkeyframeanimation.h> +#include <Qt3DAnimation/qmorphinganimation.h> +#include <qobject.h> +#include <qsignalspy.h> + +class tst_QAnimationController : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QAnimationController animationController; + + // THEN + QCOMPARE(animationController.activeAnimationGroup(), 0); + QCOMPARE(animationController.position(), 0.0f); + QCOMPARE(animationController.positionScale(), 1.0f); + QCOMPARE(animationController.positionOffset(), 0.0f); + QCOMPARE(animationController.entity(), nullptr); + QCOMPARE(animationController.recursive(), true); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QAnimationController animationController; + + { + // WHEN + QSignalSpy spy(&animationController, SIGNAL(activeAnimationGroupChanged(int))); + const int newValue = 1; + animationController.setActiveAnimationGroup(newValue); + + // THEN + QCOMPARE(animationController.activeAnimationGroup(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationController.setActiveAnimationGroup(newValue); + + // THEN + QCOMPARE(animationController.activeAnimationGroup(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&animationController, SIGNAL(positionChanged(float))); + const float newValue = 2.0f; + animationController.setPosition(newValue); + + // THEN + QCOMPARE(animationController.position(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationController.setPosition(newValue); + + // THEN + QCOMPARE(animationController.position(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&animationController, SIGNAL(positionScaleChanged(float))); + const float newValue = 3.0f; + animationController.setPositionScale(newValue); + + // THEN + QCOMPARE(animationController.positionScale(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationController.setPositionScale(newValue); + + // THEN + QCOMPARE(animationController.positionScale(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&animationController, SIGNAL(positionOffsetChanged(float))); + const float newValue = -1.0f; + animationController.setPositionOffset(newValue); + + // THEN + QCOMPARE(animationController.positionOffset(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationController.setPositionOffset(newValue); + + // THEN + QCOMPARE(animationController.positionOffset(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity); + QSignalSpy spy(&animationController, SIGNAL(entityChanged(Qt3DCore::QEntity *))); + Qt3DCore::QEntity * newValue = entity.data(); + animationController.setEntity(newValue); + + // THEN + QCOMPARE(animationController.entity(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationController.setEntity(newValue); + + // THEN + QCOMPARE(animationController.entity(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&animationController, SIGNAL(recursiveChanged(bool))); + const bool newValue = false; + animationController.setRecursive(newValue); + + // THEN + QCOMPARE(animationController.recursive(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationController.setRecursive(newValue); + + // THEN + QCOMPARE(animationController.recursive(), newValue); + QCOMPARE(spy.count(), 0); + + } + } + + void testSetEntity() + { + // GIVEN + Qt3DAnimation::QAnimationController animationController; + Qt3DAnimation::QKeyframeAnimation *keyframeAnimation; + Qt3DAnimation::QKeyframeAnimation *keyframeAnimation2; + Qt3DAnimation::QMorphingAnimation *morphingAnimation; + + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity); + keyframeAnimation = new Qt3DAnimation::QKeyframeAnimation(entity.data()); + keyframeAnimation2 = new Qt3DAnimation::QKeyframeAnimation(entity.data()); + morphingAnimation = new Qt3DAnimation::QMorphingAnimation(entity.data()); + + const QString animName1 = QString("animation1"); + const QString animName2 = QString("animation2"); + morphingAnimation->setAnimationName(animName1); + keyframeAnimation->setAnimationName(animName1); + keyframeAnimation2->setAnimationName(animName2); + + { + // WHEN + animationController.setEntity(entity.data()); + + // THEN + QVector<Qt3DAnimation::QAnimationGroup *> list = animationController.animationGroupList(); + QCOMPARE(list.size(), 2); + + QCOMPARE(list.at(0)->name(), animName1); + QCOMPARE(list.at(1)->name(), animName2); + + QCOMPARE(list.at(0)->animationList().size(), 2); + QCOMPARE(list.at(1)->animationList().size(), 1); + } + } + + void testSetEntityRecursive() + { + // GIVEN + Qt3DAnimation::QAnimationController animationController; + Qt3DAnimation::QKeyframeAnimation *keyframeAnimation; + Qt3DAnimation::QMorphingAnimation *morphingAnimation; + + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity); + keyframeAnimation = new Qt3DAnimation::QKeyframeAnimation(entity.data()); + Qt3DCore::QEntity *childEntity = new Qt3DCore::QEntity(entity.data()); + morphingAnimation = new Qt3DAnimation::QMorphingAnimation(childEntity); + + const QString animName1 = QString("animation1"); + const QString animName2 = QString("animation2"); + + keyframeAnimation->setAnimationName(animName1); + morphingAnimation->setAnimationName(animName2); + + { + // WHEN + animationController.setEntity(entity.data()); + + // THEN + QVector<Qt3DAnimation::QAnimationGroup *> list = animationController.animationGroupList(); + QCOMPARE(list.size(), 2); + + QCOMPARE(list.at(0)->name(), animName1); + QCOMPARE(list.at(1)->name(), animName2); + + QCOMPARE(list.at(0)->animationList().size(), 1); + QCOMPARE(list.at(1)->animationList().size(), 1); + + animationController.setEntity(nullptr); + } + + { + // WHEN + animationController.setRecursive(false); + animationController.setEntity(entity.data()); + + // THEN + QVector<Qt3DAnimation::QAnimationGroup *> list = animationController.animationGroupList(); + QCOMPARE(list.size(), 1); + + QCOMPARE(list.at(0)->name(), animName1); + + QCOMPARE(list.at(0)->animationList().size(), 1); + } + } + + + void testPropagatePosition() + { + // GIVEN + Qt3DAnimation::QAnimationController animationController; + Qt3DAnimation::QKeyframeAnimation *keyframeAnimation; + + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity); + keyframeAnimation = new Qt3DAnimation::QKeyframeAnimation(entity.data()); + + const QString animName1 = QString("animation1"); + keyframeAnimation->setAnimationName(animName1); + + { + // WHEN + animationController.setEntity(entity.data()); + animationController.setPosition(2.0f); + + // THEN + QCOMPARE(animationController.animationGroupList().at(0)->position(), 2.0f); + QCOMPARE(keyframeAnimation->position(), 2.0f); + } + + { + // WHEN + animationController.setPositionOffset(1.0); + animationController.setPositionScale(2.0f); + animationController.setPosition(2.0f); + + // THEN + QCOMPARE(animationController.animationGroupList().at(0)->position(), 5.0f); + QCOMPARE(keyframeAnimation->position(), 5.0f); + } + } + +}; + +QTEST_APPLESS_MAIN(tst_QAnimationController) + +#include "tst_qanimationcontroller.moc" diff --git a/tests/auto/animation/qanimationgroup/qanimationgroup.pro b/tests/auto/animation/qanimationgroup/qanimationgroup.pro new file mode 100644 index 000000000..5c39fa539 --- /dev/null +++ b/tests/auto/animation/qanimationgroup/qanimationgroup.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qanimationgroup + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation testlib + +CONFIG += testcase + +SOURCES += tst_qanimationgroup.cpp + diff --git a/tests/auto/animation/qanimationgroup/tst_qanimationgroup.cpp b/tests/auto/animation/qanimationgroup/tst_qanimationgroup.cpp new file mode 100644 index 000000000..0c7a66222 --- /dev/null +++ b/tests/auto/animation/qanimationgroup/tst_qanimationgroup.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qanimationgroup.h> +#include <qobject.h> +#include <qsignalspy.h> + +class tst_QAnimationGroup : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QAnimationGroup animationGroup; + + // THEN + QCOMPARE(animationGroup.name(), QString()); + QCOMPARE(animationGroup.position(), 0.0f); + QCOMPARE(animationGroup.duration(), 0.0f); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QAnimationGroup animationGroup; + + { + // WHEN + QSignalSpy spy(&animationGroup, SIGNAL(nameChanged(QString))); + const QString newValue = QString("group"); + animationGroup.setName(newValue); + + // THEN + QCOMPARE(animationGroup.name(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationGroup.setName(newValue); + + // THEN + QCOMPARE(animationGroup.name(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&animationGroup, SIGNAL(positionChanged(float))); + const float newValue = 2.0f; + animationGroup.setPosition(newValue); + + // THEN + QCOMPARE(animationGroup.position(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animationGroup.setPosition(newValue); + + // THEN + QCOMPARE(animationGroup.position(), newValue); + QCOMPARE(spy.count(), 0); + + } + } + +}; + +QTEST_APPLESS_MAIN(tst_QAnimationGroup) + +#include "tst_qanimationgroup.moc" diff --git a/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp b/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp index 42997d8aa..d25041886 100644 --- a/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp +++ b/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp @@ -28,11 +28,9 @@ #include <QtTest/QTest> -#include <Qt3DAnimation/qanimationclip.h> #include <Qt3DAnimation/qblendedclipanimator.h> -#include <Qt3DAnimation/private/qanimationclip_p.h> #include <Qt3DAnimation/private/qblendedclipanimator_p.h> -#include <Qt3DAnimation/qlerpblend.h> +#include <Qt3DAnimation/qlerpclipblend.h> #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qnodecreatedchange.h> @@ -62,7 +60,7 @@ private Q_SLOTS: QVERIFY(blendedClipAnimator.blendTree() == nullptr); QVERIFY(blendedClipAnimator.channelMapper() == nullptr); QCOMPARE(blendedClipAnimator.isRunning(), false); - QCOMPARE(blendedClipAnimator.loops(), 1); + QCOMPARE(blendedClipAnimator.loopCount(), 1); } void checkPropertyChanges() @@ -73,7 +71,7 @@ private Q_SLOTS: { // WHEN QSignalSpy spy(&blendedClipAnimator, SIGNAL(blendTreeChanged(QAbstractClipBlendNode *))); - Qt3DAnimation::QLerpBlend newValue; + Qt3DAnimation::QLerpClipBlend newValue; blendedClipAnimator.setBlendTree(&newValue); // THEN @@ -130,21 +128,21 @@ private Q_SLOTS: { // WHEN - QSignalSpy spy(&blendedClipAnimator, SIGNAL(loopsChanged(int))); + QSignalSpy spy(&blendedClipAnimator, SIGNAL(loopCountChanged(int))); const int newValue = 5; - blendedClipAnimator.setLoops(newValue); + blendedClipAnimator.setLoopCount(newValue); // THEN QVERIFY(spy.isValid()); - QCOMPARE(blendedClipAnimator.loops(), newValue); + QCOMPARE(blendedClipAnimator.loopCount(), newValue); QCOMPARE(spy.count(), 1); // WHEN spy.clear(); - blendedClipAnimator.setLoops(newValue); + blendedClipAnimator.setLoopCount(newValue); // THEN - QCOMPARE(blendedClipAnimator.loops(), newValue); + QCOMPARE(blendedClipAnimator.loopCount(), newValue); QCOMPARE(spy.count(), 0); } } @@ -154,7 +152,7 @@ private Q_SLOTS: // GIVEN Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator; Qt3DAnimation::QChannelMapper channelMapper; - Qt3DAnimation::QLerpBlend blendRoot; + Qt3DAnimation::QLerpClipBlend blendRoot; blendedClipAnimator.setBlendTree(&blendRoot); blendedClipAnimator.setChannelMapper(&channelMapper); @@ -182,7 +180,7 @@ private Q_SLOTS: QCOMPARE(blendedClipAnimator.isEnabled(), true); QCOMPARE(blendedClipAnimator.isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(blendedClipAnimator.metaObject(), creationChangeData->metaObject()); - QCOMPARE(blendedClipAnimator.loops(), cloneData.loops); + QCOMPARE(blendedClipAnimator.loopCount(), cloneData.loops); } // WHEN @@ -216,7 +214,7 @@ private Q_SLOTS: TestArbiter arbiter; Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator; arbiter.setArbiterOnNode(&blendedClipAnimator); - Qt3DAnimation::QLerpBlend blendRoot; + Qt3DAnimation::QLerpClipBlend blendRoot; { // WHEN @@ -251,7 +249,7 @@ private Q_SLOTS: { // WHEN - Qt3DAnimation::QLerpBlend blendRoot; + Qt3DAnimation::QLerpClipBlend blendRoot; blendedClipAnimator.setBlendTree(&blendRoot); QCOMPARE(blendedClipAnimator.blendTree(), &blendRoot); @@ -354,14 +352,14 @@ private Q_SLOTS: { // WHEN - blendedClipAnimator.setLoops(1584); + blendedClipAnimator.setLoopCount(1584); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 1); auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "loops"); - QCOMPARE(change->value().value<int>(), blendedClipAnimator.loops()); + QCOMPARE(change->value().value<int>(), blendedClipAnimator.loopCount()); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); arbiter.events.clear(); @@ -369,7 +367,7 @@ private Q_SLOTS: { // WHEN - blendedClipAnimator.setLoops(1584); + blendedClipAnimator.setLoopCount(1584); QCoreApplication::processEvents(); // THEN diff --git a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp index d210d4365..1ed4b8f13 100644 --- a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp +++ b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp @@ -28,7 +28,7 @@ #include <QtTest/QTest> -#include <Qt3DAnimation/qanimationclip.h> +#include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/qclipanimator.h> #include <Qt3DAnimation/private/qanimationclip_p.h> @@ -47,7 +47,7 @@ class tst_QClipAnimator : public QObject private Q_SLOTS: void initTestCase() { - qRegisterMetaType<Qt3DAnimation::QAnimationClip*>(); + qRegisterMetaType<Qt3DAnimation::QAbstractAnimationClip*>(); qRegisterMetaType<Qt3DAnimation::QChannelMapper*>(); } @@ -57,9 +57,9 @@ private Q_SLOTS: Qt3DAnimation::QClipAnimator animator; // THEN - QCOMPARE(animator.clip(), static_cast<Qt3DAnimation::QAnimationClip *>(nullptr)); + QCOMPARE(animator.clip(), static_cast<Qt3DAnimation::QAbstractAnimationClip *>(nullptr)); QCOMPARE(animator.channelMapper(), static_cast<Qt3DAnimation::QChannelMapper *>(nullptr)); - QCOMPARE(animator.loops(), 1); + QCOMPARE(animator.loopCount(), 1); } void checkPropertyChanges() @@ -69,8 +69,8 @@ private Q_SLOTS: { // WHEN - QSignalSpy spy(&animator, SIGNAL(clipChanged(Qt3DAnimation::QAnimationClip *))); - auto newValue = new Qt3DAnimation::QAnimationClip(); + QSignalSpy spy(&animator, SIGNAL(clipChanged(Qt3DAnimation::QAbstractAnimationClip *))); + auto newValue = new Qt3DAnimation::QAnimationClipLoader(); animator.setClip(newValue); // THEN @@ -111,21 +111,21 @@ private Q_SLOTS: { // WHEN - QSignalSpy spy(&animator, SIGNAL(loopsChanged(int))); + QSignalSpy spy(&animator, SIGNAL(loopCountChanged(int))); const int newValue = 5; - animator.setLoops(newValue); + animator.setLoopCount(newValue); // THEN QVERIFY(spy.isValid()); - QCOMPARE(animator.loops(), newValue); + QCOMPARE(animator.loopCount(), newValue); QCOMPARE(spy.count(), 1); // WHEN spy.clear(); - animator.setLoops(newValue); + animator.setLoopCount(newValue); // THEN - QCOMPARE(animator.loops(), newValue); + QCOMPARE(animator.loopCount(), newValue); QCOMPARE(spy.count(), 0); } } @@ -134,7 +134,7 @@ private Q_SLOTS: { // GIVEN Qt3DAnimation::QClipAnimator animator; - auto clip = new Qt3DAnimation::QAnimationClip(); + auto clip = new Qt3DAnimation::QAnimationClipLoader(); animator.setClip(clip); auto mapper = new Qt3DAnimation::QChannelMapper(); animator.setChannelMapper(mapper); @@ -159,7 +159,7 @@ private Q_SLOTS: QCOMPARE(animator.metaObject(), creationChangeData->metaObject()); QCOMPARE(animator.clip()->id(), data.clipId); QCOMPARE(animator.channelMapper()->id(), data.mapperId); - QCOMPARE(animator.loops(), data.loops); + QCOMPARE(animator.loopCount(), data.loops); } // WHEN @@ -187,7 +187,7 @@ private Q_SLOTS: // GIVEN TestArbiter arbiter; Qt3DAnimation::QClipAnimator animator; - auto clip = new Qt3DAnimation::QAnimationClip(); + auto clip = new Qt3DAnimation::QAnimationClipLoader(); arbiter.setArbiterOnNode(&animator); { @@ -242,7 +242,7 @@ private Q_SLOTS: { // WHEN - animator.setLoops(10); + animator.setLoopCount(10); QCoreApplication::processEvents(); // THEN @@ -250,14 +250,14 @@ private Q_SLOTS: auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "loops"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - QCOMPARE(change->value().toInt(), animator.loops()); + QCOMPARE(change->value().toInt(), animator.loopCount()); arbiter.events.clear(); } { // WHEN - animator.setLoops(10); + animator.setLoopCount(10); QCoreApplication::processEvents(); // THEN diff --git a/tests/auto/animation/qclipblendvalue/qclipblendvalue.pro b/tests/auto/animation/qclipblendvalue/qclipblendvalue.pro new file mode 100644 index 000000000..b44b387db --- /dev/null +++ b/tests/auto/animation/qclipblendvalue/qclipblendvalue.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qclipblendvalue + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qclipblendvalue.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp b/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp new file mode 100644 index 000000000..bdbee9380 --- /dev/null +++ b/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qclipblendvalue.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qclipblendvalue_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DAnimation/qclipblendnodecreatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +class tst_QClipBlendValue : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QAbstractAnimationClip*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QClipBlendValue clipBlendNode; + + // THEN; + QCOMPARE(clipBlendNode.clip(), static_cast<Qt3DAnimation::QAbstractAnimationClip *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QClipBlendValue clipBlendNode; + + { + // WHEN + QSignalSpy spy(&clipBlendNode, SIGNAL(clipChanged(Qt3DAnimation::QAbstractAnimationClip*))); + auto newValue = new Qt3DAnimation::QAnimationClipLoader(); + clipBlendNode.setClip(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(clipBlendNode.clip(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + clipBlendNode.setClip(newValue); + + // THEN + QCOMPARE(clipBlendNode.clip(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QClipBlendValue clipBlendNode; + Qt3DAnimation::QAnimationClipLoader clip; + + clipBlendNode.setClip(&clip); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&clipBlendNode); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // 1 + 1 clip + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QClipBlendValueData>>(creationChanges.first()); + const Qt3DAnimation::QClipBlendValueData cloneData = creationChangeData->data; + + QCOMPARE(clipBlendNode.id(), creationChangeData->subjectId()); + QCOMPARE(clipBlendNode.isEnabled(), true); + QCOMPARE(clipBlendNode.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(clipBlendNode.metaObject(), creationChangeData->metaObject()); + QCOMPARE(cloneData.clipId, clip.id()); + } + + // WHEN + clipBlendNode.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&clipBlendNode); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // 1 + 1 clip + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QClipBlendValueData>>(creationChanges.first()); + const Qt3DAnimation::QClipBlendValueData cloneData = creationChangeData->data; + + QCOMPARE(clipBlendNode.id(), creationChangeData->subjectId()); + QCOMPARE(clipBlendNode.isEnabled(), false); + QCOMPARE(clipBlendNode.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(clipBlendNode.metaObject(), creationChangeData->metaObject()); + QCOMPARE(cloneData.clipId, clip.id()); + } + } + + void checkClipUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QClipBlendValue clipBlendNode; + arbiter.setArbiterOnNode(&clipBlendNode); + auto clip = new Qt3DAnimation::QAnimationClipLoader(); + + { + // WHEN + clipBlendNode.setClip(clip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "clip"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), clipBlendNode.clip()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + clipBlendNode.setClip(clip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkStartClipBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DAnimation::QClipBlendValue> clipBlendNode(new Qt3DAnimation::QClipBlendValue); + { + // WHEN + Qt3DAnimation::QAnimationClipLoader clip; + clipBlendNode->setClip(&clip); + + // THEN + QCOMPARE(clip.parent(), clipBlendNode.data()); + QCOMPARE(clipBlendNode->clip(), &clip); + } + // THEN (Should not crash and clip be unset) + QVERIFY(clipBlendNode->clip() == nullptr); + + { + // WHEN + Qt3DAnimation::QClipBlendValue someOtherNode; + QScopedPointer<Qt3DAnimation::QAnimationClipLoader> clip(new Qt3DAnimation::QAnimationClipLoader(&someOtherNode)); + clipBlendNode->setClip(clip.data()); + + // THEN + QCOMPARE(clip->parent(), &someOtherNode); + QCOMPARE(clipBlendNode->clip(), clip.data()); + + // WHEN + clipBlendNode.reset(); + clip.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } +}; + +QTEST_MAIN(tst_QClipBlendValue) + +#include "tst_qclipblendvalue.moc" diff --git a/tests/auto/animation/qkeyframeanimation/qkeyframeanimation.pro b/tests/auto/animation/qkeyframeanimation/qkeyframeanimation.pro new file mode 100644 index 000000000..994d8d0d9 --- /dev/null +++ b/tests/auto/animation/qkeyframeanimation/qkeyframeanimation.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qkeyframeanimation + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation testlib + +CONFIG += testcase + +SOURCES += tst_qkeyframeanimation.cpp + diff --git a/tests/auto/animation/qkeyframeanimation/tst_qkeyframeanimation.cpp b/tests/auto/animation/qkeyframeanimation/tst_qkeyframeanimation.cpp new file mode 100644 index 000000000..33bbebc52 --- /dev/null +++ b/tests/auto/animation/qkeyframeanimation/tst_qkeyframeanimation.cpp @@ -0,0 +1,285 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** 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 <QtTest/qtest.h> +#include <Qt3DAnimation/qkeyframeanimation.h> +#include <qobject.h> +#include <qsignalspy.h> + +class tst_QKeyframeAnimation : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QKeyframeAnimation::RepeatMode>( + "QKeyframeAnimation::RepeatMode"); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QKeyframeAnimation keyframeAnimation; + + // THEN + QCOMPARE(keyframeAnimation.target(), nullptr); + QCOMPARE(keyframeAnimation.easing(), QEasingCurve()); + QCOMPARE(keyframeAnimation.targetName(), QString()); + QCOMPARE(keyframeAnimation.startMode(), Qt3DAnimation::QKeyframeAnimation::Constant); + QCOMPARE(keyframeAnimation.endMode(), Qt3DAnimation::QKeyframeAnimation::Constant); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QKeyframeAnimation keyframeAnimation; + + { + // WHEN + QScopedPointer<Qt3DCore::QTransform> transform(new Qt3DCore::QTransform); + QSignalSpy spy(&keyframeAnimation, SIGNAL(targetChanged(Qt3DCore::QTransform *))); + Qt3DCore::QTransform * newValue = transform.data(); + keyframeAnimation.setTarget(newValue); + + // THEN + QCOMPARE(keyframeAnimation.target(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + keyframeAnimation.setTarget(newValue); + + // THEN + QCOMPARE(keyframeAnimation.target(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&keyframeAnimation, SIGNAL(easingChanged(const QEasingCurve &))); + const QEasingCurve newValue = QEasingCurve(QEasingCurve::CosineCurve); + keyframeAnimation.setEasing(newValue); + + // THEN + QCOMPARE(keyframeAnimation.easing(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + keyframeAnimation.setEasing(newValue); + + // THEN + QCOMPARE(keyframeAnimation.easing(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&keyframeAnimation, SIGNAL(targetNameChanged(QString))); + const QString newValue = QString("target"); + keyframeAnimation.setTargetName(newValue); + + // THEN + QCOMPARE(keyframeAnimation.targetName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + keyframeAnimation.setTargetName(newValue); + + // THEN + QCOMPARE(keyframeAnimation.targetName(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&keyframeAnimation, + SIGNAL(startModeChanged(QKeyframeAnimation::RepeatMode))); + const Qt3DAnimation::QKeyframeAnimation::RepeatMode newValue + = Qt3DAnimation::QKeyframeAnimation::Repeat; + keyframeAnimation.setStartMode(newValue); + + // THEN + QCOMPARE(keyframeAnimation.startMode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + keyframeAnimation.setStartMode(newValue); + + // THEN + QCOMPARE(keyframeAnimation.startMode(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&keyframeAnimation, + SIGNAL(endModeChanged(QKeyframeAnimation::RepeatMode))); + const Qt3DAnimation::QKeyframeAnimation::RepeatMode newValue + = Qt3DAnimation::QKeyframeAnimation::Repeat; + keyframeAnimation.setEndMode(newValue); + + // THEN + QCOMPARE(keyframeAnimation.endMode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + keyframeAnimation.setEndMode(newValue); + + // THEN + QCOMPARE(keyframeAnimation.endMode(), newValue); + QCOMPARE(spy.count(), 0); + + } + } + + void testAnimating() + { + // GIVEN + Qt3DAnimation::QKeyframeAnimation keyframeAnimation; + Qt3DCore::QTransform targetTransform; + keyframeAnimation.setTarget(&targetTransform); + + const float positions[3] = {0.0f, 1.0f, 2.0f}; + + Qt3DCore::QTransform keyframes[3]; + keyframes[0].setScale(1.0f); + keyframes[1].setScale(2.0f); + keyframes[2].setScale(3.0f); + + keyframes[0].setTranslation(QVector3D(0.0f, 0.0f, 0.0f)); + keyframes[1].setTranslation(QVector3D(1.0f, 1.0f, 0.0f)); + keyframes[2].setTranslation(QVector3D(2.0f, 0.0f, 2.0f)); + + keyframes[0].setRotationX(0.0f); + keyframes[1].setRotationY(45.0f); + keyframes[2].setRotationZ(90.0f); + + QVector<float> framePositions; + framePositions.push_back(positions[0]); + framePositions.push_back(positions[1]); + framePositions.push_back(positions[2]); + + QVector<Qt3DCore::QTransform*> frames; + frames.push_back(&keyframes[0]); + frames.push_back(&keyframes[1]); + frames.push_back(&keyframes[2]); + + keyframeAnimation.setFramePositions(framePositions); + keyframeAnimation.setKeyframes(frames); + + { + // WHEN + keyframeAnimation.setPosition(0.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(1.0f, 1.0f, 1.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(0.0f, 0.0f, 0.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 0.0f, 0.0f)))); + + // WHEN + keyframeAnimation.setPosition(1.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(2.0f, 2.0f, 2.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(1.0f, 1.0f, 0.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 45.0f, 0.0f)))); + + // WHEN + keyframeAnimation.setPosition(2.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(3.0f, 3.0f, 3.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(2.0f, 0.0f, 2.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 0.0f, 90.0f)))); + + // WHEN + keyframeAnimation.setPosition(3.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(3.0f, 3.0f, 3.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(2.0f, 0.0f, 2.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 0.0f, 90.0f)))); + + // WHEN + keyframeAnimation.setStartMode(Qt3DAnimation::QKeyframeAnimation::None); + keyframeAnimation.setEndMode(Qt3DAnimation::QKeyframeAnimation::None); + keyframeAnimation.setPosition(-1.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(3.0f, 3.0f, 3.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(2.0f, 0.0f, 2.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 0.0f, 90.0f)))); + + // WHEN + keyframeAnimation.setPosition(5.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(3.0f, 3.0f, 3.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(2.0f, 0.0f, 2.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 0.0f, 90.0f)))); + + // WHEN + keyframeAnimation.setStartMode(Qt3DAnimation::QKeyframeAnimation::Repeat); + keyframeAnimation.setEndMode(Qt3DAnimation::QKeyframeAnimation::Repeat); + keyframeAnimation.setPosition(-1.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(2.0f, 2.0f, 2.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(1.0f, 1.0f, 0.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 45.0f, 0.0f)))); + + // WHEN + keyframeAnimation.setStartMode(Qt3DAnimation::QKeyframeAnimation::Repeat); + keyframeAnimation.setEndMode(Qt3DAnimation::QKeyframeAnimation::Repeat); + keyframeAnimation.setPosition(4.0f); + + // THEN + QVERIFY(qFuzzyCompare(targetTransform.scale3D(), QVector3D(1.0f, 1.0f, 1.0f))); + QVERIFY(qFuzzyCompare(targetTransform.translation(), QVector3D(0.0f, 0.0f, 0.0f))); + QVERIFY(qFuzzyCompare(targetTransform.rotation(), + QQuaternion::fromEulerAngles(QVector3D(0.0f, 0.0f, 0.0f)))); + } + } +}; + +QTEST_APPLESS_MAIN(tst_QKeyframeAnimation) + +#include "tst_qkeyframeanimation.moc" diff --git a/tests/auto/animation/qlerpblend/tst_qlerpblend.cpp b/tests/auto/animation/qlerpblend/tst_qlerpblend.cpp deleted file mode 100644 index 6bd6bb324..000000000 --- a/tests/auto/animation/qlerpblend/tst_qlerpblend.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> -** 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 <QtTest/QTest> -#include <Qt3DAnimation/qlerpblend.h> -#include <Qt3DAnimation/qanimationclip.h> -#include <Qt3DAnimation/private/qlerpblend_p.h> -#include <QObject> -#include <QSignalSpy> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> -#include <Qt3DAnimation/qclipblendnodecreatedchange.h> -#include <Qt3DCore/qnodecreatedchange.h> -#include "testpostmanarbiter.h" - -class tst_QLerpBlend : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - - void checkDefaultConstruction() - { - // GIVEN - Qt3DAnimation::QLerpBlend lerpBlend; - - // THEN - QCOMPARE(lerpBlend.blendFactor(), 0.0f); - } - - void checkPropertyChanges() - { - // GIVEN - Qt3DAnimation::QLerpBlend lerpBlend; - - { - // WHEN - QSignalSpy spy(&lerpBlend, SIGNAL(blendFactorChanged(float))); - const float newValue = 0.5f; - lerpBlend.setBlendFactor(newValue); - - // THEN - QVERIFY(spy.isValid()); - QCOMPARE(lerpBlend.blendFactor(), newValue); - QCOMPARE(spy.count(), 1); - - // WHEN - spy.clear(); - lerpBlend.setBlendFactor(newValue); - - // THEN - QCOMPARE(lerpBlend.blendFactor(), newValue); - QCOMPARE(spy.count(), 0); - } - } - - void checkCreationData() - { - // GIVEN - Qt3DAnimation::QLerpBlend lerpBlend; - Qt3DAnimation::QAnimationClip clip1; - Qt3DAnimation::QAnimationClip clip2; - - lerpBlend.addClip(&clip1); - lerpBlend.addClip(&clip2); - lerpBlend.setBlendFactor(0.8f); - - - // WHEN - QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; - - { - Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&lerpBlend); - creationChanges = creationChangeGenerator.creationChanges(); - } - - // THEN - { - QCOMPARE(creationChanges.size(), 3); // 1 + 2 clips - - const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpBlendData>>(creationChanges.first()); - const Qt3DAnimation::QLerpBlendData cloneData = creationChangeData->data; - - QCOMPARE(lerpBlend.blendFactor(), cloneData.blendFactor); - QCOMPARE(lerpBlend.id(), creationChangeData->subjectId()); - QCOMPARE(lerpBlend.isEnabled(), true); - QCOMPARE(lerpBlend.isEnabled(), creationChangeData->isNodeEnabled()); - QCOMPARE(lerpBlend.metaObject(), creationChangeData->metaObject()); - QCOMPARE(creationChangeData->clips().size(), 2); - QCOMPARE(creationChangeData->clips().first(), clip1.id()); - QCOMPARE(creationChangeData->clips().last(), clip2.id()); - QCOMPARE(creationChangeData->parentClipBlendNodeId(), Qt3DCore::QNodeId()); - } - - // WHEN - lerpBlend.setEnabled(false); - - { - Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&lerpBlend); - creationChanges = creationChangeGenerator.creationChanges(); - } - - // THEN - { - QCOMPARE(creationChanges.size(), 3); // 1 + 2 clips - - const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpBlendData>>(creationChanges.first()); - const Qt3DAnimation::QLerpBlendData cloneData = creationChangeData->data; - - QCOMPARE(lerpBlend.blendFactor(), cloneData.blendFactor); - QCOMPARE(lerpBlend.id(), creationChangeData->subjectId()); - QCOMPARE(lerpBlend.isEnabled(), false); - QCOMPARE(lerpBlend.isEnabled(), creationChangeData->isNodeEnabled()); - QCOMPARE(lerpBlend.metaObject(), creationChangeData->metaObject()); - QCOMPARE(creationChangeData->clips().size(), 2); - QCOMPARE(creationChangeData->clips().first(), clip1.id()); - QCOMPARE(creationChangeData->clips().last(), clip2.id()); - QCOMPARE(creationChangeData->parentClipBlendNodeId(), Qt3DCore::QNodeId()); - } - } - - void checkBlendFactorUpdate() - { - // GIVEN - TestArbiter arbiter; - Qt3DAnimation::QLerpBlend lerpBlend; - arbiter.setArbiterOnNode(&lerpBlend); - - { - // WHEN - lerpBlend.setBlendFactor(0.4f); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "blendFactor"); - QCOMPARE(change->value().value<float>(), lerpBlend.blendFactor()); - QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - - arbiter.events.clear(); - } - - { - // WHEN - lerpBlend.setBlendFactor(0.4f); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 0); - } - - } - -}; - -QTEST_MAIN(tst_QLerpBlend) - -#include "tst_qlerpblend.moc" diff --git a/tests/auto/animation/qlerpclipblend/qlerpclipblend.pro b/tests/auto/animation/qlerpclipblend/qlerpclipblend.pro new file mode 100644 index 000000000..3c26dbb19 --- /dev/null +++ b/tests/auto/animation/qlerpclipblend/qlerpclipblend.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qlerpclipblend + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qlerpclipblend.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp b/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp new file mode 100644 index 000000000..057f37786 --- /dev/null +++ b/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DAnimation/qlerpclipblend.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qlerpclipblend_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DAnimation/qclipblendnodecreatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +class tst_QLerpClipBlend : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QAbstractClipBlendNode*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QLerpClipBlend lerpBlend; + + // THEN + QCOMPARE(lerpBlend.blendFactor(), 0.0f); + QCOMPARE(lerpBlend.startClip(), static_cast<Qt3DAnimation::QAbstractClipBlendNode *>(nullptr)); + QCOMPARE(lerpBlend.endClip(), static_cast<Qt3DAnimation::QAbstractClipBlendNode *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QLerpClipBlend lerpBlend; + + { + // WHEN + QSignalSpy spy(&lerpBlend, SIGNAL(blendFactorChanged(float))); + const float newValue = 0.5f; + lerpBlend.setBlendFactor(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(lerpBlend.blendFactor(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + lerpBlend.setBlendFactor(newValue); + + // THEN + QCOMPARE(lerpBlend.blendFactor(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&lerpBlend, SIGNAL(startClipChanged(Qt3DAnimation::QAbstractClipBlendNode*))); + auto newValue = new Qt3DAnimation::QLerpClipBlend(); + lerpBlend.setStartClip(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(lerpBlend.startClip(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + lerpBlend.setStartClip(newValue); + + // THEN + QCOMPARE(lerpBlend.startClip(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&lerpBlend, SIGNAL(endClipChanged(Qt3DAnimation::QAbstractClipBlendNode*))); + auto newValue = new Qt3DAnimation::QLerpClipBlend(); + lerpBlend.setEndClip(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(lerpBlend.endClip(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + lerpBlend.setEndClip(newValue); + + // THEN + QCOMPARE(lerpBlend.endClip(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QLerpClipBlend lerpBlend; + Qt3DAnimation::QLerpClipBlend startClip; + Qt3DAnimation::QLerpClipBlend endClip; + + lerpBlend.setStartClip(&startClip); + lerpBlend.setEndClip(&endClip); + lerpBlend.setBlendFactor(0.8f); + + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&lerpBlend); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 3); // 1 + 2 clips + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpClipBlendData>>(creationChanges.first()); + const Qt3DAnimation::QLerpClipBlendData cloneData = creationChangeData->data; + + QCOMPARE(lerpBlend.blendFactor(), cloneData.blendFactor); + QCOMPARE(lerpBlend.id(), creationChangeData->subjectId()); + QCOMPARE(lerpBlend.isEnabled(), true); + QCOMPARE(lerpBlend.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(lerpBlend.metaObject(), creationChangeData->metaObject()); + QCOMPARE(cloneData.startClipId, startClip.id()); + QCOMPARE(cloneData.endClipId, endClip.id()); + } + + // WHEN + lerpBlend.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&lerpBlend); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 3); // 1 + 2 clips + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpClipBlendData>>(creationChanges.first()); + const Qt3DAnimation::QLerpClipBlendData cloneData = creationChangeData->data; + + QCOMPARE(lerpBlend.blendFactor(), cloneData.blendFactor); + QCOMPARE(lerpBlend.id(), creationChangeData->subjectId()); + QCOMPARE(lerpBlend.isEnabled(), false); + QCOMPARE(lerpBlend.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(lerpBlend.metaObject(), creationChangeData->metaObject()); + QCOMPARE(cloneData.startClipId, startClip.id()); + QCOMPARE(cloneData.endClipId, endClip.id()); + } + } + + void checkBlendFactorUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QLerpClipBlend lerpBlend; + arbiter.setArbiterOnNode(&lerpBlend); + + { + // WHEN + lerpBlend.setBlendFactor(0.4f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "blendFactor"); + QCOMPARE(change->value().value<float>(), lerpBlend.blendFactor()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + lerpBlend.setBlendFactor(0.4f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkStartClipUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QLerpClipBlend lerpBlend; + arbiter.setArbiterOnNode(&lerpBlend); + auto startClip = new Qt3DAnimation::QLerpClipBlend(); + + { + // WHEN + lerpBlend.setStartClip(startClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "startClip"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), lerpBlend.startClip()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + lerpBlend.setStartClip(startClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkEndClipUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QLerpClipBlend lerpBlend; + arbiter.setArbiterOnNode(&lerpBlend); + auto endClip = new Qt3DAnimation::QLerpClipBlend(); + + { + // WHEN + lerpBlend.setEndClip(endClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "endClip"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), lerpBlend.endClip()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + lerpBlend.setEndClip(endClip); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkStartClipBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DAnimation::QLerpClipBlend> lerpBlend(new Qt3DAnimation::QLerpClipBlend); + { + // WHEN + Qt3DAnimation::QLerpClipBlend clip; + lerpBlend->setStartClip(&clip); + + // THEN + QCOMPARE(clip.parent(), lerpBlend.data()); + QCOMPARE(lerpBlend->startClip(), &clip); + } + // THEN (Should not crash and clip be unset) + QVERIFY(lerpBlend->startClip() == nullptr); + + { + // WHEN + Qt3DAnimation::QLerpClipBlend someOtherLerpBlend; + QScopedPointer<Qt3DAnimation::QLerpClipBlend> clip(new Qt3DAnimation::QLerpClipBlend(&someOtherLerpBlend)); + lerpBlend->setStartClip(clip.data()); + + // THEN + QCOMPARE(clip->parent(), &someOtherLerpBlend); + QCOMPARE(lerpBlend->startClip(), clip.data()); + + // WHEN + lerpBlend.reset(); + clip.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } + + void checkEndClipBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DAnimation::QLerpClipBlend> lerpBlend(new Qt3DAnimation::QLerpClipBlend); + { + // WHEN + Qt3DAnimation::QLerpClipBlend clip; + lerpBlend->setEndClip(&clip); + + // THEN + QCOMPARE(clip.parent(), lerpBlend.data()); + QCOMPARE(lerpBlend->endClip(), &clip); + } + // THEN (Should not crash and clip be unset) + QVERIFY(lerpBlend->endClip() == nullptr); + + { + // WHEN + Qt3DAnimation::QLerpClipBlend someOtherLerpBlend; + QScopedPointer<Qt3DAnimation::QLerpClipBlend> clip(new Qt3DAnimation::QLerpClipBlend(&someOtherLerpBlend)); + lerpBlend->setEndClip(clip.data()); + + // THEN + QCOMPARE(clip->parent(), &someOtherLerpBlend); + QCOMPARE(lerpBlend->endClip(), clip.data()); + + // WHEN + lerpBlend.reset(); + clip.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } +}; + +QTEST_MAIN(tst_QLerpClipBlend) + +#include "tst_qlerpclipblend.moc" diff --git a/tests/auto/animation/qmorphinganimation/qmorphinganimation.pro b/tests/auto/animation/qmorphinganimation/qmorphinganimation.pro new file mode 100644 index 000000000..aaad3b763 --- /dev/null +++ b/tests/auto/animation/qmorphinganimation/qmorphinganimation.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qmorphinganimation + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation testlib + +CONFIG += testcase + +SOURCES += tst_qmorphinganimation.cpp + diff --git a/tests/auto/animation/qmorphinganimation/tst_qmorphinganimation.cpp b/tests/auto/animation/qmorphinganimation/tst_qmorphinganimation.cpp new file mode 100644 index 000000000..77ff01851 --- /dev/null +++ b/tests/auto/animation/qmorphinganimation/tst_qmorphinganimation.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** 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 <QtTest/qtest.h> +#include <Qt3DAnimation/qmorphinganimation.h> +#include <qobject.h> +#include <qsignalspy.h> + +class tst_QMorphingAnimation : public QObject +{ + Q_OBJECT + + bool verifyAttribute(Qt3DRender::QGeometry *geometry, QString name, + Qt3DRender::QAttribute *attribute) + { + const QVector<Qt3DRender::QAttribute *> attributes = geometry->attributes(); + for (const Qt3DRender::QAttribute *attr : attributes) { + if (attr->name() == name) { + if (attr == attribute) + return true; + return false; + } + } + return false; + } + +private Q_SLOTS: + + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QMorphingAnimation::Method>("QMorphingAnimation::Method"); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QMorphingAnimation morphingAnimation; + + // THEN + QCOMPARE(morphingAnimation.interpolator(), 0.0f); + QCOMPARE(morphingAnimation.target(), nullptr); + QCOMPARE(morphingAnimation.targetName(), QString()); + QCOMPARE(morphingAnimation.method(), Qt3DAnimation::QMorphingAnimation::Relative); + QCOMPARE(morphingAnimation.easing(), QEasingCurve()); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QMorphingAnimation morphingAnimation; + + { + // WHEN + QScopedPointer<Qt3DRender::QGeometryRenderer> gr(new Qt3DRender::QGeometryRenderer); + QSignalSpy spy(&morphingAnimation, + SIGNAL(targetChanged(Qt3DRender::QGeometryRenderer *))); + Qt3DRender::QGeometryRenderer *newValue = gr.data(); + morphingAnimation.setTarget(newValue); + + // THEN + QCOMPARE(morphingAnimation.target(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + morphingAnimation.setTarget(newValue); + + // THEN + QCOMPARE(morphingAnimation.target(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&morphingAnimation, SIGNAL(targetNameChanged(QString))); + const QString newValue = QString("target"); + morphingAnimation.setTargetName(newValue); + + // THEN + QCOMPARE(morphingAnimation.targetName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + morphingAnimation.setTargetName(newValue); + + // THEN + QCOMPARE(morphingAnimation.targetName(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&morphingAnimation, SIGNAL(methodChanged(QMorphingAnimation::Method))); + const Qt3DAnimation::QMorphingAnimation::Method newValue + = Qt3DAnimation::QMorphingAnimation::Normalized; + morphingAnimation.setMethod(newValue); + + // THEN + QCOMPARE(morphingAnimation.method(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + morphingAnimation.setMethod(newValue); + + // THEN + QCOMPARE(morphingAnimation.method(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&morphingAnimation, SIGNAL(easingChanged(QEasingCurve))); + const QEasingCurve newValue = QEasingCurve(QEasingCurve::InBounce); + morphingAnimation.setEasing(newValue); + + // THEN + QCOMPARE(morphingAnimation.easing(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + morphingAnimation.setEasing(newValue); + + // THEN + QCOMPARE(morphingAnimation.easing(), newValue); + QCOMPARE(spy.count(), 0); + + } + } + + void testAnimation() + { + // GIVEN + const QString baseName("position"); + const QString targetName("positionTarget"); + Qt3DAnimation::QMorphingAnimation morphingAnimation; + Qt3DRender::QAttribute *base = new Qt3DRender::QAttribute; + + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry; + Qt3DAnimation::QMorphTarget *mt1 = new Qt3DAnimation::QMorphTarget(&morphingAnimation); + Qt3DAnimation::QMorphTarget *mt2 = new Qt3DAnimation::QMorphTarget(&morphingAnimation); + Qt3DAnimation::QMorphTarget *mt3 = new Qt3DAnimation::QMorphTarget(&morphingAnimation); + Qt3DRender::QAttribute *a1 = new Qt3DRender::QAttribute(geometry); + Qt3DRender::QAttribute *a2 = new Qt3DRender::QAttribute(geometry); + Qt3DRender::QAttribute *a3 = new Qt3DRender::QAttribute(geometry); + Qt3DRender::QGeometryRenderer gr; + + base->setName(baseName); + geometry->addAttribute(base); + gr.setGeometry(geometry); + morphingAnimation.setTarget(&gr); + a1->setName(baseName); + a2->setName(baseName); + a3->setName(baseName); + mt1->addAttribute(a1); + mt2->addAttribute(a2); + mt3->addAttribute(a3); + morphingAnimation.addMorphTarget(mt1); + morphingAnimation.addMorphTarget(mt2); + morphingAnimation.addMorphTarget(mt3); + + QVector<float> positions; + QVector<float> weights; + positions.push_back(0.0f); + positions.push_back(1.0f); + positions.push_back(2.0f); + positions.push_back(3.0f); + positions.push_back(4.0f); + morphingAnimation.setTargetPositions(positions); + + weights.resize(3); + + weights[0] = 1.0f; + weights[1] = 0.0f; + weights[2] = 0.0f; + morphingAnimation.setWeights(0, weights); + weights[0] = 0.0f; + weights[1] = 0.0f; + weights[2] = 0.0f; + morphingAnimation.setWeights(1, weights); + weights[0] = 0.0f; + weights[1] = 1.0f; + weights[2] = 0.0f; + morphingAnimation.setWeights(2, weights); + weights[0] = 0.0f; + weights[1] = 0.0f; + weights[2] = 0.0f; + morphingAnimation.setWeights(3, weights); + weights[0] = 0.0f; + weights[1] = 0.0f; + weights[2] = 1.0f; + morphingAnimation.setWeights(4, weights); + + morphingAnimation.setMethod(Qt3DAnimation::QMorphingAnimation::Relative); + { + // WHEN + morphingAnimation.setPosition(0.0f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), -1.0f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a1)); + + // WHEN + morphingAnimation.setPosition(0.5f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), -0.5f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a1)); + + // WHEN + morphingAnimation.setPosition(1.0f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), -0.0f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + + // WHEN + morphingAnimation.setPosition(1.5f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), -0.5f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a2)); + + // WHEN + morphingAnimation.setPosition(4.0f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), -1.0f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a3)); + } + + morphingAnimation.setMethod(Qt3DAnimation::QMorphingAnimation::Normalized); + { + // WHEN + morphingAnimation.setPosition(0.0f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), 1.0f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a1)); + + // WHEN + morphingAnimation.setPosition(0.5f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), 0.5f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a1)); + + // WHEN + morphingAnimation.setPosition(1.0f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), 0.0f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + + // WHEN + morphingAnimation.setPosition(1.5f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), 0.5f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a2)); + + // WHEN + morphingAnimation.setPosition(4.0f); + + // THEN + QVERIFY(qFuzzyCompare(morphingAnimation.interpolator(), 1.0f)); + QVERIFY(verifyAttribute(geometry, baseName, base)); + QVERIFY(verifyAttribute(geometry, targetName, a3)); + } + } +}; + +QTEST_APPLESS_MAIN(tst_QMorphingAnimation) + +#include "tst_qmorphinganimation.moc" diff --git a/tests/auto/animation/qmorphtarget/qmorphtarget.pro b/tests/auto/animation/qmorphtarget/qmorphtarget.pro new file mode 100644 index 000000000..bb38aad19 --- /dev/null +++ b/tests/auto/animation/qmorphtarget/qmorphtarget.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qmorphtarget + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation testlib + +CONFIG += testcase + +SOURCES += tst_qmorphtarget.cpp + diff --git a/tests/auto/animation/qmorphtarget/tst_qmorphtarget.cpp b/tests/auto/animation/qmorphtarget/tst_qmorphtarget.cpp new file mode 100644 index 000000000..2cba9ba2a --- /dev/null +++ b/tests/auto/animation/qmorphtarget/tst_qmorphtarget.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** 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 <QtTest/qtest.h> +#include <Qt3DAnimation/qmorphtarget.h> +#include <qobject.h> +#include <qsignalspy.h> + +class tst_QMorphTarget : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QMorphTarget morphTarget; + + // THEN + QCOMPARE(morphTarget.attributeNames(), QStringList()); + } + + void testSetAttributes() + { + // GIVEN + Qt3DAnimation::QMorphTarget morphTarget; + Qt3DRender::QAttribute attribute1; + Qt3DRender::QAttribute attribute2; + + attribute1.setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + attribute2.setName(Qt3DRender::QAttribute::defaultNormalAttributeName()); + + { + // WHEN + morphTarget.addAttribute(&attribute1); + + // THEN + QStringList names = morphTarget.attributeNames(); + QCOMPARE(names.size(), 1); + QCOMPARE(names.at(0), Qt3DRender::QAttribute::defaultPositionAttributeName()); + } + + { + // WHEN + morphTarget.addAttribute(&attribute2); + + // THEN + QStringList names = morphTarget.attributeNames(); + QCOMPARE(names.size(), 2); + QCOMPARE(names.at(1), Qt3DRender::QAttribute::defaultNormalAttributeName()); + } + } + + void testFromGeometry() + { + // GIVEN + Qt3DRender::QGeometry geometry; + Qt3DRender::QAttribute *attribute1 = new Qt3DRender::QAttribute; + Qt3DRender::QAttribute *attribute2 = new Qt3DRender::QAttribute; + attribute1->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + attribute2->setName(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + geometry.addAttribute(attribute1); + geometry.addAttribute(attribute2); + + QStringList attributes; + attributes.push_back(Qt3DRender::QAttribute::defaultPositionAttributeName()); + + { + // WHEN + QScopedPointer<Qt3DAnimation::QMorphTarget> morphTarget( + Qt3DAnimation::QMorphTarget::fromGeometry(&geometry, attributes)); + + // THEN + QStringList names = morphTarget->attributeNames(); + QCOMPARE(names.size(), 1); + QCOMPARE(names.at(0), Qt3DRender::QAttribute::defaultPositionAttributeName()); + } + + { + // WHEN + attributes.push_back(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + QScopedPointer<Qt3DAnimation::QMorphTarget> morphTarget( + Qt3DAnimation::QMorphTarget::fromGeometry(&geometry, attributes)); + + // THEN + QStringList names = morphTarget->attributeNames(); + QCOMPARE(names.size(), 2); + QCOMPARE(names.at(0), Qt3DRender::QAttribute::defaultPositionAttributeName()); + QCOMPARE(names.at(1), Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + } + } + +}; + +QTEST_APPLESS_MAIN(tst_QMorphTarget) + +#include "tst_qmorphtarget.moc" diff --git a/tests/auto/animation/qvertexblendanimation/qvertexblendanimation.pro b/tests/auto/animation/qvertexblendanimation/qvertexblendanimation.pro new file mode 100644 index 000000000..8079ebf15 --- /dev/null +++ b/tests/auto/animation/qvertexblendanimation/qvertexblendanimation.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +TARGET = tst_qvertexblendanimation + +QT += 3dcore 3dcore-private 3drender 3drender-private 3danimation testlib + +CONFIG += testcase + +SOURCES += tst_qvertexblendanimation.cpp + diff --git a/tests/auto/animation/qvertexblendanimation/tst_qvertexblendanimation.cpp b/tests/auto/animation/qvertexblendanimation/tst_qvertexblendanimation.cpp new file mode 100644 index 000000000..dc27e4a7e --- /dev/null +++ b/tests/auto/animation/qvertexblendanimation/tst_qvertexblendanimation.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** 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 <QtTest/qtest.h> +#include <Qt3DAnimation/qvertexblendanimation.h> +#include <qobject.h> +#include <qsignalspy.h> + +class tst_QVertexBlendAnimation : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QVertexBlendAnimation vertexBlendAnimation; + + // THEN + QCOMPARE(vertexBlendAnimation.interpolator(), 0.0f); + QCOMPARE(vertexBlendAnimation.target(), nullptr); + QCOMPARE(vertexBlendAnimation.targetName(), QString()); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QVertexBlendAnimation vertexBlendAnimation; + + { + // WHEN + QScopedPointer<Qt3DRender::QGeometryRenderer> gm(new Qt3DRender::QGeometryRenderer); + QSignalSpy spy(&vertexBlendAnimation, + SIGNAL(targetChanged(Qt3DRender::QGeometryRenderer *))); + Qt3DRender::QGeometryRenderer *newValue = gm.data(); + vertexBlendAnimation.setTarget(newValue); + + // THEN + QCOMPARE(vertexBlendAnimation.target(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + vertexBlendAnimation.setTarget(newValue); + + // THEN + QCOMPARE(vertexBlendAnimation.target(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&vertexBlendAnimation, SIGNAL(targetNameChanged(QString))); + const QString newValue = QString("target"); + vertexBlendAnimation.setTargetName(newValue); + + // THEN + QCOMPARE(vertexBlendAnimation.targetName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + vertexBlendAnimation.setTargetName(newValue); + + // THEN + QCOMPARE(vertexBlendAnimation.targetName(), newValue); + QCOMPARE(spy.count(), 0); + + } + } + +}; + +QTEST_APPLESS_MAIN(tst_QVertexBlendAnimation) + +#include "tst_qvertexblendanimation.moc" diff --git a/tests/auto/core/common/qbackendnodetester.cpp b/tests/auto/core/common/qbackendnodetester.cpp index 8534a05cd..6f87e10d9 100644 --- a/tests/auto/core/common/qbackendnodetester.cpp +++ b/tests/auto/core/common/qbackendnodetester.cpp @@ -47,6 +47,12 @@ QBackendNodeTester::QBackendNodeTester(QObject *parent) { } +void QBackendNodeTester::setPeerId(QBackendNode *backend, QNodeId id) +{ + Q_ASSERT(backend); + backend->setPeerId(id); +} + void QBackendNodeTester::simulateInitialization(QNode *frontend, QBackendNode *backend) { Q_ASSERT(frontend); diff --git a/tests/auto/core/common/qbackendnodetester.h b/tests/auto/core/common/qbackendnodetester.h index fbd6c9581..9f266e40d 100644 --- a/tests/auto/core/common/qbackendnodetester.h +++ b/tests/auto/core/common/qbackendnodetester.h @@ -55,6 +55,7 @@ public: explicit QBackendNodeTester(QObject *parent = 0); // Proxies to allow test classes to call private methods on QBackendNode + void setPeerId(QBackendNode *backend, QNodeId id); void simulateInitialization(QNode *frontend, QBackendNode *backend); void sceneChangeEvent(QBackendNode *backend, const Qt3DCore::QSceneChangePtr &e); }; diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index 407e8d816..25c2a6dba 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -79,6 +79,8 @@ private slots: void appendingChildEntitiesToNode(); void removingChildEntitiesFromNode(); + void checkConstructionSetParentMix(); // QTBUG-60612 + void appendingComponentToEntity(); void appendingParentlessComponentToEntity(); void removingComponentFromEntity(); @@ -105,7 +107,7 @@ public: void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_FINAL {}; void setScene(Qt3DCore::QScene *) Q_DECL_FINAL {}; void notifyBackend(const Qt3DCore::QSceneChangePtr &change) Q_DECL_FINAL; - bool shouldNotifyFrontend(const Qt3DCore::QSceneChangePtr &changee) Q_DECL_FINAL { return false; } + bool shouldNotifyFrontend(const Qt3DCore::QSceneChangePtr &changee) Q_DECL_FINAL { Q_UNUSED(changee); return false; } private: ObserverSpy *m_spy; @@ -204,6 +206,11 @@ public: Qt3DCore::QNodePrivate::get(this)->setArbiter(arbiter); } + void setSimulateBackendCreated(bool created) + { + Qt3DCore::QNodePrivate::get(this)->m_hasBackendNode = created; + } + signals: void customPropertyChanged(); @@ -232,6 +239,11 @@ public: Qt3DCore::QNodePrivate::get(this)->setScene(scene); Qt3DCore::QNodePrivate::get(this)->setArbiter(arbiter); } + + void setSimulateBackendCreated(bool created) + { + Qt3DCore::QNodePrivate::get(this)->m_hasBackendNode = created; + } }; class MyQComponent : public Qt3DCore::QComponent @@ -250,7 +262,7 @@ public: void tst_Nodes::initTestCase() { - qRegisterMetaType<Qt3DCore::QNode::PropertyTrackMode>("PropertyTrackMode"); + qRegisterMetaType<Qt3DCore::QNode::PropertyTrackingMode>("PropertyTrackingMode"); } void tst_Nodes::defaultNodeConstruction() @@ -389,6 +401,8 @@ void tst_Nodes::appendSingleChildNodeToNodeSceneExplicitParenting() QScopedPointer<MyQNode> node(new MyQNode()); // WHEN node->setArbiterAndScene(&spy, &scene); + node->setSimulateBackendCreated(true); + // THEN QVERIFY(Qt3DCore::QNodePrivate::get(node.data())->scene() != nullptr); @@ -405,7 +419,7 @@ void tst_Nodes::appendSingleChildNodeToNodeSceneExplicitParenting() // THEN QVERIFY(child->parent() == node.data()); QVERIFY(child->parentNode() == node.data()); - QCOMPARE(spy.events.size(), 2); + QCOMPARE(spy.events.size(), 2); // Created + Child Added QCOMPARE(node->children().count(), 1); QVERIFY(Qt3DCore::QNodePrivate::get(child.data())->scene() != nullptr); @@ -482,6 +496,7 @@ void tst_Nodes::appendMultipleChildNodesToNodeScene() // WHEN node->setArbiterAndScene(&spy, &scene); + node->setSimulateBackendCreated(true); // THEN QVERIFY(Qt3DCore::QNodePrivate::get(node.data())->scene() != nullptr); @@ -664,6 +679,7 @@ void tst_Nodes::removingSingleChildNodeFromNode() // WHEN root->setArbiterAndScene(&spy, &scene); + root->setSimulateBackendCreated(true); child->setParent(root.data()); // Clear any creation event @@ -790,6 +806,47 @@ void tst_Nodes::removingChildEntitiesFromNode() QVERIFY(childEntity->parent() == nullptr); } +void tst_Nodes::checkConstructionSetParentMix() +{ + // GIVEN + ObserverSpy spy; + Qt3DCore::QScene scene; + QScopedPointer<MyQNode> root(new MyQNode()); + + // WHEN + root->setArbiterAndScene(&spy, &scene); + root->setSimulateBackendCreated(true); + + // THEN + QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr); + + // WHEN + Qt3DCore::QEntity *subTreeRoot = new Qt3DCore::QEntity(root.data()); + + for (int i = 0; i < 100; ++i) { + Qt3DCore::QEntity *child = new Qt3DCore::QEntity(); + child->setParent(subTreeRoot); + } + + // THEN + QCoreApplication::processEvents(); + QCOMPARE(root->children().count(), 1); + QCOMPARE(subTreeRoot->children().count(), 100); + QCOMPARE(spy.events.size(), 102); // 1 subTreeRoot creation change, 100 child creation, 1 child added (subTree to root) + + // Ensure first event is subTreeRoot + const Qt3DCore::QNodeCreatedChangeBasePtr firstEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!firstEvent.isNull()); + QCOMPARE(firstEvent->subjectId(), subTreeRoot->id()); + QCOMPARE(firstEvent->parentId(), root->id()); + + const Qt3DCore::QPropertyNodeAddedChangePtr lastEvent = spy.events.takeLast().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>(); + QVERIFY(!lastEvent.isNull()); + QCOMPARE(lastEvent->subjectId(), root->id()); + QCOMPARE(lastEvent->propertyName(), "children"); + QCOMPARE(lastEvent->addedNodeId(), subTreeRoot->id()); +} + void tst_Nodes::appendingParentlessComponentToEntity() { // GIVEN @@ -798,6 +855,8 @@ void tst_Nodes::appendingParentlessComponentToEntity() { QScopedPointer<MyQEntity> entity(new MyQEntity()); entity->setArbiterAndScene(&entitySpy); + entity->setSimulateBackendCreated(true); + MyQComponent *comp = new MyQComponent(); comp->setArbiter(&componentSpy); @@ -816,7 +875,7 @@ void tst_Nodes::appendingParentlessComponentToEntity() QVERIFY(comp->parentNode() == entity.data()); QCOMPARE(entitySpy.events.size(), 1); QVERIFY(entitySpy.events.first().wasLocked()); - QCOMPARE(componentSpy.events.size(), 2); // first event is parent being set + QCOMPARE(componentSpy.events.size(), 1); // Note: since QEntity has no scene in this test case, we only have the // ComponentAdded event In theory we should also get the NodeCreated event @@ -969,8 +1028,7 @@ void tst_Nodes::checkDefaultConstruction() // THEN QCOMPARE(node.parentNode(), nullptr); QCOMPARE(node.isEnabled(), true); - QCOMPARE(node.propertyTrackMode(), Qt3DCore::QNode::DefaultTrackMode); - QCOMPARE(node.trackedProperties(), QStringList()); + QCOMPARE(node.defaultPropertyTrackingMode(), Qt3DCore::QNode::TrackFinalValues); } void tst_Nodes::checkPropertyChanges() @@ -1019,41 +1077,37 @@ void tst_Nodes::checkPropertyChanges() } { // WHEN - QSignalSpy spy(&node, SIGNAL(propertyUpdateModeChanged(PropertyTrackMode))); - const Qt3DCore::QNode::PropertyTrackMode newValue = Qt3DCore::QNode::TrackAllPropertiesMode; - node.setPropertyTrackMode(newValue); + QSignalSpy spy(&node, SIGNAL(defaultPropertyTrackingModeChanged(PropertyTrackingMode))); + const Qt3DCore::QNode::PropertyTrackingMode newValue = Qt3DCore::QNode::TrackAllValues; + node.setDefaultPropertyTrackingMode(newValue); // THEN QVERIFY(spy.isValid()); - QCOMPARE(node.propertyTrackMode(), newValue); + QCOMPARE(node.defaultPropertyTrackingMode(), newValue); QCOMPARE(spy.count(), 1); // WHEN spy.clear(); - node.setPropertyTrackMode(newValue); + node.setDefaultPropertyTrackingMode(newValue); // THEN - QCOMPARE(node.propertyTrackMode(), newValue); + QCOMPARE(node.defaultPropertyTrackingMode(), newValue); QCOMPARE(spy.count(), 0); } { // WHEN - QSignalSpy spy(&node, SIGNAL(trackedPropertiesChanged(const QStringList &))); - const QStringList newValue = QStringList() << QStringLiteral("C1") << QStringLiteral("C2") << QStringLiteral("C3"); - node.setTrackedProperties(newValue); + const QString enabledPropertyName = QStringLiteral("enabled"); + node.setDefaultPropertyTrackingMode(Qt3DCore::QNode::DontTrackValues); + node.setPropertyTracking(enabledPropertyName, Qt3DCore::QNode::TrackAllValues); // THEN - QVERIFY(spy.isValid()); - QCOMPARE(node.trackedProperties(), newValue); - QCOMPARE(spy.count(), 1); + QCOMPARE(node.propertyTracking(enabledPropertyName), Qt3DCore::QNode::TrackAllValues); // WHEN - spy.clear(); - node.setTrackedProperties(newValue); + node.clearPropertyTracking(enabledPropertyName); // THEN - QCOMPARE(node.trackedProperties(), newValue); - QCOMPARE(spy.count(), 0); + QCOMPARE(node.propertyTracking(enabledPropertyName), Qt3DCore::QNode::DontTrackValues); } } @@ -1065,9 +1119,9 @@ void tst_Nodes::checkCreationData() node.setParent(&root); node.setEnabled(true); - node.setPropertyTrackMode(Qt3DCore::QNode::TrackNamedPropertiesMode); - const QStringList trackedPropertyNames = QStringList() << QStringLiteral("327"); - node.setTrackedProperties(trackedPropertyNames); + const QString enabledPropertyName = QStringLiteral("enabled"); + node.setDefaultPropertyTrackingMode(Qt3DCore::QNode::DontTrackValues); + node.setPropertyTracking(enabledPropertyName, Qt3DCore::QNode::TrackAllValues); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -1152,7 +1206,7 @@ void tst_Nodes::checkPropertyTrackModeUpdate() { // WHEN - node.setPropertyTrackMode(Qt3DCore::QNode::TrackAllPropertiesMode); + node.setDefaultPropertyTrackingMode(Qt3DCore::QNode::TrackAllValues); QCoreApplication::processEvents(); // THEN -> this properties is non notifying @@ -1161,7 +1215,7 @@ void tst_Nodes::checkPropertyTrackModeUpdate() { // WHEN - node.setPropertyTrackMode(Qt3DCore::QNode::TrackAllPropertiesMode); + node.setDefaultPropertyTrackingMode(Qt3DCore::QNode::TrackAllValues); QCoreApplication::processEvents(); // THEN @@ -1176,11 +1230,10 @@ void tst_Nodes::checkTrackedPropertyNamesUpdate() TestArbiter arbiter; Qt3DCore::QNode node; arbiter.setArbiterOnNode(&node); - const QStringList newValue = QStringList() << QStringLiteral("883") << QStringLiteral("454"); { // WHEN - node.setTrackedProperties(newValue); + node.setPropertyTracking(QStringLiteral("883"), Qt3DCore::QNode::TrackAllValues); QCoreApplication::processEvents(); // THEN -> this properties is non notifying @@ -1189,7 +1242,7 @@ void tst_Nodes::checkTrackedPropertyNamesUpdate() { // WHEN - node.setTrackedProperties(newValue); + node.setPropertyTracking(QStringLiteral("883"), Qt3DCore::QNode::DontTrackValues); QCoreApplication::processEvents(); // THEN diff --git a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp index 061de06fa..faccb6d34 100644 --- a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp +++ b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp @@ -442,6 +442,7 @@ void tst_QChangeArbiter::registerSceneObserver() tst_Node *root = new tst_Node(); Qt3DCore::QNode *child = new tst_Node(); Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); + Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; scene->addObservable(root); QList<tst_SimpleObserver *> observers; @@ -573,6 +574,7 @@ void tst_QChangeArbiter::unregisterSceneObservers() tst_Node *root = new tst_Node(); Qt3DCore::QNode *child = new tst_Node(); Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); + Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; scene->addObservable(root); QList<tst_SimpleObserver *> observers; @@ -796,6 +798,7 @@ void tst_QChangeArbiter::distributePropertyChanges() // WHEN PropertyTestNode *root = new PropertyTestNode(); Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); + Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; scene->addObservable(root); tst_SimpleObserver *rootObserver = new tst_SimpleObserver(); @@ -890,6 +893,7 @@ void tst_QChangeArbiter::distributeBackendChanges() // WHEN tst_Node *root = new tst_Node(); Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); + Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; scene->addObservable(root); tst_BackendObserverObservable *backenObserverObservable = new tst_BackendObserverObservable(); diff --git a/tests/auto/core/qpostman/tst_qpostman.cpp b/tests/auto/core/qpostman/tst_qpostman.cpp index e51c21b59..612db6257 100644 --- a/tests/auto/core/qpostman/tst_qpostman.cpp +++ b/tests/auto/core/qpostman/tst_qpostman.cpp @@ -38,21 +38,22 @@ #include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include "testpostmanarbiter.h" +using namespace Qt3DCore; namespace { -class NodeChangeReceiver: public Qt3DCore::QNode +class NodeChangeReceiver: public QNode { public: - NodeChangeReceiver(Qt3DCore::QNode *parent = nullptr) - : Qt3DCore::QNode(parent) + NodeChangeReceiver(QNode *parent = nullptr) + : QNode(parent) , m_hasReceivedChange(false) {} inline bool hasReceivedChange() const { return m_hasReceivedChange; } protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE + void sceneChangeEvent(const QSceneChangePtr &) Q_DECL_OVERRIDE { m_hasReceivedChange = true; } @@ -72,42 +73,42 @@ private Q_SLOTS: void checkSetScene() { // GIVEN - Qt3DCore::QPostman postman; + QPostman postman; // THEN - QVERIFY(Qt3DCore::QPostmanPrivate::get(&postman)->m_scene == nullptr); + QVERIFY(QPostmanPrivate::get(&postman)->m_scene == nullptr); // WHEN - Qt3DCore::QScene scene; + QScene scene; postman.setScene(&scene); // THEN - QCOMPARE(Qt3DCore::QPostmanPrivate::get(&postman)->m_scene, &scene); + QCOMPARE(QPostmanPrivate::get(&postman)->m_scene, &scene); } void checkSceneChangeEvent() { // GIVEN - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene); - Qt3DCore::QPostman postman; + QScopedPointer<QScene> scene(new QScene); + QPostman postman; TestArbiter arbiter; - Qt3DCore::QNode rootNode; + QNode rootNode; NodeChangeReceiver *receiverNode = new NodeChangeReceiver(); - Qt3DCore::QNodePrivate::get(&rootNode)->m_scene = scene.data(); + QNodePrivate::get(&rootNode)->m_scene = scene.data(); scene->setArbiter(&arbiter); postman.setScene(scene.data()); // Setting the parent (which has a scene) adds the node into the observable lookup // table of the scene which is needed by the postman to distribute changes - static_cast<Qt3DCore::QNode *>(receiverNode)->setParent(&rootNode); + static_cast<QNode *>(receiverNode)->setParent(&rootNode); QCoreApplication::processEvents(); // THEN QCOMPARE(receiverNode->hasReceivedChange(), false); - QCOMPARE(Qt3DCore::QNodePrivate::get(receiverNode)->m_scene, scene.data()); + QCOMPARE(QNodePrivate::get(receiverNode)->m_scene, scene.data()); // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + QPropertyUpdatedChangePtr updateChange(new QPropertyUpdatedChange(receiverNode->id())); updateChange->setValue(1584); updateChange->setPropertyName("someName"); postman.sceneChangeEvent(updateChange); @@ -120,8 +121,8 @@ private Q_SLOTS: void checkNotifyBackend() { // GIVEN - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene); - Qt3DCore::QPostman postman; + QScopedPointer<QScene> scene(new QScene); + QPostman postman; TestArbiter arbiter; scene->setArbiter(&arbiter); @@ -131,7 +132,7 @@ private Q_SLOTS: QCOMPARE(arbiter.events.size(), 0); // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + QPropertyUpdatedChangePtr updateChange(new QPropertyUpdatedChange(QNodeId())); updateChange->setValue(1584); updateChange->setPropertyName("someName"); postman.notifyBackend(updateChange); @@ -145,62 +146,72 @@ private Q_SLOTS: void checkShouldNotifyFrontend() { // GIVEN - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene); - Qt3DCore::QPostman postman; + QScopedPointer<QScene> scene(new QScene); + QPostman postman; TestArbiter arbiter; - Qt3DCore::QNode rootNode; + QNode rootNode; NodeChangeReceiver *receiverNode = new NodeChangeReceiver(); - Qt3DCore::QNodePrivate::get(&rootNode)->m_scene = scene.data(); + QNodePrivate::get(&rootNode)->m_scene = scene.data(); scene->setArbiter(&arbiter); postman.setScene(scene.data()); // Setting the parent (which has a scene) adds the node into the observable lookup // table of the scene which is needed by the postman to distribute changes - static_cast<Qt3DCore::QNode *>(receiverNode)->setParent(&rootNode); + static_cast<QNode *>(receiverNode)->setParent(&rootNode); QCoreApplication::processEvents(); { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); - // THEN -> we don't track properties by default Qt3DCore::QNode::DontTrackProperties - QCOMPARE(postman.shouldNotifyFrontend(updateChange), false); + + // THEN -> we do track properties by default QNode::DefaultTrackMode + // (unless marked as an intermediate change) + QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); } { // WHEN - receiverNode->setPropertyTrackMode(Qt3DCore::QNode::TrackAllPropertiesMode); + receiverNode->setDefaultPropertyTrackingMode(QNode::TrackAllValues); - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); + QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate + = true; - // THEN -> we don't track properties by default + // THEN -> we do track properties marked as intermediate when + // using TrackAllPropertiesMode QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); } { // GIVEN - receiverNode->setPropertyTrackMode(Qt3DCore::QNode::TrackNamedPropertiesMode); - receiverNode->setTrackedProperties(QStringList() << QStringLiteral("vette")); + receiverNode->setDefaultPropertyTrackingMode(QNode::DontTrackValues); + receiverNode->setPropertyTracking(QStringLiteral("vette"), Qt3DCore::QNode::TrackAllValues); { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); + QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate + = true; - // THEN -> we don't track properties by default + // THEN -> we don't track properties by default, unless named when + // using TrackNamedPropertiesMode QCOMPARE(postman.shouldNotifyFrontend(updateChange), false); } { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("vette"); + QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate + = true; // THEN QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); @@ -209,12 +220,12 @@ private Q_SLOTS: { // GIVEN - receiverNode->setTrackedProperties(QStringList() << QStringLiteral("vette")); - receiverNode->setPropertyTrackMode(Qt3DCore::QNode::TrackAllPropertiesMode); + receiverNode->setPropertyTracking(QStringLiteral("vette"), Qt3DCore::QNode::TrackAllValues); + receiverNode->setDefaultPropertyTrackingMode(QNode::TrackAllValues); { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); @@ -224,7 +235,7 @@ private Q_SLOTS: { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("vette"); @@ -235,29 +246,31 @@ private Q_SLOTS: { // GIVEN - receiverNode->setTrackedProperties(QStringList()); - receiverNode->setPropertyTrackMode(Qt3DCore::QNode::DefaultTrackMode); + receiverNode->clearPropertyTrackings(); + receiverNode->setDefaultPropertyTrackingMode(QNode::TrackFinalValues); { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); - // THEN -> we don't track properties by default - QCOMPARE(postman.shouldNotifyFrontend(updateChange), false); + // THEN -> we do track properties by default, unless marked as intermediate + QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); } { // WHEN - Qt3DCore::QPropertyNodeAddedChangePtr addedChange(new Qt3DCore::QPropertyNodeAddedChange(receiverNode->id(), receiverNode)); + auto addedChange + = QPropertyNodeAddedChangePtr::create(receiverNode->id(), receiverNode); // THEN -> only QPropertyUpdatedChangePtr are filtered QCOMPARE(postman.shouldNotifyFrontend(addedChange), true); } { // WHEN - Qt3DCore::QPropertyNodeRemovedChangePtr removedChange(new Qt3DCore::QPropertyNodeRemovedChange(receiverNode->id(), receiverNode)); + auto removedChange + = QPropertyNodeRemovedChangePtr::create(receiverNode->id(), receiverNode); // THEN -> only QPropertyUpdatedChangePtr are filtered QCOMPARE(postman.shouldNotifyFrontend(removedChange), true); @@ -266,25 +279,26 @@ private Q_SLOTS: { // GIVEN - receiverNode->setTrackedProperties(QStringList()); - receiverNode->setPropertyTrackMode(Qt3DCore::QNode::DefaultTrackMode); + receiverNode->clearPropertyTrackings(); + receiverNode->setDefaultPropertyTrackingMode(QNode::TrackFinalValues); { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); + QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate + = true; - // THEN -> we don't track properties by default + // THEN -> we don't track intermediate properties by default QCOMPARE(postman.shouldNotifyFrontend(updateChange), false); } { // WHEN - Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(receiverNode->id())); + auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); updateChange->setValue(1584); updateChange->setPropertyName("someName"); - Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isFinal = true; // THEN QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); diff --git a/tests/auto/core/qscene/tst_qscene.cpp b/tests/auto/core/qscene/tst_qscene.cpp index 9ee4d126e..78f17e8fa 100644 --- a/tests/auto/core/qscene/tst_qscene.cpp +++ b/tests/auto/core/qscene/tst_qscene.cpp @@ -48,6 +48,7 @@ private slots: void removeObservable(); void removeNodeObservable(); void addChildNode(); + void deleteChildNode(); void removeChildNode(); void addEntityForComponent(); void removeEntityForComponent(); @@ -285,6 +286,71 @@ void tst_QScene::addChildNode() } } +void tst_QScene::deleteChildNode() +{ + // GIVEN + Qt3DCore::QScene *scene = new Qt3DCore::QScene; + + QList<Qt3DCore::QNode *> nodes1, nodes2; + + Qt3DCore::QNode *root1 = new tst_Node(); + Qt3DCore::QNode *root2 = new tst_Node(); + Qt3DCore::QNodePrivate::get(root1)->setScene(scene); + Qt3DCore::QNodePrivate::get(root2)->setScene(scene); + Qt3DCore::QNodePrivate::get(root1)->m_hasBackendNode = true; + Qt3DCore::QNodePrivate::get(root2)->m_hasBackendNode = true; + + // WHEN + scene->addObservable(root1); + scene->addObservable(root2); + // THEN + QVERIFY(scene->lookupNode(root1->id()) == root1); + QVERIFY(scene->lookupNode(root2->id()) == root2); + + // WHEN + for (int i = 0; i < 10; i++) { + Qt3DCore::QNode *child1 = new tst_Node(); + child1->setParent(nodes1.isEmpty() ? root1 : nodes1.last()); + nodes1.append(child1); + + Qt3DCore::QNode *child2 = new tst_Node(); + child2->setParent(nodes2.isEmpty() ? root2 : nodes2.last()); + nodes2.append(child2); + } + QCoreApplication::processEvents(); + + // THEN + for (Qt3DCore::QNode *n : qAsConst(nodes1)) { + QVERIFY(scene->lookupNode(n->id()) == n); + } + for (Qt3DCore::QNode *n : qAsConst(nodes2)) { + QVERIFY(scene->lookupNode(n->id()) == n); + } + + // gather node IDs + Qt3DCore::QNodeIdVector root1ChildIds; + for (Qt3DCore::QNode *n : qAsConst(nodes1)) + root1ChildIds << n->id(); + + // WHEN + delete root1; + QCoreApplication::processEvents(); + + // THEN + for (Qt3DCore::QNodeId id : qAsConst(root1ChildIds)) { + QVERIFY(scene->lookupNode(id) == nullptr); + } + + // WHEN + nodes2.first()->setParent(static_cast<Qt3DCore::QNode*>(nullptr)); + QCoreApplication::processEvents(); + + // THEN + for (Qt3DCore::QNode *n : qAsConst(nodes2)) { + QVERIFY(scene->lookupNode(n->id()) == nullptr); + } +} + void tst_QScene::removeChildNode() { // GIVEN @@ -294,6 +360,7 @@ void tst_QScene::removeChildNode() Qt3DCore::QNode *root = new tst_Node; Qt3DCore::QNodePrivate::get(root)->setScene(scene); + Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; scene->addObservable(root); // WHEN @@ -423,36 +490,37 @@ void tst_QScene::setPropertyTrackData() // GIVEN Qt3DCore::QNodeId fakeNodeId = Qt3DCore::QNodeId::createId(); QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene); - const QStringList propertyNamesList = QStringList() << QStringLiteral("1340"); + QHash<QString, Qt3DCore::QNode::PropertyTrackingMode> overridenTrackedProperties; + overridenTrackedProperties.insert(QStringLiteral("1340"), Qt3DCore::QNode::TrackAllValues); // WHEN { Qt3DCore::QScene::NodePropertyTrackData trackData; - trackData.namedProperties = propertyNamesList; - trackData.updateMode = Qt3DCore::QNode::TrackNamedPropertiesMode; + trackData.trackedPropertiesOverrides = overridenTrackedProperties; + trackData.defaultTrackMode = Qt3DCore::QNode::DontTrackValues; scene->setPropertyTrackDataForNode(fakeNodeId, trackData); } // THEN { Qt3DCore::QScene::NodePropertyTrackData trackData = scene->lookupNodePropertyTrackData(fakeNodeId); - QCOMPARE(trackData.namedProperties, propertyNamesList); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::TrackNamedPropertiesMode); + QCOMPARE(trackData.trackedPropertiesOverrides, overridenTrackedProperties); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::DontTrackValues); } // WHEN { Qt3DCore::QScene::NodePropertyTrackData trackData; - trackData.namedProperties = propertyNamesList; - trackData.updateMode = Qt3DCore::QNode::DefaultTrackMode; + trackData.trackedPropertiesOverrides.clear(); + trackData.defaultTrackMode = Qt3DCore::QNode::TrackFinalValues; scene->setPropertyTrackDataForNode(fakeNodeId, trackData); } // THEN { Qt3DCore::QScene::NodePropertyTrackData trackData = scene->lookupNodePropertyTrackData(fakeNodeId); - QCOMPARE(trackData.namedProperties, propertyNamesList); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::DefaultTrackMode); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 0); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::TrackFinalValues); } } @@ -461,21 +529,20 @@ void tst_QScene::lookupNodePropertyTrackData() // GIVEN QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene); Qt3DCore::QNodeId fakeNodeId = Qt3DCore::QNodeId::createId(); - const QStringList propertyNamesList = QStringList() << QStringLiteral("383"); // THEN -> default value for non existent id Qt3DCore::QScene::NodePropertyTrackData trackData = scene->lookupNodePropertyTrackData(fakeNodeId); - QCOMPARE(trackData.namedProperties, QStringList()); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::DefaultTrackMode); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 0); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::TrackFinalValues); // WHEN - trackData.namedProperties = propertyNamesList; - trackData.updateMode = Qt3DCore::QNode::TrackNamedPropertiesMode; + trackData.trackedPropertiesOverrides.insert(QStringLiteral("383"), Qt3DCore::QNode::TrackAllValues); + trackData.defaultTrackMode = Qt3DCore::QNode::DontTrackValues; scene->setPropertyTrackDataForNode(fakeNodeId, trackData); trackData = scene->lookupNodePropertyTrackData(fakeNodeId); - QCOMPARE(trackData.namedProperties, propertyNamesList); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::TrackNamedPropertiesMode); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 1); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::DontTrackValues); } void tst_QScene::removePropertyTrackData() @@ -486,15 +553,15 @@ void tst_QScene::removePropertyTrackData() // WHEN Qt3DCore::QScene::NodePropertyTrackData trackData; - trackData.namedProperties = QStringList() << QStringLiteral("1584"); - trackData.updateMode = Qt3DCore::QNode::TrackNamedPropertiesMode; + trackData.trackedPropertiesOverrides.insert(QStringLiteral("1584"), Qt3DCore::QNode::TrackAllValues); + trackData.defaultTrackMode = Qt3DCore::QNode::DontTrackValues; scene->setPropertyTrackDataForNode(fakeNodeId, trackData); scene->removePropertyTrackDataForNode(fakeNodeId); // THEN -> default value for non existent id trackData = scene->lookupNodePropertyTrackData(fakeNodeId); - QCOMPARE(trackData.namedProperties, QStringList()); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::DefaultTrackMode); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 0); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::TrackFinalValues); } void tst_QScene::nodeSetAndUnsetPropertyTrackData() @@ -505,9 +572,8 @@ void tst_QScene::nodeSetAndUnsetPropertyTrackData() Qt3DCore::QNodePrivate::get(&parentNode)->setScene(scene.data()); Qt3DCore::QNode *childNode = new Qt3DCore::QNode(); - const QStringList propertyNamesList = QStringList() << QStringLiteral("883"); - childNode->setTrackedProperties(propertyNamesList); - childNode->setPropertyTrackMode(Qt3DCore::QNode::TrackNamedPropertiesMode); + childNode->setPropertyTracking(QStringLiteral("883"), Qt3DCore::QNode::TrackAllValues); + childNode->setDefaultPropertyTrackingMode(Qt3DCore::QNode::DontTrackValues); // WHEN childNode->setParent(&parentNode); @@ -516,8 +582,9 @@ void tst_QScene::nodeSetAndUnsetPropertyTrackData() // THEN QCOMPARE(Qt3DCore::QNodePrivate::get(childNode)->m_scene, scene.data()); Qt3DCore::QScene::NodePropertyTrackData trackData = scene->lookupNodePropertyTrackData(childNode->id()); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::TrackNamedPropertiesMode); - QCOMPARE(trackData.namedProperties, propertyNamesList); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::DontTrackValues); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 1); + QCOMPARE(trackData.trackedPropertiesOverrides[QStringLiteral("883")], Qt3DCore::QNode::TrackAllValues); // WHEN const Qt3DCore::QNodeId childNodeId = childNode->id(); @@ -526,8 +593,8 @@ void tst_QScene::nodeSetAndUnsetPropertyTrackData() // THEN -> default value for non existent id trackData = scene->lookupNodePropertyTrackData(childNodeId); - QCOMPARE(trackData.namedProperties, QStringList()); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::DefaultTrackMode); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 0); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::TrackFinalValues); } void tst_QScene::nodeUpdatePropertyTrackData() @@ -538,9 +605,9 @@ void tst_QScene::nodeUpdatePropertyTrackData() Qt3DCore::QNodePrivate::get(&parentNode)->setScene(scene.data()); Qt3DCore::QNode *childNode = new Qt3DCore::QNode(); - const QStringList propertyNamesList = QStringList() << QStringLiteral("883"); - childNode->setTrackedProperties(propertyNamesList); - childNode->setPropertyTrackMode(Qt3DCore::QNode::TrackNamedPropertiesMode); + const QString propertyName = QStringLiteral("883"); + childNode->setPropertyTracking(propertyName, Qt3DCore::QNode::TrackFinalValues); + childNode->setDefaultPropertyTrackingMode(Qt3DCore::QNode::DontTrackValues); // WHEN childNode->setParent(&parentNode); @@ -549,23 +616,26 @@ void tst_QScene::nodeUpdatePropertyTrackData() // THEN QCOMPARE(Qt3DCore::QNodePrivate::get(childNode)->m_scene, scene.data()); Qt3DCore::QScene::NodePropertyTrackData trackData = scene->lookupNodePropertyTrackData(childNode->id()); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::TrackNamedPropertiesMode); - QCOMPARE(trackData.namedProperties, propertyNamesList); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::DontTrackValues); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 1); + QCOMPARE(trackData.trackedPropertiesOverrides[propertyName], Qt3DCore::QNode::TrackFinalValues); // WHEN - childNode->setPropertyTrackMode(Qt3DCore::QNode::TrackAllPropertiesMode); + childNode->setDefaultPropertyTrackingMode(Qt3DCore::QNode::TrackAllValues); // THEN trackData = scene->lookupNodePropertyTrackData(childNode->id()); - QCOMPARE(trackData.updateMode, Qt3DCore::QNode::TrackAllPropertiesMode); + QCOMPARE(trackData.defaultTrackMode, Qt3DCore::QNode::TrackAllValues); // WHEN - const QStringList propertyNamesList2 = QStringList() << QStringLiteral("Viper"); - childNode->setTrackedProperties(propertyNamesList2); + const QString propertyName2 = QStringLiteral("Viper"); + childNode->setPropertyTracking(propertyName2, Qt3DCore::QNode::DontTrackValues); // THEN trackData = scene->lookupNodePropertyTrackData(childNode->id()); - QCOMPARE(trackData.namedProperties, propertyNamesList2); + QCOMPARE(trackData.trackedPropertiesOverrides.size(), 2); + QCOMPARE(trackData.trackedPropertiesOverrides[propertyName], Qt3DCore::QNode::TrackFinalValues); + QCOMPARE(trackData.trackedPropertiesOverrides[propertyName2], Qt3DCore::QNode::DontTrackValues); } QTEST_MAIN(tst_QScene) diff --git a/tests/auto/extras/qfirstpersoncameracontroller/tst_qfirstpersoncameracontroller.cpp b/tests/auto/extras/qfirstpersoncameracontroller/tst_qfirstpersoncameracontroller.cpp index 22046051b..ab43ff2e5 100644 --- a/tests/auto/extras/qfirstpersoncameracontroller/tst_qfirstpersoncameracontroller.cpp +++ b/tests/auto/extras/qfirstpersoncameracontroller/tst_qfirstpersoncameracontroller.cpp @@ -48,6 +48,8 @@ private Q_SLOTS: QVERIFY(firstPersonCameraController.camera() == nullptr); QCOMPARE(firstPersonCameraController.linearSpeed(), 10.0f); QCOMPARE(firstPersonCameraController.lookSpeed(), 180.0f); + QCOMPARE(firstPersonCameraController.acceleration(), -1.0f); + QCOMPARE(firstPersonCameraController.deceleration(), -1.0f); } void checkPropertyChanges() @@ -120,6 +122,44 @@ private Q_SLOTS: QCOMPARE(spy.count(), 0); } + { + // WHEN + QSignalSpy spy(&firstPersonCameraController, SIGNAL(accelerationChanged(float))); + const float newValue = 0.001f; + firstPersonCameraController.setAcceleration(newValue); + + // THEN + QCOMPARE(firstPersonCameraController.acceleration(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + firstPersonCameraController.setAcceleration(newValue); + + // THEN + QCOMPARE(firstPersonCameraController.acceleration(), newValue); + QCOMPARE(spy.count(), 0); + + } + { + // WHEN + QSignalSpy spy(&firstPersonCameraController, SIGNAL(decelerationChanged(float))); + const float newValue = 0.001f; + firstPersonCameraController.setDeceleration(newValue); + + // THEN + QCOMPARE(firstPersonCameraController.deceleration(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + firstPersonCameraController.setDeceleration(newValue); + + // THEN + QCOMPARE(firstPersonCameraController.deceleration(), newValue); + QCOMPARE(spy.count(), 0); + + } } }; diff --git a/tests/auto/extras/qforwardrenderer/tst_qforwardrenderer.cpp b/tests/auto/extras/qforwardrenderer/tst_qforwardrenderer.cpp index 122aed520..d4d856a7c 100644 --- a/tests/auto/extras/qforwardrenderer/tst_qforwardrenderer.cpp +++ b/tests/auto/extras/qforwardrenderer/tst_qforwardrenderer.cpp @@ -55,6 +55,8 @@ private Q_SLOTS: QCOMPARE(forwardRenderer.clearColor(), QColor(Qt::white)); QVERIFY(forwardRenderer.camera() == nullptr); QCOMPARE(forwardRenderer.externalRenderTargetSize(), QSize()); + QVERIFY(forwardRenderer.isFrustumCullingEnabled()); + QCOMPARE(forwardRenderer.gamma(), 2.2f); } void checkPropertyChanges() @@ -163,6 +165,51 @@ private Q_SLOTS: QCOMPARE(spy.count(), 0); } + { + // WHEN + QSignalSpy spy(&forwardRenderer, SIGNAL(frustumCullingEnabledChanged(bool))); + forwardRenderer.setFrustumCullingEnabled(false); + + // THEN + QVERIFY(!forwardRenderer.isFrustumCullingEnabled()); + QCOMPARE(spy.count(), 1); + QVERIFY(!spy.takeFirst().takeFirst().toBool()); + + // WHEN + forwardRenderer.setFrustumCullingEnabled(false); + + // THEN + QVERIFY(!forwardRenderer.isFrustumCullingEnabled()); + QCOMPARE(spy.count(), 0); + + // WHEN + forwardRenderer.setFrustumCullingEnabled(true); + + // THEN + QVERIFY(forwardRenderer.isFrustumCullingEnabled()); + QCOMPARE(spy.count(), 1); + QVERIFY(spy.takeFirst().takeFirst().toBool()); + } + { + // WHEN + QSignalSpy spy(&forwardRenderer, SIGNAL(gammaChanged(float))); + const float newValue = 1.8f; + forwardRenderer.setGamma(newValue); + + // THEN + QCOMPARE(forwardRenderer.gamma(), newValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().toFloat(), 1.8f); + + // WHEN + spy.clear(); + forwardRenderer.setClearColor(newValue); + + // THEN + QCOMPARE(forwardRenderer.gamma(), newValue); + QCOMPARE(spy.count(), 0); + + } } }; diff --git a/tests/auto/input/action/tst_action.cpp b/tests/auto/input/action/tst_action.cpp index da27446f6..91ca2f794 100644 --- a/tests/auto/input/action/tst_action.cpp +++ b/tests/auto/input/action/tst_action.cpp @@ -37,7 +37,6 @@ #include <Qt3DInput/QActionInput> #include <Qt3DInput/QAction> #include <Qt3DCore/private/qbackendnode_p.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include "testpostmanarbiter.h" class DummyActionInput : public Qt3DInput::QActionInput @@ -160,7 +159,6 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "active"); QCOMPARE(change->value().toBool(), backendAction.actionTriggered()); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); diff --git a/tests/auto/input/axis/tst_axis.cpp b/tests/auto/input/axis/tst_axis.cpp index 90f774489..dc8b225ba 100644 --- a/tests/auto/input/axis/tst_axis.cpp +++ b/tests/auto/input/axis/tst_axis.cpp @@ -38,7 +38,6 @@ #include <Qt3DInput/QAnalogAxisInput> #include <Qt3DInput/QAxis> #include <Qt3DCore/private/qbackendnode_p.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include "testpostmanarbiter.h" class DummyAxisInput : public Qt3DInput::QAbstractAxisInput @@ -160,7 +159,6 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "value"); QCOMPARE(change->value().toFloat(), backendAxis.axisValue()); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); diff --git a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp index 9728ac0d0..94cb71030 100644 --- a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp +++ b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp @@ -41,7 +41,6 @@ #include <Qt3DInput/QAxis> #include <Qt3DInput/QAxisAccumulator> #include <Qt3DCore/private/qbackendnode_p.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include "testpostmanarbiter.h" class tst_AxisAccumulator: public Qt3DCore::QBackendNodeTester @@ -170,7 +169,6 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "value"); QCOMPARE(change->value().toFloat(), backendAxisAccumulator.value()); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); @@ -193,7 +191,6 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr velocityChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(velocityChange->propertyName(), "velocity"); QCOMPARE(velocityChange->value().toFloat(), backendAxisAccumulator.velocity()); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); diff --git a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp index a5f54aec9..d19e69ecc 100644 --- a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp +++ b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp @@ -128,7 +128,6 @@ private Q_SLOTS: QCOMPARE(change->value().value<Qt3DInput::QAbstractPhysicalDevice *>(), &physicalDevice); QCOMPARE(change->subjectId(), backendPhysicalDeviceProxy.peerId()); QCOMPARE(backendPhysicalDeviceProxy.physicalDeviceId(), physicalDevice.id()); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); } void checkCleanupState() diff --git a/tests/auto/quick3d/3dcore/3dcore.qml b/tests/auto/quick3d/3dcore/3dcore.qml index 1d9d885ff..df9dd429b 100644 --- a/tests/auto/quick3d/3dcore/3dcore.qml +++ b/tests/auto/quick3d/3dcore/3dcore.qml @@ -28,6 +28,7 @@ import Qt3D.Core 2.0 as QQ3Core20 +import Qt3D.Core 2.9 as QQ3Core29 import QtQuick 2.0 Item { @@ -40,4 +41,5 @@ Item { QQ3Core20.Transform {} //Qt3DCore::QTransform QQ3Core20.QuaternionAnimation {} //Qt3DCore::Quick::QQuaternionAnimation + QQ3Core29.Entity {} //Qt3DCore::QEntity, Qt3DCore::Quick::Quick3DEntity } diff --git a/tests/auto/quick3d/quick3d.pro b/tests/auto/quick3d/quick3d.pro index 8abe04550..dd67a3ef4 100644 --- a/tests/auto/quick3d/quick3d.pro +++ b/tests/auto/quick3d/quick3d.pro @@ -7,5 +7,6 @@ qtConfig(private_tests) { 3drender \ 3dinput \ 3dcore \ - quick3dbuffer + quick3dbuffer \ + quick3dnode } diff --git a/tests/auto/quick3d/quick3dnode/quick3dnode.pro b/tests/auto/quick3d/quick3dnode/quick3dnode.pro new file mode 100644 index 000000000..5b3038c42 --- /dev/null +++ b/tests/auto/quick3d/quick3dnode/quick3dnode.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_quick3dnode + +QT += 3dcore 3dcore-private 3drender 3drender-private 3dquick 3dquick-private 3dquickrender-private testlib + +CONFIG += testcase + +include(../../render/qmlscenereader/qmlscenereader.pri) + +SOURCES += tst_quick3dnode.cpp + +RESOURCES += quick3dnode.qrc diff --git a/tests/auto/quick3d/quick3dnode/quick3dnode.qrc b/tests/auto/quick3d/quick3dnode/quick3dnode.qrc new file mode 100644 index 000000000..afdbbbb66 --- /dev/null +++ b/tests/auto/quick3d/quick3dnode/quick3dnode.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>quick3dnodev9.qml</file> + </qresource> +</RCC> diff --git a/tests/auto/quick3d/quick3dnode/quick3dnodev9.qml b/tests/auto/quick3d/quick3dnode/quick3dnodev9.qml new file mode 100644 index 000000000..5429faf4e --- /dev/null +++ b/tests/auto/quick3d/quick3dnode/quick3dnodev9.qml @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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$ +** +****************************************************************************/ + +import Qt3D.Core 2.9 + +Entity { + propertyTrackingOverrides: { + "enabled": Entity.DontTrackValues, + "displacement": Entity.TrackFinalValues + } +} diff --git a/tests/auto/animation/qconductedclipanimator/tst_qconductedclipanimator.cpp b/tests/auto/quick3d/quick3dnode/tst_quick3dnode.cpp index 7e40e5033..38bf46a7a 100644 --- a/tests/auto/animation/qconductedclipanimator/tst_qconductedclipanimator.cpp +++ b/tests/auto/quick3d/quick3dnode/tst_quick3dnode.cpp @@ -26,39 +26,30 @@ ** ****************************************************************************/ - #include <QtTest/QTest> -#include <Qt3DAnimation/qanimationclip.h> -#include <Qt3DAnimation/qconductedclipanimator.h> -#include <Qt3DAnimation/private/qanimationclip_p.h> -#include <Qt3DAnimation/private/qconductedclipanimator_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qnodecreatedchange.h> -#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DQuick/private/quick3dnode_p.h> #include <QObject> -#include <QSignalSpy> -#include <testpostmanarbiter.h> +#include <qmlscenereader.h> -class tst_QConductedClipAnimator : public QObject +class tst_Quick3DNode : public QObject { Q_OBJECT private Q_SLOTS: - void initTestCase() - { - qRegisterMetaType<Qt3DAnimation::QAnimationClip*>(); - } - void checkDefaultConstruction() + void checkPropertyTrackingOverrides_V9() { // GIVEN - Qt3DAnimation::QConductedClipAnimator animator; + QmlSceneReader sceneReader(QUrl("qrc:/quick3dnodev9.qml")); // THEN - // TODO: Check default property state + QVERIFY(sceneReader.root() != nullptr); + Qt3DCore::QNode *node = static_cast<Qt3DCore::QNode *>(sceneReader.root()); + QCOMPARE(node->propertyTracking(QLatin1String("enabled")), Qt3DCore::QNode::DontTrackValues); + QCOMPARE(node->propertyTracking(QLatin1String("displacement")), Qt3DCore::QNode::TrackFinalValues); } }; -QTEST_MAIN(tst_QConductedClipAnimator) +QTEST_MAIN(tst_Quick3DNode) -#include "tst_qconductedclipanimator.moc" +#include "tst_quick3dnode.moc" diff --git a/tests/auto/render/boundingsphere/boundingsphere.pro b/tests/auto/render/boundingsphere/boundingsphere.pro new file mode 100644 index 000000000..cebba17e7 --- /dev/null +++ b/tests/auto/render/boundingsphere/boundingsphere.pro @@ -0,0 +1,17 @@ +TEMPLATE = app + +TARGET = tst_boundingsphere +QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras testlib + +CONFIG += testcase + +SOURCES += tst_boundingsphere.cpp + +include(../commons/commons.pri) +include(../../core/common/common.pri) +include(../qmlscenereader/qmlscenereader.pri) +# Extra dependencies to build test scenes needed by the tests +QT += quick 3dquick 3dquick-private 3dextras 3dquickextras + +RESOURCES += \ + boundingsphere.qrc diff --git a/tests/auto/render/boundingsphere/boundingsphere.qrc b/tests/auto/render/boundingsphere/boundingsphere.qrc new file mode 100644 index 000000000..5ea2cb958 --- /dev/null +++ b/tests/auto/render/boundingsphere/boundingsphere.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>sphere.qml</file> + <file>cube.qml</file> + </qresource> +</RCC> diff --git a/tests/auto/render/boundingsphere/cube.qml b/tests/auto/render/boundingsphere/cube.qml new file mode 100644 index 000000000..11d6d4db1 --- /dev/null +++ b/tests/auto/render/boundingsphere/cube.qml @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: sceneRoot + + components: [ ] + + // Parent Entity + Entity { + + components: [ + CuboidMesh { id: testMesh; objectName: "testMesh" }, + PhongMaterial { id: material } + ] + } + +} diff --git a/tests/auto/render/boundingsphere/sphere.qml b/tests/auto/render/boundingsphere/sphere.qml new file mode 100644 index 000000000..1f0e2245a --- /dev/null +++ b/tests/auto/render/boundingsphere/sphere.qml @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: sceneRoot + + components: [ ] + + // Parent Entity + Entity { + + components: [ + SphereMesh { id: testMesh; objectName: "testMesh" }, + PhongMaterial { id: material } + ] + } + +} diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp new file mode 100644 index 000000000..fcbfaf6ba --- /dev/null +++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** 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 "testpostmanarbiter.h" + +#include <QUrl> + +#include <QtTest/QTest> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qtransform.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/private/qaspectjobmanager_p.h> +#include <QtQuick/qquickwindow.h> + +#include <Qt3DRender/QCamera> +#include <Qt3DRender/QObjectPicker> +#include <Qt3DRender/QPickEvent> +#include <Qt3DRender/QPickTriangleEvent> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DRender/qrenderaspect.h> +#include <Qt3DRender/private/qrenderaspect_p.h> +#include <Qt3DRender/private/pickboundingvolumejob_p.h> +#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h> +#include <Qt3DRender/private/updateworldboundingvolumejob_p.h> +#include <Qt3DRender/private/updateworldtransformjob_p.h> +#include <Qt3DRender/private/expandboundingvolumejob_p.h> +#include <Qt3DRender/private/calcboundingvolumejob_p.h> +#include <Qt3DRender/private/calcgeometrytrianglevolumes_p.h> +#include <Qt3DRender/private/loadbufferjob_p.h> +#include <Qt3DRender/private/buffermanager_p.h> +#include <Qt3DRender/private/geometryrenderermanager_p.h> +#include <Qt3DRender/private/sphere_p.h> + +#include <Qt3DExtras/qspheremesh.h> +#include <Qt3DExtras/qcylindermesh.h> +#include <Qt3DExtras/qtorusmesh.h> +#include <Qt3DExtras/qcuboidmesh.h> +#include <Qt3DExtras/qplanemesh.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class TestAspect : public Qt3DRender::QRenderAspect +{ +public: + TestAspect(Qt3DCore::QNode *root) + : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) + , m_sceneRoot(nullptr) + { + QRenderAspect::onRegistered(); + + const Qt3DCore::QNodeCreatedChangeGenerator generator(root); + const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges(); + + d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges); + + Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); + Q_ASSERT(rootEntity); + m_sceneRoot = rootEntity; + } + + ~TestAspect() + { + QRenderAspect::onUnregistered(); + } + + 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; } + +private: + Render::Entity *m_sceneRoot; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +namespace { + +void runRequiredJobs(Qt3DRender::TestAspect *test) +{ + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; + updateWorldTransform.setRoot(test->sceneRoot()); + updateWorldTransform.run(); + + // For each buffer + QVector<Qt3DRender::Render::HBuffer> bufferHandles = test->nodeManagers()->bufferManager()->activeHandles(); + for (auto bufferHandle : bufferHandles) { + Qt3DRender::Render::LoadBufferJob loadBuffer(bufferHandle); + loadBuffer.setNodeManager(test->nodeManagers()); + loadBuffer.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.run(); + + Qt3DRender::Render::UpdateMeshTriangleListJob updateTriangleList; + updateTriangleList.setManagers(test->nodeManagers()); + updateTriangleList.run(); + + // For each geometry id + QVector<Qt3DRender::Render::HGeometryRenderer> geometryRenderHandles = test->nodeManagers()->geometryRendererManager()->activeHandles(); + for (auto geometryRenderHandle : geometryRenderHandles) { + Qt3DCore::QNodeId geometryRendererId = test->nodeManagers()->geometryRendererManager()->data(geometryRenderHandle)->peerId(); + Qt3DRender::Render::CalcGeometryTriangleVolumes calcGeometryTriangles(geometryRendererId, test->nodeManagers()); + calcGeometryTriangles.run(); + } +} + +} // anonymous + +class tst_BoundingSphere : public QObject +{ + Q_OBJECT +private: + +private Q_SLOTS: + void checkExtraGeometries_data() + { + QTest::addColumn<QString>("qmlFile"); + QTest::addColumn<QVector3D>("sphereCenter"); + QTest::addColumn<float>("sphereRadius"); + QTest::newRow("SphereMesh") << "qrc:/sphere.qml" << QVector3D(0.f, 0.f, 0.f) << 1.f; + QTest::newRow("CubeMesh") << "qrc:/cube.qml" << QVector3D(0.0928356f, -0.212021f, -0.0467958f) << 1.07583f; // weird! + } + + void checkExtraGeometries() + { + // GIVEN + QFETCH(QString, qmlFile); + QFETCH(QVector3D, sphereCenter); + QFETCH(float, sphereRadius); + + QUrl qmlUrl(qmlFile); + QmlSceneReader sceneReader(qmlUrl); + QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root())); + QVERIFY(root); + + QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); + + // Runs Required jobs + runRequiredJobs(test.data()); + + // THEN + QVERIFY(test->sceneRoot()->worldBoundingVolumeWithChildren()); + const auto boundingSphere = test->sceneRoot()->worldBoundingVolumeWithChildren(); + qDebug() << qmlFile << boundingSphere->radius() << boundingSphere->center(); + QCOMPARE(boundingSphere->radius(), sphereRadius); + QVERIFY(qAbs(boundingSphere->center().x() - sphereCenter.x()) < 0.000001f); // qFuzzyCompare hates 0s + QVERIFY(qAbs(boundingSphere->center().y() - sphereCenter.y()) < 0.000001f); + QVERIFY(qAbs(boundingSphere->center().z() - sphereCenter.z()) < 0.000001f); + } +}; + +QTEST_MAIN(tst_BoundingSphere) + +#include "tst_boundingsphere.moc" diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index da5f74dd6..8049aaf37 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -33,7 +33,6 @@ #include <Qt3DRender/private/buffermanager_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qbackendnode_p.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include "testpostmanarbiter.h" #include "testrenderer.h" @@ -51,7 +50,7 @@ public: bool operator ==(const Qt3DRender::QBufferDataGenerator &other) const Q_DECL_FINAL { - const TestFunctor *otherFunctor = functor_cast<TestFunctor>(&other); + const TestFunctor *otherFunctor = Qt3DRender::functor_cast<TestFunctor>(&other); if (otherFunctor != nullptr) return otherFunctor->m_size == m_size; return false; @@ -90,6 +89,8 @@ private Q_SLOTS: QCOMPARE(renderBuffer.data(), buffer.data()); QCOMPARE(renderBuffer.dataGenerator(), buffer.dataGenerator()); QVERIFY(*renderBuffer.dataGenerator() == *buffer.dataGenerator()); + QCOMPARE(renderBuffer.pendingBufferUpdates().size(), 1); + QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1); } void checkInitialAndCleanedUpState() @@ -196,7 +197,10 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.data(), QByteArrayLiteral("LS9")); QVERIFY(renderBuffer.isDirty()); + QCOMPARE(renderBuffer.pendingBufferUpdates().size(), 1); + QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1); + renderBuffer.pendingBufferUpdates().clear(); renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -234,9 +238,11 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "data"); QCOMPARE(change->value().toByteArray(), QByteArrayLiteral("454")); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); + QCOMPARE(renderBuffer.pendingBufferUpdates().size(), 1); + QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1); arbiter.events.clear(); + renderBuffer.pendingBufferUpdates().clear(); // WHEN updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); @@ -249,6 +255,7 @@ private Q_SLOTS: // THEN QVERIFY(!renderBuffer.pendingBufferUpdates().empty()); + QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, 2); QVERIFY(renderBuffer.isDirty()); renderBuffer.unsetDirty(); diff --git a/tests/auto/render/commons/testrenderer.cpp b/tests/auto/render/commons/testrenderer.cpp index 87e60a263..5304ff142 100644 --- a/tests/auto/render/commons/testrenderer.cpp +++ b/tests/auto/render/commons/testrenderer.cpp @@ -32,6 +32,7 @@ QT_BEGIN_NAMESPACE TestRenderer::TestRenderer() : m_changes(0) + , m_managers(nullptr) { } @@ -76,4 +77,9 @@ QSurfaceFormat TestRenderer::format() return QSurfaceFormat(); } +QOpenGLContext *TestRenderer::shareContext() const +{ + return nullptr; +} + QT_END_NAMESPACE diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 2e572582e..031ca214b 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -43,10 +43,10 @@ public: API api() const Q_DECL_OVERRIDE { return AbstractRenderer::OpenGL; } qint64 time() const Q_DECL_OVERRIDE { return 0; } void setTime(qint64 time) Q_DECL_OVERRIDE { Q_UNUSED(time); } - void setNodeManagers(Qt3DRender::Render::NodeManagers *managers) Q_DECL_OVERRIDE { Q_UNUSED(managers); } + void setNodeManagers(Qt3DRender::Render::NodeManagers *m) Q_DECL_OVERRIDE { m_managers = m; } void setServices(Qt3DCore::QServiceLocator *services) Q_DECL_OVERRIDE { Q_UNUSED(services); } void setSurfaceExposed(bool exposed) Q_DECL_OVERRIDE { Q_UNUSED(exposed); } - Qt3DRender::Render::NodeManagers *nodeManagers() const Q_DECL_OVERRIDE { return nullptr; } + Qt3DRender::Render::NodeManagers *nodeManagers() const Q_DECL_OVERRIDE { return m_managers; } Qt3DCore::QServiceLocator *services() const Q_DECL_OVERRIDE { return nullptr; } void initialize() Q_DECL_OVERRIDE {} void shutdown() Q_DECL_OVERRIDE {} @@ -60,6 +60,7 @@ public: QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() Q_DECL_OVERRIDE { return QVector<Qt3DCore::QAspectJobPtr>(); } Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr syncTextureLoadingJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } + Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Qt3DRender::Render::Entity *root) Q_DECL_OVERRIDE { Q_UNUSED(factory); Q_UNUSED(root); } Qt3DRender::Render::Entity *sceneRoot() const Q_DECL_OVERRIDE { return nullptr; } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const Q_DECL_OVERRIDE { return nullptr; } @@ -74,12 +75,14 @@ public: void resetDirty(); QVariant executeCommand(const QStringList &args) Q_DECL_OVERRIDE; + QOpenGLContext *shareContext() const Q_DECL_OVERRIDE; void setOffscreenSurfaceHelper(Qt3DRender::Render::OffscreenSurfaceHelper *helper) Q_DECL_OVERRIDE; QSurfaceFormat format() Q_DECL_OVERRIDE; protected: Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet m_changes; + Qt3DRender::Render::NodeManagers *m_managers; }; QT_END_NAMESPACE diff --git a/tests/auto/render/coordinatereader/coordinatereader.pro b/tests/auto/render/coordinatereader/coordinatereader.pro new file mode 100644 index 000000000..036898c2b --- /dev/null +++ b/tests/auto/render/coordinatereader/coordinatereader.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = coordinatereader + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_coordinatereader.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/coordinatereader/tst_coordinatereader.cpp b/tests/auto/render/coordinatereader/tst_coordinatereader.cpp new file mode 100644 index 000000000..7dfe3ceba --- /dev/null +++ b/tests/auto/render/coordinatereader/tst_coordinatereader.cpp @@ -0,0 +1,491 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** 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 <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DRender/qbuffer.h> +#include <private/trianglesvisitor_p.h> +#include <private/nodemanagers_p.h> +#include <private/managers_p.h> +#include <private/geometryrenderer_p.h> +#include <private/geometryrenderermanager_p.h> +#include <private/buffermanager_p.h> +#include "testrenderer.h" + +using namespace Qt3DRender::Render; + +class TestReader : public CoordinateReader +{ +public: + TestReader(NodeManagers *manager) + : CoordinateReader(manager) + { + + } + NodeManagers *manager() const + { + return m_manager; + } + + Attribute *attribute() const + { + return m_attribute; + } + + Buffer *buffer() const + { + return m_buffer; + } + + BufferInfo bufferInfo() const + { + return m_bufferInfo; + } + bool verifyCoordinate(uint index, QVector4D value) + { + return qFuzzyCompare(getCoordinate(index), value); + } +}; + +class tst_CoordinateReader : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialize() + { + // WHEN + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + TestReader reader(nodeManagers.data()); + + // THEN + QCOMPARE(reader.manager(), nodeManagers.data()); + } + + void checkSetEmptyGeometry() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer( + new Qt3DRender::QGeometryRenderer()); + TestReader reader(nodeManagers.data()); + TestRenderer renderer; + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager() + ->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + bool ret = reader.setGeometry(backendRenderer, QString("")); + + // THEN + QCOMPARE(ret, false); + QCOMPARE(reader.attribute(), nullptr); + QCOMPARE(reader.buffer(), nullptr); + } + + void checkSetGeometry() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer( + new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestReader reader(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 3 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + + dataPtr[9] = 0; + dataPtr[10] = 0; + dataPtr[11] = 1.0f; + dataPtr[12] = 1.0f; + dataPtr[13] = 0; + dataPtr[14] = 0; + dataPtr[15] = 0; + dataPtr[16] = 1.0f; + dataPtr[17] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(6); + positionAttribute->setByteStride(3 * 4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + + Attribute *backendAttribute = nodeManagers->attributeManager() + ->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager() + ->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager() + ->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + bool ret = reader.setGeometry(backendRenderer, + Qt3DRender::QAttribute::defaultPositionAttributeName()); + + // THEN + QCOMPARE(ret, true); + QCOMPARE(reader.attribute(), backendAttribute); + QCOMPARE(reader.buffer(), backendBuffer); + QCOMPARE(reader.bufferInfo().type, Qt3DRender::QAttribute::Float); + QCOMPARE(reader.bufferInfo().dataSize, 3u); + QCOMPARE(reader.bufferInfo().count, 6u); + QCOMPARE(reader.bufferInfo().byteStride, 12u); + QCOMPARE(reader.bufferInfo().byteOffset, 0u); + } + + void testReadCoordinate() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer( + new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestReader reader(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 3 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + + dataPtr[9] = 0; + dataPtr[10] = 0; + dataPtr[11] = 1.0f; + dataPtr[12] = 1.0f; + dataPtr[13] = 0; + dataPtr[14] = 0; + dataPtr[15] = 0; + dataPtr[16] = 1.0f; + dataPtr[17] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(6); + positionAttribute->setByteStride(3 * 4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + + Attribute *backendAttribute = nodeManagers->attributeManager() + ->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager() + ->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager() + ->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + bool ret = reader.setGeometry(backendRenderer, + Qt3DRender::QAttribute::defaultPositionAttributeName()); + + // THEN + QCOMPARE(ret, true); + + QVERIFY(reader.verifyCoordinate(0, QVector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(1, QVector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(2, QVector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(3, QVector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(4, QVector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(5, QVector4D(0, 1, 0, 1))); + } + + void testReadCoordinateVec4() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer( + new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestReader reader(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 4 * 3 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + + dataPtr[4] = 1.0f; + dataPtr[5] = 0; + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + + dataPtr[8] = 0; + dataPtr[9] = 1.0f; + dataPtr[10] = 0; + dataPtr[11] = 0; + + dataPtr[12] = 0; + dataPtr[13] = 0; + dataPtr[14] = 1.0f; + dataPtr[15] = 0; + + dataPtr[16] = 1.0f; + dataPtr[17] = 0; + dataPtr[18] = 0; + dataPtr[19] = 0; + + dataPtr[20] = 0; + dataPtr[21] = 1.0f; + dataPtr[22] = 0; + dataPtr[23] = 1.0f; + + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(4); + positionAttribute->setCount(6); + positionAttribute->setByteStride(4 * 4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + + Attribute *backendAttribute = nodeManagers->attributeManager() + ->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager() + ->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager() + ->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + bool ret = reader.setGeometry(backendRenderer, + Qt3DRender::QAttribute::defaultPositionAttributeName()); + + // THEN + QCOMPARE(ret, true); + + QVERIFY(reader.verifyCoordinate(0, QVector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(1, QVector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(2, QVector4D(0, 1, 0, 0))); + QVERIFY(reader.verifyCoordinate(3, QVector4D(0, 0, 1, 0))); + QVERIFY(reader.verifyCoordinate(4, QVector4D(1, 0, 0, 0))); + QVERIFY(reader.verifyCoordinate(5, QVector4D(0, 1, 0, 1))); + } + + void testReadCoordinateFromAttribute() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer( + new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> texcoordAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestReader reader(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 3 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + + dataPtr[9] = 0; + dataPtr[10] = 0; + dataPtr[11] = 1.0f; + + dataPtr[12] = 1.0f; + dataPtr[13] = 0; + dataPtr[14] = 0; + + dataPtr[15] = 0; + dataPtr[16] = 1.0f; + dataPtr[17] = 0; + + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(3); + positionAttribute->setByteStride(3 * 4 * 2); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + texcoordAttribute->setBuffer(dataBuffer.data()); + texcoordAttribute->setName(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + texcoordAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + texcoordAttribute->setVertexSize(3); + texcoordAttribute->setCount(6); + texcoordAttribute->setByteStride(3 * 4 * 2); + texcoordAttribute->setByteOffset(3 * 4); + texcoordAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(texcoordAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource( + positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendTexcoordAttribute = nodeManagers->attributeManager() + ->getOrCreateResource(texcoordAttribute->id()); + backendTexcoordAttribute->setRenderer(&renderer); + simulateInitialization(texcoordAttribute.data(), backendTexcoordAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager() + ->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager() + ->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + bool ret = reader.setGeometry(backendRenderer, + Qt3DRender::QAttribute::defaultPositionAttributeName()); + + // THEN + QCOMPARE(ret, true); + + QVERIFY(reader.verifyCoordinate(0, QVector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(1, QVector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(2, QVector4D(1, 0, 0, 1))); + + // WHEN + ret = reader.setGeometry(backendRenderer, + Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + + // THEN + QCOMPARE(ret, true); + + QVERIFY(reader.verifyCoordinate(0, QVector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(1, QVector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(2, QVector4D(0, 1, 0, 1))); + } + +}; + +QTEST_MAIN(tst_CoordinateReader) + +#include "tst_coordinatereader.moc" diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index 0bd3a6054..d1a222c92 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -38,6 +38,7 @@ #include <Qt3DCore/QComponentRemovedChange> #include <Qt3DCore/QTransform> +#include <Qt3DRender/QEnvironmentLight> #include <Qt3DRender/QMesh> #include <Qt3DRender/QMaterial> #include <Qt3DRender/QLayer> @@ -64,6 +65,7 @@ QNodeId computeJobUuid(Entity *entity) { return entity->componentUuid<ComputeCom QVector<QNodeId> layersUuid(Entity *entity) { return entity->componentsUuid<Layer>(); } QVector<QNodeId> shadersUuid(Entity *entity) { return entity->componentsUuid<ShaderData>(); } +QVector<QNodeId> environmentLightsUuid(Entity *entity) { return entity->componentsUuid<EnvironmentLight>(); } class tst_RenderEntity : public QObject { @@ -86,7 +88,8 @@ private slots: << new QObjectPicker << new QLayer << new QShaderData - << new QComputeCommand; + << new QComputeCommand + << new QEnvironmentLight; QTest::newRow("all components") << components; } @@ -112,6 +115,7 @@ private slots: QVERIFY(entity.componentUuid<ComputeCommand>().isNull()); QVERIFY(entity.componentsUuid<Layer>().isEmpty()); QVERIFY(entity.componentsUuid<ShaderData>().isEmpty()); + QVERIFY(entity.componentsUuid<EnvironmentLight>().isEmpty()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); @@ -139,6 +143,7 @@ private slots: QVERIFY(!entity.componentUuid<ComputeCommand>().isNull()); QVERIFY(!entity.componentsUuid<Layer>().isEmpty()); QVERIFY(!entity.componentsUuid<ShaderData>().isEmpty()); + QVERIFY(!entity.componentsUuid<EnvironmentLight>().isEmpty()); QVERIFY(entity.isBoundingVolumeDirty()); QVERIFY(!entity.childrenHandles().isEmpty()); QVERIFY(renderer.dirtyBits() != 0); @@ -157,6 +162,7 @@ private slots: QVERIFY(entity.componentUuid<QComputeCommand>().isNull()); QVERIFY(entity.componentsUuid<Layer>().isEmpty()); QVERIFY(entity.componentsUuid<ShaderData>().isEmpty()); + QVERIFY(entity.componentsUuid<EnvironmentLight>().isEmpty()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); containsAll = entity.containsComponentsOfType<Transform, CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand>(); @@ -236,6 +242,10 @@ private slots: components.clear(); components << new QShaderData << new QShaderData << new QShaderData; QTest::newRow("shader data") << components << reinterpret_cast<void*>(shadersUuid); + + components.clear(); + components << new QEnvironmentLight << new QEnvironmentLight << new QEnvironmentLight; + QTest::newRow("environmentLights") << components << reinterpret_cast<void*>(environmentLightsUuid); } void shouldHandleComponentsEvents() diff --git a/tests/auto/render/framegraphvisitor/framegraphvisitor.pro b/tests/auto/render/framegraphvisitor/framegraphvisitor.pro new file mode 100644 index 000000000..2c9a0028e --- /dev/null +++ b/tests/auto/render/framegraphvisitor/framegraphvisitor.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_framegraphvisitor + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_framegraphvisitor.cpp + +CONFIG += useCommonTestAspect + +include(../commons/commons.pri) diff --git a/tests/auto/render/framegraphvisitor/tst_framegraphvisitor.cpp b/tests/auto/render/framegraphvisitor/tst_framegraphvisitor.cpp new file mode 100644 index 000000000..5344d7eb3 --- /dev/null +++ b/tests/auto/render/framegraphvisitor/tst_framegraphvisitor.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DCore/qentity.h> + +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/entity_p.h> + +#include <Qt3DRender/private/framegraphnode_p.h> +#include <Qt3DRender/private/framegraphvisitor_p.h> + +#include <Qt3DRender/qtechniquefilter.h> +#include <Qt3DRender/qnodraw.h> +#include <Qt3DRender/qfrustumculling.h> +#include <Qt3DRender/qviewport.h> + +#include "testaspect.h" + +namespace { + + + +} // anonymous + +using FGIdType = QPair<Qt3DCore::QNodeId, Qt3DRender::Render::FrameGraphNode::FrameGraphNodeType>; +using BranchIdsAndTypes = QVector<FGIdType>; + +Q_DECLARE_METATYPE(QVector<BranchIdsAndTypes>) + +class tst_FrameGraphVisitor : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void visitFGTree_data() + { + QTest::addColumn<Qt3DCore::QEntity *>("rootEntity"); + QTest::addColumn<Qt3DRender::QFrameGraphNode *>("fgRoot"); + QTest::addColumn<QVector<BranchIdsAndTypes>>("fgNodeIdsPerBranch"); + + { + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(); + Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(entity); + + QTest::newRow("singleNode") << entity + << static_cast<Qt3DRender::QFrameGraphNode *>(techniqueFilter) + << (QVector<BranchIdsAndTypes>() + << (BranchIdsAndTypes() << FGIdType(techniqueFilter->id(), Qt3DRender::Render::FrameGraphNode::TechniqueFilter)) + ); + } + + { + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(); + Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(entity); + Qt3DRender::QFrustumCulling *frustumCulling = new Qt3DRender::QFrustumCulling(techniqueFilter); + Qt3DRender::QNoDraw *noDraw = new Qt3DRender::QNoDraw(frustumCulling); + + QTest::newRow("singleBranch") << entity + << static_cast<Qt3DRender::QFrameGraphNode *>(techniqueFilter) + << (QVector<BranchIdsAndTypes>() + << (BranchIdsAndTypes() + << FGIdType(noDraw->id(), Qt3DRender::Render::FrameGraphNode::NoDraw) + << FGIdType(frustumCulling->id(), Qt3DRender::Render::FrameGraphNode::FrustumCulling) + << FGIdType(techniqueFilter->id(), Qt3DRender::Render::FrameGraphNode::TechniqueFilter) + ) + ); + } + { + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(); + Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(entity); + Qt3DRender::QFrustumCulling *frustumCulling = new Qt3DRender::QFrustumCulling(techniqueFilter); + Qt3DRender::QNoDraw *noDraw = new Qt3DRender::QNoDraw(frustumCulling); + Qt3DRender::QViewport *viewPort = new Qt3DRender::QViewport(frustumCulling); + + QTest::newRow("dualBranch") << entity + << static_cast<Qt3DRender::QFrameGraphNode *>(techniqueFilter) + << (QVector<BranchIdsAndTypes>() + << (BranchIdsAndTypes() + << FGIdType(noDraw->id(), Qt3DRender::Render::FrameGraphNode::NoDraw) + << FGIdType(frustumCulling->id(), Qt3DRender::Render::FrameGraphNode::FrustumCulling) + << FGIdType(techniqueFilter->id(), Qt3DRender::Render::FrameGraphNode::TechniqueFilter) + ) + << (BranchIdsAndTypes() + << FGIdType(viewPort->id(), Qt3DRender::Render::FrameGraphNode::Viewport) + << FGIdType(frustumCulling->id(), Qt3DRender::Render::FrameGraphNode::FrustumCulling) + << FGIdType(techniqueFilter->id(), Qt3DRender::Render::FrameGraphNode::TechniqueFilter) + ) + ); + } + + } + + void visitFGTree() + { + // GIVEN + QFETCH(Qt3DCore::QEntity *, rootEntity); + QFETCH(Qt3DRender::QFrameGraphNode *, fgRoot); + QFETCH(QVector<BranchIdsAndTypes>, fgNodeIdsPerBranch); + QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(rootEntity)); + + // THEN + Qt3DRender::Render::FrameGraphManager *fgManager = aspect->nodeManagers()->frameGraphManager(); + Qt3DRender::Render::FrameGraphNode *backendFGRoot = fgManager->lookupNode(fgRoot->id()); + QVERIFY(backendFGRoot != nullptr); + + + // WHEN + Qt3DRender::Render::FrameGraphVisitor visitor(fgManager); + const QVector<Qt3DRender::Render::FrameGraphNode *> fgNodes = visitor.traverse(backendFGRoot); + + // THEN + QCOMPARE(fgNodeIdsPerBranch.size(), fgNodes.size()); + + for (int i = 0; i < fgNodeIdsPerBranch.size(); ++i) { + const BranchIdsAndTypes brandIdsAndTypes = fgNodeIdsPerBranch.at(i); + + Qt3DRender::Render::FrameGraphNode *fgNode = fgNodes.at(i); + for (int j = 0; j < brandIdsAndTypes.size(); ++j) { + const FGIdType idAndType = brandIdsAndTypes.at(j); + QVERIFY(fgNode != nullptr); + QCOMPARE(fgNode->peerId(), idAndType.first); + QCOMPARE(fgNode->nodeType(), idAndType.second); + fgNode = fgNode->parent(); + } + + QVERIFY(fgNode == nullptr); + } + + delete rootEntity; + } +}; + +QTEST_MAIN(tst_FrameGraphVisitor) + +#include "tst_framegraphvisitor.moc" diff --git a/tests/auto/render/geometryloaders/tst_geometryloaders.cpp b/tests/auto/render/geometryloaders/tst_geometryloaders.cpp index 15600dc75..7b9f09d23 100644 --- a/tests/auto/render/geometryloaders/tst_geometryloaders.cpp +++ b/tests/auto/render/geometryloaders/tst_geometryloaders.cpp @@ -102,6 +102,9 @@ void tst_geometryloaders::testOBJLoader() case QAttribute::VertexAttribute: QCOMPARE(attr->count(), 24u); break; + default: + Q_UNREACHABLE(); + break; } } @@ -141,6 +144,9 @@ void tst_geometryloaders::testPLYLoader() case QAttribute::VertexAttribute: QCOMPARE(attr->count(), 24u); break; + default: + Q_UNREACHABLE(); + break; } } @@ -212,6 +218,9 @@ void tst_geometryloaders::testGLTFLoader() case QAttribute::VertexAttribute: QCOMPARE(attr->count(), 24u); break; + default: + Q_UNREACHABLE(); + break; } } diff --git a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp index 7cf70c03c..70fe957c5 100644 --- a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp +++ b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp @@ -51,7 +51,7 @@ public: bool operator ==(const Qt3DRender::QGeometryFactory &other) const Q_DECL_FINAL { - const TestFactory *otherFactory = functor_cast<TestFactory>(&other); + const TestFactory *otherFactory = Qt3DRender::functor_cast<TestFactory>(&other); if (otherFactory != nullptr) return otherFactory->m_size == m_size; return false; diff --git a/tests/auto/render/gltfplugins/tst_gltfplugins.cpp b/tests/auto/render/gltfplugins/tst_gltfplugins.cpp index a800fc1fa..e5a0eef21 100644 --- a/tests/auto/render/gltfplugins/tst_gltfplugins.cpp +++ b/tests/auto/render/gltfplugins/tst_gltfplugins.cpp @@ -139,8 +139,10 @@ private: Qt3DRender::QEffect *createOnTopEffect(); QTemporaryDir *m_exportDir; +#ifdef VISUAL_CHECK Qt3DExtras::Qt3DWindow *m_view1; Qt3DExtras::Qt3DWindow *m_view2; +#endif Qt3DCore::QEntity *m_sceneRoot1; Qt3DCore::QEntity *m_sceneRoot2; QHash<QString, Qt3DCore::QEntity *> m_entityMap; @@ -781,7 +783,7 @@ void tst_gltfPlugins::compareComponents(Qt3DCore::QComponent *c1, Qt3DCore::QCom auto property = c1->metaObject()->property(i); auto v1 = c1->property(property.name()); auto v2 = c2->property(property.name()); - if (v1.type() == QMetaType::Bool) { + if (v1.type() == QVariant::Bool) { QCOMPARE(v1.toBool(), v2.toBool()); } else if (v1.type() == QVariant::Color) { QCOMPARE(v1.value<QColor>(), v2.value<QColor>()); diff --git a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp index 9bc234c50..473e43d09 100644 --- a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp +++ b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp @@ -124,7 +124,7 @@ class tst_GraphicsHelperGL2 : public QObject Q_OBJECT private Q_SLOTS: - void initTestCase() + void init() { m_window.reset(new QWindow); m_window->setSurfaceType(QWindow::OpenGLSurface); @@ -160,7 +160,7 @@ private Q_SLOTS: } } - void cleanupTestCase() + void cleanup() { m_glContext.doneCurrent(); } @@ -1302,7 +1302,7 @@ private Q_SLOTS: // WHEN m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7, 383.0f, 6.2f, 5.3f, 327.0f }; + GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; const GLint location = shaderProgram.uniformLocation("m4"); m_glHelper.glUniformMatrix4fv(location, 1, values); diff --git a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp index fb0265427..b66192835 100644 --- a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp +++ b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp @@ -177,7 +177,7 @@ class tst_GraphicsHelperGL3_2 : public QObject Q_OBJECT private Q_SLOTS: - void initTestCase() + void init() { m_window.reset(new QWindow); m_window->setSurfaceType(QWindow::OpenGLSurface); @@ -209,7 +209,7 @@ private Q_SLOTS: } } - void cleanupTestCase() + void cleanup() { m_glContext.doneCurrent(); } @@ -1867,6 +1867,11 @@ private Q_SLOTS: if (!m_initializationSuccessful) QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + GLint maxSamples; + m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples < 1) + QSKIP("This test requires an implementation that supports multisampled textures"); + // GIVEN GLuint fbos[2]; GLuint fboTextures[2]; @@ -1875,7 +1880,7 @@ private Q_SLOTS: m_func->glGenTextures(2, fboTextures); m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); - m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 10, 10, true); + m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); diff --git a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp index 293750dbf..b7cc1cdac 100644 --- a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp +++ b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp @@ -176,7 +176,7 @@ class tst_GraphicsHelperGL3_3 : public QObject Q_OBJECT private Q_SLOTS: - void initTestCase() + void init() { m_window.reset(new QWindow); m_window->setSurfaceType(QWindow::OpenGLSurface); @@ -209,7 +209,7 @@ private Q_SLOTS: } } - void cleanupTestCase() + void cleanup() { m_glContext.doneCurrent(); } @@ -1967,6 +1967,11 @@ private Q_SLOTS: if (!m_initializationSuccessful) QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + GLint maxSamples; + m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples < 1) + QSKIP("This test requires an implementation that supports multisampled textures"); + // GIVEN GLuint fbos[2]; GLuint fboTextures[2]; @@ -1975,7 +1980,7 @@ private Q_SLOTS: m_func->glGenTextures(2, fboTextures); m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); - m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 10, 10, true); + m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); @@ -1986,13 +1991,13 @@ private Q_SLOTS: m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); m_func->glEnable(GL_MULTISAMPLE); m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); diff --git a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp index c6a306910..0ee14841c 100644 --- a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp +++ b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp @@ -201,7 +201,7 @@ class tst_GraphicsHelperGL4 : public QObject { Q_OBJECT private Q_SLOTS: - void initTestCase() + void init() { m_window.reset(new QWindow); m_window->setSurfaceType(QWindow::OpenGLSurface); @@ -234,7 +234,7 @@ private Q_SLOTS: } } - void cleanupTestCase() + void cleanup() { m_glContext.doneCurrent(); } diff --git a/tests/auto/render/levelofdetail/tst_levelofdetail.cpp b/tests/auto/render/levelofdetail/tst_levelofdetail.cpp index ab0e8c4b8..148c54e58 100644 --- a/tests/auto/render/levelofdetail/tst_levelofdetail.cpp +++ b/tests/auto/render/levelofdetail/tst_levelofdetail.cpp @@ -29,7 +29,7 @@ #include <QtTest/QTest> #include <qbackendnodetester.h> #include <Qt3DRender/QLevelOfDetail> -#include <Qt3DRender/QBoundingSphere> +#include <Qt3DRender/QLevelOfDetailBoundingSphere> #include <Qt3DRender/private/levelofdetail_p.h> #include <Qt3DRender/private/qlevelofdetail_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -57,8 +57,8 @@ private Q_SLOTS: QCOMPARE(renderLod.currentIndex(), lod.currentIndex()); QCOMPARE(renderLod.thresholdType(), lod.thresholdType()); QCOMPARE(renderLod.thresholds(), lod.thresholds()); - QCOMPARE(renderLod.center(), lod.volumeOverride()->center()); - QCOMPARE(renderLod.radius(), lod.volumeOverride()->radius()); + QCOMPARE(renderLod.center(), lod.volumeOverride().center()); + QCOMPARE(renderLod.radius(), lod.volumeOverride().radius()); } void checkInitialAndCleanedUpState() @@ -70,7 +70,7 @@ private Q_SLOTS: // THEN QCOMPARE(renderLod.camera(), Qt3DCore::QNodeId{}); QCOMPARE(renderLod.currentIndex(), 0); - QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::DistanceToCamera); + QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::DistanceToCameraThreshold); QVERIFY(renderLod.thresholds().empty()); QCOMPARE(renderLod.radius(), 1.f); QCOMPARE(renderLod.center(), QVector3D{}); @@ -78,7 +78,7 @@ private Q_SLOTS: // GIVEN Qt3DRender::QLevelOfDetail lod; - lod.setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + lod.setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold); // WHEN renderLod.setRenderer(&renderer); @@ -96,18 +96,18 @@ private Q_SLOTS: renderLod.setRenderer(&renderer); // THEN - QVERIFY(renderLod.thresholdType() != Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + QVERIFY(renderLod.thresholdType() != Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold); QVERIFY(renderLod.camera().isNull()); { // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - updateChange->setValue(static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize)); + updateChange->setValue(static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold)); updateChange->setPropertyName("thresholdType"); renderLod.sceneChangeEvent(updateChange); // THEN - QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold); QVERIFY(renderer.dirtyBits() != 0); } @@ -129,8 +129,9 @@ private Q_SLOTS: { // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - updateChange->setValue(QVector3D(1., 2., 3.)); - updateChange->setPropertyName("center"); + Qt3DRender::QLevelOfDetailBoundingSphere sphere(QVector3D(1.0f, 2.0f, 3.0f), 1.0f); + updateChange->setValue(QVariant::fromValue(sphere)); + updateChange->setPropertyName("volumeOverride"); renderLod.sceneChangeEvent(updateChange); // THEN diff --git a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp index 08d1caace..e2e3997af 100644 --- a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp +++ b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp @@ -50,8 +50,14 @@ public: m_source = source; } - bool isFileTypeSupported(const QUrl &) const Q_DECL_OVERRIDE + void setData(const QByteArray& data, const QString &basePath) Q_DECL_OVERRIDE { + + } + + bool areFileTypesSupported(const QStringList &extensions) const + { + Q_UNUSED(extensions); return m_supportsFormat; } @@ -99,7 +105,7 @@ private Q_SLOTS: void checkInitialize() { // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); const Qt3DCore::QNodeId sceneId = Qt3DCore::QNodeId::createId(); Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, true); @@ -120,8 +126,10 @@ private Q_SLOTS: void checkRunValidSourceSupportedFormat() { + QSKIP("Can't test successful loading"); + // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, false); @@ -202,8 +210,11 @@ private Q_SLOTS: void checkRunValidSourceUnsupportedFormat() { + // no data is loaded so... + QSKIP("Can't differentiate between no data and unsupported data"); + // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(false, false); @@ -241,7 +252,7 @@ private Q_SLOTS: void checkRunErrorAtLoading() { // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, true); @@ -259,7 +270,7 @@ private Q_SLOTS: loadSceneJob.run(); // THEN - QCOMPARE(arbiter.events.count(), 4); + QCOMPARE(arbiter.events.count(), 3); auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "status"); @@ -267,16 +278,11 @@ private Q_SLOTS: change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); - QCOMPARE(change->propertyName(), "status"); - QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Loading); - - change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "scene"); QVERIFY(change->value().value<Qt3DCore::QEntity *>() == nullptr); delete change->value().value<Qt3DCore::QEntity *>(); - change = arbiter.events.at(3).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "status"); QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Error); diff --git a/tests/auto/render/memorybarrier/tst_memorybarrier.cpp b/tests/auto/render/memorybarrier/tst_memorybarrier.cpp index d4f54f3af..f0d4931d9 100644 --- a/tests/auto/render/memorybarrier/tst_memorybarrier.cpp +++ b/tests/auto/render/memorybarrier/tst_memorybarrier.cpp @@ -50,14 +50,14 @@ private Q_SLOTS: QCOMPARE(backendMemoryBarrier.nodeType(), Qt3DRender::Render::FrameGraphNode::MemoryBarrier); QCOMPARE(backendMemoryBarrier.isEnabled(), false); QVERIFY(backendMemoryBarrier.peerId().isNull()); - QCOMPARE(backendMemoryBarrier.barrierTypes(), Qt3DRender::QMemoryBarrier::None); + QCOMPARE(backendMemoryBarrier.waitOperations(), Qt3DRender::QMemoryBarrier::None); } void checkInitializeFromPeer() { // GIVEN Qt3DRender::QMemoryBarrier memoryBarrier; - memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::VertexAttributeArrayBarrier); + memoryBarrier.setWaitOperations(Qt3DRender::QMemoryBarrier::VertexAttributeArray); { // WHEN @@ -67,7 +67,7 @@ private Q_SLOTS: // THEN QCOMPARE(backendMemoryBarrier.isEnabled(), true); QCOMPARE(backendMemoryBarrier.peerId(), memoryBarrier.id()); - QCOMPARE(backendMemoryBarrier.barrierTypes(), Qt3DRender::QMemoryBarrier::VertexAttributeArrayBarrier); + QCOMPARE(backendMemoryBarrier.waitOperations(), Qt3DRender::QMemoryBarrier::VertexAttributeArray); } { // WHEN @@ -101,14 +101,14 @@ private Q_SLOTS: } { // WHEN - const Qt3DRender::QMemoryBarrier::BarrierTypes newValue(Qt3DRender::QMemoryBarrier::AtomicCounterBarrier|Qt3DRender::QMemoryBarrier::ElementArrayBarrier); + const Qt3DRender::QMemoryBarrier::Operations newValue(Qt3DRender::QMemoryBarrier::AtomicCounter|Qt3DRender::QMemoryBarrier::ElementArray); const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); - change->setPropertyName("barrierTypes"); + change->setPropertyName("waitOperations"); change->setValue(QVariant::fromValue(newValue)); backendMemoryBarrier.sceneChangeEvent(change); // THEN - QCOMPARE(backendMemoryBarrier.barrierTypes(), newValue); + QCOMPARE(backendMemoryBarrier.waitOperations(), newValue); } } diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index 6aef510ea..bf5f0d55f 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -46,7 +46,7 @@ public: bool operator ==(const Qt3DRender::QGeometryFactory &other) const Q_DECL_OVERRIDE { - return functor_cast<MeshFunctorA>(&other); + return Qt3DRender::functor_cast<MeshFunctorA>(&other); } QT3D_FUNCTOR(MeshFunctorA) @@ -68,7 +68,7 @@ public: bool operator ==(const Qt3DRender::QGeometryFactory &other) const Q_DECL_OVERRIDE { - return functor_cast<MeshFunctorB>(&other); + return Qt3DRender::functor_cast<MeshFunctorB>(&other); } QT3D_FUNCTOR(MeshFunctorB) @@ -85,7 +85,7 @@ public: bool operator ==(const Qt3DRender::QGeometryFactory &other) const Q_DECL_OVERRIDE { - return functor_cast<MeshFunctorASub>(&other); + return Qt3DRender::functor_cast<MeshFunctorASub>(&other); } QT3D_FUNCTOR(MeshFunctorASub) diff --git a/tests/auto/render/objectpicker/tst_objectpicker.cpp b/tests/auto/render/objectpicker/tst_objectpicker.cpp index 9140bb503..c1b06ccd8 100644 --- a/tests/auto/render/objectpicker/tst_objectpicker.cpp +++ b/tests/auto/render/objectpicker/tst_objectpicker.cpp @@ -33,7 +33,6 @@ #include <Qt3DRender/qobjectpicker.h> #include <Qt3DCore/private/qbackendnode_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include "testpostmanarbiter.h" #include "testrenderer.h" @@ -113,7 +112,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "pressed"); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); @@ -124,7 +122,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "released"); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); @@ -135,7 +132,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "clicked"); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); @@ -146,7 +142,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "entered"); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); @@ -157,7 +152,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "exited"); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); } diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index 5ebf10338..1d391101e 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -809,13 +809,13 @@ private Q_SLOTS: QVERIFY(!backendPicker1->isPressed()); QCOMPARE(arbiter.events.count(), 2); change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "clicked"); + QCOMPARE(change->propertyName(), "released"); pickEvent = change->value().value<Qt3DRender::QPickEventPtr>(); QVERIFY(pickEvent); if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) QVERIFY(pickEvent.dynamicCast<Qt3DRender::QPickTriangleEvent>()); change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "released"); + QCOMPARE(change->propertyName(), "clicked"); pickEvent = change->value().value<Qt3DRender::QPickEventPtr>(); QVERIFY(pickEvent); if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) @@ -1034,9 +1034,9 @@ private Q_SLOTS: QVERIFY(!backendPicker->isPressed()); QCOMPARE(arbiter.events.count(), 2); change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "clicked"); - change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "released"); + change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "clicked"); arbiter.events.clear(); @@ -1145,7 +1145,10 @@ private Q_SLOTS: change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "moved"); } 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"); } diff --git a/tests/auto/render/qbuffer/tst_qbuffer.cpp b/tests/auto/render/qbuffer/tst_qbuffer.cpp index a65f27cb6..fdc25cbca 100644 --- a/tests/auto/render/qbuffer/tst_qbuffer.cpp +++ b/tests/auto/render/qbuffer/tst_qbuffer.cpp @@ -51,7 +51,7 @@ public: bool operator ==(const Qt3DRender::QBufferDataGenerator &other) const Q_DECL_FINAL { - const TestFunctor *otherFunctor = functor_cast<TestFunctor>(&other); + const TestFunctor *otherFunctor = Qt3DRender::functor_cast<TestFunctor>(&other); if (otherFunctor != nullptr) return otherFunctor->m_size == m_size; return false; diff --git a/tests/auto/render/qcameralens/tst_qcameralens.cpp b/tests/auto/render/qcameralens/tst_qcameralens.cpp index aab43d553..adff66dc5 100644 --- a/tests/auto/render/qcameralens/tst_qcameralens.cpp +++ b/tests/auto/render/qcameralens/tst_qcameralens.cpp @@ -63,6 +63,7 @@ private Q_SLOTS: QCOMPARE(cameraLens.right(), 0.5f); QCOMPARE(cameraLens.bottom(), -0.5f); QCOMPARE(cameraLens.top(), 0.5f); + QCOMPARE(cameraLens.exposure(), 0.0f); } void checkPropertyChanges() @@ -243,6 +244,26 @@ private Q_SLOTS: } { // WHEN + QSignalSpy spy(&cameraLens, SIGNAL(exposureChanged(float))); + const float newValue = -2.0f; + cameraLens.setExposure(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(cameraLens.exposure(), newValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().toFloat(), -2.0f); + + // WHEN + spy.clear(); + cameraLens.setExposure(newValue); + + // THEN + QCOMPARE(cameraLens.exposure(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN QSignalSpy spy(&cameraLens, SIGNAL(projectionMatrixChanged(QMatrix4x4))); QMatrix4x4 newValue; newValue.translate(5.0f, 2.0f, 4.3f); @@ -340,6 +361,7 @@ private Q_SLOTS: cameraLens.setFarPlane(1005.0f); cameraLens.setFieldOfView(35.0f); cameraLens.setAspectRatio(16.0f/9.0f); + cameraLens.setExposure(1.0f); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -357,6 +379,7 @@ private Q_SLOTS: const Qt3DRender::QCameraLensData cloneData = creationChangeData->data; QCOMPARE(cameraLens.projectionMatrix(), cloneData.projectionMatrix); + QCOMPARE(cameraLens.exposure(), cloneData.exposure); QCOMPARE(cameraLens.id(), creationChangeData->subjectId()); QCOMPARE(cameraLens.isEnabled(), true); QCOMPARE(cameraLens.isEnabled(), creationChangeData->isNodeEnabled()); @@ -379,6 +402,7 @@ private Q_SLOTS: const Qt3DRender::QCameraLensData cloneData = creationChangeData->data; QCOMPARE(cameraLens.projectionMatrix(), cloneData.projectionMatrix); + QCOMPARE(cameraLens.exposure(), cloneData.exposure); QCOMPARE(cameraLens.id(), creationChangeData->subjectId()); QCOMPARE(cameraLens.isEnabled(), false); QCOMPARE(cameraLens.isEnabled(), creationChangeData->isNodeEnabled()); @@ -674,6 +698,38 @@ private Q_SLOTS: } + void checkExposureUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QCameraLens cameraLens; + arbiter.setArbiterOnNode(&cameraLens); + + { + // WHEN + cameraLens.setExposure(2.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "exposure"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + cameraLens.setExposure(2.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + void checkProjectionMatrixUpdate() { // GIVEN diff --git a/tests/auto/render/qenvironmentlight/qenvironmentlight.pro b/tests/auto/render/qenvironmentlight/qenvironmentlight.pro new file mode 100644 index 000000000..8a66f65ba --- /dev/null +++ b/tests/auto/render/qenvironmentlight/qenvironmentlight.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +TARGET = tst_environmentlight + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qenvironmentlight.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/render/qenvironmentlight/tst_qenvironmentlight.cpp b/tests/auto/render/qenvironmentlight/tst_qenvironmentlight.cpp new file mode 100644 index 000000000..76b3603c9 --- /dev/null +++ b/tests/auto/render/qenvironmentlight/tst_qenvironmentlight.cpp @@ -0,0 +1,301 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** 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 <QtTest/QTest> +#include <QSignalSpy> + +#include <Qt3DRender/qtexture.h> +#include <Qt3DRender/qenvironmentlight.h> +#include <Qt3DRender/private/qenvironmentlight_p.h> +#include <Qt3DRender/private/qshaderdata_p.h> + +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +class tst_QEnvironmentLight: public QObject +{ + Q_OBJECT +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::QEnvironmentLight light; + + // THEN + QVERIFY(light.findChild<Qt3DRender::QShaderData*>()); + QCOMPARE(light.irradiance(), nullptr); + QCOMPARE(light.specular(), nullptr); + } + + void shouldTakeOwnershipOfParentlessTextures() + { + // GIVEN + Qt3DRender::QEnvironmentLight light; + auto irradiance = new Qt3DRender::QTexture2D; + auto specular = new Qt3DRender::QTexture2D; + + // WHEN + light.setIrradiance(irradiance); + light.setSpecular(specular); + + // THEN + QCOMPARE(irradiance->parent(), &light); + QCOMPARE(specular->parent(), &light); + } + + void shouldNotChangeOwnershipOfParentedTextures() + { + // GIVEN + Qt3DCore::QNode node; + Qt3DRender::QEnvironmentLight light; + auto irradiance = new Qt3DRender::QTexture2D(&node); + auto specular = new Qt3DRender::QTexture2D(&node); + + // WHEN + light.setIrradiance(irradiance); + light.setSpecular(specular); + + // WHEN + delete irradiance; + delete specular; + + // THEN + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::QEnvironmentLight light; + auto shaderData = light.findChild<Qt3DRender::QShaderData*>(); + + { + auto texture = new Qt3DRender::QTexture2D(&light); + QSignalSpy spy(&light, &Qt3DRender::QEnvironmentLight::irradianceChanged); + + // WHEN + light.setIrradiance(texture); + + // THEN + QCOMPARE(light.irradiance(), texture); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), texture); + + // WHEN + light.setIrradiance(texture); + + // THEN + QCOMPARE(light.irradiance(), texture); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 0); + + // WHEN + light.setIrradiance(nullptr); + + // THEN + QCOMPARE(light.irradiance(), nullptr); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), nullptr); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), nullptr); + } + { + auto texture = new Qt3DRender::QTexture2D(&light); + QSignalSpy spy(&light, &Qt3DRender::QEnvironmentLight::irradianceChanged); + + // WHEN + light.setIrradiance(texture); + + // THEN + QCOMPARE(light.irradiance(), texture); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), texture); + + // WHEN + delete texture; + + // THEN + QCOMPARE(light.irradiance(), nullptr); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), nullptr); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), nullptr); + } + { + auto texture = new Qt3DRender::QTexture2D; + QSignalSpy spy(&light, &Qt3DRender::QEnvironmentLight::irradianceChanged); + + // WHEN + light.setIrradiance(texture); + + // THEN + QCOMPARE(light.irradiance(), texture); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), texture); + + // WHEN + delete texture; + + // THEN + QCOMPARE(light.irradiance(), nullptr); + QCOMPARE(shaderData->property("irradiance").value<Qt3DRender::QAbstractTexture*>(), nullptr); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), nullptr); + } + { + auto texture = new Qt3DRender::QTexture2D(&light); + QSignalSpy spy(&light, &Qt3DRender::QEnvironmentLight::specularChanged); + + // WHEN + light.setSpecular(texture); + + // THEN + QCOMPARE(light.specular(), texture); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), texture); + + // WHEN + light.setSpecular(texture); + + // THEN + QCOMPARE(light.specular(), texture); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 0); + + // WHEN + light.setSpecular(nullptr); + + // THEN + QCOMPARE(light.specular(), nullptr); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), nullptr); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), nullptr); + } + { + auto texture = new Qt3DRender::QTexture2D(&light); + QSignalSpy spy(&light, &Qt3DRender::QEnvironmentLight::specularChanged); + + // WHEN + light.setSpecular(texture); + + // THEN + QCOMPARE(light.specular(), texture); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), texture); + + // WHEN + delete texture; + + // THEN + QCOMPARE(light.specular(), nullptr); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), nullptr); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), nullptr); + } + { + auto texture = new Qt3DRender::QTexture2D; + QSignalSpy spy(&light, &Qt3DRender::QEnvironmentLight::specularChanged); + + // WHEN + light.setSpecular(texture); + + // THEN + QCOMPARE(light.specular(), texture); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), texture); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), texture); + + // WHEN + delete texture; + + // THEN + QCOMPARE(light.specular(), nullptr); + QCOMPARE(shaderData->property("specular").value<Qt3DRender::QAbstractTexture*>(), nullptr); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().first().value<Qt3DRender::QAbstractTexture*>(), nullptr); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::QEnvironmentLight light; + auto shaderData = light.findChild<Qt3DRender::QShaderData*>(); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&light); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // EnvironmentLight + ShaderData + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QEnvironmentLightData>>(creationChanges.first()); + const Qt3DRender::QEnvironmentLightData cloneData = creationChangeData->data; + + QCOMPARE(cloneData.shaderDataId, shaderData->id()); + QCOMPARE(light.id(), creationChangeData->subjectId()); + QCOMPARE(light.isEnabled(), true); + QCOMPARE(light.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(light.metaObject(), creationChangeData->metaObject()); + } + + // WHEN + light.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&light); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // EnvironmentLight + ShaderData + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QEnvironmentLightData>>(creationChanges.first()); + const Qt3DRender::QEnvironmentLightData cloneData = creationChangeData->data; + + QCOMPARE(cloneData.shaderDataId, shaderData->id()); + QCOMPARE(light.id(), creationChangeData->subjectId()); + QCOMPARE(light.isEnabled(), false); + QCOMPARE(light.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(light.metaObject(), creationChangeData->metaObject()); + } + } +}; + +QTEST_MAIN(tst_QEnvironmentLight) + +#include "tst_qenvironmentlight.moc" diff --git a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp index 76c3288e3..94f720097 100644 --- a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp +++ b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp @@ -58,7 +58,7 @@ public: bool operator ==(const Qt3DRender::QGeometryFactory &other) const Q_DECL_FINAL { - const TestFactory *otherFactory = functor_cast<TestFactory>(&other); + const TestFactory *otherFactory = Qt3DRender::functor_cast<TestFactory>(&other); if (otherFactory != nullptr) return otherFactory->m_size == m_size; return false; diff --git a/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp b/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp index e2ffdd9da..ba357c8c9 100644 --- a/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp +++ b/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp @@ -89,14 +89,14 @@ private Q_SLOTS: { // WHEN - lod->setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + lod->setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 1); Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "thresholdType"); - QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize)); + QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold)); arbiter.events.clear(); } diff --git a/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp b/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp index 87c813a03..25ee10cad 100644 --- a/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp +++ b/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp @@ -45,7 +45,7 @@ private Q_SLOTS: void initTestCase() { - qRegisterMetaType<Qt3DRender::QMemoryBarrier::BarrierTypes>("QMemoryBarrier::BarrierTypes"); + qRegisterMetaType<Qt3DRender::QMemoryBarrier::Operations>("QMemoryBarrier::Operations"); } void checkDefaultConstruction() @@ -54,7 +54,7 @@ private Q_SLOTS: Qt3DRender::QMemoryBarrier memoryBarrier; // THEN - QCOMPARE(memoryBarrier.barrierTypes(), Qt3DRender::QMemoryBarrier::None); + QCOMPARE(memoryBarrier.waitOperations(), Qt3DRender::QMemoryBarrier::None); } void checkPropertyChanges() @@ -64,21 +64,21 @@ private Q_SLOTS: { // WHEN - QSignalSpy spy(&memoryBarrier, SIGNAL(barrierTypesChanged(QMemoryBarrier::BarrierTypes))); - const Qt3DRender::QMemoryBarrier::BarrierTypes newValue(Qt3DRender::QMemoryBarrier::ShaderStorageBarrier|Qt3DRender::QMemoryBarrier::VertexAttributeArrayBarrier); - memoryBarrier.setBarrierTypes(newValue); + QSignalSpy spy(&memoryBarrier, SIGNAL(waitOperationsChanged(QMemoryBarrier::Operations))); + const Qt3DRender::QMemoryBarrier::Operations newValue(Qt3DRender::QMemoryBarrier::ShaderStorage|Qt3DRender::QMemoryBarrier::VertexAttributeArray); + memoryBarrier.setWaitOperations(newValue); // THEN QVERIFY(spy.isValid()); - QCOMPARE(memoryBarrier.barrierTypes(), newValue); + QCOMPARE(memoryBarrier.waitOperations(), newValue); QCOMPARE(spy.count(), 1); // WHEN spy.clear(); - memoryBarrier.setBarrierTypes(newValue); + memoryBarrier.setWaitOperations(newValue); // THEN - QCOMPARE(memoryBarrier.barrierTypes(), newValue); + QCOMPARE(memoryBarrier.waitOperations(), newValue); QCOMPARE(spy.count(), 0); } } @@ -88,7 +88,7 @@ private Q_SLOTS: // GIVEN Qt3DRender::QMemoryBarrier memoryBarrier; - memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::CommandBarrier); + memoryBarrier.setWaitOperations(Qt3DRender::QMemoryBarrier::Command); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -105,7 +105,7 @@ private Q_SLOTS: const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QMemoryBarrierData>>(creationChanges.first()); const Qt3DRender::QMemoryBarrierData cloneData = creationChangeData->data; - QCOMPARE(memoryBarrier.barrierTypes(), cloneData.barrierTypes); + QCOMPARE(memoryBarrier.waitOperations(), cloneData.waitOperations); QCOMPARE(memoryBarrier.id(), creationChangeData->subjectId()); QCOMPARE(memoryBarrier.isEnabled(), true); QCOMPARE(memoryBarrier.isEnabled(), creationChangeData->isNodeEnabled()); @@ -127,7 +127,7 @@ private Q_SLOTS: const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QMemoryBarrierData>>(creationChanges.first()); const Qt3DRender::QMemoryBarrierData cloneData = creationChangeData->data; - QCOMPARE(memoryBarrier.barrierTypes(), cloneData.barrierTypes); + QCOMPARE(memoryBarrier.waitOperations(), cloneData.waitOperations); QCOMPARE(memoryBarrier.id(), creationChangeData->subjectId()); QCOMPARE(memoryBarrier.isEnabled(), false); QCOMPARE(memoryBarrier.isEnabled(), creationChangeData->isNodeEnabled()); @@ -144,14 +144,14 @@ private Q_SLOTS: { // WHEN - memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::ShaderStorageBarrier); + memoryBarrier.setWaitOperations(Qt3DRender::QMemoryBarrier::ShaderStorage); QCoreApplication::processEvents(); // THEN QCOMPARE(arbiter.events.size(), 1); auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "barrierTypes"); - QCOMPARE(change->value().value<Qt3DRender::QMemoryBarrier::BarrierTypes>(), memoryBarrier.barrierTypes()); + QCOMPARE(change->propertyName(), "waitOperations"); + QCOMPARE(change->value().value<Qt3DRender::QMemoryBarrier::Operations>(), memoryBarrier.waitOperations()); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); arbiter.events.clear(); @@ -159,7 +159,7 @@ private Q_SLOTS: { // WHEN - memoryBarrier.setBarrierTypes(Qt3DRender::QMemoryBarrier::ShaderStorageBarrier); + memoryBarrier.setWaitOperations(Qt3DRender::QMemoryBarrier::ShaderStorage); QCoreApplication::processEvents(); // THEN diff --git a/tests/auto/render/qmesh/tst_qmesh.cpp b/tests/auto/render/qmesh/tst_qmesh.cpp index 2122d7eb5..a0278f4e4 100644 --- a/tests/auto/render/qmesh/tst_qmesh.cpp +++ b/tests/auto/render/qmesh/tst_qmesh.cpp @@ -121,7 +121,7 @@ private Q_SLOTS: const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QGeometryRendererData>>(creationChanges.first()); const Qt3DRender::QGeometryRendererData cloneData = creationChangeData->data; - Qt3DRender::MeshFunctor meshFunctor(mesh.source(), mesh.meshName()); + Qt3DRender::MeshLoaderFunctor meshFunctor(&mesh, nullptr); QVERIFY(meshFunctor == *cloneData.geometryFactory); QCOMPARE(mesh.id(), creationChangeData->subjectId()); @@ -169,7 +169,7 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - Qt3DRender::MeshFunctor meshFunctor(mesh.source()); + Qt3DRender::MeshLoaderFunctor meshFunctor(&mesh, nullptr); Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>(); QVERIFY(meshFunctor == *factory); @@ -205,7 +205,7 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - Qt3DRender::MeshFunctor meshFunctor(QUrl(), mesh.meshName()); + Qt3DRender::MeshLoaderFunctor meshFunctor(&mesh, nullptr); Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>(); QVERIFY(meshFunctor == *factory); diff --git a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp index ef1e9f53c..e0037f3dd 100644 --- a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp +++ b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp @@ -67,7 +67,7 @@ private Q_SLOTS: arbiter.setArbiterOnNode(renderCapture.data()); // WHEN - QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture(12)); + QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture()); // THEN QCOMPARE(arbiter.events.size(), 1); @@ -75,7 +75,7 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "renderCaptureRequest"); QCOMPARE(change->subjectId(),renderCapture->id()); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - QCOMPARE(change->value().toInt(), 12); + QCOMPARE(change->value().toInt(), 1); arbiter.events.clear(); } @@ -84,12 +84,12 @@ private Q_SLOTS: { // GIVEN QScopedPointer<MyRenderCapture> renderCapture(new MyRenderCapture()); - QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture(52)); + QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture()); QImage img = QImage(20, 20, QImage::Format_ARGB32); // WHEN Qt3DRender::RenderCaptureDataPtr data = Qt3DRender::RenderCaptureDataPtr::create(); - data.data()->captureId = 52; + data.data()->captureId = 2; data.data()->image = img; auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(renderCapture->id()); @@ -101,7 +101,6 @@ private Q_SLOTS: // THEN QCOMPARE(reply->isComplete(), true); - QCOMPARE(reply->captureId(), 52); QCOMPARE(reply->image().width(), 20); QCOMPARE(reply->image().height(), 20); QCOMPARE(reply->image().format(), QImage::Format_ARGB32); diff --git a/tests/auto/render/qscene2d/qscene2d.pro b/tests/auto/render/qscene2d/qscene2d.pro new file mode 100644 index 000000000..b1d4d45a9 --- /dev/null +++ b/tests/auto/render/qscene2d/qscene2d.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = qscene2d + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib 3dquickscene2d 3dquickscene2d-private + +CONFIG += testcase + +SOURCES += tst_qscene2d.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qscene2d/tst_qscene2d.cpp b/tests/auto/render/qscene2d/tst_qscene2d.cpp new file mode 100644 index 000000000..846207456 --- /dev/null +++ b/tests/auto/render/qscene2d/tst_qscene2d.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** 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 <QtTest/QTest> +#include <Qt3DQuickScene2D/qscene2d.h> +#include <Qt3DRender/qrendertargetoutput.h> +#include <private/qscene2d_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +using namespace Qt3DRender::Quick; + +class tst_QScene2D : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void initTestCase() + { + qRegisterMetaType<Qt3DRender::Quick::QScene2D::RenderPolicy>( + "QScene2D::RenderPolicy"); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::Quick::QScene2D scene2d; + + // THEN + QCOMPARE(scene2d.output(), nullptr); + QCOMPARE(scene2d.renderPolicy(), QScene2D::Continuous); + QCOMPARE(scene2d.item(), nullptr); + QCOMPARE(scene2d.isMouseEnabled(), true); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::Quick::QScene2D scene2d; + QScopedPointer<Qt3DRender::QRenderTargetOutput> output(new Qt3DRender::QRenderTargetOutput()); + QScopedPointer<QQuickItem> item(new QQuickItem()); + + { + // WHEN + QSignalSpy spy(&scene2d, SIGNAL(outputChanged(Qt3DRender::QRenderTargetOutput*))); + Qt3DRender::QRenderTargetOutput *newValue = output.data(); + scene2d.setOutput(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(scene2d.output(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + scene2d.setOutput(newValue); + + // THEN + QCOMPARE(scene2d.output(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&scene2d, SIGNAL(renderPolicyChanged(QScene2D::RenderPolicy))); + const QScene2D::RenderPolicy newValue = QScene2D::SingleShot; + scene2d.setRenderPolicy(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(scene2d.renderPolicy(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + scene2d.setRenderPolicy(newValue); + + // THEN + QCOMPARE(scene2d.renderPolicy(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&scene2d, SIGNAL(itemChanged(QQuickItem*))); + QQuickItem *newValue = item.data(); + scene2d.setItem(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(scene2d.item(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + scene2d.setItem(newValue); + + // THEN + QCOMPARE(scene2d.item(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + QSignalSpy spy(&scene2d, SIGNAL(mouseEnabledChanged(bool))); + bool newValue = false; + scene2d.setMouseEnabled(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(scene2d.isMouseEnabled(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + scene2d.setMouseEnabled(newValue); + + // THEN + QCOMPARE(scene2d.isMouseEnabled(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::Quick::QScene2D scene2d; + QScopedPointer<Qt3DRender::QRenderTargetOutput> output(new Qt3DRender::QRenderTargetOutput()); + + scene2d.setOutput(output.data()); + scene2d.setRenderPolicy(QScene2D::SingleShot); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&scene2d); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange< + Qt3DRender::Quick::QScene2DData>>(creationChanges.first()); + const Qt3DRender::Quick::QScene2DData cloneData = creationChangeData->data; + + QCOMPARE(scene2d.output()->id(), cloneData.output); + QCOMPARE(scene2d.renderPolicy(), cloneData.renderPolicy); + QCOMPARE(scene2d.id(), creationChangeData->subjectId()); + QCOMPARE(scene2d.isEnabled(), true); + QCOMPARE(scene2d.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(scene2d.metaObject(), creationChangeData->metaObject()); + QCOMPARE(scene2d.isMouseEnabled(), cloneData.mouseEnabled); + } + + // WHEN + scene2d.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&scene2d); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange< + Qt3DRender::Quick::QScene2DData>>(creationChanges.first()); + const Qt3DRender::Quick::QScene2DData cloneData = creationChangeData->data; + + QCOMPARE(scene2d.output()->id(), cloneData.output); + QCOMPARE(scene2d.renderPolicy(), cloneData.renderPolicy); + QCOMPARE(scene2d.id(), creationChangeData->subjectId()); + QCOMPARE(scene2d.isEnabled(), false); + QCOMPARE(scene2d.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(scene2d.metaObject(), creationChangeData->metaObject()); + } + } + + void checkOutputUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::Quick::QScene2D scene2d; + arbiter.setArbiterOnNode(&scene2d); + QScopedPointer<Qt3DRender::QRenderTargetOutput> output(new Qt3DRender::QRenderTargetOutput()); + + { + // WHEN + scene2d.setOutput(output.data()); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "output"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), scene2d.output()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + scene2d.setOutput(output.data()); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkRenderPolicyUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::Quick::QScene2D scene2d; + arbiter.setArbiterOnNode(&scene2d); + + { + // WHEN + scene2d.setRenderPolicy(QScene2D::SingleShot); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "renderPolicy"); + QCOMPARE(change->value().value<Qt3DRender::Quick::QScene2D::RenderPolicy>(), + scene2d.renderPolicy()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + scene2d.setRenderPolicy(QScene2D::SingleShot); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkMouseEnabledUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::Quick::QScene2D scene2d; + arbiter.setArbiterOnNode(&scene2d); + + { + // WHEN + scene2d.setMouseEnabled(false); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "mouseEnabled"); + QCOMPARE(change->value().toBool(), scene2d.isMouseEnabled()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + scene2d.setMouseEnabled(false); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + +}; + +QTEST_MAIN(tst_QScene2D) + +#include "tst_qscene2d.moc" diff --git a/tests/auto/render/qshaderprogram/qshaderprogram.pro b/tests/auto/render/qshaderprogram/qshaderprogram.pro new file mode 100644 index 000000000..6f40caee9 --- /dev/null +++ b/tests/auto/render/qshaderprogram/qshaderprogram.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qshaderprogram + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qshaderprogram.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp new file mode 100644 index 000000000..901ee7349 --- /dev/null +++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp @@ -0,0 +1,518 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> +** 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 <QtTest/QTest> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/private/qshaderprogram_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +// We need to call QShaderProgram::sceneChangeEvent +class tst_QShaderProgram : public Qt3DRender::QShaderProgram +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::QShaderProgram shaderProgram; + + // THEN + QCOMPARE(shaderProgram.vertexShaderCode(), QByteArray()); + QCOMPARE(shaderProgram.tessellationControlShaderCode(), QByteArray()); + QCOMPARE(shaderProgram.tessellationEvaluationShaderCode(), QByteArray()); + QCOMPARE(shaderProgram.geometryShaderCode(), QByteArray()); + QCOMPARE(shaderProgram.fragmentShaderCode(), QByteArray()); + QCOMPARE(shaderProgram.computeShaderCode(), QByteArray()); + QCOMPARE(shaderProgram.log(), QString()); + QCOMPARE(shaderProgram.status(), Qt3DRender::QShaderProgram::NotReady); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::QShaderProgram shaderProgram; + + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(vertexShaderCodeChanged(QByteArray))); + const QByteArray newValue = "VERTEX"; + shaderProgram.setVertexShaderCode(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.vertexShaderCode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setVertexShaderCode(newValue); + + // THEN + QCOMPARE(shaderProgram.vertexShaderCode(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(tessellationControlShaderCodeChanged(QByteArray))); + const QByteArray newValue = "TESSELATION_CONTROL"; + shaderProgram.setTessellationControlShaderCode(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.tessellationControlShaderCode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setTessellationControlShaderCode(newValue); + + // THEN + QCOMPARE(shaderProgram.tessellationControlShaderCode(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(tessellationEvaluationShaderCodeChanged(QByteArray))); + const QByteArray newValue = "TESSELATION_EVALUTATION"; + shaderProgram.setTessellationEvaluationShaderCode(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.tessellationEvaluationShaderCode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setTessellationEvaluationShaderCode(newValue); + + // THEN + QCOMPARE(shaderProgram.tessellationEvaluationShaderCode(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(geometryShaderCodeChanged(QByteArray))); + const QByteArray newValue = "GEOMETRY"; + shaderProgram.setGeometryShaderCode(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.geometryShaderCode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setGeometryShaderCode(newValue); + + // THEN + QCOMPARE(shaderProgram.geometryShaderCode(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(fragmentShaderCodeChanged(QByteArray))); + const QByteArray newValue = "FRAGMENT"; + shaderProgram.setFragmentShaderCode(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.fragmentShaderCode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setFragmentShaderCode(newValue); + + // THEN + QCOMPARE(shaderProgram.fragmentShaderCode(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(computeShaderCodeChanged(QByteArray))); + const QByteArray newValue = "COMPUTE"; + shaderProgram.setComputeShaderCode(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.computeShaderCode(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setComputeShaderCode(newValue); + + // THEN + QCOMPARE(shaderProgram.computeShaderCode(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::QShaderProgram shaderProgram; + + shaderProgram.setVertexShaderCode(QByteArrayLiteral("Vertex")); + shaderProgram.setTessellationControlShaderCode(QByteArrayLiteral("TesselControl")); + shaderProgram.setTessellationEvaluationShaderCode(QByteArrayLiteral("TesselEval")); + shaderProgram.setGeometryShaderCode(QByteArrayLiteral("Geometry")); + shaderProgram.setFragmentShaderCode(QByteArrayLiteral("Fragment")); + shaderProgram.setComputeShaderCode(QByteArrayLiteral("Compute")); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&shaderProgram); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramData>>(creationChanges.first()); + const Qt3DRender::QShaderProgramData cloneData = creationChangeData->data; + + QCOMPARE(shaderProgram.vertexShaderCode(), cloneData.vertexShaderCode); + QCOMPARE(shaderProgram.tessellationControlShaderCode(), cloneData.tessellationControlShaderCode); + QCOMPARE(shaderProgram.tessellationEvaluationShaderCode(), cloneData.tessellationEvaluationShaderCode); + QCOMPARE(shaderProgram.geometryShaderCode(), cloneData.geometryShaderCode); + QCOMPARE(shaderProgram.fragmentShaderCode(), cloneData.fragmentShaderCode); + QCOMPARE(shaderProgram.computeShaderCode(), cloneData.computeShaderCode); + QCOMPARE(shaderProgram.id(), creationChangeData->subjectId()); + QCOMPARE(shaderProgram.isEnabled(), true); + QCOMPARE(shaderProgram.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(shaderProgram.metaObject(), creationChangeData->metaObject()); + } + + // WHEN + shaderProgram.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&shaderProgram); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramData>>(creationChanges.first()); + const Qt3DRender::QShaderProgramData cloneData = creationChangeData->data; + + QCOMPARE(shaderProgram.vertexShaderCode(), cloneData.vertexShaderCode); + QCOMPARE(shaderProgram.tessellationControlShaderCode(), cloneData.tessellationControlShaderCode); + QCOMPARE(shaderProgram.tessellationEvaluationShaderCode(), cloneData.tessellationEvaluationShaderCode); + QCOMPARE(shaderProgram.geometryShaderCode(), cloneData.geometryShaderCode); + QCOMPARE(shaderProgram.fragmentShaderCode(), cloneData.fragmentShaderCode); + QCOMPARE(shaderProgram.computeShaderCode(), cloneData.computeShaderCode); + QCOMPARE(shaderProgram.id(), creationChangeData->subjectId()); + QCOMPARE(shaderProgram.isEnabled(), false); + QCOMPARE(shaderProgram.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(shaderProgram.metaObject(), creationChangeData->metaObject()); + } + } + + void checkVertexShaderCodeUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + { + // WHEN + shaderProgram.setVertexShaderCode(QByteArrayLiteral("in vec3 toto;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "vertexShaderCode"); + QCOMPARE(change->value().value<QByteArray>(), shaderProgram.vertexShaderCode()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + shaderProgram.setVertexShaderCode(QByteArrayLiteral("in vec3 toto;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkTessellationControlShaderCodeUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + { + // WHEN + shaderProgram.setTessellationControlShaderCode(QByteArrayLiteral("in vec3 toto2;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "tessellationControlShaderCode"); + QCOMPARE(change->value().value<QByteArray>(), shaderProgram.tessellationControlShaderCode()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + shaderProgram.setTessellationControlShaderCode(QByteArrayLiteral("in vec3 toto2;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkTessellationEvaluationShaderCodeUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + { + // WHEN + shaderProgram.setTessellationEvaluationShaderCode(QByteArrayLiteral("in vec3 toto3;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "tessellationEvaluationShaderCode"); + QCOMPARE(change->value().value<QByteArray>(), shaderProgram.tessellationEvaluationShaderCode()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + shaderProgram.setTessellationEvaluationShaderCode(QByteArrayLiteral("in vec3 toto3;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkGeometryShaderCodeUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + { + // WHEN + shaderProgram.setGeometryShaderCode(QByteArrayLiteral("in vec3 toto4;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "geometryShaderCode"); + QCOMPARE(change->value().value<QByteArray>(), shaderProgram.geometryShaderCode()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + shaderProgram.setGeometryShaderCode(QByteArrayLiteral("in vec3 toto4;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkFragmentShaderCodeUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + { + // WHEN + shaderProgram.setFragmentShaderCode(QByteArrayLiteral("out vec4 fragColor;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "fragmentShaderCode"); + QCOMPARE(change->value().value<QByteArray>(), shaderProgram.fragmentShaderCode()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + shaderProgram.setFragmentShaderCode(QByteArrayLiteral("out vec4 fragColor;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkComputeShaderCodeUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + { + // WHEN + shaderProgram.setComputeShaderCode(QByteArrayLiteral("uniform vec3 temp;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "computeShaderCode"); + QCOMPARE(change->value().value<QByteArray>(), shaderProgram.computeShaderCode()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + shaderProgram.setComputeShaderCode(QByteArrayLiteral("uniform vec3 temp;")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkLogPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + arbiter.setArbiterOnNode(this); + QSignalSpy spy(this, SIGNAL(logChanged(QString))); + const QString logValue = QStringLiteral("Some log..."); + + // THEN + QVERIFY(spy.isValid()); + + // WHEN + Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + valueChange->setPropertyName("log"); + valueChange->setValue(QVariant::fromValue(logValue)); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(log(), logValue); + + // WHEN + spy.clear(); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 0); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(log(), logValue); + } + + void checkStatusPropertyUpdate() + { + // GIVEN + qRegisterMetaType<Qt3DRender::QShaderProgram::Status>("Status"); + TestArbiter arbiter; + arbiter.setArbiterOnNode(this); + QSignalSpy spy(this, SIGNAL(statusChanged(Status))); + const Qt3DRender::QShaderProgram::Status newStatus = Qt3DRender::QShaderProgram::Error; + + // THEN + QVERIFY(spy.isValid()); + + // WHEN + Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + valueChange->setPropertyName("status"); + valueChange->setValue(QVariant::fromValue(newStatus)); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(status(), newStatus); + + // WHEN + spy.clear(); + sceneChangeEvent(valueChange); + + // THEN + QCOMPARE(spy.count(), 0); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(status(), newStatus); + } + +}; + +QTEST_MAIN(tst_QShaderProgram) + +#include "tst_qshaderprogram.moc" diff --git a/tests/auto/render/qsortcriterion/tst_qsortcriterion.cpp b/tests/auto/render/qsortcriterion/tst_qsortcriterion.cpp deleted file mode 100644 index bac9fb3e8..000000000 --- a/tests/auto/render/qsortcriterion/tst_qsortcriterion.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the S 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 <QtTest/QTest> -#include <Qt3DCore/private/qnode_p.h> -#include <Qt3DCore/private/qscene_p.h> -#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> - -#include <Qt3DRender/qsortcriterion.h> -#include <Qt3DRender/private/qsortcriterion_p.h> - -#include "testpostmanarbiter.h" - -class tst_QSortCriterion: public QObject -{ - Q_OBJECT - -private Q_SLOTS: - - void checkCloning_data() - { - QTest::addColumn<Qt3DRender::QSortCriterion *>("sortCriterion"); - QTest::addColumn<Qt3DRender::QSortCriterion::SortType>("sortType"); - - Qt3DRender::QSortCriterion *defaultConstructed = new Qt3DRender::QSortCriterion(); - QTest::newRow("defaultConstructed") << defaultConstructed << Qt3DRender::QSortCriterion::StateChangeCost; - - Qt3DRender::QSortCriterion *backToFrontSort = new Qt3DRender::QSortCriterion(); - backToFrontSort->setSort(Qt3DRender::QSortCriterion::BackToFront); - QTest::newRow("backToFrontSort") << backToFrontSort << Qt3DRender::QSortCriterion::BackToFront; - - Qt3DRender::QSortCriterion *materialSort = new Qt3DRender::QSortCriterion(); - materialSort->setSort(Qt3DRender::QSortCriterion::Material); - QTest::newRow("materialSort") << materialSort << Qt3DRender::QSortCriterion::Material; - } - - void checkCloning() - { - // GIVEN - QFETCH(Qt3DRender::QSortCriterion *, sortCriterion); - QFETCH(Qt3DRender::QSortCriterion::SortType, sortType); - - // THEN - QCOMPARE(sortCriterion->sort(), sortType); - -// TO DO: Add creation change -// // WHEN -// Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(sortCriterion); -// QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); - -// // THEN -// QCOMPARE(creationChanges.size(), 1); - -// const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QCameraSelectorData> creationChangeData = -// qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QSortCriterion>>(creationChanges.first()); -// const Qt3DRender::QCameraSelectorData &cloneData = creationChangeData->data; - - -// // THEN -// QCOMPARE(sortCriterion->id(), creationChangeData->subjectId()); -// QCOMPARE(sortCriterion->isEnabled(), creationChangeData->isNodeEnabled()); -// QCOMPARE(sortCriterion->metaObject(), creationChangeData->metaObject()); -// QCOMPARE(sortCriterion->sort(), cloneData.sort); - - delete sortCriterion; - } - - void checkPropertyUpdates() - { - // GIVEN - QScopedPointer<Qt3DRender::QSortCriterion> sortCriterion(new Qt3DRender::QSortCriterion()); - TestArbiter arbiter(sortCriterion.data()); - - // WHEN - sortCriterion->setSort(Qt3DRender::QSortCriterion::BackToFront); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - Qt3DCore::QNodePropertyChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QNodePropertyChange>(); - QCOMPARE(change->propertyName(), "sort"); - QCOMPARE(change->subjectId(), sortCriterion->id()); - QCOMPARE(change->value().value<Qt3DRender::QSortCriterion::SortType>(), Qt3DRender::QSortCriterion::BackToFront); - QCOMPARE(change->type(), Qt3DCore::NodeUpdated); - - arbiter.events.clear(); - - // WHEN - sortCriterion->setSort(Qt3DRender::QSortCriterion::BackToFront); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 0); - - // WHEN - sortCriterion->setSort(Qt3DRender::QSortCriterion::Material); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QNodePropertyChange>(); - QCOMPARE(change->propertyName(), "sort"); - QCOMPARE(change->subjectId(), sortCriterion->id()); - QCOMPARE(change->value().value<Qt3DRender::QSortCriterion::SortType>(), Qt3DRender::QSortCriterion::Material); - QCOMPARE(change->type(), Qt3DCore::NodeUpdated); - - arbiter.events.clear(); - } -}; - -QTEST_MAIN(tst_QSortCriterion) - -#include "tst_qsortcriterion.moc" diff --git a/tests/auto/render/qtextureloader/tst_qtextureloader.cpp b/tests/auto/render/qtextureloader/tst_qtextureloader.cpp index 252bc85af..56ad55adf 100644 --- a/tests/auto/render/qtextureloader/tst_qtextureloader.cpp +++ b/tests/auto/render/qtextureloader/tst_qtextureloader.cpp @@ -51,6 +51,13 @@ private Q_SLOTS: // THEN QCOMPARE(textureLoader.source(), QUrl()); QCOMPARE(textureLoader.isMirrored(), true); + QCOMPARE(textureLoader.target(), Qt3DRender::QTextureLoader::TargetAutomatic); + QCOMPARE(textureLoader.wrapMode()->x(), Qt3DRender::QTextureWrapMode::Repeat); + QCOMPARE(textureLoader.wrapMode()->y(), Qt3DRender::QTextureWrapMode::Repeat); + QCOMPARE(textureLoader.magnificationFilter(), Qt3DRender::QTextureLoader::Linear); + QCOMPARE(textureLoader.minificationFilter(), Qt3DRender::QTextureLoader::LinearMipMapLinear); + QCOMPARE(textureLoader.generateMipMaps(), true); + QCOMPARE(textureLoader.maximumAnisotropy(), 16.0f); } void checkPropertyChanges() diff --git a/tests/auto/render/qviewport/tst_qviewport.cpp b/tests/auto/render/qviewport/tst_qviewport.cpp index 87b22e22b..93a2735f2 100644 --- a/tests/auto/render/qviewport/tst_qviewport.cpp +++ b/tests/auto/render/qviewport/tst_qviewport.cpp @@ -46,14 +46,15 @@ private Q_SLOTS: { QTest::addColumn<Qt3DRender::QViewport *>("viewport"); QTest::addColumn<QRectF>("normalizedRect"); + QTest::addColumn<float>("gamma"); Qt3DRender::QViewport *defaultConstructed = new Qt3DRender::QViewport(); - QTest::newRow("defaultConstructed") << defaultConstructed << QRectF(0.0f, 0.0f, 1.0f, 1.0f); + QTest::newRow("defaultConstructed") << defaultConstructed << QRectF(0.0f, 0.0f, 1.0f, 1.0f) << 2.2f; Qt3DRender::QViewport *smallGreenViewport = new Qt3DRender::QViewport(); smallGreenViewport->setNormalizedRect(QRectF(0.2f, 0.2f, 0.6f, 0.6f)); - QTest::newRow("smallGreenViewport") << smallGreenViewport << QRectF(0.2f, 0.2f, 0.6f, 0.6f); - + smallGreenViewport->setGamma(1.8f); + QTest::newRow("smallGreenViewport") << smallGreenViewport << QRectF(0.2f, 0.2f, 0.6f, 0.6f) << 1.8f; } void checkCloning() @@ -61,9 +62,11 @@ private Q_SLOTS: // GIVEN QFETCH(Qt3DRender::QViewport *, viewport); QFETCH(QRectF, normalizedRect); + QFETCH(float, gamma); // THEN QCOMPARE(viewport->normalizedRect(), normalizedRect); + QCOMPARE(viewport->gamma(), gamma); // WHEN Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(viewport); @@ -80,6 +83,7 @@ private Q_SLOTS: QCOMPARE(viewport->isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(viewport->metaObject(), creationChangeData->metaObject()); QCOMPARE(viewport->normalizedRect(), cloneData.normalizedRect); + QCOMPARE(viewport->gamma(), cloneData.gamma); delete viewport; } @@ -91,39 +95,77 @@ private Q_SLOTS: QScopedPointer<Qt3DRender::QViewport> viewport(new Qt3DRender::QViewport()); arbiter.setArbiterOnNode(viewport.data()); - // WHEN - viewport->setNormalizedRect(QRectF(0.5f, 0.5f, 1.0f, 1.0f)); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "normalizedRect"); - QCOMPARE(change->subjectId(), viewport->id()); - QCOMPARE(change->value().value<QRectF>(), QRectF(0.5f, 0.5f, 1.0f, 1.0f)); - QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + { + // WHEN + viewport->setNormalizedRect(QRectF(0.5f, 0.5f, 1.0f, 1.0f)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "normalizedRect"); + QCOMPARE(change->subjectId(), viewport->id()); + QCOMPARE(change->value().value<QRectF>(), QRectF(0.5f, 0.5f, 1.0f, 1.0f)); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + viewport->setNormalizedRect(QRectF(0.5f, 0.5f, 1.0f, 1.0f)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "normalizedRect"); + QCOMPARE(change->subjectId(), viewport->id()); + QCOMPARE(change->value().value<QRectF>(), QRectF(0.0f, 0.0f, 1.0f, 1.0f)); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + } arbiter.events.clear(); - // WHEN - viewport->setNormalizedRect(QRectF(0.5f, 0.5f, 1.0f, 1.0f)); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 0); - - // WHEN - viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f)); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->propertyName(), "normalizedRect"); - QCOMPARE(change->subjectId(), viewport->id()); - QCOMPARE(change->value().value<QRectF>(), QRectF(0.0f, 0.0f, 1.0f, 1.0f)); - QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - + { + // WHEN + viewport->setGamma(1.8f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "gamma"); + QCOMPARE(change->subjectId(), viewport->id()); + QCOMPARE(change->value().toFloat(), 1.8f); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + viewport->setGamma(1.8f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + viewport->setGamma(2.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "gamma"); + QCOMPARE(change->subjectId(), viewport->id()); + QCOMPARE(change->value().toFloat(), 2.0f); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + } } }; diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index c1de2aff8..8eea3d032 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -31,6 +31,7 @@ qtConfig(private_tests) { qframegraphnode \ qlayerfilter \ qabstractlight \ + qenvironmentlight \ qray3d \ qrenderpassfilter \ qrendertargetselector \ @@ -45,6 +46,7 @@ qtConfig(private_tests) { picking \ # qboundingvolumedebug \ # boundingvolumedebug \ + boundingsphere \ qdefaultmeshes \ trianglesextractor \ triangleboundingvolume \ @@ -100,7 +102,12 @@ qtConfig(private_tests) { rendercapture \ trianglevisitor \ qmemorybarrier \ - memorybarrier + memorybarrier \ + qshaderprogram \ + qscene2d \ + scene2d \ + coordinatereader \ + framegraphvisitor !macos: SUBDIRS += graphicshelpergl4 } diff --git a/tests/auto/render/renderqueue/tst_renderqueue.cpp b/tests/auto/render/renderqueue/tst_renderqueue.cpp index 2d25cbe57..163a699c1 100644 --- a/tests/auto/render/renderqueue/tst_renderqueue.cpp +++ b/tests/auto/render/renderqueue/tst_renderqueue.cpp @@ -55,10 +55,14 @@ void tst_RenderQueue::setRenderViewCount() // GIVEN Qt3DRender::Render::RenderQueue renderQueue; + // THEN + QCOMPARE(renderQueue.wasReset(), true); + // WHEN renderQueue.setTargetRenderViewCount(7); // THEN + QCOMPARE(renderQueue.wasReset(), false); QVERIFY(renderQueue.targetRenderViewCount() == 7); QVERIFY(renderQueue.currentRenderViewCount()== 0); } @@ -214,6 +218,7 @@ void tst_RenderQueue::resetQueue() // WHEN renderQueue.setTargetRenderViewCount(5); // THEN + QCOMPARE(renderQueue.wasReset(), false); QVERIFY(renderQueue.currentRenderViewCount() == 0); // WHEN @@ -227,6 +232,7 @@ void tst_RenderQueue::resetQueue() // WHEN renderQueue.reset(); + QCOMPARE(renderQueue.wasReset(), true); // THEN QVERIFY(renderQueue.currentRenderViewCount() == 0); } diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp index 70109d718..d469298f4 100644 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/renderviews/tst_renderviews.cpp @@ -93,7 +93,7 @@ private Q_SLOTS: QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); // WHEN - const QMemoryBarrier::BarrierTypes barriers(QMemoryBarrier::BufferUpdateBarrier|QMemoryBarrier::ShaderImageAccessBarrier); + const QMemoryBarrier::Operations barriers(QMemoryBarrier::BufferUpdate|QMemoryBarrier::ShaderImageAccess); renderView.setMemoryBarrier(barriers); // THEN @@ -104,7 +104,7 @@ private Q_SLOTS: { { // GIVEN - const QMemoryBarrier::BarrierTypes barriers(QMemoryBarrier::AtomicCounterBarrier|QMemoryBarrier::ShaderStorageBarrier); + const QMemoryBarrier::Operations barriers(QMemoryBarrier::AtomicCounter|QMemoryBarrier::ShaderStorage); Qt3DRender::QMemoryBarrier frontendBarrier; FrameGraphManager frameGraphManager; MemoryBarrier backendBarrier; @@ -113,18 +113,18 @@ private Q_SLOTS: backendBarrier.setFrameGraphManager(&frameGraphManager); // WHEN - frontendBarrier.setBarrierTypes(barriers); + frontendBarrier.setWaitOperations(barriers); simulateInitialization(&frontendBarrier, &backendBarrier); // THEN QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); - QCOMPARE(backendBarrier.barrierTypes(), barriers); + QCOMPARE(backendBarrier.waitOperations(), barriers); // WHEN Qt3DRender::Render::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier); // THEN - QCOMPARE(backendBarrier.barrierTypes(), renderView.memoryBarrier()); + QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier()); } // TO DO: Complete tests for other framegraph node types } diff --git a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp index e4681a257..fa0dce6af 100644 --- a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp +++ b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp @@ -43,7 +43,10 @@ class tst_RenderViewUtils : public Qt3DCore::QBackendNodeTester private Q_SLOTS: void topLevelScalarValueNoUniforms(); void topLevelScalarValue(); + void topLevelTextureValueNoUniforms(); + void topLevelTextureValue(); void topLevelArrayValue(); + void nestedShaderDataValue(); void topLevelStructValue_data(); void topLevelStructValue(); void topLevelDynamicProperties(); @@ -66,6 +69,15 @@ private: // Init the backend element simulateInitialization(frontend, backend); } + + void initBackendTexture(Qt3DRender::QAbstractTexture *frontend, + Qt3DRender::Render::TextureManager *manager) + { + // Create backend element for frontend one + Qt3DRender::Render::Texture *backend = manager->getOrCreateResource(frontend->id()); + // Init the backend element + simulateInitialization(frontend, backend); + } }; class ScalarShaderData : public Qt3DRender::QShaderData @@ -74,8 +86,8 @@ class ScalarShaderData : public Qt3DRender::QShaderData Q_PROPERTY(float scalar READ scalar WRITE setScalar NOTIFY scalarChanged) public: - ScalarShaderData() - : Qt3DRender::QShaderData() + ScalarShaderData(Qt3DCore::QNode *parent = nullptr) + : Qt3DRender::QShaderData(parent) , m_scalar(0.0f) { } @@ -109,6 +121,47 @@ private: float m_scalar; }; +class TextureShaderData : public Qt3DRender::QShaderData +{ + Q_OBJECT + Q_PROPERTY(Qt3DRender::QAbstractTexture* texture READ texture WRITE setTexture NOTIFY textureChanged) + +public: + TextureShaderData() + : Qt3DRender::QShaderData() + , m_texture(nullptr) + { + } + + void setTexture(Qt3DRender::QAbstractTexture *texture) + { + if (texture != m_texture) { + m_texture = texture; + emit textureChanged(); + } + } + + Qt3DRender::QAbstractTexture *texture() const + { + return m_texture; + } + + QHash<QString, Qt3DRender::Render::ShaderUniform> buildUniformMap(const QString &blockName) + { + QHash<QString, Qt3DRender::Render::ShaderUniform> uniforms; + + uniforms.insert(blockName + QStringLiteral(".texture"), Qt3DRender::Render::ShaderUniform()); + + return uniforms; + } + +Q_SIGNALS: + void textureChanged(); + +private: + Qt3DRender::QAbstractTexture *m_texture; +}; + class ArrayShaderData : public Qt3DRender::QShaderData { @@ -294,6 +347,7 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms() // GIVEN QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN shaderData->setScalar(883.0f); @@ -306,6 +360,7 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms() // WHEB Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); @@ -320,6 +375,7 @@ void tst_RenderViewUtils::topLevelScalarValue() // GIVEN QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN shaderData->setScalar(883.0f); @@ -332,6 +388,7 @@ void tst_RenderViewUtils::topLevelScalarValue() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); // build name-value map @@ -353,11 +410,83 @@ void tst_RenderViewUtils::topLevelScalarValue() } } +void tst_RenderViewUtils::topLevelTextureValueNoUniforms() +{ + // GIVEN + QScopedPointer<TextureShaderData> shaderData(new TextureShaderData); + QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager); + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + shaderData->setTexture(texture.data()); + initBackendShaderData(shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEB + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); + + // THEN + // activeUniformNamesToValue should be empty as blockBuilder.uniforms is + QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); +} + +void tst_RenderViewUtils::topLevelTextureValue() +{ + // GIVEN + QScopedPointer<TextureShaderData> shaderData(new TextureShaderData); + QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager); + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + initBackendTexture(texture.data(), textureManager.data()); + shaderData->setTexture(texture.data()); + initBackendShaderData(shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 1); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + + while (it != end) { + // THEN + QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QCOMPARE(it.value(), QVariant::fromValue(shaderData->texture()->id())); + ++it; + } +} + void tst_RenderViewUtils::topLevelArrayValue() { // GIVEN QScopedPointer<ArrayShaderData> shaderData(new ArrayShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; @@ -371,6 +500,7 @@ void tst_RenderViewUtils::topLevelArrayValue() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); // build name-value map @@ -392,6 +522,73 @@ void tst_RenderViewUtils::topLevelArrayValue() } } +void tst_RenderViewUtils::nestedShaderDataValue() +{ + // GIVEN + QScopedPointer<ArrayShaderData> arrayShaderData(new ArrayShaderData()); + QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); + + QScopedPointer<ScalarShaderData> shaderData1(new ScalarShaderData(arrayShaderData.data())); + QScopedPointer<ScalarShaderData> shaderData2(new ScalarShaderData(arrayShaderData.data())); + QScopedPointer<ScalarShaderData> shaderData3(new ScalarShaderData(arrayShaderData.data())); + + shaderData1->setScalar(883.0f); + shaderData2->setScalar(1200.0f); + shaderData3->setScalar(1340.0f); + QHash<QString, QVariant> scalarValues; + scalarValues[QStringLiteral("MyBlock.array[0].scalar")] = shaderData1->scalar(); + scalarValues[QStringLiteral("MyBlock.array[1].scalar")] = shaderData2->scalar(); + scalarValues[QStringLiteral("MyBlock.array[2].scalar")] = shaderData3->scalar(); + + + const Qt3DCore::QNodeId id1 = shaderData1->id(); + const Qt3DCore::QNodeId id2 = shaderData2->id(); + const Qt3DCore::QNodeId id3 = shaderData3->id(); + + // WHEN + const QVariantList arrayValues = QVariantList() << QVariant::fromValue(id1) << QVariant::fromValue(id2) << QVariant::fromValue(id3); + arrayShaderData->setArray(arrayValues); + initBackendShaderData(arrayShaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendArrayShaderData = manager->lookupResource(arrayShaderData->id()); + Qt3DRender::Render::ShaderData *backendShaderData1 = manager->lookupResource(id1); + Qt3DRender::Render::ShaderData *backendShaderData2 = manager->lookupResource(id2); + Qt3DRender::Render::ShaderData *backendShaderData3 = manager->lookupResource(id3); + QVERIFY(backendArrayShaderData != nullptr); + QVERIFY(backendShaderData1 != nullptr); + QVERIFY(backendShaderData2 != nullptr); + QVERIFY(backendShaderData3 != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0].scalar"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[1].scalar"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[2].scalar"), Qt3DRender::Render::ShaderUniform()); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendArrayShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 3); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); + + // WHEN + auto it = blockBuilder.uniforms.cbegin(); + const auto end = blockBuilder.uniforms.cend(); + + while (it != end) { + // THEN + const int nameId = Qt3DRender::Render::StringToInt::lookupId(it.key()); + QVERIFY(blockBuilder.activeUniformNamesToValue.contains(nameId)); + QCOMPARE(blockBuilder.activeUniformNamesToValue[nameId], scalarValues.value(it.key())); + ++it; + } +} + void tst_RenderViewUtils::topLevelStructValue_data() { QTest::addColumn<StructShaderData*>("shaderData"); @@ -430,6 +627,7 @@ void tst_RenderViewUtils::topLevelStructValue() QFETCH(StructShaderData *, shaderData); QFETCH(QString, blockName); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN initBackendShaderData(shaderData, manager.data()); @@ -441,6 +639,7 @@ void tst_RenderViewUtils::topLevelStructValue() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms = shaderData->buildUniformMap(blockName); const QHash<QString, QVariant> expectedValues = shaderData->buildUniformMapValues(blockName); @@ -468,10 +667,14 @@ void tst_RenderViewUtils::topLevelDynamicProperties() // GIVEN QScopedPointer<Qt3DRender::QShaderData> shaderData(new Qt3DRender::QShaderData()); QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager()); // WHEN + initBackendTexture(texture.data(), textureManager.data()); shaderData->setProperty("scalar", 883.0f); shaderData->setProperty("array", QVariantList() << 454 << 350 << 383 << 427 << 552); + shaderData->setProperty("texture", QVariant::fromValue(texture.data())); initBackendShaderData(shaderData.data(), manager.data()); // THEN @@ -481,20 +684,24 @@ void tst_RenderViewUtils::topLevelDynamicProperties() // WHEN Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::ShaderUniform()); blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::ShaderUniform()); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); // THEN - QVERIFY(blockBuilder.uniforms.count() == 2); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 2); + QVERIFY(blockBuilder.uniforms.count() == 3); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.scalar")), shaderData->property("scalar")); QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.array[0]")), shaderData->property("array")); + QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.texture")), + QVariant::fromValue(texture->id())); } void tst_RenderViewUtils::transformedProperties() @@ -558,6 +765,19 @@ void tst_RenderViewUtils::shouldNotifyDynamicPropertyChanges() QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); QCOMPARE(change->propertyName(), QByteArrayLiteral("scalar")); QCOMPARE(change->value().toFloat(), 883.0f); + + arbiter.events.clear(); + + // WHEN + QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D); + shaderData->setProperty("texture", QVariant::fromValue(texture.data())); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().dynamicCast<Qt3DCore::QDynamicPropertyUpdatedChange>(); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->propertyName(), QByteArrayLiteral("texture")); + QCOMPARE(change->value(), QVariant::fromValue(texture->id())); } QTEST_MAIN(tst_RenderViewUtils) diff --git a/tests/auto/render/scene2d/scene2d.pro b/tests/auto/render/scene2d/scene2d.pro new file mode 100644 index 000000000..aacdea3e4 --- /dev/null +++ b/tests/auto/render/scene2d/scene2d.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_scene2d + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib 3dquickscene2d 3dquickscene2d-private + +CONFIG += testcase + +SOURCES += tst_scene2d.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/scene2d/tst_scene2d.cpp b/tests/auto/render/scene2d/tst_scene2d.cpp new file mode 100644 index 000000000..a78ed0ab1 --- /dev/null +++ b/tests/auto/render/scene2d/tst_scene2d.cpp @@ -0,0 +1,450 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** 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 <QtTest/QTest> +#include <Qt3DQuickScene2D/qscene2d.h> +#include <private/qscene2d_p.h> +#include <private/scene2d_p.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DRender/qbuffer.h> +#include <private/trianglesvisitor_p.h> +#include <private/nodemanagers_p.h> +#include <private/managers_p.h> +#include <private/geometryrenderer_p.h> +#include <private/geometryrenderermanager_p.h> +#include <private/buffermanager_p.h> +#include <Qt3DRender/qpicktriangleevent.h> +#include <private/qpickevent_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <qbackendnodetester.h> +#include "testrenderer.h" + +using namespace Qt3DRender::Quick; +using namespace Qt3DRender::Render; +using namespace Qt3DRender::Render::Quick; + +bool qFuzzyComparePointF(const QPointF& a, const QPointF& b) { + return qFuzzyCompare(a.x(), b.x()) && qFuzzyCompare(a.y(), b.y()); +} + +class TestWindow : public QQuickWindow +{ + Q_OBJECT +public: + TestWindow() + : QQuickWindow() + { + + } + + bool event(QEvent *e) Q_DECL_OVERRIDE + { + if (e->type() >= QEvent::MouseButtonPress && + e->type() <= QEvent::MouseMove) { + QMouseEvent *me = static_cast<QMouseEvent *>(e); + m_eventTypes.push_back(e->type()); + m_mousePoints.push_back(me->localPos()); + } + return QQuickWindow::event(e); + } + + bool verifyEventPos(uint index, QEvent::Type type, const QPointF& pos) + { + if (index >= unsigned(m_eventTypes.size()) || + m_eventTypes[index] != type || + !qFuzzyComparePointF(pos, m_mousePoints[index])) + return false; + return true; + } + + void clear() + { + m_eventTypes.clear(); + m_mousePoints.clear(); + } + +private: + QVector<QEvent::Type> m_eventTypes; + QVector<QPointF> m_mousePoints; +}; + +class tst_Scene2D : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Scene2D backendScene2d; + + // THEN + QCOMPARE(backendScene2d.isEnabled(), false); + QVERIFY(backendScene2d.peerId().isNull()); + QCOMPARE(backendScene2d.m_context, nullptr); + QCOMPARE(backendScene2d.m_shareContext, nullptr); + QCOMPARE(backendScene2d.m_renderThread, nullptr); + QCOMPARE(backendScene2d.m_outputId, Qt3DCore::QNodeId()); + QCOMPARE(backendScene2d.m_initialized, false); + QCOMPARE(backendScene2d.m_renderInitialized, false); + QCOMPARE(backendScene2d.m_renderPolicy, QScene2D::Continuous); + QCOMPARE(backendScene2d.m_mouseEnabled, true); + backendScene2d.cleanup(); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DRender::Quick::QScene2D frontend; + TestRenderer renderer; + + { + // WHEN + QScopedPointer<Scene2D> backendScene2d(new Scene2D()); + backendScene2d->setRenderer(&renderer); + simulateInitialization(&frontend, backendScene2d.data()); + + // THEN + QCOMPARE(backendScene2d->isEnabled(), true); + QCOMPARE(backendScene2d->peerId(), frontend.id()); + QCOMPARE(backendScene2d->m_outputId, Qt3DCore::QNodeId()); + QVERIFY(backendScene2d->m_sharedObject.data() != nullptr); + QCOMPARE(backendScene2d->m_renderPolicy, QScene2D::Continuous); + QCOMPARE(backendScene2d->m_mouseEnabled, true); + backendScene2d->cleanup(); + } + { + // WHEN + QScopedPointer<Scene2D> backendScene2d(new Scene2D()); + frontend.setEnabled(false); + backendScene2d->setRenderer(&renderer); + simulateInitialization(&frontend, backendScene2d.data()); + + // THEN + QCOMPARE(backendScene2d->peerId(), frontend.id()); + QCOMPARE(backendScene2d->isEnabled(), false); + backendScene2d->cleanup(); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + QScopedPointer<Scene2D> backendScene2d(new Scene2D()); + TestRenderer renderer; + QScopedPointer<Qt3DRender::QRenderTargetOutput> output(new Qt3DRender::QRenderTargetOutput()); + backendScene2d->setRenderer(&renderer); + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendScene2d->sceneChangeEvent(change); + + // THEN + QCOMPARE(backendScene2d->isEnabled(), newValue); + } + { + // WHEN + const Qt3DCore::QNodeId newValue = output.data()->id(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("output"); + change->setValue(QVariant::fromValue(newValue)); + backendScene2d->sceneChangeEvent(change); + + // THEN + QCOMPARE(backendScene2d->m_outputId, newValue); + } + { + // WHEN + const QScene2D::RenderPolicy newValue = QScene2D::SingleShot; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("renderPolicy"); + change->setValue(QVariant::fromValue(newValue)); + backendScene2d->sceneChangeEvent(change); + + // THEN + QCOMPARE(backendScene2d->m_renderPolicy, newValue); + } + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("mouseEnabled"); + change->setValue(newValue); + backendScene2d->sceneChangeEvent(change); + + // THEN + QCOMPARE(backendScene2d->isEnabled(), newValue); + } + + backendScene2d->cleanup(); + } + + + void testCoordinateCalculation() + { + // GIVEN + QScopedPointer<TestWindow> testWindow(new TestWindow()); + Scene2DSharedObjectPtr sharedObject(new Scene2DSharedObject(nullptr)); + QScopedPointer<Scene2D> scene2d(new Scene2D()); + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DRender::QGeometryRenderer(); + Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute(); + Qt3DRender::QAttribute *texcoordAttribute = new Qt3DRender::QAttribute(); + Qt3DRender::QBuffer *dataBuffer =new Qt3DRender::QBuffer(); + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity()); + entity->addComponent(geometryRenderer); + TestRenderer renderer; + renderer.setNodeManagers(nodeManagers.data()); + scene2d->setRenderer(&renderer); + scene2d->setEnabled(true); + sharedObject->m_quickWindow = testWindow.data(); + scene2d->setSharedObject(sharedObject); + testWindow->setGeometry(0,0,1024,1024); + + QByteArray data; + data.resize(sizeof(float) * 5 * 6); + float *dataPtr = reinterpret_cast<float *>(data.data()); + int i = 0; + dataPtr[i++] = -1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 0; + dataPtr[i++] = 0; + + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 0; + + dataPtr[i++] = 1.0f; + dataPtr[i++] = -1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + + dataPtr[i++] = -1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 0; + dataPtr[i++] = 0; + + dataPtr[i++] = 1.0f; + dataPtr[i++] = -1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 1.0f; + + dataPtr[i++] = -1.0f; + dataPtr[i++] = -1.0f; + dataPtr[i++] = 1.0f; + dataPtr[i++] = 0.0f; + dataPtr[i++] = 1.0f; + + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer, backendBuffer); + + positionAttribute->setBuffer(dataBuffer); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(6); + positionAttribute->setByteStride(sizeof(float) * 5); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute); + + texcoordAttribute->setBuffer(dataBuffer); + texcoordAttribute->setName(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); + texcoordAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + texcoordAttribute->setVertexSize(2); + texcoordAttribute->setCount(6); + texcoordAttribute->setByteStride(sizeof(float) * 5); + texcoordAttribute->setByteOffset(sizeof(float) * 3); + texcoordAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(texcoordAttribute); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource( + positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute, backendAttribute); + + Attribute *backendTexcoordAttribute = nodeManagers->attributeManager() + ->getOrCreateResource(texcoordAttribute->id()); + backendTexcoordAttribute->setRenderer(&renderer); + simulateInitialization(texcoordAttribute, backendTexcoordAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager() + ->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager() + ->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer, backendRenderer); + + Entity *backendEntity = nodeManagers->renderNodesManager()->getOrCreateResource(entity->id()); + backendEntity->setRenderer(&renderer); + backendEntity->setNodeManagers(nodeManagers.data()); + simulateInitialization(entity.data(), backendEntity); + +#define PICK_TRIANGLE(tri, v0, v1, v2, uvw) \ + new Qt3DRender::QPickTriangleEvent(QPointF(), QVector3D(), QVector3D(), 0.0f, \ + tri, v0, v1, v2, Qt3DRender::QPickEvent::LeftButton, Qt::LeftButton, 0, uvw) + + { + // WHEN + QVector3D uvw(1.0, 0.0f, 0.0f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(0,1024))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(0.0, 1.0f, 0.0f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(1024,1024))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(0.0, 0.0f, 1.0f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(1024,0))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(1.0, 0.0f, 0.0f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(0,1024))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(0.0, 1.0f, 0.0f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(1024,0))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(0.0, 0.0f, 1.0f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(0,0))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(0.5f, 0.25f, 0.25f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(512.0f, 768.0f))); + testWindow->clear(); + } + + { + // WHEN + QVector3D uvw(0.875f, 0.09375f, 0.03125f); + Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw)); + Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id(); + scene2d->handlePickEvent(QEvent::MouseButtonPress, ev); + + QCoreApplication::processEvents(); + + // THEN + QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(96.0f, 896.0f))); + testWindow->clear(); + } + } +}; + +QTEST_MAIN(tst_Scene2D) + +#include "tst_scene2d.moc" diff --git a/tests/auto/render/sceneloader/tst_sceneloader.cpp b/tests/auto/render/sceneloader/tst_sceneloader.cpp index edd6fabda..975c2c892 100644 --- a/tests/auto/render/sceneloader/tst_sceneloader.cpp +++ b/tests/auto/render/sceneloader/tst_sceneloader.cpp @@ -79,7 +79,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::QSceneLoader frontendSceneLoader; - frontendSceneLoader.setSource(QUrl(QStringLiteral("CorvetteMuseum"))); + frontendSceneLoader.setSource(QUrl(QStringLiteral("file:///CorvetteMuseum"))); Qt3DRender::Render::Scene sceneLoader; Qt3DRender::Render::SceneManager sceneManager; @@ -109,7 +109,7 @@ private Q_SLOTS: // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - const QUrl newUrl(QStringLiteral("Bownling_Green_KY")); + const QUrl newUrl(QStringLiteral("file:///Bownling_Green_KY")); updateChange->setValue(newUrl); updateChange->setPropertyName("source"); sceneLoader.sceneChangeEvent(updateChange); @@ -147,7 +147,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); QCOMPARE(change->propertyName(), "scene"); QCOMPARE(change->value().value<Qt3DCore::QEntity *>(), &subtree); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); } @@ -170,7 +169,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.count(), 1); QCOMPARE(change->propertyName(), "status"); QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Ready); - QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true); arbiter.events.clear(); } diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp index 95576afe0..f6ed41a8b 100644 --- a/tests/auto/render/shader/tst_shader.cpp +++ b/tests/auto/render/shader/tst_shader.cpp @@ -81,6 +81,7 @@ void tst_RenderShader::hasCoherentInitialState() QVERIFY(shader->uniforms().isEmpty()); QVERIFY(shader->attributes().isEmpty()); QVERIFY(shader->uniformBlocks().isEmpty()); + QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady); } void tst_RenderShader::matchesFrontendPeer() @@ -114,6 +115,7 @@ void tst_RenderShader::cleanupLeavesACoherentState() QVERIFY(shader->uniforms().isEmpty()); QVERIFY(shader->attributes().isEmpty()); QVERIFY(shader->uniformBlocks().isEmpty()); + QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady); } QTEST_APPLESS_MAIN(tst_RenderShader) diff --git a/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp b/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp index b76495d93..5ba43aedc 100644 --- a/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp +++ b/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp @@ -58,7 +58,9 @@ class FakeData public: explicit FakeData(int value) : m_value(value) - {} + { + Q_UNUSED(m_value); + } private: int m_value; diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp index 9246bba34..82c638275 100644 --- a/tests/auto/render/textures/tst_textures.cpp +++ b/tests/auto/render/textures/tst_textures.cpp @@ -52,12 +52,12 @@ class TestImageDataGenerator : public Qt3DRender::QTextureImageDataGenerator public: TestImageDataGenerator(int id) : m_id(id) {} - Qt3DRender::QTextureImageDataPtr operator ()() { + Qt3DRender::QTextureImageDataPtr operator ()() Q_DECL_OVERRIDE { return Qt3DRender::QTextureImageDataPtr::create(); } - bool operator ==(const Qt3DRender::QTextureImageDataGenerator &other) const { - const TestImageDataGenerator *otherFunctor = functor_cast<TestImageDataGenerator>(&other); + bool operator ==(const Qt3DRender::QTextureImageDataGenerator &other) const Q_DECL_OVERRIDE { + const TestImageDataGenerator *otherFunctor = Qt3DRender::functor_cast<TestImageDataGenerator>(&other); return (otherFunctor != Q_NULLPTR && otherFunctor->m_id == m_id); } @@ -73,12 +73,12 @@ class TestTextureGenerator : public Qt3DRender::QTextureGenerator public: TestTextureGenerator(int id) : m_id(id) {} - Qt3DRender::QTextureDataPtr operator ()() { + Qt3DRender::QTextureDataPtr operator ()() Q_DECL_OVERRIDE { return Qt3DRender::QTextureDataPtr::create(); } - bool operator ==(const Qt3DRender::QTextureGenerator &other) const { - const TestTextureGenerator *otherFunctor = functor_cast<TestTextureGenerator>(&other); + bool operator ==(const Qt3DRender::QTextureGenerator &other) const Q_DECL_OVERRIDE { + const TestTextureGenerator *otherFunctor = Qt3DRender::functor_cast<TestTextureGenerator>(&other); return (otherFunctor != Q_NULLPTR && otherFunctor->m_id == m_id); } diff --git a/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_eye.qml b/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_eye.qml index 20585b5de..3b21b08ba 100644 --- a/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_eye.qml +++ b/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_eye.qml @@ -48,9 +48,9 @@ ** ****************************************************************************/ -import Qt3D.Core 2.0 -import Qt3D.Render 2.0 -import Qt3D.Extras 2.0 +import Qt3D.Core 2.9 +import Qt3D.Render 2.9 +import Qt3D.Extras 2.9 import QtQuick.Window 2.0 Entity { diff --git a/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_world.qml b/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_world.qml index d3e766021..59ccdd27f 100644 --- a/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_world.qml +++ b/tests/auto/render/updateshaderdatatransformjob/test_scene_model_to_world.qml @@ -48,9 +48,9 @@ ** ****************************************************************************/ -import Qt3D.Core 2.0 -import Qt3D.Render 2.0 -import Qt3D.Extras 2.0 +import Qt3D.Core 2.9 +import Qt3D.Render 2.9 +import Qt3D.Extras 2.9 import QtQuick.Window 2.0 Entity { diff --git a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp index 9b53d1f65..c076aa21e 100644 --- a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp +++ b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp @@ -165,7 +165,7 @@ private Q_SLOTS: Qt3DRender::Render::ShaderData *backendShaderData = collection.backendShaderData.first(); // THEN - QCOMPARE(backendShaderData->properties().size(), 2); + QCOMPARE(backendShaderData->properties().size(), 3); QVERIFY(backendShaderData->properties().contains(QLatin1String("eyePosition"))); QVERIFY(backendShaderData->properties().contains(QLatin1String("eyePositionTransformed"))); @@ -205,7 +205,7 @@ private Q_SLOTS: Qt3DRender::Render::ShaderData *backendShaderData = collection.backendShaderData.first(); // THEN - QCOMPARE(backendShaderData->properties().size(), 2); + QCOMPARE(backendShaderData->properties().size(), 3); QVERIFY(backendShaderData->properties().contains(QLatin1String("position"))); QVERIFY(backendShaderData->properties().contains(QLatin1String("positionTransformed"))); diff --git a/tests/auto/render/vsyncframeadvanceservice/BLACKLIST b/tests/auto/render/vsyncframeadvanceservice/BLACKLIST new file mode 100644 index 000000000..34dccc8fe --- /dev/null +++ b/tests/auto/render/vsyncframeadvanceservice/BLACKLIST @@ -0,0 +1,2 @@ +[checkSynchronisation] +opensuse-42.1 diff --git a/tests/manual/anim-viewer/main.qml b/tests/manual/anim-viewer/main.qml index 95a4900e3..15e9cd3f9 100644 --- a/tests/manual/anim-viewer/main.qml +++ b/tests/manual/anim-viewer/main.qml @@ -42,7 +42,8 @@ import QtQuick.Controls.Styles 1.4 import Qt3D.Core 2.0 import Qt3D.Render 2.0 import Qt3D.Input 2.0 -import Qt3D.Extras 2.2 +import Qt3D.Extras 2.9 +import Qt3D.Animation 2.9 import QtQuick.Scene3D 2.0 diff --git a/tests/manual/animation-keyframe-blendtree/DefaultSceneEntity.qml b/tests/manual/animation-keyframe-blendtree/DefaultSceneEntity.qml new file mode 100644 index 000000000..f1c6110d6 --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/DefaultSceneEntity.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: root + property Camera camera + + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + camera: root.camera + } + }, + // Event Source will be set by the Qt3DQuickWindow + InputSettings { } + ] + + Entity { + components: [ + PointLight { intensity: 0.5 }, + Transform { translation: camera.position } + ] + } +} diff --git a/tests/manual/animation-keyframe-blendtree/animation-keyframe-blendtree.pro b/tests/manual/animation-keyframe-blendtree/animation-keyframe-blendtree.pro new file mode 100644 index 000000000..04db4207e --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/animation-keyframe-blendtree.pro @@ -0,0 +1,5 @@ +TEMPLATE = app +QT += 3dquickextras 3dquickanimation +SOURCES += main.cpp +RESOURCES += main.qrc +OTHER_FILES += main.qml DefaultSceneEntity.qml diff --git a/tests/manual/animation-keyframe-blendtree/main.cpp b/tests/manual/animation-keyframe-blendtree/main.cpp new file mode 100644 index 000000000..fce9ecc5f --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <Qt3DAnimation/QAnimationAspect> +#include <Qt3DQuickExtras/Qt3DQuickWindow> +#include <Qt3DQuick/QQmlAspectEngine> +#include <QQmlEngine> +#include <QQmlContext> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + Qt3DExtras::Quick::Qt3DQuickWindow view; + view.registerAspect(new Qt3DAnimation::QAnimationAspect()); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + return app.exec(); +} diff --git a/tests/manual/animation-keyframe-blendtree/main.qml b/tests/manual/animation-keyframe-blendtree/main.qml new file mode 100644 index 000000000..23aba4b79 --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/main.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Animation 2.9 +import Qt3D.Extras 2.0 + +DefaultSceneEntity { + id: scene + + Entity { + id: cube + + components: [ + Transform { + id: cubeTransform + translation: Qt.vector3d(5, 0, 0) + onTranslationChanged: console.log("t = " + translation) + }, + CuboidMesh { + }, + PhongMaterial { + id: cubeMaterial + ambient: Qt.rgba(0.02, 0.02, 0.02, 1.0) + diffuse: "red" + shininess: 50 + }, + ObjectPicker { + onClicked: blendedAnimator.running = true + }, + BlendedClipAnimator { + id: blendedAnimator + loops: 2 + + onRunningChanged: console.log("running = " + running) + + blendTree: LerpClipBlend { + blendFactor: 0.2 + startClip: ClipBlendValue { + clip: AnimationClipLoader { source: "sliding-cube.json" } + } + endClip: ClipBlendValue { + clip: AnimationClipLoader { source: "sliding-pulsing-cube.json" } + } + } + + channelMapper: ChannelMapper { + mappings: [ + ChannelMapping { channelName: "Location"; target: cubeTransform; property: "translation" }, + ChannelMapping { channelName: "Scale"; target: cubeTransform; property: "scale3D" } + ] + } + } + ] + } + + camera: Camera { + position: Qt.vector3d(10, 3, 15) + viewCenter: Qt.vector3d(2.5, 1, 0) + } + + OrbitCameraController { + camera: scene.camera + linearSpeed: 8 + lookSpeed: 180 + } +} diff --git a/tests/manual/animation-keyframe-blendtree/main.qrc b/tests/manual/animation-keyframe-blendtree/main.qrc new file mode 100644 index 000000000..4422a677e --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/main.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>DefaultSceneEntity.qml</file> + <file>sliding-cube.json</file> + <file>sliding-pulsing-cube.json</file> + </qresource> +</RCC> diff --git a/tests/manual/animation-keyframe-blendtree/sliding-cube.json b/tests/manual/animation-keyframe-blendtree/sliding-cube.json new file mode 100644 index 000000000..2404ea325 --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/sliding-cube.json @@ -0,0 +1,469 @@ +{ + "animations": [ + { + "animationName": "PulsingSlidingCube", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.22774004936218262, + 0.0 + ], + "rightHandle": [ + 0.22774004936218262, + 0.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.6238380670547485 + ], + "leftHandle": [ + 0.3555932839711507, + 0.20872697234153748 + ], + "rightHandle": [ + 0.8273405234018961, + 1.0685999393463135 + ] + }, + { + "coords": [ + 1.2083333333333333, + 2.2338662147521973 + ], + "leftHandle": [ + 0.9643261432647705, + 1.5640573501586914 + ], + "rightHandle": [ + 1.4523404439290364, + 2.903675079345703 + ] + }, + { + "coords": [ + 1.8333333333333333, + 4.0551347732543945 + ], + "leftHandle": [ + 1.5893262227376301, + 3.515169620513916 + ], + "rightHandle": [ + 2.0773404439290366, + 4.595099925994873 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 2.2143262227376304, + 5.0 + ], + "rightHandle": [ + 2.7023404439290366, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.22774004936218262, + 0.0 + ], + "rightHandle": [ + 0.22774004936218262, + 0.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.0 + ], + "leftHandle": [ + 0.3555932839711507, + 0.0 + ], + "rightHandle": [ + 0.8273405234018961, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 0.9643261432647705, + 0.0 + ], + "rightHandle": [ + 1.4523404439290364, + 0.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.0 + ], + "leftHandle": [ + 1.5893262227376301, + 0.0 + ], + "rightHandle": [ + 2.0773404439290366, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 2.2143262227376304, + 0.0 + ], + "rightHandle": [ + 2.7023404439290366, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.22774004936218262, + 0.0 + ], + "rightHandle": [ + 0.22774004936218262, + 0.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.0 + ], + "leftHandle": [ + 0.3555932839711507, + 0.0 + ], + "rightHandle": [ + 0.8273405234018961, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 0.9643261432647705, + 0.0 + ], + "rightHandle": [ + 1.4523404439290364, + 0.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.0 + ], + "leftHandle": [ + 1.5893262227376301, + 0.0 + ], + "rightHandle": [ + 2.0773404439290366, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 2.2143262227376304, + 0.0 + ], + "rightHandle": [ + 2.7023404439290366, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.22774004936218262, + 1.0 + ], + "rightHandle": [ + 0.22774004936218262, + 1.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 1.0 + ], + "leftHandle": [ + 0.3555932839711507, + 1.0 + ], + "rightHandle": [ + 0.8273405234018961, + 1.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 0.9643261432647705, + 1.0 + ], + "rightHandle": [ + 1.4523404439290364, + 1.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 1.0 + ], + "leftHandle": [ + 1.5893262227376301, + 1.0 + ], + "rightHandle": [ + 2.0773404439290366, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 1.0 + ], + "leftHandle": [ + 2.2143262227376304, + 1.0 + ], + "rightHandle": [ + 2.7023404439290366, + 1.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.22774004936218262, + 1.0 + ], + "rightHandle": [ + 0.22774004936218262, + 1.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 1.0 + ], + "leftHandle": [ + 0.3555932839711507, + 1.0 + ], + "rightHandle": [ + 0.8273405234018961, + 1.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 0.9643261432647705, + 1.0 + ], + "rightHandle": [ + 1.4523404439290364, + 1.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 1.0 + ], + "leftHandle": [ + 1.5893262227376301, + 1.0 + ], + "rightHandle": [ + 2.0773404439290366, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 1.0 + ], + "leftHandle": [ + 2.2143262227376304, + 1.0 + ], + "rightHandle": [ + 2.7023404439290366, + 1.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.22774004936218262, + 1.0 + ], + "rightHandle": [ + 0.22774004936218262, + 1.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 1.0 + ], + "leftHandle": [ + 0.3555932839711507, + 1.0 + ], + "rightHandle": [ + 0.8273405234018961, + 1.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 0.9643261432647705, + 1.0 + ], + "rightHandle": [ + 1.4523404439290364, + 1.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 1.0 + ], + "leftHandle": [ + 1.5893262227376301, + 1.0 + ], + "rightHandle": [ + 2.0773404439290366, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 1.0 + ], + "leftHandle": [ + 2.2143262227376304, + 1.0 + ], + "rightHandle": [ + 2.7023404439290366, + 1.0 + ] + } + ] + } + ], + "channelName": "Scale" + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/manual/animation-keyframe-blendtree/sliding-pulsing-cube.json b/tests/manual/animation-keyframe-blendtree/sliding-pulsing-cube.json new file mode 100644 index 000000000..9d6a8c7b8 --- /dev/null +++ b/tests/manual/animation-keyframe-blendtree/sliding-pulsing-cube.json @@ -0,0 +1,469 @@ +{ + "animations": [ + { + "animationName": "PulsingSlidingCube", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.22774004936218262, + 0.0 + ], + "rightHandle": [ + 0.22774004936218262, + 0.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.6238380670547485 + ], + "leftHandle": [ + 0.3555932839711507, + 0.20872697234153748 + ], + "rightHandle": [ + 0.8273405234018961, + 1.0685999393463135 + ] + }, + { + "coords": [ + 1.2083333333333333, + 2.2338662147521973 + ], + "leftHandle": [ + 0.9643261432647705, + 1.5640573501586914 + ], + "rightHandle": [ + 1.4523404439290364, + 2.903675079345703 + ] + }, + { + "coords": [ + 1.8333333333333333, + 4.0551347732543945 + ], + "leftHandle": [ + 1.5893262227376301, + 3.515169620513916 + ], + "rightHandle": [ + 2.0773404439290366, + 4.595099925994873 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 2.2143262227376304, + 5.0 + ], + "rightHandle": [ + 2.7023404439290366, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.22774004936218262, + 0.0 + ], + "rightHandle": [ + 0.22774004936218262, + 0.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.0 + ], + "leftHandle": [ + 0.3555932839711507, + 0.0 + ], + "rightHandle": [ + 0.8273405234018961, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 0.9643261432647705, + 0.0 + ], + "rightHandle": [ + 1.4523404439290364, + 0.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.0 + ], + "leftHandle": [ + 1.5893262227376301, + 0.0 + ], + "rightHandle": [ + 2.0773404439290366, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 2.2143262227376304, + 0.0 + ], + "rightHandle": [ + 2.7023404439290366, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.22774004936218262, + 0.0 + ], + "rightHandle": [ + 0.22774004936218262, + 0.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.0 + ], + "leftHandle": [ + 0.3555932839711507, + 0.0 + ], + "rightHandle": [ + 0.8273405234018961, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 0.9643261432647705, + 0.0 + ], + "rightHandle": [ + 1.4523404439290364, + 0.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.0 + ], + "leftHandle": [ + 1.5893262227376301, + 0.0 + ], + "rightHandle": [ + 2.0773404439290366, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 2.2143262227376304, + 0.0 + ], + "rightHandle": [ + 2.7023404439290366, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.22774004936218262, + 1.0 + ], + "rightHandle": [ + 0.22774004936218262, + 1.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.5 + ], + "leftHandle": [ + 0.3555932839711507, + 0.5 + ], + "rightHandle": [ + 0.8273405234018961, + 0.5 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 0.9643261432647705, + 1.0 + ], + "rightHandle": [ + 1.4523404439290364, + 1.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.5 + ], + "leftHandle": [ + 1.5893262227376301, + 0.5 + ], + "rightHandle": [ + 2.0773404439290366, + 0.5 + ] + }, + { + "coords": [ + 2.4583333333333335, + 1.0 + ], + "leftHandle": [ + 2.2143262227376304, + 1.0 + ], + "rightHandle": [ + 2.7023404439290366, + 1.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.22774004936218262, + 1.0 + ], + "rightHandle": [ + 0.22774004936218262, + 1.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.5 + ], + "leftHandle": [ + 0.3555932839711507, + 0.5 + ], + "rightHandle": [ + 0.8273405234018961, + 0.5 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 0.9643261432647705, + 1.0 + ], + "rightHandle": [ + 1.4523404439290364, + 1.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.5 + ], + "leftHandle": [ + 1.5893262227376301, + 0.5 + ], + "rightHandle": [ + 2.0773404439290366, + 0.5 + ] + }, + { + "coords": [ + 2.4583333333333335, + 1.0 + ], + "leftHandle": [ + 2.2143262227376304, + 1.0 + ], + "rightHandle": [ + 2.7023404439290366, + 1.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.22774004936218262, + 1.0 + ], + "rightHandle": [ + 0.22774004936218262, + 1.0 + ] + }, + { + "coords": [ + 0.5833333333333334, + 0.5 + ], + "leftHandle": [ + 0.3555932839711507, + 0.5 + ], + "rightHandle": [ + 0.8273405234018961, + 0.5 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 0.9643261432647705, + 1.0 + ], + "rightHandle": [ + 1.4523404439290364, + 1.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.5 + ], + "leftHandle": [ + 1.5893262227376301, + 0.5 + ], + "rightHandle": [ + 2.0773404439290366, + 0.5 + ] + }, + { + "coords": [ + 2.4583333333333335, + 1.0 + ], + "leftHandle": [ + 2.2143262227376304, + 1.0 + ], + "rightHandle": [ + 2.7023404439290366, + 1.0 + ] + } + ] + } + ], + "channelName": "Scale" + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/manual/animation-keyframe-programmatic/DefaultSceneEntity.qml b/tests/manual/animation-keyframe-programmatic/DefaultSceneEntity.qml new file mode 100644 index 000000000..f1c6110d6 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/DefaultSceneEntity.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: root + property Camera camera + + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + camera: root.camera + } + }, + // Event Source will be set by the Qt3DQuickWindow + InputSettings { } + ] + + Entity { + components: [ + PointLight { intensity: 0.5 }, + Transform { translation: camera.position } + ] + } +} diff --git a/tests/manual/animation-keyframe-programmatic/animation-keyframe-programmatic.pro b/tests/manual/animation-keyframe-programmatic/animation-keyframe-programmatic.pro new file mode 100644 index 000000000..e38990808 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/animation-keyframe-programmatic.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +QT += 3dquickextras 3dquickanimation + +SOURCES += \ + main.cpp \ + animationfactory.cpp + +HEADERS += \ + animationfactory.h + +RESOURCES += main.qrc +OTHER_FILES += main.qml DefaultSceneEntity.qml diff --git a/tests/manual/animation-keyframe-programmatic/animationfactory.cpp b/tests/manual/animation-keyframe-programmatic/animationfactory.cpp new file mode 100644 index 000000000..e3b1c6165 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/animationfactory.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "animationfactory.h" + +using namespace Qt3DAnimation; + +AnimationFactory::AnimationFactory(QObject *parent) + : QObject(parent) +{ + updateClipData(); +} + +void AnimationFactory::updateClipData() +{ + m_clipData.clearChannels(); + + // Add a channel for a Location animation + QChannel location(QLatin1String("Location")); + + QChannelComponent locationX(QLatin1String("Location X")); + locationX.appendKeyFrame(QKeyFrame({0.0f, 0.0f}, {-1.0f, 0.0f}, {1.0f, 0.0f})); + locationX.appendKeyFrame(QKeyFrame({2.45f, 5.0f}, {1.45f, 5.0f}, {3.45f, 5.0f})); + + QChannelComponent locationY(QLatin1String("Location Y")); + locationY.appendKeyFrame(QKeyFrame({0.0f, 0.0f}, {-1.0f, 0.0f}, {1.0f, 0.0f})); + locationY.appendKeyFrame(QKeyFrame({2.45f, 0.0f}, {1.45f, 0.0f}, {3.45f, 0.0f})); + + QChannelComponent locationZ(QLatin1String("Location Z")); + locationZ.appendKeyFrame(QKeyFrame({0.0f, 0.0f}, {-1.0f, 0.0f}, {1.0f, 0.0f})); + locationZ.appendKeyFrame(QKeyFrame({2.45f, 0.0f}, {1.45f, 0.0f}, {3.45f, 0.0f})); + + location.appendChannelComponent(locationX); + location.appendChannelComponent(locationY); + location.appendChannelComponent(locationZ); + + m_clipData.appendChannel(location); +} diff --git a/tests/manual/animation-keyframe-programmatic/animationfactory.h b/tests/manual/animation-keyframe-programmatic/animationfactory.h new file mode 100644 index 000000000..b73db0b68 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/animationfactory.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ANIMATIONFACTORY_H +#define ANIMATIONFACTORY_H + +#include <QObject> +#include <Qt3DAnimation/qanimationclipdata.h> + +class AnimationFactory : public QObject +{ + Q_OBJECT + Q_PROPERTY(Qt3DAnimation::QAnimationClipData clipData READ clipData NOTIFY clipDataChanged) + +public: + explicit AnimationFactory(QObject *parent = 0); + + Qt3DAnimation::QAnimationClipData clipData() const + { + return m_clipData; + } + +signals: + void clipDataChanged(Qt3DAnimation::QAnimationClipData clipData); + +private: + void updateClipData(); + + Qt3DAnimation::QAnimationClipData m_clipData; +}; + +#endif // ANIMATIONFACTORY_H diff --git a/tests/manual/animation-keyframe-programmatic/main.cpp b/tests/manual/animation-keyframe-programmatic/main.cpp new file mode 100644 index 000000000..eb3a22df1 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <Qt3DAnimation/QAnimationAspect> +#include <Qt3DQuickExtras/Qt3DQuickWindow> +#include <Qt3DQuick/QQmlAspectEngine> +#include <QQmlEngine> +#include <QQmlContext> + +#include "animationfactory.h" + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + AnimationFactory animationFactory; + + Qt3DExtras::Quick::Qt3DQuickWindow view; + view.registerAspect(new Qt3DAnimation::QAnimationAspect()); + view.engine()->qmlEngine()->rootContext()->setContextProperty("_animationFactory", &animationFactory); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + return app.exec(); +} diff --git a/tests/manual/animation-keyframe-programmatic/main.qml b/tests/manual/animation-keyframe-programmatic/main.qml new file mode 100644 index 000000000..c34e44d51 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/main.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Animation 2.9 +import Qt3D.Extras 2.0 + +DefaultSceneEntity { + id: scene + + Entity { + id: cube + + components: [ + Transform { + id: cubeTransform + + onTranslationChanged: console.log("t = " + translation) + }, + CuboidMesh { + }, + PhongMaterial { + id: cubeMaterial + ambient: Qt.rgba(0.02, 0.02, 0.02, 1.0) + diffuse: "blue" + shininess: 50 + }, + ObjectPicker { + onClicked: animator.running = true + }, + ClipAnimator { + id: animator + loops: 3 + onRunningChanged: console.log("running = " + running) + + clip: AnimationClip { + clipData: _animationFactory.clipData + onDurationChanged: console.log("duration = " + duration) + } + + // By default introspect parent Entity and try + // to map fcurve groups to properties of QTransform + // mapping: AutomaticAnimationMapping {} + + // To do more, we can be explicit + channelMapper: ChannelMapper { + mappings: [ + ChannelMapping { channelName: "Location"; target: cubeTransform; property: "translation" }, + ChannelMapping { channelName: "Rotation"; target: cubeTransform; property: "rotation" }, + ChannelMapping { channelName: "Diffuse Color"; target: cubeMaterial; property: "diffuse" } + ] + } + } + ] + } + + camera: Camera { + position: Qt.vector3d(10, 3, 15) + viewCenter: Qt.vector3d(2.5, 1, 0) + } + + OrbitCameraController { + camera: scene.camera + linearSpeed: 8 + lookSpeed: 180 + } +} diff --git a/tests/manual/animation-keyframe-programmatic/main.qrc b/tests/manual/animation-keyframe-programmatic/main.qrc new file mode 100644 index 000000000..8bcf0c762 --- /dev/null +++ b/tests/manual/animation-keyframe-programmatic/main.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>DefaultSceneEntity.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml b/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml index efffd44c9..f1c6110d6 100644 --- a/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml +++ b/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml @@ -1,11 +1,52 @@ -/************************************************************************* - * - * Copyright (c) 2016, Klaralvdalens Datakonsult AB (KDAB) - * All rights reserved. - * - * See the LICENSE.txt file shipped along with this file for the license. - * - *************************************************************************/ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ import Qt3D.Core 2.0 import Qt3D.Render 2.0 diff --git a/tests/manual/animation-keyframe-simple/cubeanimation.json b/tests/manual/animation-keyframe-simple/cubeanimation.json index addf92907..3faff409c 100644 --- a/tests/manual/animation-keyframe-simple/cubeanimation.json +++ b/tests/manual/animation-keyframe-simple/cubeanimation.json @@ -1,87 +1,250 @@ { "animations": [ - { "object": "Cube", - "action": "CubeAction", - "range": [0.0, 60.0], - "groups": [ - { "group": "Location", - "channels": [ - { "name": "x", - "keyframes": [ - { "co": [0.0, 0.0], - "handle_left": [-0.4717472394307454, 0.0], - "handle_right": [0.4717472394307454, 0.0]} - ,{ "co": [1.2083333333333333, 2.430499792098999], - "handle_left": [0.7365860939025879, 1.4711904525756836], - "handle_right": [1.696347713470459, 3.42288875579834]} - ,{ "co": [2.4583333333333335, 5.0], - "handle_left": [1.9703189531962078, 5.0], - "handle_right": [2.9463475545247397, 5.0]} - ]} - ,{ "name": "z", - "keyframes": [ - { "co": [0.0, 0.0], - "handle_left": [-0.4717472394307454, 0.0], - "handle_right": [0.4717472394307454, 0.0]} - ,{ "co": [1.2083333333333333, 0.0], - "handle_left": [0.7365860939025879, 0.0], - "handle_right": [1.696347713470459, 0.0]} - ,{ "co": [2.4583333333333335, 0.0], - "handle_left": [1.9703189531962078, 0.0], - "handle_right": [2.9463475545247397, 0.0]} - ]} - ,{ "name": "y", - "keyframes": [ - { "co": [0.0, 0.0], - "handle_left": [-0.4717472394307454, 0.0], - "handle_right": [0.4717472394307454, 0.0]} - ,{ "co": [1.2083333333333333, 3.0], - "handle_left": [0.7365860939025879, 3.0], - "handle_right": [1.696347713470459, 3.0]} - ,{ "co": [2.4583333333333335, 0.0], - "handle_left": [1.9703189531962078, 0.0], - "handle_right": [2.9463475545247397, 0.0]} - ]} - ]} - ,{ "group": "Rotation", - "channels": [ - { "name": "w", - "keyframes": [ - { "co": [0.0, 1.0], - "handle_left": [-0.9597616195678711, 1.0], - "handle_right": [0.9597616195678711, 1.0]} - ,{ "co": [2.4583333333333335, -4.371138828673793e-08], - "handle_left": [1.4985717137654622, -4.371138828673793e-08], - "handle_right": [3.4180949529012046, -4.371138828673793e-08]} - ]} - ,{ "name": "x", - "keyframes": [ - { "co": [0.0, 0.0], - "handle_left": [-0.9597616195678711, 0.0], - "handle_right": [0.9597616195678711, 0.0]} - ,{ "co": [2.4583333333333335, 0.0], - "handle_left": [1.4985717137654622, 0.0], - "handle_right": [3.4180949529012046, 0.0]} - ]} - ,{ "name": "z", - "keyframes": [ - { "co": [0.0, -0.0], - "handle_left": [-0.9597616195678711, -0.0], - "handle_right": [0.9597616195678711, -0.0]} - ,{ "co": [2.4583333333333335, -1.0], - "handle_left": [1.4985717137654622, -1.0], - "handle_right": [3.4180949529012046, -1.0]} - ]} - ,{ "name": "y", - "keyframes": [ - { "co": [0.0, 0.0], - "handle_left": [-0.9597616195678711, 0.0], - "handle_right": [0.9597616195678711, 0.0]} - ,{ "co": [2.4583333333333335, 0.0], - "handle_left": [1.4985717137654622, 0.0], - "handle_right": [3.4180949529012046, 0.0]} - ]} - ]} - ]} - ] -} + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation" + } + ] + } + ] +}
\ No newline at end of file diff --git a/tests/manual/animation-keyframe-simple/main.cpp b/tests/manual/animation-keyframe-simple/main.cpp index fc48fc702..fce9ecc5f 100644 --- a/tests/manual/animation-keyframe-simple/main.cpp +++ b/tests/manual/animation-keyframe-simple/main.cpp @@ -1,11 +1,52 @@ -/************************************************************************* - * - * Copyright (c) 2016, Klaralvdalens Datakonsult AB (KDAB) - * All rights reserved. - * - * See the LICENSE.txt file shipped along with this file for the license. - * - *************************************************************************/ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include <QGuiApplication> #include <Qt3DAnimation/QAnimationAspect> diff --git a/tests/manual/animation-keyframe-simple/main.qml b/tests/manual/animation-keyframe-simple/main.qml index 8546d8b34..79fb75fbd 100644 --- a/tests/manual/animation-keyframe-simple/main.qml +++ b/tests/manual/animation-keyframe-simple/main.qml @@ -1,16 +1,57 @@ -/************************************************************************* - * - * Copyright (c) 2016, Klaralvdalens Datakonsult AB (KDAB) - * All rights reserved. - * - * See the LICENSE.txt file shipped along with this file for the license. - * - *************************************************************************/ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ import Qt3D.Core 2.0 import Qt3D.Render 2.0 import Qt3D.Input 2.0 -import Qt3D.Animation 2.2 +import Qt3D.Animation 2.9 import Qt3D.Extras 2.0 DefaultSceneEntity { @@ -41,7 +82,7 @@ DefaultSceneEntity { loops: 3 onRunningChanged: console.log("running = " + running) - clip: AnimationClip { + clip: AnimationClipLoader { source: "cubeanimation.json" onDurationChanged: console.log("duration = " + duration) } @@ -62,64 +103,6 @@ DefaultSceneEntity { ] } - Entity { - id: sphere - - components: [ - Transform { - id: sphereTransform - translation: Qt.vector3d(5, 0, 0) - onTranslationChanged: console.log("t = " + translation) - }, - SphereMesh { - }, - PhongMaterial { - id: sphereMaterial - ambient: Qt.rgba(0.02, 0.02, 0.02, 1.0) - diffuse: "red" - shininess: 50 - }, - ObjectPicker { - onClicked: blendedAnimator.running = true - }, - BlendedClipAnimator { - id: blendedAnimator - loops: 2 - - onRunningChanged: console.log("running = " + running) - - blendTree: LerpBlend { - blendFactor: 0.5 - clips: [ - AnimationClip { - source: "cubeanimation.json" - onDurationChanged: console.log("duration = " + duration) - }, - AnimationClip { - source: "pulsing-moving-cube.json" - onDurationChanged: console.log("duration = " + duration) - }] - } - - - // By default introspect parent Entity and try - // to map fcurve groups to properties of QTransform - // mapping: AutomaticAnimationMapping {} - - // To do more, we can be explicit - channelMapper: ChannelMapper { - mappings: [ - ChannelMapping { channelName: "Location"; target: sphereTransform; property: "translation" }, - ChannelMapping { channelName: "Rotation"; target: sphereTransform; property: "rotation" }, - ChannelMapping { channelName: "Scaling"; target: sphereTransform; property: "scale3D" }, - ChannelMapping { channelName: "Diffuse Color"; target: sphereMaterial; property: "diffuse" } - ] - } - } - ] - } - - camera: Camera { position: Qt.vector3d(10, 3, 15) viewCenter: Qt.vector3d(2.5, 1, 0) diff --git a/tests/manual/animation-keyframe-simple/main.qrc b/tests/manual/animation-keyframe-simple/main.qrc index 323756a88..b59429895 100644 --- a/tests/manual/animation-keyframe-simple/main.qrc +++ b/tests/manual/animation-keyframe-simple/main.qrc @@ -4,5 +4,6 @@ <file>DefaultSceneEntity.qml</file> <file>cubeanimation.json</file> <file>pulsing-moving-cube.json</file> + <file>pulsing-cube-additive.json</file> </qresource> </RCC> diff --git a/tests/manual/animation-keyframe-simple/pulsing-cube-additive.json b/tests/manual/animation-keyframe-simple/pulsing-cube-additive.json new file mode 100644 index 000000000..1373a5002 --- /dev/null +++ b/tests/manual/animation-keyframe-simple/pulsing-cube-additive.json @@ -0,0 +1,84 @@ +{ + "animations": [ + { "object": "Cube", + "action": "CubeAction", + "range": [0.0, 60.0], + "groups": [ + { "group": "Scaling", + "channels": [ + { "name": "x", + "keyframes": [ + { "co": [0.0, 1.0], + "handle_left": [-0.1464043160279592, 1.0], + "handle_right": [0.14640430609385172, 1.0]} + ,{ "co": [0.375, 0.5], + "handle_left": [0.22859569390614828, 0.5], + "handle_right": [0.5376714468002319, 0.5]} + ,{ "co": [0.7916666666666666, 1.0], + "handle_left": [0.6289951801300049, 1.0], + "handle_right": [0.9543381532033285, 1.0]} + ,{ "co": [1.2083333333333333, 0.5], + "handle_left": [1.0456619262695312, 0.5], + "handle_right": [1.371035893758138, 0.5]} + ,{ "co": [1.625, 1.0], + "handle_left": [1.462328592936198, 1.0], + "handle_right": [1.787671407063802, 1.0]} + ,{ "co": [2.0416666666666665, 0.5], + "handle_left": [1.8789952596028645, 0.5], + "handle_right": [2.2043380737304688, 0.5]} + ,{ "co": [2.4583333333333335, 1.0], + "handle_left": [2.2956619262695312, 1.0], + "handle_right": [2.6210047403971353, 1.0]} + ]} + ,{ "name": "z", + "keyframes": [ + { "co": [0.0, 1.0], + "handle_left": [-0.1464043160279592, 1.0], + "handle_right": [0.14640430609385172, 1.0]} + ,{ "co": [0.375, 0.5], + "handle_left": [0.22859569390614828, 0.5], + "handle_right": [0.5376714468002319, 0.5]} + ,{ "co": [0.7916666666666666, 1.0], + "handle_left": [0.6289951801300049, 1.0], + "handle_right": [0.9543381532033285, 1.0]} + ,{ "co": [1.2083333333333333, 0.5], + "handle_left": [1.0456618467966716, 0.5], + "handle_right": [1.3710047403971355, 0.5]} + ,{ "co": [1.625, 1.0], + "handle_left": [1.462328592936198, 1.0], + "handle_right": [1.787671407063802, 1.0]} + ,{ "co": [2.0416666666666665, 0.5], + "handle_left": [1.8789952596028645, 0.5], + "handle_right": [2.2043380737304688, 0.5]} + ,{ "co": [2.4583333333333335, 1.0], + "handle_left": [2.2956619262695312, 1.0], + "handle_right": [2.6210047403971353, 1.0]} + ]} + ,{ "name": "y", + "keyframes": [ + { "co": [0.0, 1.0], + "handle_left": [-0.1464043160279592, 1.0], + "handle_right": [0.14640430609385172, 1.0]} + ,{ "co": [0.375, 0.5], + "handle_left": [0.22859569390614828, 0.5], + "handle_right": [0.5376714468002319, 0.5]} + ,{ "co": [0.7916666666666666, 1.0], + "handle_left": [0.6289951801300049, 1.0], + "handle_right": [0.9543381532033285, 1.0]} + ,{ "co": [1.2083333333333333, 0.5441937446594238], + "handle_left": [1.0456618467966716, 0.5441937446594238], + "handle_right": [1.3710047403971355, 0.5441937446594238]} + ,{ "co": [1.625, 1.0], + "handle_left": [1.462328592936198, 1.0], + "handle_right": [1.787671407063802, 1.0]} + ,{ "co": [2.0416666666666665, 0.5771476030349731], + "handle_left": [1.8789952596028645, 0.5771476030349731], + "handle_right": [2.2043380737304688, 0.5771476030349731]} + ,{ "co": [2.4583333333333335, 1.0], + "handle_left": [2.2956619262695312, 1.0], + "handle_right": [2.6210047403971353, 1.0]} + ]} + ]} + ]} + ] +} diff --git a/tests/manual/buffercapture-qml/BufferSetterScene.qml b/tests/manual/buffercapture-qml/BufferSetterScene.qml new file mode 100644 index 000000000..2b2b2a85a --- /dev/null +++ b/tests/manual/buffercapture-qml/BufferSetterScene.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 as QQ2 +import Qt3D.Core 2.0 +import Qt3D.Render 2.9 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: sceneRoot + + Camera { + id: sceneCamera + projectionType: CameraLens.PerspectiveProjection + upVector: Qt.vector3d(0, 1, 0) + position: Qt.vector3d(0, 0, -800) + viewCenter: Qt.vector3d(0, 0, 0) + nearPlane: 0.1 + farPlane: 1000 + fieldOfView: 25 + aspectRatio: 1.33 + } + + components: [ + RenderSettings { + ComputeFrameGraph { + } + // explicitly set RenderingPolicy to AlwaysRender, as changes in the + // scene won't be reflected in actual Qt scene-graph changes (due to + // GPU compute calls) + renderPolicy: RenderSettings.Always + } + ] + + function initGraphBuffer() { + var bufferData = new Uint32Array(1024); + for (var i = 0; i < 1024; ++i) { + bufferData[i] = 1; + } + return bufferData + } + + + Buffer { + id: graphBuffer + objectName: "buffer" + type: Buffer.VertexBuffer + data: initGraphBuffer() + accessType: Buffer.ReadWrite + } + + ComputeMaterial { + id: computeMaterial + dataBuffer: graphBuffer + inputSize: 1024 + } + + Entity { + id: particleComputeEntity + readonly property ComputeCommand particlesComputeJob: ComputeCommand {} + components: [ + particlesComputeJob, + computeMaterial + ] + } +} diff --git a/tests/manual/buffercapture-qml/ComputeFrameGraph.qml b/tests/manual/buffercapture-qml/ComputeFrameGraph.qml new file mode 100644 index 000000000..bc2061e1a --- /dev/null +++ b/tests/manual/buffercapture-qml/ComputeFrameGraph.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.9 + +Viewport { + RenderSurfaceSelector { + id: surfaceSelector + + // Compute Pass + DispatchCompute { + workGroupX: 50; workGroupY: 1; workGroupZ: 1 + BufferCapture { + TechniqueFilter { + matchAll: [ + FilterKey { name: "type"; value: "compute"} + ] + } + } + } + + NoDraw { } + } +} + + diff --git a/tests/manual/buffercapture-qml/ComputeMaterial.qml b/tests/manual/buffercapture-qml/ComputeMaterial.qml new file mode 100644 index 000000000..05c56901c --- /dev/null +++ b/tests/manual/buffercapture-qml/ComputeMaterial.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 + +Material { + property Buffer dataBuffer; + property int inputSize; + + parameters: [ + Parameter { name: "inputSize"; value: inputSize} + ] + + ShaderProgram { + id: computeShader + computeShaderCode: loadSource("qrc:/bufferSetter.comp") + } + + effect: Effect { + techniques: [ + Technique { + renderPasses: [ + RenderPass { + shaderProgram: computeShader + // We set the buffer as the parameter data + parameters: [ + Parameter { name: "input"; value: dataBuffer } + ] + } + ] + filterKeys: [ + FilterKey { name: "type"; value: "compute" } + ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.CoreProfile + majorVersion: 4 + minorVersion: 3 + } + } + ] // techniques + } +} diff --git a/tests/manual/buffercapture-qml/bufferSetter.comp b/tests/manual/buffercapture-qml/bufferSetter.comp new file mode 100755 index 000000000..d7c383669 --- /dev/null +++ b/tests/manual/buffercapture-qml/bufferSetter.comp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#version 430 core + +layout (local_size_x=32) in; + +layout (std430, binding = 1) buffer input +{ + uint d[]; +}; + +layout (location=1) uniform int inputSize; + +void main() +{ + if (gl_GlobalInvocationID.x < inputSize) + d[gl_GlobalInvocationID.x] = d[gl_GlobalInvocationID.x] + gl_GlobalInvocationID.x * 2; +} diff --git a/tests/manual/buffercapture-qml/buffercapture-qml.pro b/tests/manual/buffercapture-qml/buffercapture-qml.pro new file mode 100644 index 000000000..32b79a36e --- /dev/null +++ b/tests/manual/buffercapture-qml/buffercapture-qml.pro @@ -0,0 +1,16 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dinput 3dextras 3dquick 3dlogic qml quick 3dquickextras + +SOURCES += \ + main.cpp + +DISTFILES += \ + main.qml \ + main.qml + +RESOURCES += \ + resources.qrc + diff --git a/tests/manual/buffercapture-qml/main.cpp b/tests/manual/buffercapture-qml/main.cpp new file mode 100644 index 000000000..6928c5724 --- /dev/null +++ b/tests/manual/buffercapture-qml/main.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QQuickItem> +#include <QQuickView> +#include <Qt3DQuick/QQmlAspectEngine> +#include <QGuiApplication> +#include <QQmlEngine> +#include <QQmlContext> + +#include <Qt3DRender> +#include <iostream> + + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + QQuickView view; + + view.setSource(QUrl("qrc:/main.qml")); + + QObject *rootObject = view.rootObject(); + Qt3DRender::QBuffer *buffer = rootObject->findChild<Qt3DRender::QBuffer*>("buffer"); + + QObject::connect(buffer, &Qt3DRender::QBuffer::dataChanged, + [=](const QByteArray &bytes) { + //I know I'm receiving int data + const uint *data = reinterpret_cast<const uint*>(bytes.data()); + qDebug() << "Data received"; + for (uint i = 0; i < 1024; ++i) + qDebug() << data[i]; + } + ); + + view.show(); + + return app.exec(); +} diff --git a/tests/manual/buffercapture-qml/main.qml b/tests/manual/buffercapture-qml/main.qml new file mode 100644 index 000000000..a2680e921 --- /dev/null +++ b/tests/manual/buffercapture-qml/main.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import QtQuick.Scene3D 2.0 + +Item { + width: 128 + height: width + Scene3D { + anchors.fill: parent + BufferSetterScene { + id: scene + } + } +} diff --git a/tests/manual/buffercapture-qml/resources.qrc b/tests/manual/buffercapture-qml/resources.qrc new file mode 100644 index 000000000..167957feb --- /dev/null +++ b/tests/manual/buffercapture-qml/resources.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>BufferSetterScene.qml</file> + <file>bufferSetter.comp</file> + <file>main.qml</file> + <file>ComputeFrameGraph.qml</file> + <file>ComputeMaterial.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/custom-mesh-update-data-cpp/main.cpp b/tests/manual/custom-mesh-update-data-cpp/main.cpp index 7485dbec5..80ee2088d 100644 --- a/tests/manual/custom-mesh-update-data-cpp/main.cpp +++ b/tests/manual/custom-mesh-update-data-cpp/main.cpp @@ -277,7 +277,7 @@ int main(int argc, char* argv[]) void TimerObject::timeout() { - angle += M_PI / 360.0f; + angle += qDegreesToRadians(0.5f); QByteArray updateData; updateData.resize(3*sizeof(float)); diff --git a/tests/manual/custom-mesh-update-data-qml/main.qml b/tests/manual/custom-mesh-update-data-qml/main.qml index e95c05a26..909dbf9ca 100644 --- a/tests/manual/custom-mesh-update-data-qml/main.qml +++ b/tests/manual/custom-mesh-update-data-qml/main.qml @@ -224,7 +224,7 @@ Entity { byteOffset: 0 byteStride: 9 * 4 count: 4 - name: defaultPositionAttributeName() + name: defaultPositionAttributeName buffer: vertexBuffer } @@ -235,7 +235,7 @@ Entity { byteOffset: 3 * 4 byteStride: 9 * 4 count: 4 - name: defaultNormalAttributeName() + name: defaultNormalAttributeName buffer: vertexBuffer } @@ -246,7 +246,7 @@ Entity { byteOffset: 6 * 4 byteStride: 9 * 4 count: 4 - name: defaultColorAttributeName() + name: defaultColorAttributeName buffer: vertexBuffer } diff --git a/tests/manual/deferred-renderer-cpp/gbuffer.h b/tests/manual/deferred-renderer-cpp/gbuffer.h index dab8b6752..7ffaffe2a 100644 --- a/tests/manual/deferred-renderer-cpp/gbuffer.h +++ b/tests/manual/deferred-renderer-cpp/gbuffer.h @@ -75,7 +75,6 @@ public: private: Qt3DRender::QAbstractTexture *m_textures[AttachmentsCount]; - Qt3DRender::QRenderTargetOutput *m_attachments[AttachmentsCount]; }; #endif // GBUFFER_H diff --git a/tests/manual/distancefieldtext/TextScene.qml b/tests/manual/distancefieldtext/TextScene.qml new file mode 100644 index 000000000..5e94a9aaf --- /dev/null +++ b/tests/manual/distancefieldtext/TextScene.qml @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.9 +import QtQuick 2.0 as QQ2; + +Entity { + id: sceneRoot + + property alias fontFamily : text.font.family + property alias fontBold : text.font.bold + property alias fontItalic : text.font.italic + + signal clicked() + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, 20.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + FirstPersonCameraController { + camera: camera + linearSpeed: 0.1 + camera.position.z + } + + components: [ + RenderSettings { + activeFrameGraph : ForwardRenderer { + camera: camera + clearColor: "black" + } + }, + InputSettings { + } + ] + + function getChars(n) { + var s = ""; + for (var i = 0; i < n; i++) { + s += String.fromCharCode(32+i); + if (i % 16 == 15) + s += "\n"; + } + return s; + } + + property int strLen : 28 + + onClicked: { + strLen += 1 + if (strLen > 96) + strLen = 10 + } + + Entity { + components: [ + Transform { + id: rot + translation: Qt.vector3d(-5, -5, 0) + } + ] + + QQ2.SequentialAnimation { + loops: QQ2.Animation.Infinite + running: true + QQ2.NumberAnimation { + target: rot + property: "rotationY" + from: 0; to: -80; + duration: 2000 + } + QQ2.NumberAnimation { + target: rot + property: "rotationY" + from: -80; to: 80; + duration: 4000 + } + QQ2.NumberAnimation { + target: rot + property: "rotationY" + from: 80; to: 0; + duration: 2000 + } + } + + Text2DEntity { + id: text + font.pointSize: 1 + text: getChars(strLen) + width: 20 + height: 10 + } + } +} diff --git a/tests/manual/distancefieldtext/distancefieldtext.pro b/tests/manual/distancefieldtext/distancefieldtext.pro new file mode 100644 index 000000000..01f080917 --- /dev/null +++ b/tests/manual/distancefieldtext/distancefieldtext.pro @@ -0,0 +1,15 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + TextScene.qml \ + main.qml + +RESOURCES += \ + distancefieldtext.qrc diff --git a/tests/manual/distancefieldtext/distancefieldtext.qrc b/tests/manual/distancefieldtext/distancefieldtext.qrc new file mode 100644 index 000000000..5a60978c0 --- /dev/null +++ b/tests/manual/distancefieldtext/distancefieldtext.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>TextScene.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/distancefieldtext/main.cpp b/tests/manual/distancefieldtext/main.cpp new file mode 100644 index 000000000..28ba977d8 --- /dev/null +++ b/tests/manual/distancefieldtext/main.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QQuickView> +#include <QOpenGLContext> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + QSurfaceFormat format; + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(3, 2); + format.setProfile(QSurfaceFormat::CoreProfile); + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + } + + QQuickView view; + view.setFormat(format); + view.resize(1200, 600); + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/distancefieldtext/main.qml b/tests/manual/distancefieldtext/main.qml new file mode 100644 index 000000000..69c76bb8f --- /dev/null +++ b/tests/manual/distancefieldtext/main.qml @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Scene3D 2.0 + +Item { + id: root + property string currentFont + property bool bold : false + property bool italic : false + + Scene3D { + id: scene3d + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: settingsPane.left + focus: true + aspects: ["input", "logic", "render"] + cameraAspectRatioMode: Scene3D.AutomaticAspectRatio + + TextScene { + id: textScene + fontFamily: root.currentFont + fontBold: bold + fontItalic: italic + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + textScene.clicked() + } + } + + Item { + id: settingsPane + + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 400 + + Rectangle { + width: parent.width/2 + height:50 + color: root.bold ? "#000066" : "#222222" + Text { + anchors.centerIn: parent + text: "Bold" + font.pointSize: 20 + color: "#ffffff" + } + MouseArea { + anchors.fill: parent + onClicked: root.bold = !root.bold + } + } + + Rectangle { + x: parent.width/2 + width: parent.width/2 + height:50 + color: root.italic ? "#000066" : "#222222" + Text { + anchors.centerIn: parent + text: "Italic" + font.pointSize: 20 + color: "#ffffff" + } + MouseArea { + anchors.fill: parent + onClicked: root.italic = !root.italic + } + } + + ListView { + anchors.fill: parent + anchors.topMargin: 50 + model: Qt.fontFamilies() + + delegate: Rectangle { + height: fontFamilyText.height + 10 + width: parent.width + color: (modelData == root.currentFont) ? "#000066" : "#222222" + + Text { + id: fontFamilyText + anchors.centerIn: parent + font.pointSize: 14 + font.family: modelData + text: modelData + color: "#ffffff" + } + + MouseArea { + anchors.fill: parent + onClicked: { + root.currentFont = modelData; + + } + } + } + } + } +} diff --git a/tests/manual/downloading/downloading.pro b/tests/manual/downloading/downloading.pro new file mode 100644 index 000000000..6f1b6e3d5 --- /dev/null +++ b/tests/manual/downloading/downloading.pro @@ -0,0 +1,14 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + main.qml + +RESOURCES += \ + downloading.qrc diff --git a/tests/manual/downloading/downloading.qrc b/tests/manual/downloading/downloading.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/downloading/downloading.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/downloading/main.cpp b/tests/manual/downloading/main.cpp new file mode 100644 index 000000000..dba6e0bff --- /dev/null +++ b/tests/manual/downloading/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <Qt3DQuickExtras/qt3dquickwindow.h> +#include <QGuiApplication> + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + Qt3DExtras::Quick::Qt3DQuickWindow view; + + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/downloading/main.qml b/tests/manual/downloading/main.qml new file mode 100644 index 000000000..e2f42284d --- /dev/null +++ b/tests/manual/downloading/main.qml @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: sceneRoot + + Camera { + id: camera + position: Qt.vector3d( 0.0, 0.5, 15.0 ) + viewCenter: Qt.vector3d( 0.0, 0.5, 0.0 ) + } + + OrbitCameraController { camera: camera } + + RenderSettings { + id : external_forward_renderer + activeFrameGraph : ForwardRenderer { + camera: camera + clearColor: "white" + } + } + + // Event Source will be set by the Qt3DQuickWindow + InputSettings { id: inputSettings } + + DirectionalLight { id: light; worldDirection: camera.viewVector } + + components: [external_forward_renderer, inputSettings, light] + + Mesh { + id: mesh + source: "https://codereview.qt-project.org/gitweb?p=qt/qt3d.git;a=blob_plain;hb=refs/heads/dev;f=examples/qt3d/exampleresources/assets/chest/Chest.obj" + } + + Transform { + id: transform + scale: 0.03 + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 30) + } + + DiffuseMapMaterial { + id: material + diffuse: TextureLoader { source: "https://codereview.qt-project.org/gitweb?p=qt/qt3d.git;a=blob_plain;hb=refs/heads/dev;f=examples/qt3d/planets-qml/images/earthmap1k.jpg" } + specular: Qt.rgba( 0.2, 0.2, 0.2, 1.0 ) + shininess: 2.0 + } + + Entity { + id: mainEntity + objectName: "mainEntity" + components: [ mesh, material, transform ] + } +} diff --git a/tests/manual/dynamic-model-loader-qml/CuboidEntity.qml b/tests/manual/dynamic-model-loader-qml/CuboidEntity.qml index 8555b6903..d9b33c511 100644 --- a/tests/manual/dynamic-model-loader-qml/CuboidEntity.qml +++ b/tests/manual/dynamic-model-loader-qml/CuboidEntity.qml @@ -76,7 +76,7 @@ Entity { QQ2.ColorAnimation { target: phongMaterial - property: "warmColor" + property: "warm" from: "red" to: "blue" duration: 2500 diff --git a/tests/manual/gltf/main.qml b/tests/manual/gltf/main.qml index 1afb8c48e..39fbb9acf 100644 --- a/tests/manual/gltf/main.qml +++ b/tests/manual/gltf/main.qml @@ -79,7 +79,7 @@ Entity { buffers : ClearBuffers.ColorDepthBuffer clearColor: "black" SortPolicy { - sortTypes: [ SortType.BackToFront ] + sortTypes: [ SortPolicy.BackToFront ] } } } diff --git a/tests/manual/loader-qml/CuboidEntity.qml b/tests/manual/loader-qml/CuboidEntity.qml index 8555b6903..d9b33c511 100644 --- a/tests/manual/loader-qml/CuboidEntity.qml +++ b/tests/manual/loader-qml/CuboidEntity.qml @@ -76,7 +76,7 @@ Entity { QQ2.ColorAnimation { target: phongMaterial - property: "warmColor" + property: "warm" from: "red" to: "blue" duration: 2500 diff --git a/tests/manual/lod/main.qml b/tests/manual/lod/main.qml index 8d9c8722a..80547dcff 100644 --- a/tests/manual/lod/main.qml +++ b/tests/manual/lod/main.qml @@ -49,9 +49,9 @@ ****************************************************************************/ import Qt3D.Core 2.0 -import Qt3D.Render 2.2 +import Qt3D.Render 2.9 import Qt3D.Input 2.0 -import Qt3D.Extras 2.2 +import Qt3D.Extras 2.9 import QtQuick 2.0 as QQ2 @@ -126,10 +126,8 @@ Entity { id: lod camera: camera thresholds: [1000, 600, 300, 180] - thresholdType: LevelOfDetail.ProjectedScreenPixelSize - volumeOverride: BoundingSphere { - radius: 2. - } + thresholdType: LevelOfDetail.ProjectedScreenPixelSizeThreshold + volumeOverride: lod.createBoundingSphere(Qt.vector3d(0, 0, 0), 2.0) } ] } @@ -143,6 +141,7 @@ Entity { ] LevelOfDetailLoader { + id: lodLoader components: [ Transform { scale: .5 translation: Qt.vector3d(-8, 0, 0) @@ -150,8 +149,8 @@ Entity { camera: camera thresholds: [20, 35, 50, 65] - thresholdType: LevelOfDetail.DistanceToCamera - volumeOverride: null + thresholdType: LevelOfDetail.DistanceToCameraThreshold + volumeOverride: lodLoader.createBoundingSphere(Qt.vector3d(0, 0, 0), -1) sources: ["qrc:/SphereEntity.qml", "qrc:/CylinderEntity.qml", "qrc:/ConeEntity.qml", "qrc:/CuboidEntity.qml"] } } @@ -172,7 +171,7 @@ Entity { LevelOfDetailSwitch { camera: camera thresholds: [20, 35, 50, 65] - thresholdType: LevelOfDetail.DistanceToCamera + thresholdType: LevelOfDetail.DistanceToCameraThreshold } ] diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 0c42b72f0..1dd418500 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -16,6 +16,7 @@ SUBDIRS += \ cylinder-qml \ deferred-renderer-cpp \ deferred-renderer-qml \ + downloading \ dragging \ dynamicscene-cpp \ enabled-qml \ @@ -38,9 +39,16 @@ SUBDIRS += \ rendercapture-qml \ additional-attributes-qml \ dynamic-model-loader-qml \ + buffercapture-qml \ + render-qml-to-texture \ + render-qml-to-texture-qml \ + video-texture-qml \ animation-keyframe-simple \ + animation-keyframe-blendtree \ + distancefieldtext \ mesh-morphing \ - anim-viewer + anim-viewer \ + animation-keyframe-programmatic qtHaveModule(widgets): { SUBDIRS += \ diff --git a/tests/manual/mesh-morphing/main.cpp b/tests/manual/mesh-morphing/main.cpp index 4ae791181..641722a4c 100644 --- a/tests/manual/mesh-morphing/main.cpp +++ b/tests/manual/mesh-morphing/main.cpp @@ -43,8 +43,8 @@ #include <Qt3DExtras/qcylindermesh.h> #include <Qt3DExtras/QPhongMaterial> #include <Qt3DExtras/QMorphPhongMaterial> -#include <Qt3DExtras/QVertexBlendAnimation> -#include <Qt3DExtras/QMorphTarget> +#include <Qt3DAnimation/QVertexBlendAnimation> +#include <Qt3DAnimation/QMorphTarget> #include <Qt3DExtras/QCylinderGeometry> #include <Qt3DCore/qentity.h> @@ -111,13 +111,13 @@ int main(int argc, char **argv) attributes.push_back(Qt3DRender::QAttribute::defaultPositionAttributeName()); attributes.push_back(Qt3DRender::QAttribute::defaultNormalAttributeName()); - QVector<Qt3DExtras::QMorphTarget*> morphTargets; - morphTargets.push_back(Qt3DExtras::QMorphTarget::fromGeometry(cylinder1, attributes)); - morphTargets.push_back(Qt3DExtras::QMorphTarget::fromGeometry(cylinder2, attributes)); - morphTargets.push_back(Qt3DExtras::QMorphTarget::fromGeometry(cylinder3, attributes)); + QVector<Qt3DAnimation::QMorphTarget*> morphTargets; + morphTargets.push_back(Qt3DAnimation::QMorphTarget::fromGeometry(cylinder1, attributes)); + morphTargets.push_back(Qt3DAnimation::QMorphTarget::fromGeometry(cylinder2, attributes)); + morphTargets.push_back(Qt3DAnimation::QMorphTarget::fromGeometry(cylinder3, attributes)); morphTargets.push_back(morphTargets.first()); - Qt3DExtras::QVertexBlendAnimation *animation = new Qt3DExtras::QVertexBlendAnimation; + Qt3DAnimation::QVertexBlendAnimation *animation = new Qt3DAnimation::QVertexBlendAnimation; QVector<float> times; times.push_back(0.0f); times.push_back(5.0f); @@ -132,7 +132,7 @@ int main(int argc, char **argv) Qt3DExtras::QMorphPhongMaterial *material = new Qt3DExtras::QMorphPhongMaterial(rootEntity); material->setDiffuse(Qt::red); - QObject::connect(animation, &Qt3DExtras::QVertexBlendAnimation::interpolatorChanged, + QObject::connect(animation, &Qt3DAnimation::QVertexBlendAnimation::interpolatorChanged, material, &Qt3DExtras::QMorphPhongMaterial::setInterpolator); // Cylinder diff --git a/tests/manual/mesh-morphing/mesh-morphing.pro b/tests/manual/mesh-morphing/mesh-morphing.pro index ad2a31b8b..27419655f 100644 --- a/tests/manual/mesh-morphing/mesh-morphing.pro +++ b/tests/manual/mesh-morphing/mesh-morphing.pro @@ -2,7 +2,7 @@ error( "Couldn't find the manual.pri file!" ) } -QT += 3dcore 3drender 3dquick 3dinput quick qml 3dextras 3dquickextras +QT += 3dcore 3drender 3dquick 3dinput quick qml 3dextras 3dquickextras 3danimation 3dquickanimation SOURCES += \ main.cpp diff --git a/tests/manual/render-qml-to-texture-qml/InteractiveGui.qml b/tests/manual/render-qml-to-texture-qml/InteractiveGui.qml new file mode 100644 index 000000000..65e5f27de --- /dev/null +++ b/tests/manual/render-qml-to-texture-qml/InteractiveGui.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.3 + +Rectangle { + width: 1024 + height: 1024 + color: "white" + focus: true + + Rectangle { + id: rect + x: 0 + y: 0 + width: 200 + height: 200 + color: "red" + } + + Rectangle { + id: rect2 + width: 300 + height: 100 + anchors.right: parent.right + anchors.bottom: parent.bottom + color: "blue" + } + + Button { + id: button + width: 100 + height: 80 + anchors.top: rect.bottom + anchors.left: parent.left + text: "button" + scale: 2.0 + } + CheckBox { + id: checkbox + width: 200 + height: 180 + scale: 2.0 + text: "checkbox" + checked: true + anchors.top: parent.top + anchors.right: parent.right + } + Slider { + anchors.bottom: parent.bottom + anchors.left: parent.left + width: 400 + value: 1 + minimumValue: 0 + maximumValue: 1 + + onValueChanged: { + rect.color = Qt.rgba(value, 0, 0, 1) + rect2.color = Qt.rgba(0, 0, value, 1) + } + } +} diff --git a/tests/manual/render-qml-to-texture-qml/PlaneMaterial.qml b/tests/manual/render-qml-to-texture-qml/PlaneMaterial.qml new file mode 100644 index 000000000..6c65de9b3 --- /dev/null +++ b/tests/manual/render-qml-to-texture-qml/PlaneMaterial.qml @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 + +Material { + + property Texture2D texture + property vector2d textureScale: Qt.vector2d(1,-1) + property vector2d textureBias: Qt.vector2d(0, 1) + + parameters: [ + Parameter { name: "surfaceTexture"; value: texture }, + Parameter { name: "texCoordScale"; value: textureScale }, + Parameter { name: "texCoordBias"; value: textureBias } + ] + + effect: Effect { + FilterKey { + id: forward + name: "renderingStyle" + value: "forward" + } + + ShaderProgram { + id: gl2Es2Shader + vertexShaderCode: loadSource("qrc:/shaders/es2/texturing.vert") + fragmentShaderCode: loadSource("qrc:/shaders/es2/texturing.frag") + } + + ShaderProgram { + id: gl3Shader + vertexShaderCode: loadSource("qrc:/shaders/gl3/texturing.vert") + fragmentShaderCode: loadSource("qrc:/shaders/gl3/texturing.frag") + } + techniques: [ + // OpenGL 3.1 + Technique { + filterKeys: [ forward ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.CoreProfile + majorVersion: 3 + minorVersion: 1 + } + + renderPasses: RenderPass { + shaderProgram: gl3Shader + } + }, + + // OpenGL 2.1 + Technique { + filterKeys: [ forward ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.NoProfile + majorVersion: 2 + minorVersion: 0 + } + + renderPasses: RenderPass { + shaderProgram: gl2Es2Shader + } + }, + + // OpenGL ES 2 + Technique { + filterKeys: [ forward ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGLES + profile: GraphicsApiFilter.NoProfile + majorVersion: 2 + minorVersion: 0 + } + renderPasses: RenderPass { + shaderProgram: gl2Es2Shader + } + } + ] + } +} diff --git a/tests/manual/render-qml-to-texture-qml/main.cpp b/tests/manual/render-qml-to-texture-qml/main.cpp new file mode 100644 index 000000000..ac85cbe46 --- /dev/null +++ b/tests/manual/render-qml-to-texture-qml/main.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> + +#include <QtQuick/QQuickView> +#include <Qt3DQuick/QQmlAspectEngine> +#include <QQmlContext> +#include <QOpenGLContext> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QSurfaceFormat format; + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(3, 2); + format.setProfile(QSurfaceFormat::CoreProfile); + } + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + format.setSamples(4); + + QQuickView view; + view.setFormat(format); + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:/main.qml")); + view.setColor("#000000"); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/render-qml-to-texture-qml/main.qml b/tests/manual/render-qml-to-texture-qml/main.qml new file mode 100644 index 000000000..65a0a8783 --- /dev/null +++ b/tests/manual/render-qml-to-texture-qml/main.qml @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.9 +import Qt3D.Input 2.0 +import QtQuick 2.0 as QQ2 +import QtQuick.Scene3D 2.0 +import QtQuick.Scene2D 2.9 +import QtQuick.Window 2.0 as QW2 +import Qt3D.Extras 2.0 + + +QQ2.Item { + width: 1024 + height: 768 + + Scene3D { + id: scene + focus: true + anchors.fill: parent + + aspects: ["input", "logic"] + + Entity { + id: sceneRoot + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: scene.width / scene.height + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, 6.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + Scene2D { + id: qmlTexture + output: RenderTargetOutput { + attachmentPoint: RenderTargetOutput.Color0 + texture: Texture2D { + id: offscreenTexture + width: 1024 + height: 1024 + format: Texture.RGBA8_UNorm + generateMipMaps: true + magnificationFilter: Texture.Linear + minificationFilter: Texture.LinearMipMapLinear + wrapMode { + x: WrapMode.ClampToEdge + y: WrapMode.ClampToEdge + } + } + + } + + entities: [plane1] + + mouseEnabled: plane1.picker.pressed + + InteractiveGui { + + } + } + + FirstPersonCameraController { + id: controller + camera: camera + enabled: !plane1.picker.pressed + } + + components: [ + RenderSettings { + pickingSettings.pickMethod: PickingSettings.TrianglePicking + activeFrameGraph: + ForwardRenderer { + camera: camera + } + }, + InputSettings {} + ] + + PlaneMesh { + id: planeMesh + width: 4 + height: 4 + } + + Entity { + id: plane1 + + property Transform transform: Transform { + scale: 1 + translation: Qt.vector3d(0,0,0) + rotation: fromAxisAndAngle(Qt.vector3d(1,0,0), 90) + } + + property Material material: PlaneMaterial { + texture: offscreenTexture + } + + property ObjectPicker picker: ObjectPicker { + hoverEnabled: true + dragEnabled: true + } + + components: [planeMesh, material, transform, picker] + } + } + } +} diff --git a/tests/manual/render-qml-to-texture-qml/render-qml-to-texture-qml.pro b/tests/manual/render-qml-to-texture-qml/render-qml-to-texture-qml.pro new file mode 100644 index 000000000..23729957c --- /dev/null +++ b/tests/manual/render-qml-to-texture-qml/render-qml-to-texture-qml.pro @@ -0,0 +1,21 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +!include ( ../render-qml-to-texture/render-qml-to-texture.pri ) { + error( "Couldn't find the render-qml-to-texture.pri file!") +} + +QT += 3dextras 3dcore 3drender 3dinput 3dquick qml quick + +SOURCES += main.cpp + +RESOURCES += \ + render-qml-to-texture-qml.qrc + +OTHER_FILES += \ + main.qml + +HEADERS += + + diff --git a/tests/manual/render-qml-to-texture-qml/render-qml-to-texture-qml.qrc b/tests/manual/render-qml-to-texture-qml/render-qml-to-texture-qml.qrc new file mode 100644 index 000000000..51ec4790c --- /dev/null +++ b/tests/manual/render-qml-to-texture-qml/render-qml-to-texture-qml.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>PlaneMaterial.qml</file> + <file>InteractiveGui.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/render-qml-to-texture/OffscreenGui.qml b/tests/manual/render-qml-to-texture/OffscreenGui.qml new file mode 100644 index 000000000..20fb0937d --- /dev/null +++ b/tests/manual/render-qml-to-texture/OffscreenGui.qml @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.3 + +Rectangle { + width: 1024 + height: 1024 + color: "white" + + TextRectangle { + id: textRect + } + + Rectangle { + id: rect + x: 0 + y: 0 + width: 200 + height: 200 + color: "red" + + ColorAnimation { + target: rect + loops: Animation.Infinite + property: "color" + from: "blue" + to: "green" + duration: 2000 + running: true + } + } + + Rectangle { + id: rect2 + width: 300 + height: 100 + anchors.right: parent.right + anchors.bottom: parent.bottom + color: "red" + + ColorAnimation { + target: rect2 + loops: Animation.Infinite + property: "color" + from: "red" + to: "white" + duration: 2000 + running: true + } + } + + Button { + id: button + width: 100 + height: 80 + anchors.top: rect.bottom + anchors.left: parent.left + text: "button" + scale: 2.0 + } + CheckBox { + id: checkbox + width: 200 + height: 180 + scale: 2.0 + text: "checkbox" + checked: true + anchors.top: parent.top + anchors.right: parent.right + + Timer { + interval: 1000 + repeat: true + running: true + onTriggered: { + checkbox.checked = !checkbox.checked; + } + } + } + Slider { + anchors.bottom: parent.bottom + anchors.left: parent.left + width: 400 + value: 0.0 + minimumValue: 0 + maximumValue: 1 + + PropertyAnimation on value { + loops: Animation.Infinite + duration: 3000 + from: 0.0 + to: 1.0 + running: true + } + } +} diff --git a/tests/manual/render-qml-to-texture/TextRectangle.qml b/tests/manual/render-qml-to-texture/TextRectangle.qml new file mode 100644 index 000000000..b47fa965b --- /dev/null +++ b/tests/manual/render-qml-to-texture/TextRectangle.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + id: rectangle + property string myText: "The quick brown fox jumps over the lazy dog." + x: 352 + y: 272 + width: 320 + height: 480 + color: "steelblue" + + FontLoader { id: fixedFont; name: "Courier" } + + Column { + anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 10 } + spacing: 15 + + Text { + text: rectangle.myText + color: "lightsteelblue" + width: parent.width + wrapMode: Text.WordWrap + font.family: "Times" + font.pixelSize: 20 + } + Text { + text: rectangle.myText + color: "lightsteelblue" + width: parent.width + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + font { family: "Times"; pixelSize: 20; capitalization: Font.AllUppercase } + } + Text { + text: rectangle.myText + color: "lightsteelblue" + width: parent.width + horizontalAlignment: Text.AlignRight + wrapMode: Text.WordWrap + font { family: fixedFont.name; pixelSize: 20; weight: Font.Bold; capitalization: Font.AllLowercase } + } + Text { + text: rectangle.myText + color: "lightsteelblue" + width: parent.width + wrapMode: Text.WordWrap + font { family: fixedFont.name; pixelSize: 20; italic: true; capitalization: Font.SmallCaps } + } + } +} diff --git a/tests/manual/render-qml-to-texture/main.cpp b/tests/manual/render-qml-to-texture/main.cpp new file mode 100644 index 000000000..2420c8560 --- /dev/null +++ b/tests/manual/render-qml-to-texture/main.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QAnimationDriver> +#include <QPropertyAnimation> +#include <QQmlComponent> +#include <QQmlEngine> + +#include <Qt3DCore/QEntity> +#include <Qt3DCore/QAspectEngine> +#include <Qt3DCore/QTransform> +#include <Qt3DRender/QCamera> + +#include <Qt3DInput/QInputAspect> + +#include <Qt3DRender/QRenderAspect> +#include <Qt3DRender/QEffect> +#include <Qt3DRender/QMaterial> +#include <Qt3DExtras/QForwardRenderer> +#include <Qt3DQuickScene2D/QScene2D> +#include <Qt3DExtras/QPlaneMesh> +#include <Qt3DRender/QTextureWrapMode> +#include <Qt3DRender/QClearBuffers> +#include <Qt3DRender/QTexture> + +#include "qt3dwindow.h" +#include "qfirstpersoncameracontroller.h" +#include "planematerial.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + Qt3DExtras::Qt3DWindow view; + + // Scene Root + Qt3DCore::QEntity *sceneRoot = new Qt3DCore::QEntity(); + + // Scene Camera + Qt3DRender::QCamera *basicCamera = view.camera(); + basicCamera->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection); + basicCamera->setAspectRatio(view.width() / view.height()); + basicCamera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f)); + basicCamera->setPosition(QVector3D(0.0f, 0.0f, 6.0f)); + basicCamera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f)); + basicCamera->setNearPlane(0.1f); + basicCamera->setFarPlane(1000.0f); + basicCamera->setFieldOfView(45.0f); + + // For camera controls + Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(sceneRoot); + camController->setCamera(basicCamera); + + Qt3DRender::QFrameGraphNode* frameGraphNode = view.activeFrameGraph(); + while (frameGraphNode->childNodes().size() > 0) + frameGraphNode = (Qt3DRender::QFrameGraphNode*)frameGraphNode->childNodes().at(0); + view.defaultFrameGraph()->setClearColor(QColor::fromRgbF(1.0f, 1.0f, 1.0f)); + Qt3DRender::Quick::QScene2D *qmlTextureRenderer = new Qt3DRender::Quick::QScene2D(frameGraphNode); + + Qt3DRender::QTexture2D* offscreenTexture = new Qt3DRender::QTexture2D(qmlTextureRenderer); + offscreenTexture->setSize(1024, 1024); + offscreenTexture->setFormat(Qt3DRender::QAbstractTexture::RGBA8_UNorm); + offscreenTexture->setGenerateMipMaps(true); + offscreenTexture->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear); + offscreenTexture->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear); + offscreenTexture->setWrapMode(Qt3DRender::QTextureWrapMode(Qt3DRender::QTextureWrapMode::ClampToEdge, offscreenTexture)); + + Qt3DRender::QRenderTargetOutput *output = new Qt3DRender::QRenderTargetOutput(qmlTextureRenderer); + output->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0); + output->setTexture(offscreenTexture); + + qmlTextureRenderer->setOutput(output); + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/OffscreenGui.qml"))); + qmlTextureRenderer->setItem(static_cast<QQuickItem *>(component.create())); + + Qt3DCore::QEntity* planeEntity = new Qt3DCore::QEntity(sceneRoot); + Qt3DExtras::QPlaneMesh* planeMesh = new Qt3DExtras::QPlaneMesh(planeEntity); + planeMesh->setWidth(4); + planeMesh->setHeight(4); + planeEntity->addComponent(planeMesh); + + PlaneMaterial* material = new PlaneMaterial(offscreenTexture, planeEntity); + planeEntity->addComponent(material); + + Qt3DCore::QTransform* transform = new Qt3DCore::QTransform(planeEntity); + transform->setRotation(QQuaternion::fromAxisAndAngle(1,0,0,90)); + planeEntity->addComponent(transform); + + view.setRootEntity(sceneRoot); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/render-qml-to-texture/planematerial.cpp b/tests/manual/render-qml-to-texture/planematerial.cpp new file mode 100644 index 000000000..4435766bb --- /dev/null +++ b/tests/manual/render-qml-to-texture/planematerial.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <Qt3DRender/QParameter> +#include <Qt3DRender/QEffect> +#include <Qt3DRender/QTechnique> +#include <Qt3DRender/QAbstractTexture> +#include <Qt3DRender/QShaderProgram> +#include <Qt3DRender/QRenderPass> +#include <Qt3DRender/QBlendEquation> +#include <Qt3DRender/QBlendEquationArguments> +#include <Qt3DRender/QFilterKey> +#include <Qt3DRender/QGraphicsApiFilter> +#include <QColor> +#include <QVector2D> +#include <QUrl> + +#include "planematerial.h" + +PlaneMaterial::PlaneMaterial(Qt3DRender::QAbstractTexture *texture, Qt3DCore::QNode *parent) + : QMaterial(parent) + , m_effect(new Qt3DRender::QEffect(this)) + , m_texture(texture) +{ + setEffect(m_effect); + + m_texCoordScaleParam = new Qt3DRender::QParameter(QStringLiteral("texCoordScale"), QVector2D(1.0f, -1.0f)); + m_texCoordBiasParam = new Qt3DRender::QParameter(QStringLiteral("texCoordBias"), QVector2D(0.0f, 1.0f)); + m_textureParam = new Qt3DRender::QParameter(QStringLiteral("surfaceTexture"), m_texture); + + m_effect->addParameter(m_texCoordScaleParam); + m_effect->addParameter(m_texCoordBiasParam); + m_effect->addParameter(m_textureParam); + + m_filter = new Qt3DRender::QFilterKey(this); + m_filter->setName(QStringLiteral("renderingStyle")); + m_filter->setValue(QStringLiteral("forward")); + + m_techniqueGLES = new Qt3DRender::QTechnique(m_effect); + m_techniqueGL3 = new Qt3DRender::QTechnique(m_effect); + m_techniqueGL2 = new Qt3DRender::QTechnique(m_effect); + + m_techniqueGLES->addFilterKey(m_filter); + m_techniqueGL3->addFilterKey(m_filter); + m_techniqueGL2->addFilterKey(m_filter); + + m_effect->addTechnique(m_techniqueGLES); + m_effect->addTechnique(m_techniqueGL3); + m_effect->addTechnique(m_techniqueGL2); + + m_programGLES = new Qt3DRender::QShaderProgram(m_effect); + m_programGLES->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/texturing.vert")))); + m_programGLES->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/texturing.frag")))); + + m_programGL3 = new Qt3DRender::QShaderProgram(m_effect); + m_programGL3->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/texturing.vert")))); + m_programGL3->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/texturing.frag")))); + + m_renderPassGLES = new Qt3DRender::QRenderPass(m_effect); + m_renderPassGL3 = new Qt3DRender::QRenderPass(m_effect); + m_renderPassGL2 = new Qt3DRender::QRenderPass(m_effect); + + m_renderPassGLES->setShaderProgram(m_programGLES); + m_renderPassGL3->setShaderProgram(m_programGL3); + m_renderPassGL2->setShaderProgram(m_programGL3); + + m_techniqueGL2->addRenderPass(m_renderPassGL2); + m_techniqueGLES->addRenderPass(m_renderPassGLES); + m_techniqueGL3->addRenderPass(m_renderPassGL3); + + m_techniqueGLES->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES); + m_techniqueGLES->graphicsApiFilter()->setMajorVersion(2); + m_techniqueGLES->graphicsApiFilter()->setMinorVersion(0); + m_techniqueGLES->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + + m_techniqueGL2->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + m_techniqueGL2->graphicsApiFilter()->setMajorVersion(2); + m_techniqueGL2->graphicsApiFilter()->setMinorVersion(0); + m_techniqueGL2->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + + m_techniqueGL3->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + m_techniqueGL3->graphicsApiFilter()->setMajorVersion(3); + m_techniqueGL3->graphicsApiFilter()->setMinorVersion(1); + m_techniqueGL3->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); +} + diff --git a/tests/manual/render-qml-to-texture/planematerial.h b/tests/manual/render-qml-to-texture/planematerial.h new file mode 100644 index 000000000..8de7a19c9 --- /dev/null +++ b/tests/manual/render-qml-to-texture/planematerial.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLANEMATERIAL_H +#define PLANEMATERIAL_H + +#include <Qt3DRender/QMaterial> +#include <Qt3DRender/QFilterKey> +#include <Qt3DRender/QTechnique> +#include <Qt3DRender/QMaterial> + +class PlaneMaterial : public Qt3DRender::QMaterial +{ +public: + explicit PlaneMaterial(Qt3DRender::QAbstractTexture *texture, Qt3DCore::QNode *parent = nullptr); +private: + Qt3DRender::QEffect *m_effect; + Qt3DRender::QAbstractTexture *m_texture; + Qt3DRender::QParameter *m_textureParam, *m_texCoordScaleParam, *m_texCoordBiasParam; + Qt3DRender::QFilterKey *m_filter; + Qt3DRender::QTechnique *m_techniqueGLES, *m_techniqueGL3, *m_techniqueGL2; + Qt3DRender::QShaderProgram *m_programGLES, *m_programGL3; + Qt3DRender::QRenderPass *m_renderPassGLES, *m_renderPassGL3, *m_renderPassGL2; +}; + +#endif // PLANEMATERIAL_H diff --git a/tests/manual/render-qml-to-texture/render-qml-to-texture.pri b/tests/manual/render-qml-to-texture/render-qml-to-texture.pri new file mode 100644 index 000000000..b02c23840 --- /dev/null +++ b/tests/manual/render-qml-to-texture/render-qml-to-texture.pri @@ -0,0 +1,6 @@ +SOURCES += + +RESOURCES += \ + ../render-qml-to-texture/render-qml-to-texture.qrc + +HEADERS += diff --git a/tests/manual/render-qml-to-texture/render-qml-to-texture.pro b/tests/manual/render-qml-to-texture/render-qml-to-texture.pro new file mode 100644 index 000000000..45c213803 --- /dev/null +++ b/tests/manual/render-qml-to-texture/render-qml-to-texture.pro @@ -0,0 +1,21 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dextras 3dcore 3drender 3dinput 3dquick qml quick 3dquickrender 3dquickscene2d + +SOURCES += main.cpp \ + planematerial.cpp + +RESOURCES += \ + render-qml-to-texture.qrc + +OTHER_FILES += \ + main.qml + +DISTFILES += \ + OffscreenGui.qml \ + TextRectangle.qml + +HEADERS += \ + planematerial.h diff --git a/tests/manual/render-qml-to-texture/render-qml-to-texture.qrc b/tests/manual/render-qml-to-texture/render-qml-to-texture.qrc new file mode 100644 index 000000000..792a74b70 --- /dev/null +++ b/tests/manual/render-qml-to-texture/render-qml-to-texture.qrc @@ -0,0 +1,10 @@ +<RCC> + <qresource prefix="/"> + <file>shaders/es2/texturing.frag</file> + <file>shaders/es2/texturing.vert</file> + <file>shaders/gl3/texturing.frag</file> + <file>shaders/gl3/texturing.vert</file> + <file>OffscreenGui.qml</file> + <file>TextRectangle.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/render-qml-to-texture/shaders/es2/texturing.frag b/tests/manual/render-qml-to-texture/shaders/es2/texturing.frag new file mode 100644 index 000000000..b651bd5ed --- /dev/null +++ b/tests/manual/render-qml-to-texture/shaders/es2/texturing.frag @@ -0,0 +1,16 @@ +#define FP highp + +uniform FP vec3 eyePosition; + +uniform sampler2D surfaceTexture; + +varying FP vec3 worldPosition; +varying FP vec3 worldNormal; +varying FP vec2 texCoord; + + + +void main() +{ + gl_FragColor = texture2D(surfaceTexture, texCoord); +} diff --git a/tests/manual/render-qml-to-texture/shaders/es2/texturing.vert b/tests/manual/render-qml-to-texture/shaders/es2/texturing.vert new file mode 100644 index 000000000..cfbd338d2 --- /dev/null +++ b/tests/manual/render-qml-to-texture/shaders/es2/texturing.vert @@ -0,0 +1,26 @@ + + +attribute vec3 vertexPosition; +attribute vec3 vertexNormal; +attribute vec2 vertexTexCoord; + +varying vec3 worldPosition; +varying vec3 worldNormal; +varying vec2 texCoord; + +uniform mat4 modelMatrix; +uniform mat3 modelNormalMatrix; +uniform mat4 mvp; + +uniform vec2 texCoordScale; +uniform vec2 texCoordBias; + +void main() +{ + texCoord = vertexTexCoord * texCoordScale + texCoordBias; + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} + diff --git a/tests/manual/render-qml-to-texture/shaders/gl3/texturing.frag b/tests/manual/render-qml-to-texture/shaders/gl3/texturing.frag new file mode 100644 index 000000000..b051dc254 --- /dev/null +++ b/tests/manual/render-qml-to-texture/shaders/gl3/texturing.frag @@ -0,0 +1,16 @@ +#version 150 core + +uniform vec3 eyePosition; + +uniform sampler2D surfaceTexture; + +in vec3 worldPosition; +in vec3 worldNormal; +in vec2 texCoord; + +out vec4 fragColor; + +void main() +{ + fragColor = texture(surfaceTexture, texCoord); +} diff --git a/tests/manual/render-qml-to-texture/shaders/gl3/texturing.vert b/tests/manual/render-qml-to-texture/shaders/gl3/texturing.vert new file mode 100644 index 000000000..2b8a08b0a --- /dev/null +++ b/tests/manual/render-qml-to-texture/shaders/gl3/texturing.vert @@ -0,0 +1,25 @@ +#version 150 core + +in vec3 vertexPosition; +in vec3 vertexNormal; +in vec2 vertexTexCoord; + +out vec3 worldPosition; +out vec3 worldNormal; +out vec2 texCoord; + +uniform mat4 modelMatrix; +uniform mat3 modelNormalMatrix; +uniform mat4 mvp; + +uniform vec2 texCoordScale; +uniform vec2 texCoordBias; + +void main() +{ + texCoord = vertexTexCoord * texCoordScale + texCoordBias; + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} diff --git a/tests/manual/rendercapture-cpp/mycapture.h b/tests/manual/rendercapture-cpp/mycapture.h index 803ef7336..fea1abe46 100644 --- a/tests/manual/rendercapture-cpp/mycapture.h +++ b/tests/manual/rendercapture-cpp/mycapture.h @@ -60,31 +60,26 @@ class MyCapture : public QObject public: MyCapture(Qt3DRender::QRenderCapture* capture, QLabel *imageLabel) : m_capture(capture) - , m_cid(1) - , m_imageLabel(imageLabel) , m_reply(nullptr) + , m_imageLabel(imageLabel) , m_continuous(false) { } public slots: - void onCompleted(bool isComplete) + void onCompleted() { - if (isComplete) { - QObject::disconnect(connection); - - m_imageLabel->setPixmap(QPixmap::fromImage(m_reply->image())); + QObject::disconnect(connection); - ++m_cid; + m_imageLabel->setPixmap(QPixmap::fromImage(m_reply->image())); - m_reply->saveToFile("capture.bmp"); + m_reply->saveImage("capture.bmp"); - delete m_reply; - m_reply = nullptr; + delete m_reply; + m_reply = nullptr; - if (m_continuous) - capture(); - } + if (m_continuous) + capture(); } void setContinuous(bool continuos) @@ -94,9 +89,11 @@ public slots: void capture() { - m_reply = m_capture->requestCapture(m_cid); - connection = QObject::connect(m_reply, &Qt3DRender::QRenderCaptureReply::completeChanged, - this, &MyCapture::onCompleted); + if (!m_reply) { + m_reply = m_capture->requestCapture(); + connection = QObject::connect(m_reply, &Qt3DRender::QRenderCaptureReply::completed, + this, &MyCapture::onCompleted); + } } private: @@ -105,7 +102,6 @@ private: QMetaObject::Connection connection; QLabel *m_imageLabel; bool m_continuous; - int m_cid; }; #endif diff --git a/tests/manual/rendercapture-qml/CaptureScene.qml b/tests/manual/rendercapture-qml/CaptureScene.qml index 2329e4730..ea355042a 100644 --- a/tests/manual/rendercapture-qml/CaptureScene.qml +++ b/tests/manual/rendercapture-qml/CaptureScene.qml @@ -57,9 +57,9 @@ import Qt3D.Extras 2.0 Entity { id: sceneRoot - function requestRenderCapture(cid) + function requestRenderCapture() { - return renderCapture.requestCapture(cid) + return renderCapture.requestCapture() } Camera { diff --git a/tests/manual/rendercapture-qml/main.qml b/tests/manual/rendercapture-qml/main.qml index 77e96d739..9aff1fefe 100644 --- a/tests/manual/rendercapture-qml/main.qml +++ b/tests/manual/rendercapture-qml/main.qml @@ -51,7 +51,7 @@ import QtQuick 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls 1.4 -import Qt3D.Render 2.1 +import Qt3D.Render 2.9 import QtQuick.Scene3D 2.0 Item { @@ -96,7 +96,7 @@ Item { function doRenderCapture() { - reply = scene.requestRenderCapture(cid) + reply = scene.requestRenderCapture() reply.completeChanged.connect(onRenderCaptureComplete) } @@ -104,7 +104,7 @@ Item { { _renderCaptureProvider.updateImage(reply) image.source = "image://rendercapture/" + cid - reply.saveToFile("capture" + cid + ".png") + reply.saveImage("capture" + cid + ".png") cid++ if (continuous === true) doRenderCapture() diff --git a/tests/manual/video-texture-qml/PlaneMaterial.qml b/tests/manual/video-texture-qml/PlaneMaterial.qml new file mode 100644 index 000000000..6c65de9b3 --- /dev/null +++ b/tests/manual/video-texture-qml/PlaneMaterial.qml @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 + +Material { + + property Texture2D texture + property vector2d textureScale: Qt.vector2d(1,-1) + property vector2d textureBias: Qt.vector2d(0, 1) + + parameters: [ + Parameter { name: "surfaceTexture"; value: texture }, + Parameter { name: "texCoordScale"; value: textureScale }, + Parameter { name: "texCoordBias"; value: textureBias } + ] + + effect: Effect { + FilterKey { + id: forward + name: "renderingStyle" + value: "forward" + } + + ShaderProgram { + id: gl2Es2Shader + vertexShaderCode: loadSource("qrc:/shaders/es2/texturing.vert") + fragmentShaderCode: loadSource("qrc:/shaders/es2/texturing.frag") + } + + ShaderProgram { + id: gl3Shader + vertexShaderCode: loadSource("qrc:/shaders/gl3/texturing.vert") + fragmentShaderCode: loadSource("qrc:/shaders/gl3/texturing.frag") + } + techniques: [ + // OpenGL 3.1 + Technique { + filterKeys: [ forward ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.CoreProfile + majorVersion: 3 + minorVersion: 1 + } + + renderPasses: RenderPass { + shaderProgram: gl3Shader + } + }, + + // OpenGL 2.1 + Technique { + filterKeys: [ forward ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.NoProfile + majorVersion: 2 + minorVersion: 0 + } + + renderPasses: RenderPass { + shaderProgram: gl2Es2Shader + } + }, + + // OpenGL ES 2 + Technique { + filterKeys: [ forward ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGLES + profile: GraphicsApiFilter.NoProfile + majorVersion: 2 + minorVersion: 0 + } + renderPasses: RenderPass { + shaderProgram: gl2Es2Shader + } + } + ] + } +} diff --git a/tests/manual/video-texture-qml/main.cpp b/tests/manual/video-texture-qml/main.cpp new file mode 100644 index 000000000..5146d5939 --- /dev/null +++ b/tests/manual/video-texture-qml/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <Qt3DQuick/QQmlAspectEngine> +#include <QGuiApplication> +#include <QQmlEngine> +#include <QQmlContext> +#include <Qt3DQuickExtras/Qt3DQuickWindow> + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + Qt3DExtras::Quick::Qt3DQuickWindow view; + + view.engine()->qmlEngine()->rootContext()->setContextProperty("_window", &view); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/video-texture-qml/main.qml b/tests/manual/video-texture-qml/main.qml new file mode 100644 index 000000000..6a8dff3d5 --- /dev/null +++ b/tests/manual/video-texture-qml/main.qml @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.9 +import Qt3D.Input 2.0 +import QtQuick 2.2 as QQ2 +import QtQuick.Scene2D 2.9 +import QtQuick.Window 2.0 as QW2 +import Qt3D.Extras 2.0 +import QtMultimedia 5.6 as QMM +import QtQuick.Dialogs 1.0 + +Entity { + id: sceneRoot + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: _window.width / _window.height + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, 3.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + Scene2D { + output: RenderTargetOutput { + attachmentPoint: RenderTargetOutput.Color0 + texture: Texture2D { + id: offscreenTexture + width: 1024 + height: 1024 + format: Texture.RGBA8_UNorm + generateMipMaps: false + magnificationFilter: Texture.Linear + minificationFilter: Texture.Linear + wrapMode { + x: WrapMode.ClampToEdge + y: WrapMode.ClampToEdge + } + } + } + QQ2.Rectangle { + width: 400 + height: 300 + color: "green" + + QMM.MediaPlayer { + id: player + autoPlay: false + loops: QMM.MediaPlayer.Infinite + } + + QMM.VideoOutput { + id: videoOutput + source: player + anchors.fill: parent + } + } + } + + FirstPersonCameraController { + camera: camera + } + + components: [ + RenderSettings { + activeFrameGraph: + ForwardRenderer { + camera: camera + } + }, + InputSettings {} + ] + + CuboidMesh { + id: mesh + } + + Entity { + id: entity + + property Transform transform: Transform { + scale: 1 + translation: Qt.vector3d(0,0,0) + } + + property Material material: PlaneMaterial { + texture: offscreenTexture + } + + components: [mesh, material, transform] + } + + FileDialog { + id: fileDialog + title: "Please choose a video" + folder: shortcuts.home + onAccepted: { + visible = false + player.source = fileDialog.fileUrl + player.play() + } + onRejected: { + Qt.quit() + } + QQ2.Component.onCompleted: { + visible = true + } + } +} diff --git a/tests/manual/video-texture-qml/video-texture-qml.pro b/tests/manual/video-texture-qml/video-texture-qml.pro new file mode 100644 index 000000000..713ef8cfe --- /dev/null +++ b/tests/manual/video-texture-qml/video-texture-qml.pro @@ -0,0 +1,21 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +!include ( ../render-qml-to-texture/render-qml-to-texture.pri ) { + error( "Couldn't find the render-qml-to-texture.pri file!") +} + +QT += 3dquickextras 3dcore 3drender 3dinput 3dquick qml quick 3dquickrender + +SOURCES += main.cpp + +RESOURCES += \ + video-texture-qml.qrc + +OTHER_FILES += \ + main.qml + +DISTFILES += \ + PlaneMaterial.qml + diff --git a/tests/manual/video-texture-qml/video-texture-qml.qrc b/tests/manual/video-texture-qml/video-texture-qml.qrc new file mode 100644 index 000000000..6b2a1aef6 --- /dev/null +++ b/tests/manual/video-texture-qml/video-texture-qml.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>PlaneMaterial.qml</file> + </qresource> +</RCC> |