diff options
Diffstat (limited to 'src')
279 files changed, 2251 insertions, 2695 deletions
diff --git a/src/animation/backend/abstractevaluateclipanimatorjob.cpp b/src/animation/backend/abstractevaluateclipanimatorjob.cpp new file mode 100644 index 000000000..236a96efe --- /dev/null +++ b/src/animation/backend/abstractevaluateclipanimatorjob.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** 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 "abstractevaluateclipanimatorjob_p.h" +#include <Qt3DCore/private/qaspectjob_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DCore/private/qskeleton_p.h> +#include <Qt3DAnimation/qabstractclipanimator.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DAnimation { +namespace Animation { + +class AbstractEvaluateClipAnimatorJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + AbstractEvaluateClipAnimatorJobPrivate() { } + ~AbstractEvaluateClipAnimatorJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Q_DECLARE_PUBLIC(AbstractEvaluateClipAnimatorJob) + + AnimationRecord m_record; + QVector<AnimationCallbackAndValue> m_callbacks; + +private: + AbstractEvaluateClipAnimatorJob *q_ptr; +}; + +AbstractEvaluateClipAnimatorJob::AbstractEvaluateClipAnimatorJob() + : Qt3DCore::QAspectJob(*new AbstractEvaluateClipAnimatorJobPrivate) +{ +} + +void AbstractEvaluateClipAnimatorJob::setPostFrameData(const AnimationRecord &record, const QVector<AnimationCallbackAndValue> &callbacks) +{ + auto mainThreadCB = callbacks; + mainThreadCB.erase(std::remove_if(mainThreadCB.begin(), mainThreadCB.end(), [](const AnimationCallbackAndValue &callback) { + if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) { + // call these now and remove them from the list + callback.callback->valueChanged(callback.value); + return true; + } + return false; + }), mainThreadCB.end()); + // Should now only have callbacks to be called on main thread + + Q_D(AbstractEvaluateClipAnimatorJob); + d->m_record = record; + d->m_callbacks = mainThreadCB; +} + +void AbstractEvaluateClipAnimatorJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + if (m_record.animatorId.isNull()) + return; + + for (auto targetData : qAsConst(m_record.targetChanges)) { + Qt3DCore::QNode *node = manager->lookupNode(targetData.targetId); + if (node) + node->setProperty(targetData.propertyName, targetData.value); + } + + for (auto skeletonData : qAsConst(m_record.skeletonChanges)) { + Qt3DCore::QAbstractSkeleton *node = qobject_cast<Qt3DCore::QAbstractSkeleton *>(manager->lookupNode(skeletonData.first)); + if (node) { + auto d = Qt3DCore::QAbstractSkeletonPrivate::get(node); + d->m_localPoses = skeletonData.second; + d->update(); + } + } + + QAbstractClipAnimator *animator = qobject_cast<QAbstractClipAnimator *>(manager->lookupNode(m_record.animatorId)); + if (animator) { + if (isValidNormalizedTime(m_record.normalizedTime)) + animator->setNormalizedTime(m_record.normalizedTime); + if (m_record.finalFrame) + animator->setRunning(false); + } + + for (const AnimationCallbackAndValue &callback: qAsConst(m_callbacks)) { + if (callback.callback) + callback.callback->valueChanged(callback.value); + } + + m_record = {}; +} + +} // Animation +} // Qt3DAnimation + +QT_END_NAMESPACE diff --git a/src/animation/backend/abstractevaluateclipanimatorjob_p.h b/src/animation/backend/abstractevaluateclipanimatorjob_p.h new file mode 100644 index 000000000..2a8914faa --- /dev/null +++ b/src/animation/backend/abstractevaluateclipanimatorjob_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** 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 QT3DANIMATION_ANIMATION_ABSTRACTEVALUATECLIPANIMATORJOB_P_H +#define QT3DANIMATION_ANIMATION_ABSTRACTEVALUATECLIPANIMATORJOB_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DCore/qaspectjob.h> +#include <Qt3DAnimation/private/animationutils_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DAnimation { +namespace Animation { + +class AbstractEvaluateClipAnimatorJobPrivate; + +class AbstractEvaluateClipAnimatorJob : public Qt3DCore::QAspectJob +{ +protected: + AbstractEvaluateClipAnimatorJob(); + + void setPostFrameData(const AnimationRecord &record, const QVector<AnimationCallbackAndValue> &callbacks); + +private: + Q_DECLARE_PRIVATE(AbstractEvaluateClipAnimatorJob) +}; + +} // Animation +} // Qt3DAnimation + +QT_END_NAMESPACE + +#endif // QT3DANIMATION_ANIMATION_ABSTRACTEVALUATECLIPANIMATORJOB_P_H diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp index 690972075..2dea81b52 100644 --- a/src/animation/backend/animationclip.cpp +++ b/src/animation/backend/animationclip.cpp @@ -43,7 +43,6 @@ #include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/private/gltfimporter_p.h> #include <Qt3DRender/private/qurlhelper_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtCore/qbytearray.h> #include <QtCore/qfile.h> @@ -90,11 +89,6 @@ void AnimationClip::setStatus(QAnimationClipLoader::Status status) { if (status != m_status) { m_status = status; - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("status"); - e->setValue(QVariant::fromValue(m_status)); - notifyObservers(e); } } @@ -124,7 +118,7 @@ void AnimationClip::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool first Q_ASSERT(m_dataType == File); if (m_source != loaderNode->source()) { m_source = loaderNode->source(); - if (m_clipData.isValid()) + if (!m_source.isEmpty()) setDirty(Handler::AnimationClipDirty); } } @@ -317,13 +311,6 @@ void AnimationClip::setDuration(float duration) return; m_duration = duration; - - // Send a change to the frontend - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("duration"); - e->setValue(m_duration); - notifyObservers(e); } int AnimationClip::channelIndex(const QString &channelName, int jointIndex) const diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index 24c484dc2..80c296a89 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -40,8 +40,6 @@ #include <Qt3DAnimation/private/clipblendnode_p.h> #include <Qt3DAnimation/private/clipblendnodevisitor_p.h> #include <Qt3DAnimation/private/clipblendvalue_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> #include <QtGui/qvector2d.h> #include <QtGui/qvector3d.h> #include <QtGui/qvector4d.h> @@ -407,13 +405,17 @@ QVariant buildPropertyValue(const MappingData &mappingData, const QVector<float> return QVariant(); } -QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId animatorId, - const QVector<MappingData> &mappingDataVec, - const QVector<float> &channelResults, - bool finalFrame, - float normalizedLocalTime) +AnimationRecord prepareAnimationRecord(Qt3DCore::QNodeId animatorId, + const QVector<MappingData> &mappingDataVec, + const QVector<float> &channelResults, + bool finalFrame, + float normalizedLocalTime) { - QVector<Qt3DCore::QSceneChangePtr> changes; + AnimationRecord record; + record.finalFrame = finalFrame; + record.animatorId = animatorId; + record.normalizedTime = normalizedLocalTime; + QVarLengthArray<Skeleton *, 4> dirtySkeletons; // Iterate over the mappings @@ -453,43 +455,14 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim break; } } else { - // TODOSYNC remove once we've found a way to propagate animation changes - // Construct a property update change, set target, property and delivery options - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(mappingData.targetId); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName(mappingData.propertyName); - // Handle intermediate updates vs final flag properly - Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isIntermediate = !finalFrame; - // Assign new value and send - e->setValue(v); - changes.push_back(e); + record.targetChanges.push_back({mappingData.targetId, mappingData.propertyName, v}); } } for (const auto skeleton : dirtySkeletons) - skeleton->sendLocalPoses(); - - if (isValidNormalizedTime(normalizedLocalTime)) { - // TODOSYNC remove once we've found a way to propagate animation changes - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("normalizedTime"); - e->setValue(normalizedLocalTime); - Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isIntermediate = !finalFrame; - changes.push_back(e); - } - - // If it's the final frame, notify the frontend that we've stopped - if (finalFrame) { - // TODOSYNC remove once we've found a way to propagate animation changes - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("running"); - e->setValue(false); - changes.push_back(e); - } + record.skeletonChanges.push_back({skeleton->peerId(), skeleton->joints()}); - return changes; + return record; } QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> &mappingDataVec, diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index bded12bd2..eab15f0e5 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -53,6 +53,7 @@ #include <Qt3DAnimation/qanimationcallback.h> #include <Qt3DCore/qnodeid.h> #include <Qt3DCore/qscenechange.h> +#include <Qt3DCore/private/sqt_p.h> #include <QtCore/qbitarray.h> #include <QtCore/qdebug.h> @@ -183,7 +184,7 @@ struct ChannelNameAndType case Rotation: componentCount = 4; break; - }; + } } bool operator==(const ChannelNameAndType &rhs) const @@ -264,6 +265,32 @@ struct AnimationCallbackAndValue QVariant value; }; +struct AnimationRecord { + struct TargetChange { + TargetChange(Qt3DCore::QNodeId id, const char *name, QVariant v) + : targetId(id), propertyName(name), value(v) { + + } + + Qt3DCore::QNodeId targetId; + const char *propertyName = nullptr; + QVariant value; + }; + + Qt3DCore::QNodeId animatorId; + QVector<TargetChange> targetChanges; + QVector<QPair<Qt3DCore::QNodeId, QVector<Qt3DCore::Sqt>>> skeletonChanges; + float normalizedTime = -1.f; + bool finalFrame = false; +}; + +Q_AUTOTEST_EXPORT +AnimationRecord prepareAnimationRecord(Qt3DCore::QNodeId animatorId, + const QVector<MappingData> &mappingDataVec, + const QVector<float> &channelResults, + bool finalFrame, + float normalizedLocalTime); + inline constexpr double toSecs(qint64 nsecs) { return nsecs / 1.0e9; } inline qint64 toNsecs(double seconds) { return qRound64(seconds * 1.0e9); } @@ -328,12 +355,6 @@ ClipResults evaluateClipAtPhase(AnimationClip *clip, float phase); Q_AUTOTEST_EXPORT -QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId animatorId, - const QVector<MappingData> &mappingDataVec, - const QVector<float> &channelResults, - bool finalFrame, float normalizedLocalTime); - -Q_AUTOTEST_EXPORT QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> &mappingDataVec, const QVector<float> &channelResults); @@ -390,5 +411,7 @@ void applyComponentDefaultValues(const QVector<ComponentValue> &componentDefault QT_END_NAMESPACE +Q_DECLARE_METATYPE(Qt3DAnimation::Animation::AnimationRecord) // LCOV_EXCL_LINE + #endif // QT3DANIMATION_ANIMATION_ANIMATIONUTILS_P_H diff --git a/src/animation/backend/backend.pri b/src/animation/backend/backend.pri index cc1104102..ef7da55f0 100644 --- a/src/animation/backend/backend.pri +++ b/src/animation/backend/backend.pri @@ -17,6 +17,7 @@ HEADERS += \ $$PWD/channelmapping_p.h \ $$PWD/channelmapper_p.h \ $$PWD/findrunningclipanimatorsjob_p.h \ + $$PWD/abstractevaluateclipanimatorjob_p.h \ $$PWD/evaluateclipanimatorjob_p.h \ $$PWD/clipblendnode_p.h \ $$PWD/clipblendnodevisitor_p.h \ @@ -43,6 +44,7 @@ SOURCES += \ $$PWD/channelmapping.cpp \ $$PWD/channelmapper.cpp \ $$PWD/findrunningclipanimatorsjob.cpp \ + $$PWD/abstractevaluateclipanimatorjob.cpp \ $$PWD/evaluateclipanimatorjob.cpp \ $$PWD/clipblendnode.cpp \ $$PWD/managers.cpp \ diff --git a/src/animation/backend/blendedclipanimator.cpp b/src/animation/backend/blendedclipanimator.cpp index 254883478..7d771745b 100644 --- a/src/animation/backend/blendedclipanimator.cpp +++ b/src/animation/backend/blendedclipanimator.cpp @@ -40,8 +40,6 @@ #include <Qt3DAnimation/qclock.h> #include <Qt3DAnimation/qabstractclipblendnode.h> #include <Qt3DAnimation/private/qblendedclipanimator_p.h> -#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -123,27 +121,6 @@ void BlendedClipAnimator::setRunning(bool running) setDirty(Handler::BlendedClipAnimatorDirty); } -void BlendedClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes) -{ - for (const Qt3DCore::QSceneChangePtr &change : changes) - notifyObservers(change); -} - -void BlendedClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks) -{ - for (const AnimationCallbackAndValue &callback : callbacks) { - if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) { - callback.callback->valueChanged(callback.value); - } else { - auto e = QAnimationCallbackTriggerPtr::create(peerId()); - e->setCallback(callback.callback); - e->setValue(callback.value); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - notifyObservers(e); - } - } -} - Qt3DCore::QNodeId BlendedClipAnimator::blendTreeRootId() const { diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h index f47b55796..04f609438 100644 --- a/src/animation/backend/blendedclipanimator_p.h +++ b/src/animation/backend/blendedclipanimator_p.h @@ -92,9 +92,6 @@ public: void setMappingData(const QVector<MappingData> &mappingData) { m_mappingData = mappingData; } QVector<MappingData> mappingData() const { return m_mappingData; } - void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes); - void sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks); - void animationClipMarkedDirty() { setDirty(Handler::BlendedClipAnimatorDirty); } qint64 nsSincePreviousFrame(qint64 currentGlobalTimeNS); diff --git a/src/animation/backend/channelmapper.cpp b/src/animation/backend/channelmapper.cpp index 7ea07557b..e5d4eb009 100644 --- a/src/animation/backend/channelmapper.cpp +++ b/src/animation/backend/channelmapper.cpp @@ -40,9 +40,6 @@ #include <Qt3DAnimation/private/qchannelmapper_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> #include <Qt3DAnimation/private/managers_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp index b6bcc9239..32b02d2bb 100644 --- a/src/animation/backend/clipanimator.cpp +++ b/src/animation/backend/clipanimator.cpp @@ -42,9 +42,6 @@ #include <Qt3DAnimation/private/animationclip_p.h> #include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> -#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> QT_BEGIN_NAMESPACE @@ -146,27 +143,6 @@ void ClipAnimator::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstT setDirty(Handler::ClipAnimatorDirty); } -void ClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes) -{ - for (const Qt3DCore::QSceneChangePtr &change : changes) - notifyObservers(change); -} - -void ClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks) -{ - for (const AnimationCallbackAndValue &callback : callbacks) { - if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) { - callback.callback->valueChanged(callback.value); - } else { - auto e = QAnimationCallbackTriggerPtr::create(peerId()); - e->setCallback(callback.callback); - e->setValue(callback.value); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - notifyObservers(e); - } - } -} - qint64 ClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS) { return currentGlobalTimeNS - m_lastGlobalTimeNS; diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h index 54d1527a4..d154bdab9 100644 --- a/src/animation/backend/clipanimator_p.h +++ b/src/animation/backend/clipanimator_p.h @@ -93,9 +93,6 @@ public: int currentLoop() const { return m_currentLoop; } void setCurrentLoop(int currentLoop) { m_currentLoop = currentLoop; } - void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes); - void sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks); - void animationClipMarkedDirty() { setDirty(Handler::ClipAnimatorDirty); } void setClipFormat(const ClipFormat &clipFormat) { m_clipFormat = clipFormat; } diff --git a/src/animation/backend/clipblendnode.cpp b/src/animation/backend/clipblendnode.cpp index 81fc61910..57fbdb920 100644 --- a/src/animation/backend/clipblendnode.cpp +++ b/src/animation/backend/clipblendnode.cpp @@ -37,8 +37,6 @@ #include "clipblendnode_p.h" #include <Qt3DAnimation/qclipblendnodecreatedchange.h> #include <Qt3DAnimation/qabstractanimationclip.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/animation/backend/clipblendvalue.cpp b/src/animation/backend/clipblendvalue.cpp index e1586953b..0db9544f6 100644 --- a/src/animation/backend/clipblendvalue.cpp +++ b/src/animation/backend/clipblendvalue.cpp @@ -38,7 +38,6 @@ #include <Qt3DAnimation/qclipblendnodecreatedchange.h> #include <Qt3DAnimation/qclipblendvalue.h> #include <Qt3DAnimation/private/qclipblendvalue_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/animation/backend/clock.cpp b/src/animation/backend/clock.cpp index ab30f735c..a9446c2d6 100644 --- a/src/animation/backend/clock.cpp +++ b/src/animation/backend/clock.cpp @@ -38,8 +38,6 @@ #include <Qt3DAnimation/qclock.h> #include <Qt3DAnimation/private/qclock_p.h> #include <Qt3DAnimation/private/animationutils_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> QT_BEGIN_NAMESPACE diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp index e0bb8b155..9b6802d3b 100644 --- a/src/animation/backend/evaluateblendclipanimatorjob.cpp +++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp @@ -35,6 +35,9 @@ ****************************************************************************/ #include "evaluateblendclipanimatorjob_p.h" +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DCore/private/qskeleton_p.h> +#include <Qt3DAnimation/qblendedclipanimator.h> #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> @@ -50,9 +53,9 @@ namespace Qt3DAnimation { namespace Animation { EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob() - : Qt3DCore::QAspectJob() + : AbstractEvaluateClipAnimatorJob() { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0) } void EvaluateBlendClipAnimatorJob::run() @@ -105,7 +108,7 @@ void EvaluateBlendClipAnimatorJob::run() AnimationClip *clip = clipLoaderManager->lookupResource(valueNode->clipId()); Q_ASSERT(clip); - ClipResults rawClipResults = evaluateClipAtPhase(clip, phase); + ClipResults rawClipResults = evaluateClipAtPhase(clip, float(phase)); // Reformat the clip results into the layout used by this animator/blend tree const ClipFormat format = valueNode->clipFormat(blendedClipAnimator->peerId()); @@ -120,24 +123,23 @@ void EvaluateBlendClipAnimatorJob::run() const double localTime = phase * duration; blendedClipAnimator->setLastGlobalTimeNS(globalTimeNS); blendedClipAnimator->setLastLocalTime(localTime); - blendedClipAnimator->setLastNormalizedLocalTime(phase); + blendedClipAnimator->setLastNormalizedLocalTime(float(phase)); blendedClipAnimator->setNormalizedLocalTime(-1.0f); // Re-set to something invalid. blendedClipAnimator->setCurrentLoop(animatorData.currentLoop); - const bool finalFrame = isFinalFrame(localTime, duration, animatorData.currentLoop, animatorData.loopCount); - // Prepare the property change events + // Prepare the change record + const bool finalFrame = isFinalFrame(localTime, duration, animatorData.currentLoop, animatorData.loopCount); const QVector<MappingData> mappingData = blendedClipAnimator->mappingData(); - const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(blendedClipAnimator->peerId(), - mappingData, - blendedResults, - finalFrame, - phase); - // Send the property changes - blendedClipAnimator->sendPropertyChanges(changes); + auto record = prepareAnimationRecord(blendedClipAnimator->peerId(), + mappingData, + blendedResults, + finalFrame, + float(phase)); // Trigger callbacks either on this thread or by notifying the gui thread. - const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(mappingData, blendedResults); - blendedClipAnimator->sendCallbacks(callbacks); + auto callbacks = prepareCallbacks(mappingData, blendedResults); + + setPostFrameData(record, callbacks); } } // Animation diff --git a/src/animation/backend/evaluateblendclipanimatorjob_p.h b/src/animation/backend/evaluateblendclipanimatorjob_p.h index 7548168e9..b2a5a6d17 100644 --- a/src/animation/backend/evaluateblendclipanimatorjob_p.h +++ b/src/animation/backend/evaluateblendclipanimatorjob_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include <Qt3DCore/qaspectjob.h> +#include <Qt3DAnimation/private/abstractevaluateclipanimatorjob_p.h> #include <Qt3DAnimation/private/handle_types_p.h> #include <Qt3DAnimation/private/animationutils_p.h> #include <Qt3DAnimation/private/blendedclipanimator_p.h> @@ -60,8 +60,9 @@ namespace Animation { class Handler; class ClipBlendNode; +class EvaluateBlendClipAnimatorJobPrivate; -class EvaluateBlendClipAnimatorJob : public Qt3DCore::QAspectJob +class EvaluateBlendClipAnimatorJob : public AbstractEvaluateClipAnimatorJob { public: EvaluateBlendClipAnimatorJob(); diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp index 74f9012d7..7a568e829 100644 --- a/src/animation/backend/evaluateclipanimatorjob.cpp +++ b/src/animation/backend/evaluateclipanimatorjob.cpp @@ -35,6 +35,9 @@ ****************************************************************************/ #include "evaluateclipanimatorjob_p.h" +#include <Qt3DCore/private/qaspectjob_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DAnimation/qclipanimator.h> #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> @@ -46,10 +49,11 @@ QT_BEGIN_NAMESPACE namespace Qt3DAnimation { namespace Animation { + EvaluateClipAnimatorJob::EvaluateClipAnimatorJob() - : Qt3DCore::QAspectJob() + : AbstractEvaluateClipAnimatorJob() { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0) } void EvaluateClipAnimatorJob::run() @@ -98,19 +102,16 @@ void EvaluateClipAnimatorJob::run() clipAnimator->setNormalizedLocalTime(-1.0f); // Re-set to something invalid. // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend) - const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(), - clipAnimator->mappingData(), - formattedClipResults, - preEvaluationDataForClip.isFinalFrame, - preEvaluationDataForClip.normalizedLocalTime); - - // Send the property changes - clipAnimator->sendPropertyChanges(changes); + auto record = prepareAnimationRecord(clipAnimator->peerId(), + clipAnimator->mappingData(), + formattedClipResults, + preEvaluationDataForClip.isFinalFrame, + preEvaluationDataForClip.normalizedLocalTime); // Trigger callbacks either on this thread or by notifying the gui thread. - const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(clipAnimator->mappingData(), - formattedClipResults); - clipAnimator->sendCallbacks(callbacks); + auto callbacks = prepareCallbacks(clipAnimator->mappingData(), formattedClipResults); + + setPostFrameData(record, callbacks); } } // namespace Animation diff --git a/src/animation/backend/evaluateclipanimatorjob_p.h b/src/animation/backend/evaluateclipanimatorjob_p.h index c9b1a8f96..2e88c9579 100644 --- a/src/animation/backend/evaluateclipanimatorjob_p.h +++ b/src/animation/backend/evaluateclipanimatorjob_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include <Qt3DCore/qaspectjob.h> +#include <Qt3DAnimation/private/abstractevaluateclipanimatorjob_p.h> #include <Qt3DAnimation/private/handle_types_p.h> QT_BEGIN_NAMESPACE @@ -58,7 +58,7 @@ namespace Animation { class Handler; -class EvaluateClipAnimatorJob : public Qt3DCore::QAspectJob +class EvaluateClipAnimatorJob : public AbstractEvaluateClipAnimatorJob { public: EvaluateClipAnimatorJob(); diff --git a/src/animation/backend/loadanimationclipjob.cpp b/src/animation/backend/loadanimationclipjob.cpp index d3319f8e1..977564c7f 100644 --- a/src/animation/backend/loadanimationclipjob.cpp +++ b/src/animation/backend/loadanimationclipjob.cpp @@ -36,7 +36,11 @@ #include "loadanimationclipjob_p.h" +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/private/qanimationcliploader_p.h> #include <Qt3DAnimation/private/animationclip_p.h> +#include <Qt3DAnimation/private/qabstractanimationclip_p.h> #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/private/job_common_p.h> @@ -46,16 +50,27 @@ QT_BEGIN_NAMESPACE namespace Qt3DAnimation { namespace Animation { +class LoadAnimationClipJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + LoadAnimationClipJobPrivate() { } + ~LoadAnimationClipJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<AnimationClip *> m_updatedNodes; +}; + LoadAnimationClipJob::LoadAnimationClipJob() - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new LoadAnimationClipJobPrivate) , m_animationClipHandles() { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadAnimationClip, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadAnimationClip, 0) } void LoadAnimationClipJob::addDirtyAnimationClips(const QVector<HAnimationClip> &animationClipHandles) { - for (const auto handle : animationClipHandles) { + for (const auto &handle : animationClipHandles) { if (!m_animationClipHandles.contains(handle)) m_animationClipHandles.push_back(handle); } @@ -69,16 +84,40 @@ void LoadAnimationClipJob::clearDirtyAnimationClips() void LoadAnimationClipJob::run() { Q_ASSERT(m_handler); + Q_D(LoadAnimationClipJob); + + d->m_updatedNodes.reserve(m_animationClipHandles.size()); AnimationClipLoaderManager *animationClipManager = m_handler->animationClipLoaderManager(); for (const auto &animationClipHandle : qAsConst(m_animationClipHandles)) { AnimationClip *animationClip = animationClipManager->data(animationClipHandle); Q_ASSERT(animationClip); animationClip->loadAnimation(); + d->m_updatedNodes.push_back(animationClip); } clearDirtyAnimationClips(); } +void LoadAnimationClipJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (AnimationClip *clip: qAsConst(m_updatedNodes)) { + QAbstractAnimationClip *node = qobject_cast<QAbstractAnimationClip *>(manager->lookupNode(clip->peerId())); + if (!node) + continue; + + QAbstractAnimationClipPrivate *dnode = static_cast<QAbstractAnimationClipPrivate *>(Qt3DCore::QNodePrivate::get(node)); + dnode->setDuration(clip->duration()); + + QAnimationClipLoader *loader = qobject_cast<QAnimationClipLoader *>(node); + if (loader) { + QAnimationClipLoaderPrivate *dloader = static_cast<QAnimationClipLoaderPrivate *>(dnode); + dloader->setStatus(clip->status()); + } + } + + m_updatedNodes.clear(); +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/loadanimationclipjob_p.h b/src/animation/backend/loadanimationclipjob_p.h index 25de2c6b6..07d78d416 100644 --- a/src/animation/backend/loadanimationclipjob_p.h +++ b/src/animation/backend/loadanimationclipjob_p.h @@ -59,6 +59,7 @@ namespace Animation { class Handler; class FindGraphJob; +class LoadAnimationClipJobPrivate; class LoadAnimationClipJob : public Qt3DCore::QAspectJob { @@ -75,6 +76,8 @@ protected: void run() override; private: + Q_DECLARE_PRIVATE(LoadAnimationClipJob) + QVector<HAnimationClip> m_animationClipHandles; Handler *m_handler; }; diff --git a/src/animation/backend/skeleton.cpp b/src/animation/backend/skeleton.cpp index 720b43e33..60e436a71 100644 --- a/src/animation/backend/skeleton.cpp +++ b/src/animation/backend/skeleton.cpp @@ -36,6 +36,7 @@ #include "skeleton_p.h" #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qabstractskeleton_p.h> QT_BEGIN_NAMESPACE @@ -62,40 +63,20 @@ void Skeleton::cleanup() m_jointLocalPoses.clear(); } -// TODOSYNC remove once backend > backend communication no longer requires messages -void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Skeleton::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - // Get the joint names and initial local poses from a change sent - // by the render aspect when the skeleton has been loaded. - switch (e->type()) { - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("jointNamesAndLocalPoses")) { - const auto payload = change->value().value<JointNamesAndLocalPoses>(); - m_jointNames = payload.names; - m_jointLocalPoses = payload.localPoses; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); - // TODO: Mark joint info as dirty so we can rebuild any indexes used - // by the animators and channel mappings. - } + const Qt3DCore::QAbstractSkeleton *node = qobject_cast<const Qt3DCore::QAbstractSkeleton *>(frontEnd); + if (!node) + return; - break; - } + auto dnode = Qt3DCore::QAbstractSkeletonPrivate::get(node); - default: - break; - } - - BackendNode::sceneChangeEvent(e); -} - -void Skeleton::sendLocalPoses() -{ - auto e = QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes); - e->setPropertyName("localPoses"); - e->setValue(QVariant::fromValue(m_jointLocalPoses)); - notifyObservers(e); + // TODO: Mark joint info as dirty so we can rebuild any indexes used + // by the animators and channel mappings. + m_jointNames = dnode->m_jointNames; + m_jointLocalPoses = dnode->m_localPoses; } } // namespace Animation diff --git a/src/animation/backend/skeleton_p.h b/src/animation/backend/skeleton_p.h index 668ff8712..d44f8fc1c 100644 --- a/src/animation/backend/skeleton_p.h +++ b/src/animation/backend/skeleton_p.h @@ -62,8 +62,9 @@ public: Skeleton(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + QVector<Qt3DCore::Sqt> joints() const { return m_jointLocalPoses; } int jointCount() const { return m_jointLocalPoses.size(); } QString jointName(int jointIndex) const { return m_jointNames.at(jointIndex); } @@ -97,8 +98,6 @@ public: return m_jointLocalPoses[jointIndex].translation; } - void sendLocalPoses(); - #if defined(QT_BUILD_INTERNAL) void setJointCount(int jointCount) { diff --git a/src/animation/frontend/qabstractanimationclip.cpp b/src/animation/frontend/qabstractanimationclip.cpp index 7e6df4d70..e662a1408 100644 --- a/src/animation/frontend/qabstractanimationclip.cpp +++ b/src/animation/frontend/qabstractanimationclip.cpp @@ -153,19 +153,6 @@ float QAbstractAnimationClip::duration() const return d->m_duration; } -/*! - \internal -*/ -void QAbstractAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QAbstractAnimationClip); - if (change->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->propertyName() == QByteArrayLiteral("duration")) - d->setDuration(e->value().toFloat()); - } -} - } // namespace Qt3DAnimation QT_END_NAMESPACE diff --git a/src/animation/frontend/qabstractanimationclip.h b/src/animation/frontend/qabstractanimationclip.h index 79464b13d..f68950c4c 100644 --- a/src/animation/frontend/qabstractanimationclip.h +++ b/src/animation/frontend/qabstractanimationclip.h @@ -62,7 +62,6 @@ Q_SIGNALS: protected: QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QAbstractAnimationClip) diff --git a/src/animation/frontend/qabstractclipanimator.cpp b/src/animation/frontend/qabstractclipanimator.cpp index 238dbea8c..b2f6f817f 100644 --- a/src/animation/frontend/qabstractclipanimator.cpp +++ b/src/animation/frontend/qabstractclipanimator.cpp @@ -41,7 +41,6 @@ #include "qabstractclipanimator_p.h" #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/qclock.h> -#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h> QT_BEGIN_NAMESPACE @@ -123,18 +122,6 @@ QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Q { } -/*! \internal */ -void QAbstractClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - if (change->type() == Qt3DCore::CallbackTriggered) { - QAnimationCallbackTriggerPtr callbackTrigger = qSharedPointerCast<Qt3DAnimation::QAnimationCallbackTrigger>(change); - if (callbackTrigger->callback()) - callbackTrigger->callback()->valueChanged(callbackTrigger->value()); - } else { - QComponent::sceneChangeEvent(change); - } -} - QAbstractClipAnimator::~QAbstractClipAnimator() { } diff --git a/src/animation/frontend/qabstractclipanimator.h b/src/animation/frontend/qabstractclipanimator.h index a3bce0600..687589b5e 100644 --- a/src/animation/frontend/qabstractclipanimator.h +++ b/src/animation/frontend/qabstractclipanimator.h @@ -94,8 +94,6 @@ protected: explicit QAbstractClipAnimator(Qt3DCore::QNode *parent = nullptr); QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - private: Q_DECLARE_PRIVATE(QAbstractClipAnimator) }; diff --git a/src/animation/frontend/qanimationcliploader.cpp b/src/animation/frontend/qanimationcliploader.cpp index d31f9bd5d..446995b17 100644 --- a/src/animation/frontend/qanimationcliploader.cpp +++ b/src/animation/frontend/qanimationcliploader.cpp @@ -142,19 +142,6 @@ void QAnimationClipLoader::setSource(const QUrl &source) emit sourceChanged(source); } -/*! - \internal -*/ -void QAnimationClipLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QAnimationClipLoader); - if (change->type() == Qt3DCore::PropertyUpdated) { - const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->propertyName() == QByteArrayLiteral("status")) - d->setStatus(static_cast<QAnimationClipLoader::Status>(e->value().toInt())); - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QAnimationClipLoader::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAnimationClipLoaderData>::create(this); diff --git a/src/animation/frontend/qanimationcliploader.h b/src/animation/frontend/qanimationcliploader.h index bf82f742e..1ff388297 100644 --- a/src/animation/frontend/qanimationcliploader.h +++ b/src/animation/frontend/qanimationcliploader.h @@ -78,7 +78,6 @@ Q_SIGNALS: protected: explicit QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QAnimationClipLoader) diff --git a/src/animation/frontend/qcallbackmapping.cpp b/src/animation/frontend/qcallbackmapping.cpp index f312ddaa5..53f7a5e33 100644 --- a/src/animation/frontend/qcallbackmapping.cpp +++ b/src/animation/frontend/qcallbackmapping.cpp @@ -38,7 +38,6 @@ #include "qcallbackmapping_p.h" #include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtCore/qmetaobject.h> #include <QtCore/QMetaProperty> diff --git a/src/animation/frontend/qchannelmapper.cpp b/src/animation/frontend/qchannelmapper.cpp index 34b5ffbe6..2146290e4 100644 --- a/src/animation/frontend/qchannelmapper.cpp +++ b/src/animation/frontend/qchannelmapper.cpp @@ -37,8 +37,6 @@ #include "qchannelmapper.h" #include "qchannelmapper_p.h" #include <Qt3DAnimation/qchannelmapping.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/animation/frontend/qchannelmapping.cpp b/src/animation/frontend/qchannelmapping.cpp index fa89d5042..59620ab49 100644 --- a/src/animation/frontend/qchannelmapping.cpp +++ b/src/animation/frontend/qchannelmapping.cpp @@ -38,7 +38,6 @@ #include "qchannelmapping_p.h" #include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtCore/qmetaobject.h> #include <QtCore/QMetaProperty> diff --git a/src/animation/frontend/qclock.cpp b/src/animation/frontend/qclock.cpp index 717982902..f38c21807 100644 --- a/src/animation/frontend/qclock.cpp +++ b/src/animation/frontend/qclock.cpp @@ -36,7 +36,6 @@ #include "qclock.h" #include "qclock_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp index 866a0ce25..05afdd293 100644 --- a/src/core/aspects/qabstractaspect.cpp +++ b/src/core/aspects/qabstractaspect.cpp @@ -43,8 +43,13 @@ #include <QMetaObject> #include <QMetaProperty> +#include <Qt3DCore/qcomponent.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qpropertyvalueaddedchange.h> +#include <Qt3DCore/qpropertyvalueremovedchange.h> +#include <Qt3DCore/qcomponentaddedchange.h> +#include <Qt3DCore/qcomponentremovedchange.h> #include <Qt3DCore/private/corelogging_p.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> @@ -209,6 +214,12 @@ void QAbstractAspect::syncDirtyFrontEndNodes(const QVector<QNode *> &nodes) d->syncDirtyFrontEndNodes(nodes); } +void QAbstractAspect::syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes) +{ + Q_D(QAbstractAspect); + d->syncDirtyFrontEndSubNodes(nodes); +} + QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperForNode(const QMetaObject *metaObj) const { Q_ASSERT(metaObj); @@ -243,6 +254,103 @@ void QAbstractAspectPrivate::syncDirtyFrontEndNodes(const QVector<QNode *> &node } } +void QAbstractAspectPrivate::syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes) +{ + for (const auto &nodeChange: qAsConst(nodes)) { + auto getBackend = [this](QNode *node) -> std::tuple<QBackendNode *, bool> { + const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo; + const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj); + const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first; + + if (!backendNodeMapper) + return {}; + + QBackendNode *backend = backendNodeMapper->get(node->id()); + if (!backend) + return {}; + + const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing; + + return std::tuple<QBackendNode *, bool>(backend, supportsSyncing); + }; + + auto nodeInfo = getBackend(nodeChange.node); + if (!std::get<0>(nodeInfo)) + continue; + + auto subNodeInfo = getBackend(nodeChange.subNode); + if (!std::get<0>(subNodeInfo)) + continue; + + switch (nodeChange.change) { + case PropertyValueAdded: { + if (std::get<1>(nodeInfo)) + break; // do nothing as the node will be dirty anyway + + QPropertyValueAddedChange change(nodeChange.node->id()); + change.setPropertyName(nodeChange.property); + change.setAddedValue(QVariant::fromValue(nodeChange.subNode->id())); + QPropertyValueAddedChangePtr pChange(&change, [](QPropertyValueAddedChange *) { }); + std::get<0>(nodeInfo)->sceneChangeEvent(pChange); + } + break; + case PropertyValueRemoved: { + if (std::get<1>(nodeInfo)) + break; // do nothing as the node will be dirty anyway + + QPropertyValueRemovedChange change(nodeChange.node->id()); + change.setPropertyName(nodeChange.property); + change.setRemovedValue(QVariant::fromValue(nodeChange.subNode->id())); + QPropertyValueRemovedChangePtr pChange(&change, [](QPropertyValueRemovedChange *) { }); + std::get<0>(nodeInfo)->sceneChangeEvent(pChange); + } + break; + case ComponentAdded: { + // let the entity know it has a new component + if (std::get<1>(nodeInfo)) { + QBackendNodePrivate::get(std::get<0>(nodeInfo))->componentAdded(nodeChange.subNode); + } else { + QComponentAddedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node)); + QComponentAddedChangePtr pChange(&change, [](QComponentAddedChange *) { }); + std::get<0>(nodeInfo)->sceneChangeEvent(pChange); + } + + // let the component know it was added to an entity + if (std::get<1>(subNodeInfo)) { + QBackendNodePrivate::get(std::get<0>(subNodeInfo))->addedToEntity(nodeChange.node); + } else { + QComponentAddedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node)); + QComponentAddedChangePtr pChange(&change, [](QComponentAddedChange *) { }); + std::get<0>(subNodeInfo)->sceneChangeEvent(pChange); + } + } + break; + case ComponentRemoved: { + // let the entity know a component was removed + if (std::get<1>(nodeInfo)) { + QBackendNodePrivate::get(std::get<0>(nodeInfo))->componentRemoved(nodeChange.subNode); + } else { + QComponentRemovedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node)); + QComponentRemovedChangePtr pChange(&change, [](QComponentRemovedChange *) { }); + std::get<0>(nodeInfo)->sceneChangeEvent(pChange); + } + + // let the component know it was removed from an entity + if (std::get<1>(subNodeInfo)) { + QBackendNodePrivate::get(std::get<0>(subNodeInfo))->removedFromEntity(nodeChange.node); + } else { + QComponentRemovedChange change(qobject_cast<Qt3DCore::QEntity *>(nodeChange.node), qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode)); + QComponentRemovedChangePtr pChange(&change, [](QComponentRemovedChange *) { }); + std::get<0>(nodeInfo)->sceneChangeEvent(pChange); + } + } + break; + default: + break; + } + } +} + void QAbstractAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const { Q_ASSERT(false); // overload in derived class diff --git a/src/core/aspects/qabstractaspect.h b/src/core/aspects/qabstractaspect.h index a9f4f03fc..8c191c1d8 100644 --- a/src/core/aspects/qabstractaspect.h +++ b/src/core/aspects/qabstractaspect.h @@ -42,6 +42,7 @@ #include <Qt3DCore/qt3dcore_global.h> #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/qscenechange.h> #include <QtCore/QObject> #include <QtCore/QSharedPointer> @@ -86,6 +87,7 @@ protected: private: void syncDirtyFrontEndNodes(const QVector<QNode *> &nodes); + void syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes); void registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor, bool supportsSyncing); virtual QVariant executeCommand(const QStringList &args); diff --git a/src/core/aspects/qabstractaspect_p.h b/src/core/aspects/qabstractaspect_p.h index 8bd26cf00..670302cfa 100644 --- a/src/core/aspects/qabstractaspect_p.h +++ b/src/core/aspects/qabstractaspect_p.h @@ -130,6 +130,7 @@ public: QBackendNode *createBackendNode(const NodeTreeChange &change) const; void clearBackendNode(const NodeTreeChange &change) const; void syncDirtyFrontEndNodes(const QVector<QNode *> &nodes); + void syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes); virtual void syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const; void sendPropertyMessages(QNode *node, QBackendNode *backend) const; diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp index a33f771e9..71e05b34f 100644 --- a/src/core/aspects/qaspectmanager.cpp +++ b/src/core/aspects/qaspectmanager.cpp @@ -62,6 +62,7 @@ #include <Qt3DCore/private/qtickclockservice_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> #include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> #include <QtCore/QCoreApplication> @@ -379,6 +380,24 @@ void QAspectManager::setPostConstructorInit(NodePostConstructorInit *postConstru m_postConstructorInit = postConstructorInit; } +QNode *QAspectManager::lookupNode(QNodeId id) const +{ + if (!m_root) + return nullptr; + + QNodePrivate *d = QNodePrivate::get(m_root); + return d->m_scene ? d->m_scene->lookupNode(id) : nullptr; +} + +QVector<QNode *> QAspectManager::lookupNodes(const QVector<QNodeId> &ids) const +{ + if (!m_root) + return {}; + + QNodePrivate *d = QNodePrivate::get(m_root); + return d->m_scene ? d->m_scene->lookupNodes(ids) : QVector<QNode *>{}; +} + /*! \internal \brief Drives the Qt3D simulation loop in the main thread @@ -456,11 +475,18 @@ void QAspectManager::processFrame() } } + // Sync node / subnode relationship changes + const auto dirtySubNodes = m_changeArbiter->takeDirtyFrontEndSubNodes(); + if (dirtySubNodes.size()) + for (QAbstractAspect *aspect : qAsConst(m_aspects)) + aspect->syncDirtyFrontEndSubNodes(dirtySubNodes); + // Sync property updates const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes(); if (dirtyFrontEndNodes.size()) for (QAbstractAspect *aspect : qAsConst(m_aspects)) aspect->syncDirtyFrontEndNodes(dirtyFrontEndNodes); + // TO DO: Having this done in the main thread actually means aspects could just // as simply read info out of the Frontend classes without risk of introducing // races. This could therefore be removed for Qt 6. diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h index 38ddbc55d..d9a6c41ec 100644 --- a/src/core/aspects/qaspectmanager_p.h +++ b/src/core/aspects/qaspectmanager_p.h @@ -108,6 +108,9 @@ public: QServiceLocator *serviceLocator() const; void setPostConstructorInit(NodePostConstructorInit *postConstructorInit); + QNode *lookupNode(QNodeId id) const; + QVector<QNode *> lookupNodes(const QVector<QNodeId> &ids) const; + private: bool event(QEvent *event) override; void requestNextFrame(); diff --git a/src/core/changes/qscenechange.h b/src/core/changes/qscenechange.h index 7d88d334f..e8c0ea748 100644 --- a/src/core/changes/qscenechange.h +++ b/src/core/changes/qscenechange.h @@ -63,6 +63,15 @@ enum ChangeFlag { Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag) Q_DECLARE_OPERATORS_FOR_FLAGS(ChangeFlags) +class QNode; +//! internal +struct NodeRelationshipChange { + QNode *node; + QNode *subNode; + ChangeFlag change; + const char *property; +}; + class QSceneChangePrivate; class Q_3DCORESHARED_EXPORT QSceneChange diff --git a/src/core/jobs/qaspectjob.cpp b/src/core/jobs/qaspectjob.cpp index ccb9c3a0e..00ad1ace8 100644 --- a/src/core/jobs/qaspectjob.cpp +++ b/src/core/jobs/qaspectjob.cpp @@ -59,11 +59,18 @@ QAspectJobPrivate::QAspectJobPrivate() { } +QAspectJobPrivate::~QAspectJobPrivate() = default; + QAspectJobPrivate *QAspectJobPrivate::get(QAspectJob *job) { return job->d_func(); } +void QAspectJobPrivate::postFrame(QAspectManager *aspectManager) +{ + Q_UNUSED(aspectManager) +} + QAspectJob::QAspectJob() : d_ptr(new QAspectJobPrivate) { @@ -133,6 +140,13 @@ QVector<QWeakPointer<QAspectJob> > QAspectJob::dependencies() const return d->m_dependencies; } +void QAspectJob::postFrame(QAspectManager *aspectManager) +{ + Q_D(QAspectJob); + if (aspectManager) + d->postFrame(aspectManager); +} + } // namespace Qt3DCore QT_END_NAMESPACE diff --git a/src/core/jobs/qaspectjob.h b/src/core/jobs/qaspectjob.h index 5c088fd1a..7cc784e0f 100644 --- a/src/core/jobs/qaspectjob.h +++ b/src/core/jobs/qaspectjob.h @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { class QAspectJobPrivate; +class QAspectManager; class Q_3DCORESHARED_EXPORT QAspectJob { @@ -62,14 +63,15 @@ public: QVector<QWeakPointer<QAspectJob> > dependencies() const; virtual void run() = 0; + void postFrame(QAspectManager *aspectManager); protected: explicit QAspectJob(QAspectJobPrivate &dd); + QAspectJobPrivate *d_ptr; private: Q_DISABLE_COPY(QAspectJob) Q_DECLARE_PRIVATE(QAspectJob) - QAspectJobPrivate *d_ptr; }; typedef QSharedPointer<QAspectJob> QAspectJobPtr; diff --git a/src/core/jobs/qaspectjob_p.h b/src/core/jobs/qaspectjob_p.h index 7aa3151a0..b16c3cad2 100644 --- a/src/core/jobs/qaspectjob_p.h +++ b/src/core/jobs/qaspectjob_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { class QAspectJob; +class QAspectManager; #if QT_CONFIG(qt3d_profile_jobs) struct FrameHeader @@ -107,9 +108,12 @@ class Q_3DCORE_PRIVATE_EXPORT QAspectJobPrivate { public: QAspectJobPrivate(); + virtual ~QAspectJobPrivate(); static QAspectJobPrivate *get(QAspectJob *job); + virtual void postFrame(QAspectManager *aspectManager); + QVector<QWeakPointer<QAspectJob> > m_dependencies; #if QT_CONFIG(qt3d_profile_jobs) JobRunStats m_stats; diff --git a/src/core/nodes/qbackendnode.cpp b/src/core/nodes/qbackendnode.cpp index 3eb1cd9f7..e5f93e96f 100644 --- a/src/core/nodes/qbackendnode.cpp +++ b/src/core/nodes/qbackendnode.cpp @@ -95,6 +95,26 @@ QBackendNodePrivate *QBackendNodePrivate::get(QBackendNode *n) return n->d_func(); } +void QBackendNodePrivate::addedToEntity(QNode *frontend) +{ + Q_UNUSED(frontend) +} + +void QBackendNodePrivate::removedFromEntity(QNode *frontend) +{ + Q_UNUSED(frontend) +} + +void QBackendNodePrivate::componentAdded(QNode *frontend) +{ + Q_UNUSED(frontend) +} + +void QBackendNodePrivate::componentRemoved(QNode *frontend) +{ + Q_UNUSED(frontend) +} + /*! * \class Qt3DCore::QBackendNodeMapper * \inheaderfile Qt3DCore/QBackendNodeMapper diff --git a/src/core/nodes/qbackendnode_p.h b/src/core/nodes/qbackendnode_p.h index dde86fa48..260eef087 100644 --- a/src/core/nodes/qbackendnode_p.h +++ b/src/core/nodes/qbackendnode_p.h @@ -63,6 +63,8 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { +class QNode; + class Q_3DCORE_PRIVATE_EXPORT QBackendNodePrivate : public QObserverInterface , public QObservableInterface @@ -85,6 +87,11 @@ public: QNodeId m_peerId; bool m_enabled; + virtual void addedToEntity(QNode *frontend); + virtual void removedFromEntity(QNode *frontend); + virtual void componentAdded(QNode *frontend); + virtual void componentRemoved(QNode *frontend); + private: Q_DISABLE_COPY(QBackendNodePrivate) }; diff --git a/src/core/nodes/qcomponent.cpp b/src/core/nodes/qcomponent.cpp index 2fe3c8094..79bba229d 100644 --- a/src/core/nodes/qcomponent.cpp +++ b/src/core/nodes/qcomponent.cpp @@ -40,9 +40,6 @@ #include "qcomponent.h" #include "qcomponent_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qcomponentaddedchange.h> -#include <Qt3DCore/qcomponentremovedchange.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/private/qentity_p.h> @@ -73,8 +70,6 @@ void QComponentPrivate::addEntity(QEntity *entity) m_scene->addEntityForComponent(m_id, entity->id()); } - const auto componentAddedChange = QComponentAddedChangePtr::create(q, entity); // TODOSYNC notify backend directly - notifyObservers(componentAddedChange); Q_EMIT q->addedToEntity(entity); } @@ -86,8 +81,6 @@ void QComponentPrivate::removeEntity(QEntity *entity) m_entities.removeAll(entity); - const auto componentRemovedChange = QComponentRemovedChangePtr::create(q, entity); // TODOSYNC notify backend directly - notifyObservers(componentRemovedChange); Q_EMIT q->removedFromEntity(entity); } diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp index 0ff8c4646..024991387 100644 --- a/src/core/nodes/qentity.cpp +++ b/src/core/nodes/qentity.cpp @@ -41,10 +41,7 @@ #include "qentity_p.h" #include <Qt3DCore/qcomponent.h> -#include <Qt3DCore/qcomponentaddedchange.h> -#include <Qt3DCore/qcomponentremovedchange.h> #include <Qt3DCore/qnodecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtCore/QMetaObject> #include <QtCore/QMetaProperty> @@ -102,13 +99,8 @@ void QEntityPrivate::removeDestroyedComponent(QComponent *comp) Q_CHECK_PTR(comp); qCDebug(Nodes) << Q_FUNC_INFO << comp; - Q_Q(QEntity); - - if (m_changeArbiter) { - const auto componentRemovedChange = QComponentRemovedChangePtr::create(q, comp); // TODOSYNC notify backend directly - notifyObservers(componentRemovedChange); - } + updateNode(comp, nullptr, ComponentRemoved); m_components.removeOne(comp); // Remove bookkeeping connection @@ -187,10 +179,7 @@ void QEntity::addComponent(QComponent *comp) // Ensures proper bookkeeping d->registerPrivateDestructionHelper(comp, &QEntityPrivate::removeDestroyedComponent); - if (d->m_changeArbiter) { - const auto componentAddedChange = QComponentAddedChangePtr::create(this, comp); // TODOSYNC notify backend directly - d->notifyObservers(componentAddedChange); - } + d->updateNode(comp, nullptr, ComponentAdded); static_cast<QComponentPrivate *>(QComponentPrivate::get(comp))->addEntity(this); } @@ -205,10 +194,7 @@ void QEntity::removeComponent(QComponent *comp) static_cast<QComponentPrivate *>(QComponentPrivate::get(comp))->removeEntity(this); - if (d->m_changeArbiter) { - const auto componentRemovedChange = QComponentRemovedChangePtr::create(this, comp); - d->notifyObservers(componentRemovedChange); - } + d->updateNode(comp, nullptr, ComponentRemoved); d->m_components.removeOne(comp); diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp index 2cea47372..cfe83f4db 100644 --- a/src/core/nodes/qnode.cpp +++ b/src/core/nodes/qnode.cpp @@ -526,10 +526,11 @@ void QNodePrivate::_q_ensureBackendNodeCreated() * Sends the \a change QSceneChangePtr to any QBackendNodes in the registered * aspects that correspond to this QNode. * - * For the common case of a QObject property change, QNode handles this for you - * automatically by sending a QPropertyUpdatedChange event to the backend nodes. * You only need to call this function if you wish to send a specific type of * change in place of the automatic handling. + * + * Note: as of Qt 5.14, change messages are deprecated and should not be used, + * in particular for properties. */ void QNode::notifyObservers(const QSceneChangePtr &change) { @@ -679,6 +680,14 @@ void QNodePrivate::update() } } +void QNodePrivate::updateNode(QNode *node, const char *property, ChangeFlag change) +{ + if (m_changeArbiter) { + Q_Q(QNode); + m_changeArbiter->addDirtyFrontEndNode(q, node, property, change); + } +} + /*! \internal */ diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index 839751a5e..a7a300a5e 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -90,6 +90,7 @@ public: void updatePropertyTrackMode(); void update(); + void updateNode(QNode *node, const char* property, ChangeFlag change); Q_DECLARE_PUBLIC(QNode) diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp index 60cdc3bd2..e5745b017 100644 --- a/src/core/qchangearbiter.cpp +++ b/src/core/qchangearbiter.cpp @@ -249,13 +249,24 @@ void QChangeArbiter::sceneChangeEventWithLock(const QSceneChangeList &e) void QChangeArbiter::addDirtyFrontEndNode(QNode *node) { - if (!m_dirtyFrontEndNodes.contains(node)) + if (!m_dirtyFrontEndNodes.contains(node)) { m_dirtyFrontEndNodes += node; + emit receivedChange(); + } +} + +void QChangeArbiter::addDirtyFrontEndNode(QNode *node, QNode *subNode, const char *property, ChangeFlag change) +{ + addDirtyFrontEndNode(node); + m_dirtySubNodeChanges.push_back({node, subNode, change, property}); } void QChangeArbiter::removeDirtyFrontEndNode(QNode *node) { m_dirtyFrontEndNodes.removeOne(node); + m_dirtySubNodeChanges.erase(std::remove_if(m_dirtySubNodeChanges.begin(), m_dirtySubNodeChanges.end(), [node](const NodeRelationshipChange &elt) { + return elt.node == node || elt.subNode == node; + }), m_dirtySubNodeChanges.end()); } QVector<QNode *> QChangeArbiter::takeDirtyFrontEndNodes() @@ -263,6 +274,11 @@ QVector<QNode *> QChangeArbiter::takeDirtyFrontEndNodes() return std::move(m_dirtyFrontEndNodes); } +QVector<NodeRelationshipChange> QChangeArbiter::takeDirtyFrontEndSubNodes() +{ + return std::move(m_dirtySubNodeChanges); +} + // Either we have the postman or we could make the QChangeArbiter agnostic to the postman // but that would require adding it to every QObserverList in m_aspectObservations. void QChangeArbiter::setPostman(QAbstractPostman *postman) diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h index 0a6196756..f31480685 100644 --- a/src/core/qchangearbiter_p.h +++ b/src/core/qchangearbiter_p.h @@ -83,6 +83,7 @@ public: virtual QAbstractPostman *postman() const = 0; virtual void addDirtyFrontEndNode(QNode *node) = 0; virtual void removeDirtyFrontEndNode(QNode *node) = 0; + virtual void addDirtyFrontEndNode(QNode *node, QNode *subNode, const char *property, ChangeFlag change) = 0; }; class Q_3DCORE_PRIVATE_EXPORT QChangeArbiter final @@ -109,8 +110,10 @@ public: void sceneChangeEventWithLock(const QSceneChangeList &e) override; // QLockableObserverInterface impl void addDirtyFrontEndNode(QNode *node) override; + void addDirtyFrontEndNode(QNode *node, QNode *subNode, const char *property, ChangeFlag change) override; void removeDirtyFrontEndNode(QNode *node) override; QVector<QNode *> takeDirtyFrontEndNodes(); + QVector<NodeRelationshipChange> takeDirtyFrontEndSubNodes(); void setPostman(Qt3DCore::QAbstractPostman *postman); void setScene(Qt3DCore::QScene *scene); @@ -159,6 +162,7 @@ private: QScene *m_scene; QVector<QNode *> m_dirtyFrontEndNodes; + QVector<NodeRelationshipChange> m_dirtySubNodeChanges; }; } // namespace Qt3DCore diff --git a/src/core/qscheduler.cpp b/src/core/qscheduler.cpp index cc2f9081e..edfbb391c 100644 --- a/src/core/qscheduler.cpp +++ b/src/core/qscheduler.cpp @@ -91,6 +91,9 @@ void QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time) // whilst the threadpool works its way through the jobs m_aspectManager->jobManager()->waitForAllJobs(); + + for (auto &job : qAsConst(jobQueue)) + job->postFrame(m_aspectManager); } } // namespace Qt3DCore diff --git a/src/core/transforms/qabstractskeleton.cpp b/src/core/transforms/qabstractskeleton.cpp index 1bc7247a7..5f3b05eb8 100644 --- a/src/core/transforms/qabstractskeleton.cpp +++ b/src/core/transforms/qabstractskeleton.cpp @@ -60,6 +60,14 @@ const QAbstractSkeletonPrivate *QAbstractSkeletonPrivate::get(const QAbstractSke } /*! + \internal + */ +QAbstractSkeletonPrivate *QAbstractSkeletonPrivate::get(QAbstractSkeleton *q) +{ + return q->d_func(); +} + +/*! \qmltype AbstractSkeleton \inqmlmodule Qt3D.Core \inherits Node diff --git a/src/core/transforms/qabstractskeleton_p.h b/src/core/transforms/qabstractskeleton_p.h index 51d57f8c4..35d0df755 100644 --- a/src/core/transforms/qabstractskeleton_p.h +++ b/src/core/transforms/qabstractskeleton_p.h @@ -53,12 +53,13 @@ #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qskeletoncreatedchange_p.h> +#include <Qt3DCore/private/sqt_p.h> QT_BEGIN_NAMESPACE namespace Qt3DCore { -class QAbstractSkeletonPrivate : public Qt3DCore::QNodePrivate +class Q_3DCORE_PRIVATE_EXPORT QAbstractSkeletonPrivate : public Qt3DCore::QNodePrivate { public: QAbstractSkeletonPrivate(); @@ -67,10 +68,13 @@ public: Q_DECLARE_PUBLIC(QAbstractSkeleton) static const QAbstractSkeletonPrivate *get(const QAbstractSkeleton *q); + static QAbstractSkeletonPrivate *get(QAbstractSkeleton *q); QSkeletonCreatedChangeBase::SkeletonType m_type; int m_jointCount; + QVector<Sqt> m_localPoses; + QVector<QString> m_jointNames; }; } // namespace Qt3DCore diff --git a/src/core/transforms/qarmature_p.h b/src/core/transforms/qarmature_p.h index 1fc241dc2..3474349a6 100644 --- a/src/core/transforms/qarmature_p.h +++ b/src/core/transforms/qarmature_p.h @@ -60,7 +60,7 @@ namespace Qt3DCore { class QAbstractSkeleton; -class QArmaturePrivate : public Qt3DCore::QComponentPrivate +class Q_3DCORE_PRIVATE_EXPORT QArmaturePrivate : public Qt3DCore::QComponentPrivate { public: QArmaturePrivate(); diff --git a/src/core/transforms/qjoint.cpp b/src/core/transforms/qjoint.cpp index 553fbd654..408d42f6d 100644 --- a/src/core/transforms/qjoint.cpp +++ b/src/core/transforms/qjoint.cpp @@ -41,9 +41,6 @@ #include "qjoint_p.h" #include <Qt3DCore/qnodecreatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -353,7 +350,7 @@ void QJoint::addChildJoint(QJoint *joint) d->registerDestructionHelper(joint, &QJoint::removeChildJoint, d->m_childJoints); if (d->m_changeArbiter != nullptr) - d->update(); + d->updateNode(joint, "childJoint", PropertyValueAdded); } } @@ -365,9 +362,8 @@ void QJoint::removeChildJoint(QJoint *joint) { Q_D(QJoint); if (d->m_childJoints.contains(joint)) { - if (d->m_changeArbiter != nullptr) - d->update(); + d->updateNode(joint, "childJoint", PropertyValueRemoved); d->m_childJoints.removeOne(joint); diff --git a/src/core/transforms/qjoint_p.h b/src/core/transforms/qjoint_p.h index 82439d55a..cb0bfe847 100644 --- a/src/core/transforms/qjoint_p.h +++ b/src/core/transforms/qjoint_p.h @@ -60,7 +60,7 @@ namespace Qt3DCore { class QJoint; -class QJointPrivate : public QNodePrivate +class Q_3DCORE_PRIVATE_EXPORT QJointPrivate : public QNodePrivate { public: QJointPrivate(); diff --git a/src/core/transforms/qskeleton_p.h b/src/core/transforms/qskeleton_p.h index c8b6554f9..2ce5fce07 100644 --- a/src/core/transforms/qskeleton_p.h +++ b/src/core/transforms/qskeleton_p.h @@ -60,7 +60,7 @@ namespace Qt3DCore { class QJoint; -class QSkeletonPrivate : public QAbstractSkeletonPrivate +class Q_3DCORE_PRIVATE_EXPORT QSkeletonPrivate : public QAbstractSkeletonPrivate { public: QSkeletonPrivate(); diff --git a/src/core/transforms/qskeletonloader_p.h b/src/core/transforms/qskeletonloader_p.h index ab0babe00..5c415745b 100644 --- a/src/core/transforms/qskeletonloader_p.h +++ b/src/core/transforms/qskeletonloader_p.h @@ -64,7 +64,7 @@ namespace Qt3DCore { class QJoint; -class QSkeletonLoaderPrivate : public QAbstractSkeletonPrivate +class Q_3DCORE_PRIVATE_EXPORT QSkeletonLoaderPrivate : public QAbstractSkeletonPrivate { public: QSkeletonLoaderPrivate(); diff --git a/src/core/transforms/qtransform_p.h b/src/core/transforms/qtransform_p.h index 028a9aba7..56053309e 100644 --- a/src/core/transforms/qtransform_p.h +++ b/src/core/transforms/qtransform_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { -class QTransformPrivate : public QComponentPrivate +class Q_3DCORE_PRIVATE_EXPORT QTransformPrivate : public QComponentPrivate { Q_DECLARE_PUBLIC(QTransform) diff --git a/src/extras/defaults/qforwardrenderer.cpp b/src/extras/defaults/qforwardrenderer.cpp index dd3c872cc..f1306e787 100644 --- a/src/extras/defaults/qforwardrenderer.cpp +++ b/src/extras/defaults/qforwardrenderer.cpp @@ -139,7 +139,7 @@ QForwardRenderer::QForwardRenderer(QNode *parent) { Q_D(QForwardRenderer); QObject::connect(d->m_clearBuffer, &QClearBuffers::clearColorChanged, this, &QForwardRenderer::clearColorChanged); - QObject::connect(d->m_clearBuffer, &QClearBuffers::buffersChanged, this, &QForwardRenderer::clearBuffersChanged); + QObject::connect(d->m_clearBuffer, &QClearBuffers::buffersChanged, this, &QForwardRenderer::buffersToClearChanged); QObject::connect(d->m_viewport, &QViewport::normalizedRectChanged, this, &QForwardRenderer::viewportRectChanged); QObject::connect(d->m_cameraSelector, &QCameraSelector::cameraChanged, this, &QForwardRenderer::cameraChanged); QObject::connect(d->m_surfaceSelector, &QRenderSurfaceSelector::surfaceChanged, this, &QForwardRenderer::surfaceChanged); @@ -165,7 +165,7 @@ void QForwardRenderer::setClearColor(const QColor &clearColor) d->m_clearBuffer->setClearColor(clearColor); } -void QForwardRenderer::setClearBuffers(QClearBuffers::BufferType buffers) +void QForwardRenderer::setBuffersToClear(QClearBuffers::BufferType buffers) { Q_D(QForwardRenderer); d->m_clearBuffer->setBuffers(buffers); @@ -236,18 +236,18 @@ QColor QForwardRenderer::clearColor() const } /*! - \qmlproperty color ForwardRenderer::clearBuffers + \qmlproperty color ForwardRenderer::buffersToClear Holds the current buffers to be cleared. Default value is ColorDepthBuffer \since 5.14 */ /*! - \property QForwardRenderer::clearBuffers + \property QForwardRenderer::buffersToClear Holds the current buffers to be cleared. Default value is ColorDepthBuffer \since 5.14 */ -QClearBuffers::BufferType QForwardRenderer::clearBuffers() const +QClearBuffers::BufferType QForwardRenderer::buffersToClear() const { Q_D(const QForwardRenderer); return d->m_clearBuffer->buffers(); diff --git a/src/extras/defaults/qforwardrenderer.h b/src/extras/defaults/qforwardrenderer.h index 0b53a094b..a34d39560 100644 --- a/src/extras/defaults/qforwardrenderer.h +++ b/src/extras/defaults/qforwardrenderer.h @@ -61,7 +61,7 @@ class Q_3DEXTRASSHARED_EXPORT QForwardRenderer : public Qt3DRender::QTechniqueFi Q_PROPERTY(QObject *window READ surface WRITE setSurface NOTIFY surfaceChanged) Q_PROPERTY(QRectF viewportRect READ viewportRect WRITE setViewportRect NOTIFY viewportRectChanged) Q_PROPERTY(QColor clearColor READ clearColor WRITE setClearColor NOTIFY clearColorChanged) - Q_PROPERTY(Qt3DRender::QClearBuffers::BufferType clearBuffers READ clearBuffers WRITE setClearBuffers NOTIFY clearBuffersChanged REVISION 14) + Q_PROPERTY(Qt3DRender::QClearBuffers::BufferType buffersToClear READ buffersToClear WRITE setBuffersToClear NOTIFY buffersToClearChanged REVISION 14) Q_PROPERTY(Qt3DCore::QEntity *camera READ camera WRITE setCamera NOTIFY cameraChanged) Q_PROPERTY(QSize externalRenderTargetSize READ externalRenderTargetSize WRITE setExternalRenderTargetSize NOTIFY externalRenderTargetSizeChanged) Q_PROPERTY(bool frustumCulling READ isFrustumCullingEnabled WRITE setFrustumCullingEnabled NOTIFY frustumCullingEnabledChanged) @@ -72,7 +72,7 @@ public: QRectF viewportRect() const; QColor clearColor() const; - Qt3DRender::QClearBuffers::BufferType clearBuffers() const; + Qt3DRender::QClearBuffers::BufferType buffersToClear() const; Qt3DCore::QEntity *camera() const; QObject *surface() const; QSize externalRenderTargetSize() const; @@ -82,7 +82,7 @@ public: public Q_SLOTS: void setViewportRect(const QRectF &viewportRect); void setClearColor(const QColor &clearColor); - void setClearBuffers(Qt3DRender::QClearBuffers::BufferType); + void setBuffersToClear(Qt3DRender::QClearBuffers::BufferType); void setCamera(Qt3DCore::QEntity *camera); void setSurface(QObject * surface); void setExternalRenderTargetSize(const QSize &size); @@ -92,7 +92,7 @@ public Q_SLOTS: Q_SIGNALS: void viewportRectChanged(const QRectF &viewportRect); void clearColorChanged(const QColor &clearColor); - void clearBuffersChanged(Qt3DRender::QClearBuffers::BufferType); + void buffersToClearChanged(Qt3DRender::QClearBuffers::BufferType); void cameraChanged(Qt3DCore::QEntity *camera); void surfaceChanged(QObject *surface); void externalRenderTargetSizeChanged(const QSize &size); diff --git a/src/extras/text/qtextureatlas.cpp b/src/extras/text/qtextureatlas.cpp index 1f4b22d83..4ab992224 100644 --- a/src/extras/text/qtextureatlas.cpp +++ b/src/extras/text/qtextureatlas.cpp @@ -41,9 +41,6 @@ #include "qtextureatlas_p_p.h" #include <Qt3DRender/qtexturedata.h> #include <Qt3DRender/qabstracttextureimage.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/input/backend/abstractactioninput.cpp b/src/input/backend/abstractactioninput.cpp index 1d4366554..ec469204e 100644 --- a/src/input/backend/abstractactioninput.cpp +++ b/src/input/backend/abstractactioninput.cpp @@ -46,7 +46,7 @@ namespace Qt3DInput { namespace Input { AbstractActionInput::AbstractActionInput() - : Qt3DCore::QBackendNode() + : BackendNode() { } diff --git a/src/input/backend/abstractactioninput_p.h b/src/input/backend/abstractactioninput_p.h index 267d276c7..e200990e7 100644 --- a/src/input/backend/abstractactioninput_p.h +++ b/src/input/backend/abstractactioninput_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -62,7 +62,7 @@ namespace Input { class InputHandler; -class Q_AUTOTEST_EXPORT AbstractActionInput : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT AbstractActionInput : public BackendNode { public: AbstractActionInput(); diff --git a/src/input/backend/abstractaxisinput.cpp b/src/input/backend/abstractaxisinput.cpp index aae165a7e..f69c046b3 100644 --- a/src/input/backend/abstractaxisinput.cpp +++ b/src/input/backend/abstractaxisinput.cpp @@ -41,7 +41,6 @@ #include "qabstractaxisinput_p.h" #include <Qt3DInput/qabstractphysicaldevice.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/abstractaxisinput_p.h> #include <Qt3DInput/private/inputhandler_p.h> @@ -54,32 +53,24 @@ namespace Qt3DInput { namespace Input { AbstractAxisInput::AbstractAxisInput() - : Qt3DCore::QBackendNode() + : BackendNode() { } -void AbstractAxisInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractAxisInputData>>(change); - const auto &data = typedChange->data; - m_sourceDevice = data.sourceDeviceId; -} - void AbstractAxisInput::cleanup() { QBackendNode::setEnabled(false); m_sourceDevice = Qt3DCore::QNodeId(); } -void AbstractAxisInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void AbstractAxisInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("sourceDevice")) { - m_sourceDevice = propertyChange->value().value<Qt3DCore::QNodeId>(); - } - } - QBackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractAxisInput *node = qobject_cast<const QAbstractAxisInput *>(frontEnd); + if (!node) + return; + + m_sourceDevice = Qt3DCore::qIdForNode(node->sourceDevice()); } } // Input diff --git a/src/input/backend/abstractaxisinput_p.h b/src/input/backend/abstractaxisinput_p.h index 765e2214f..07a063908 100644 --- a/src/input/backend/abstractaxisinput_p.h +++ b/src/input/backend/abstractaxisinput_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -64,19 +64,18 @@ namespace Input { class InputHandler; -class Q_AUTOTEST_EXPORT AbstractAxisInput : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT AbstractAxisInput : public BackendNode { public: virtual void cleanup(); inline Qt3DCore::QNodeId sourceDevice() const { return m_sourceDevice; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; virtual float process(InputHandler *inputHandler, qint64 currentTime) = 0; protected: AbstractAxisInput(); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; Qt3DCore::QNodeId m_sourceDevice; }; diff --git a/src/input/backend/action.cpp b/src/input/backend/action.cpp index 601961dd9..a34ff164f 100644 --- a/src/input/backend/action.cpp +++ b/src/input/backend/action.cpp @@ -41,9 +41,6 @@ #include <Qt3DInput/qaction.h> #include <Qt3DInput/qabstractactioninput.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DInput/private/qaction_p.h> @@ -54,18 +51,11 @@ namespace Qt3DInput { namespace Input { Action::Action() - : Qt3DCore::QBackendNode(ReadWrite) + : BackendNode(ReadWrite) , m_actionTriggered(false) { } -void Action::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QActionData>>(change); - const auto &data = typedChange->data; - m_inputs = data.inputIds; -} - void Action::cleanup() { QBackendNode::setEnabled(false); @@ -75,38 +65,19 @@ void Action::cleanup() void Action::setActionTriggered(bool actionTriggered) { - if (isEnabled() && (actionTriggered != m_actionTriggered)) { + if (isEnabled() && (actionTriggered != m_actionTriggered)) m_actionTriggered = actionTriggered; - - // Send change to the frontend - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("active"); - e->setValue(m_actionTriggered); - notifyObservers(e); - } } -void Action::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Action::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("input")) - m_inputs.push_back(change->addedNodeId()); - break; - } - - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("input")) - m_inputs.removeOne(change->removedNodeId()); - } + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QAction *node = qobject_cast<const Qt3DInput::QAction *>(frontEnd); + if (!node) + return; - default: - break; - } - QBackendNode::sceneChangeEvent(e); + auto ids = Qt3DCore::qIdsForNodes(node->inputs()); + m_inputs = ids; } } // Input diff --git a/src/input/backend/action_p.h b/src/input/backend/action_p.h index 8fe2759fd..7036f04b9 100644 --- a/src/input/backend/action_p.h +++ b/src/input/backend/action_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -60,7 +60,7 @@ namespace Qt3DInput { namespace Input { -class Q_AUTOTEST_EXPORT Action : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT Action : public BackendNode { public: Action(); @@ -68,11 +68,9 @@ public: inline QVector<Qt3DCore::QNodeId> inputs() const { return m_inputs; } inline bool actionTriggered() const { return m_actionTriggered; } void setActionTriggered(bool actionTriggered); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_inputs; bool m_actionTriggered; }; diff --git a/src/input/backend/actioninput.cpp b/src/input/backend/actioninput.cpp index 46dc7f584..b02da0a4d 100644 --- a/src/input/backend/actioninput.cpp +++ b/src/input/backend/actioninput.cpp @@ -40,8 +40,7 @@ #include "actioninput_p.h" #include <Qt3DInput/qactioninput.h> -#include <Qt3DCore/qpropertyupdatedchange.h> - +#include <Qt3DInput/qabstractphysicaldevice.h> #include <Qt3DInput/private/qactioninput_p.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/utils_p.h> @@ -58,14 +57,6 @@ ActionInput::ActionInput() { } -void ActionInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QActionInputData>>(change); - const auto &data = typedChange->data; - m_buttons = data.buttons; - m_sourceDevice = data.sourceDeviceId; -} - void ActionInput::cleanup() { setEnabled(false); @@ -73,21 +64,20 @@ void ActionInput::cleanup() m_buttons.clear(); } -void ActionInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void ActionInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("sourceDevice")) - m_sourceDevice = propertyChange->value().value<Qt3DCore::QNodeId>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("buttons")) - m_buttons = propertyChange->value().value<QVector<int>>(); - } - AbstractActionInput::sceneChangeEvent(e); + AbstractActionInput::syncFromFrontEnd(frontEnd, firstTime); + const QActionInput *node = qobject_cast<const QActionInput *>(frontEnd); + if (!node) + return; + + m_sourceDevice = Qt3DCore::qIdForNode(node->sourceDevice()); + m_buttons = node->buttons(); } bool ActionInput::process(InputHandler *inputHandler, qint64 currentTime) { - Q_UNUSED(currentTime); + Q_UNUSED(currentTime) if (!isEnabled()) return false; diff --git a/src/input/backend/actioninput_p.h b/src/input/backend/actioninput_p.h index 00fb0475c..eecf1d10e 100644 --- a/src/input/backend/actioninput_p.h +++ b/src/input/backend/actioninput_p.h @@ -69,13 +69,11 @@ public: inline QVector<int> buttons() const { return m_buttons; } inline Qt3DCore::QNodeId sourceDevice() const { return m_sourceDevice; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; bool process(InputHandler *inputHandler, qint64 currentTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<int> m_buttons; Qt3DCore::QNodeId m_sourceDevice; }; diff --git a/src/input/backend/analogaxisinput.cpp b/src/input/backend/analogaxisinput.cpp index 4a801baec..9dece6b9b 100644 --- a/src/input/backend/analogaxisinput.cpp +++ b/src/input/backend/analogaxisinput.cpp @@ -41,7 +41,6 @@ #include <Qt3DInput/qanalogaxisinput.h> #include <Qt3DInput/qabstractphysicaldevice.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h> #include <Qt3DInput/private/qanalogaxisinput_p.h> @@ -59,29 +58,20 @@ AnalogAxisInput::AnalogAxisInput() { } -void AnalogAxisInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAnalogAxisInputData>>(change); - const auto &data = typedChange->data; - m_axis = data.axis; - AbstractAxisInput::initializeFromPeer(change); -} - void AnalogAxisInput::cleanup() { m_axis = 0; AbstractAxisInput::cleanup(); } -void AnalogAxisInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void AnalogAxisInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("axis")) { - m_axis = propertyChange->value().toInt(); - } - } - AbstractAxisInput::sceneChangeEvent(e); + AbstractAxisInput::syncFromFrontEnd(frontEnd, firstTime); + const QAnalogAxisInput *node = qobject_cast<const QAnalogAxisInput *>(frontEnd); + if (!node) + return; + + m_axis = node->axis(); } float AnalogAxisInput::process(InputHandler *inputHandler, qint64 currentTime) diff --git a/src/input/backend/analogaxisinput_p.h b/src/input/backend/analogaxisinput_p.h index cd43e7d23..f13a2a2e1 100644 --- a/src/input/backend/analogaxisinput_p.h +++ b/src/input/backend/analogaxisinput_p.h @@ -66,13 +66,11 @@ public: void cleanup() final; inline int axis() const { return m_axis; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final; float process(InputHandler *inputHandler, qint64 currentTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - int m_axis; }; diff --git a/src/input/backend/assignkeyboardfocusjob.cpp b/src/input/backend/assignkeyboardfocusjob.cpp index 385074812..5fe329004 100644 --- a/src/input/backend/assignkeyboardfocusjob.cpp +++ b/src/input/backend/assignkeyboardfocusjob.cpp @@ -38,7 +38,8 @@ ****************************************************************************/ #include "assignkeyboardfocusjob_p.h" - +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DInput/qkeyboardhandler.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/job_common_p.h> @@ -50,12 +51,23 @@ QT_BEGIN_NAMESPACE namespace Qt3DInput { namespace Input { +class AssignKeyboardFocusJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + AssignKeyboardFocusJobPrivate() { } + ~AssignKeyboardFocusJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<Qt3DCore::QNodeId, bool>> updates; +}; + AssignKeyboardFocusJob::AssignKeyboardFocusJob(Qt3DCore::QNodeId keyboardDevice) - : QAspectJob() + : QAspectJob(*new AssignKeyboardFocusJobPrivate()) , m_inputHandler(nullptr) , m_keyboardDevice(keyboardDevice) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::AssignKeyboardFocus, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::AssignKeyboardFocus, 0) } void AssignKeyboardFocusJob::setInputHandler(InputHandler *handler) @@ -65,20 +77,40 @@ void AssignKeyboardFocusJob::setInputHandler(InputHandler *handler) void AssignKeyboardFocusJob::run() { + Q_D(AssignKeyboardFocusJob); + KeyboardDevice *keyboardDevice = m_inputHandler->keyboardDeviceManager()->lookupResource(m_keyboardDevice); const auto handles = m_inputHandler->keyboardInputManager()->activeHandles(); + d->updates.reserve(handles.size()); + for (const HKeyboardHandler &handle : handles) { KeyboardHandler *input = m_inputHandler->keyboardInputManager()->data(handle); Q_ASSERT(input); if (input->keyboardDevice() == m_keyboardDevice) { bool hasFocus = input->peerId() == keyboardDevice->lastKeyboardInputRequester(); input->setFocus(hasFocus); + d->updates.push_back({input->peerId(), hasFocus}); if (hasFocus) keyboardDevice->setCurrentFocusItem(input->peerId()); } } } +void AssignKeyboardFocusJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (const auto &data: qAsConst(updates)) { + QKeyboardHandler *node = qobject_cast<QKeyboardHandler *>(manager->lookupNode(data.first)); + if (!node) + continue; + + const bool b = node->blockNotifications(true); + node->setFocus(data.second); + node->blockNotifications(b); + } + + updates.clear(); +} + } // namespace Input } // namespace Qt3DInput diff --git a/src/input/backend/assignkeyboardfocusjob_p.h b/src/input/backend/assignkeyboardfocusjob_p.h index 8a74de85f..200fd72f1 100644 --- a/src/input/backend/assignkeyboardfocusjob_p.h +++ b/src/input/backend/assignkeyboardfocusjob_p.h @@ -60,6 +60,7 @@ namespace Qt3DInput { namespace Input { class InputHandler; +class AssignKeyboardFocusJobPrivate; class AssignKeyboardFocusJob : public Qt3DCore::QAspectJob { @@ -69,6 +70,8 @@ public: void run() override; private: + Q_DECLARE_PRIVATE(AssignKeyboardFocusJob) + InputHandler *m_inputHandler; const Qt3DCore::QNodeId m_keyboardDevice; }; diff --git a/src/input/backend/axis.cpp b/src/input/backend/axis.cpp index 20c05a49f..6c04d8fac 100644 --- a/src/input/backend/axis.cpp +++ b/src/input/backend/axis.cpp @@ -41,7 +41,6 @@ #include <Qt3DInput/qaxis.h> #include <Qt3DInput/qabstractaxisinput.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/qaxis_p.h> #include <algorithm> @@ -67,16 +66,8 @@ void Axis::cleanup() void Axis::setAxisValue(float axisValue) { - if (isEnabled() && (!qFuzzyCompare(axisValue, m_axisValue))) { + if (isEnabled() && (!qFuzzyCompare(axisValue, m_axisValue))) m_axisValue = axisValue; - - // Send a change to the frontend - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); // TODOSYNC replace with direct access - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("value"); - e->setValue(m_axisValue); - notifyObservers(e); - } } void Axis::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) diff --git a/src/input/backend/axisaccumulator.cpp b/src/input/backend/axisaccumulator.cpp index edc282bec..8e93c120e 100644 --- a/src/input/backend/axisaccumulator.cpp +++ b/src/input/backend/axisaccumulator.cpp @@ -39,8 +39,7 @@ #include "axisaccumulator_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> - +#include <Qt3DInput/qaxis.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/qaxisaccumulator_p.h> @@ -50,7 +49,7 @@ namespace Qt3DInput { namespace Input { AxisAccumulator::AxisAccumulator() - : Qt3DCore::QBackendNode(ReadWrite) + : BackendNode(ReadWrite) , m_sourceAxisId() , m_sourceAxisType(QAxisAccumulator::Velocity) , m_scale(1.0f) @@ -59,17 +58,6 @@ AxisAccumulator::AxisAccumulator() { } -void AxisAccumulator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAxisAccumulatorData>>(change); - const auto &data = typedChange->data; - m_sourceAxisId = data.sourceAxisId; - m_sourceAxisType = data.sourceAxisType; - m_scale = data.scale; - m_value = 0.0f; - m_velocity = 0.0f; -} - void AxisAccumulator::cleanup() { QBackendNode::setEnabled(false); @@ -81,50 +69,31 @@ void AxisAccumulator::cleanup() void AxisAccumulator::setValue(float value) { - if (isEnabled() && value != m_value) { + if (isEnabled() && value != m_value) m_value = value; - - // Send a change to the frontend - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("value"); - e->setValue(m_value); - notifyObservers(e); - } } void AxisAccumulator::setVelocity(float velocity) { - if (isEnabled() && velocity != m_velocity) { + if (isEnabled() && velocity != m_velocity) m_velocity = velocity; - - // Send a change to the frontend - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("velocity"); - e->setValue(m_velocity); - notifyObservers(e); - } } -void AxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void AxisAccumulator::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("sourceAxis")) - m_sourceAxisId = change->value().value<Qt3DCore::QNodeId>(); - else if (change->propertyName() == QByteArrayLiteral("sourceAxisType")) - m_sourceAxisType = change->value().value<QAxisAccumulator::SourceAxisType>(); - else if (change->propertyName() == QByteArrayLiteral("scale")) - m_scale = change->value().toFloat(); - break; - } + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAxisAccumulator *node = qobject_cast<const QAxisAccumulator *>(frontEnd); + if (!node) + return; - default: - break; + m_sourceAxisId = Qt3DCore::qIdForNode(node->sourceAxis()); + m_sourceAxisType = node->sourceAxisType(); + m_scale = node->scale(); + + if (firstTime) { + m_value = 0.f; + m_velocity = 0.f; } - QBackendNode::sceneChangeEvent(e); } void AxisAccumulator::stepIntegration(AxisManager *axisManager, float dt) diff --git a/src/input/backend/axisaccumulator_p.h b/src/input/backend/axisaccumulator_p.h index bb1a35812..2f5a7de63 100644 --- a/src/input/backend/axisaccumulator_p.h +++ b/src/input/backend/axisaccumulator_p.h @@ -52,6 +52,7 @@ // #include <Qt3DInput/qaxisaccumulator.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qbackendnode.h> #include <Qt3DCore/qnodeid.h> @@ -62,7 +63,7 @@ namespace Input { class AxisManager; -class Q_AUTOTEST_EXPORT AxisAccumulator : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT AxisAccumulator : public BackendNode { public: AxisAccumulator(); @@ -78,13 +79,11 @@ public: float velocity() const Q_DECL_NOTHROW { return m_velocity; } void setVelocity(float velocity); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void stepIntegration(AxisManager *axisManager, float dt); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_sourceAxisId; QAxisAccumulator::SourceAxisType m_sourceAxisType; float m_scale; diff --git a/src/input/backend/axisaccumulatorjob.cpp b/src/input/backend/axisaccumulatorjob.cpp index cda8a5e26..16a68349e 100644 --- a/src/input/backend/axisaccumulatorjob.cpp +++ b/src/input/backend/axisaccumulatorjob.cpp @@ -38,7 +38,9 @@ ****************************************************************************/ #include "axisaccumulatorjob_p.h" - +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DInput/qaxisaccumulator.h> +#include <Qt3DInput/private/qaxisaccumulator_p.h> #include <Qt3DInput/private/axisaccumulator_p.h> #include <Qt3DInput/private/job_common_p.h> #include <Qt3DInput/private/inputmanagers_p.h> @@ -48,24 +50,53 @@ QT_BEGIN_NAMESPACE namespace Qt3DInput { namespace Input { +class AxisAccumulatorJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + AxisAccumulatorJobPrivate() { } + ~AxisAccumulatorJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<AxisAccumulator *> updates; +}; + AxisAccumulatorJob::AxisAccumulatorJob(AxisAccumulatorManager *axisAccumulatormanager, AxisManager *axisManager) - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new AxisAccumulatorJobPrivate) , m_axisAccumulatorManager(axisAccumulatormanager) , m_axisManager(axisManager) , m_dt(0.0f) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::AxisAccumulatorIntegration, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::AxisAccumulatorIntegration, 0) } void AxisAccumulatorJob::run() { + Q_D(AxisAccumulatorJob); // Iterate over the accumulators and ask each to step the integrations const auto activeHandles = m_axisAccumulatorManager->activeHandles(); + d->updates.reserve(activeHandles.size()); + for (const auto &accumulatorHandle : activeHandles) { AxisAccumulator *accumulator = m_axisAccumulatorManager->data(accumulatorHandle); - if (accumulator->isEnabled()) + if (accumulator->isEnabled()) { accumulator->stepIntegration(m_axisManager, m_dt); + d->updates.push_back(accumulator); + } + } +} + +void AxisAccumulatorJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (auto backend: qAsConst(updates)) { + QAxisAccumulator *node = qobject_cast<QAxisAccumulator *>(manager->lookupNode(backend->peerId())); + if (!node) + continue; + + QAxisAccumulatorPrivate *dnode = static_cast<QAxisAccumulatorPrivate *>(QAxisAccumulatorPrivate::get(node)); + dnode->setValue(backend->value()); + dnode->setVelocity(backend->velocity()); } } diff --git a/src/input/backend/axisaccumulatorjob_p.h b/src/input/backend/axisaccumulatorjob_p.h index 4d38fd70f..702004dd2 100644 --- a/src/input/backend/axisaccumulatorjob_p.h +++ b/src/input/backend/axisaccumulatorjob_p.h @@ -62,6 +62,7 @@ namespace Input { class AxisAccumulatorManager; class AxisManager; +class AxisAccumulatorJobPrivate; class Q_AUTOTEST_EXPORT AxisAccumulatorJob : public Qt3DCore::QAspectJob { @@ -74,6 +75,8 @@ public: void run() override; private: + Q_DECLARE_PRIVATE(AxisAccumulatorJob) + AxisAccumulatorManager *m_axisAccumulatorManager; AxisManager *m_axisManager; float m_dt; diff --git a/src/input/backend/axissetting.cpp b/src/input/backend/axissetting.cpp index b3c81f84d..53e645c4d 100644 --- a/src/input/backend/axissetting.cpp +++ b/src/input/backend/axissetting.cpp @@ -40,7 +40,6 @@ #include "axissetting_p.h" #include <Qt3DInput/qaxissetting.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/qaxissetting_p.h> @@ -50,22 +49,13 @@ namespace Qt3DInput { namespace Input { AxisSetting::AxisSetting() - : Qt3DCore::QBackendNode() + : BackendNode() , m_deadZoneRadius(0.0f) , m_axes(0) , m_smooth(false) { } -void AxisSetting::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAxisSettingData>>(change); - const auto &data = typedChange->data; - m_deadZoneRadius = data.deadZoneRadius; - m_axes = data.axes; - m_smooth = data.smooth; -} - void AxisSetting::cleanup() { QBackendNode::setEnabled(false); @@ -74,19 +64,16 @@ void AxisSetting::cleanup() m_smooth = false; } -void AxisSetting::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void AxisSetting::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("deadZoneRadius")) { - m_deadZoneRadius = propertyChange->value().toFloat(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("axes")) { - m_axes = propertyChange->value().value<QVector<int>>(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("smooth")) { - m_smooth = propertyChange->value().toBool(); - } - } - QBackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAxisSetting *node = qobject_cast<const QAxisSetting *>(frontEnd); + if (!node) + return; + + m_deadZoneRadius = node->deadZoneRadius(); + m_axes = node->axes(); + m_smooth = node->isSmoothEnabled(); } } // namespace Input diff --git a/src/input/backend/axissetting_p.h b/src/input/backend/axissetting_p.h index 42e1010d5..7d1e6ed4c 100644 --- a/src/input/backend/axissetting_p.h +++ b/src/input/backend/axissetting_p.h @@ -51,14 +51,14 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> QT_BEGIN_NAMESPACE namespace Qt3DInput { namespace Input { -class Q_AUTOTEST_EXPORT AxisSetting : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT AxisSetting : public BackendNode { public: AxisSetting(); @@ -68,11 +68,9 @@ public: inline QVector<int> axes() const { return m_axes; } inline bool isSmoothEnabled() const { return m_smooth; } -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; float m_deadZoneRadius; QVector<int> m_axes; diff --git a/src/input/backend/buttonaxisinput.cpp b/src/input/backend/buttonaxisinput.cpp index fef8f6d41..011d7df56 100644 --- a/src/input/backend/buttonaxisinput.cpp +++ b/src/input/backend/buttonaxisinput.cpp @@ -41,7 +41,6 @@ #include <Qt3DInput/qbuttonaxisinput.h> #include <Qt3DInput/qabstractphysicaldevice.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h> #include <Qt3DInput/private/qbuttonaxisinput_p.h> @@ -63,17 +62,6 @@ ButtonAxisInput::ButtonAxisInput() { } -void ButtonAxisInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QButtonAxisInputData>>(change); - const auto &data = typedChange->data; - m_buttons = data.buttons; - m_scale = data.scale; - m_acceleration = data.acceleration; - m_deceleration = data.deceleration; - AbstractAxisInput::initializeFromPeer(change); -} - void ButtonAxisInput::cleanup() { m_scale = 0.0f; @@ -101,21 +89,17 @@ void ButtonAxisInput::updateSpeedRatio(qint64 currentTime, ButtonAxisInput::Upda m_lastUpdateTime = currentTime; } -void ButtonAxisInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void ButtonAxisInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("scale")) { - m_scale = propertyChange->value().toFloat(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("buttons")) { - m_buttons = propertyChange->value().value<QVector<int>>(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("acceleration")) { - m_acceleration = propertyChange->value().toFloat(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("deceleration")) { - m_deceleration = propertyChange->value().toFloat(); - } - } - AbstractAxisInput::sceneChangeEvent(e); + AbstractAxisInput::syncFromFrontEnd(frontEnd, firstTime); + const QButtonAxisInput *node = qobject_cast<const QButtonAxisInput *>(frontEnd); + if (!node) + return; + + m_scale = node->scale(); + m_buttons = node->buttons(); + m_acceleration = node->acceleration(); + m_deceleration = node->deceleration(); } namespace { diff --git a/src/input/backend/buttonaxisinput_p.h b/src/input/backend/buttonaxisinput_p.h index f47a9b5cc..761b9e92a 100644 --- a/src/input/backend/buttonaxisinput_p.h +++ b/src/input/backend/buttonaxisinput_p.h @@ -78,13 +78,12 @@ public: inline float speedRatio() const { return m_speedRatio; } inline qint64 lastUpdateTime() const { return m_lastUpdateTime; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final; float process(InputHandler *inputHandler, qint64 currentTime) override; private: void updateSpeedRatio(qint64 currentTime, UpdateType type); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; QVector<int> m_buttons; float m_scale; diff --git a/src/input/backend/genericdevicebackendnode.cpp b/src/input/backend/genericdevicebackendnode.cpp index 40202b4a5..d56a674fc 100644 --- a/src/input/backend/genericdevicebackendnode.cpp +++ b/src/input/backend/genericdevicebackendnode.cpp @@ -40,10 +40,11 @@ #include "genericdevicebackendnode_p.h" #include <Qt3DInput/qabstractphysicaldevice.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> +#include <Qt3DInput/private/qgenericinputdevice_p.h> +#include <Qt3DInput/private/qabstractphysicaldevice_p.h> QT_BEGIN_NAMESPACE @@ -60,19 +61,24 @@ GenericDeviceBackendNode::~GenericDeviceBackendNode() { } -void GenericDeviceBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void GenericDeviceBackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("axisEvent")) { - QPair<int, qreal> val = propertyChange->value().value<QPair<int, qreal>>(); - const QMutexLocker lock(&m_mutex); + QAbstractPhysicalDeviceBackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QGenericInputDevice *node = qobject_cast<const Qt3DInput::QGenericInputDevice *>(frontEnd); + if (!node) + return; + + auto *d = static_cast<Qt3DInput::QAbstractPhysicalDevicePrivate *>( Qt3DCore::QNodePrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd)) ); + + { + const QMutexLocker lock(&m_mutex); + for (const auto &val: qAsConst(d->m_pendingAxisEvents)) m_axesValues[val.first] = val.second; - } else if (propertyChange->propertyName() == QByteArrayLiteral("buttonEvent")) { - QPair<int, qreal> val = propertyChange->value().value<QPair<int, qreal>>(); - const QMutexLocker lock(&m_mutex); + for (const auto &val: qAsConst(d->m_pendingButtonsEvents)) m_buttonsValues[val.first] = val.second; - } + + d->m_pendingAxisEvents.clear(); + d->m_pendingButtonsEvents.clear(); } } diff --git a/src/input/backend/genericdevicebackendnode_p.h b/src/input/backend/genericdevicebackendnode_p.h index c3ee1e467..3ae712115 100644 --- a/src/input/backend/genericdevicebackendnode_p.h +++ b/src/input/backend/genericdevicebackendnode_p.h @@ -73,7 +73,7 @@ public: void updateEvents(); // QAbstractPhysicalDeviceBackendNode interface - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void cleanup() override; float axisValue(int axisIdentifier) const override; bool isButtonPressed(int buttonIdentifier) const override; diff --git a/src/input/backend/inputchord.cpp b/src/input/backend/inputchord.cpp index 731fd91e3..fa8112e6d 100644 --- a/src/input/backend/inputchord.cpp +++ b/src/input/backend/inputchord.cpp @@ -40,9 +40,6 @@ #include "inputchord_p.h" #include <Qt3DInput/qinputchord.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DInput/private/qinputchord_p.h> #include <Qt3DInput/private/inputhandler_p.h> @@ -62,15 +59,6 @@ InputChord::InputChord() { } -void InputChord::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputChordData>>(change); - const QInputChordData &data = typedChange->data; - m_chords = data.chordIds; - m_timeout = milliToNano(data.timeout); - m_inputsToTrigger = m_chords; -} - void InputChord::cleanup() { setEnabled(false); @@ -102,38 +90,16 @@ void InputChord::setStartTime(qint64 time) m_startTime = time; } -void InputChord::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void InputChord::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("timeout")) - m_timeout = milliToNano(change->value().toInt()); - break; - } + AbstractActionInput::syncFromFrontEnd(frontEnd, firstTime); + const QInputChord *node = qobject_cast<const QInputChord *>(frontEnd); + if (!node) + return; - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("chord")) { - m_chords.push_back(change->addedNodeId()); - m_inputsToTrigger.push_back(change->addedNodeId()); - } - break; - } - - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("chord")) { - m_chords.removeOne(change->removedNodeId()); - m_inputsToTrigger.removeOne(change->removedNodeId()); - } - break; - } - - default: - break; - } - AbstractActionInput::sceneChangeEvent(e); + m_timeout = milliToNano(node->timeout()); + m_chords = Qt3DCore::qIdsForNodes(node->chords()); + m_inputsToTrigger = m_chords; } bool InputChord::process(InputHandler *inputHandler, qint64 currentTime) diff --git a/src/input/backend/inputchord_p.h b/src/input/backend/inputchord_p.h index efad2c4af..0a654aa87 100644 --- a/src/input/backend/inputchord_p.h +++ b/src/input/backend/inputchord_p.h @@ -73,13 +73,11 @@ public: void setStartTime(qint64 time); void reset(); bool actionTriggered(Qt3DCore::QNodeId input); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; bool process(InputHandler *inputHandler, qint64 currentTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_chords; QVector<Qt3DCore::QNodeId> m_inputsToTrigger; qint64 m_timeout; diff --git a/src/input/backend/inputsequence.cpp b/src/input/backend/inputsequence.cpp index e45fae364..690a7f0d1 100644 --- a/src/input/backend/inputsequence.cpp +++ b/src/input/backend/inputsequence.cpp @@ -41,9 +41,6 @@ #include <Qt3DInput/qabstractphysicaldevice.h> #include <Qt3DInput/qinputsequence.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtCore/QDateTime> #include <Qt3DInput/private/inputhandler_p.h> @@ -66,16 +63,6 @@ InputSequence::InputSequence() { } -void InputSequence::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputSequenceData>>(change); - const QInputSequenceData &data = typedChange->data; - m_sequences = data.sequenceIds; - m_timeout = milliToNano(data.timeout); - m_buttonInterval = milliToNano(data.buttonInterval); - m_inputsToTrigger = m_sequences; -} - void InputSequence::cleanup() { setEnabled(false); @@ -127,41 +114,17 @@ bool InputSequence::actionTriggered(Qt3DCore::QNodeId input, const qint64 curren return false; } -void InputSequence::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void InputSequence::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("timeout")) { - m_timeout = milliToNano(change->value().toInt()); - } else if (change->propertyName() == QByteArrayLiteral("buttonInterval")) { - m_buttonInterval = milliToNano(change->value().toInt()); - } - break; - } - - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("sequence")) { - m_sequences.push_back(change->addedNodeId()); - m_inputsToTrigger.push_back(change->addedNodeId()); - } - break; - } - - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("sequence")) { - m_sequences.removeOne(change->removedNodeId()); - m_inputsToTrigger.removeOne(change->removedNodeId()); - } - break; - } - - default: - break; - } - AbstractActionInput::sceneChangeEvent(e); + AbstractActionInput::syncFromFrontEnd(frontEnd, firstTime); + const QInputSequence *node = qobject_cast<const QInputSequence *>(frontEnd); + if (!node) + return; + + m_timeout = milliToNano(node->timeout()); + m_buttonInterval = milliToNano(node->buttonInterval()); + m_sequences = Qt3DCore::qIdsForNodes(node->sequences()); + m_inputsToTrigger = m_sequences; } bool InputSequence::process(InputHandler *inputHandler, qint64 currentTime) diff --git a/src/input/backend/inputsequence_p.h b/src/input/backend/inputsequence_p.h index 395021035..53407bd1d 100644 --- a/src/input/backend/inputsequence_p.h +++ b/src/input/backend/inputsequence_p.h @@ -75,13 +75,11 @@ public: bool sequenceTriggered() const; void reset(); bool actionTriggered(Qt3DCore::QNodeId input, const qint64 currentTime); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; bool process(InputHandler *inputHandler, qint64 currentTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_sequences; QVector<Qt3DCore::QNodeId> m_inputsToTrigger; qint64 m_timeout; diff --git a/src/input/backend/inputsettings.cpp b/src/input/backend/inputsettings.cpp index b695ed600..4fdd61a1b 100644 --- a/src/input/backend/inputsettings.cpp +++ b/src/input/backend/inputsettings.cpp @@ -40,7 +40,6 @@ #include "inputsettings_p.h" #include <Qt3DInput/qinputsettings.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/qinputsettings_p.h> @@ -52,26 +51,19 @@ namespace Qt3DInput { namespace Input { InputSettings::InputSettings() - : QBackendNode(QBackendNode::ReadOnly) + : BackendNode(QBackendNode::ReadOnly) , m_eventSource(nullptr) { } -void InputSettings::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void InputSettings::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputSettingsData>>(change); - const auto &data = typedChange->data; - m_eventSource = data.eventSource; -} + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QInputSettings *node = qobject_cast<const QInputSettings *>(frontEnd); + if (!node) + return; -void InputSettings::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("eventSource")) - m_eventSource = propertyChange->value().value<QObject *>(); - } - QBackendNode::sceneChangeEvent(e); + m_eventSource = node->eventSource(); } InputSettingsFunctor::InputSettingsFunctor(InputHandler *handler) diff --git a/src/input/backend/inputsettings_p.h b/src/input/backend/inputsettings_p.h index 87cb4debf..33f56cc0b 100644 --- a/src/input/backend/inputsettings_p.h +++ b/src/input/backend/inputsettings_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <QtCore/QPointer> QT_BEGIN_NAMESPACE @@ -62,18 +62,15 @@ namespace Input { class InputHandler; -class InputSettings : public Qt3DCore::QBackendNode +class InputSettings : public BackendNode { public: InputSettings(); inline QObject *eventSource() const { return m_eventSource; } -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QPointer<QObject> m_eventSource; }; diff --git a/src/input/backend/keyboarddevice.cpp b/src/input/backend/keyboarddevice.cpp index 33578bdad..0e45d1c84 100644 --- a/src/input/backend/keyboarddevice.cpp +++ b/src/input/backend/keyboarddevice.cpp @@ -427,11 +427,6 @@ void KeyboardDevice::updateKeyEvents(const QList<QT_PREPEND_NAMESPACE(QKeyEvent) setButtonValue(e.key(), e.type() == QT_PREPEND_NAMESPACE(QKeyEvent)::KeyPress ? true : false); } - -void KeyboardDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) -{ -} - KeyboardDeviceFunctor::KeyboardDeviceFunctor(QInputAspect *inputaspect, InputHandler *handler) : m_inputAspect(inputaspect) , m_handler(handler) diff --git a/src/input/backend/keyboarddevice_p.h b/src/input/backend/keyboarddevice_p.h index 781e8ead5..2df5eb64d 100644 --- a/src/input/backend/keyboarddevice_p.h +++ b/src/input/backend/keyboarddevice_p.h @@ -86,9 +86,6 @@ public: inline Qt3DCore::QNodeId currentFocusItem() const { return m_currentFocusItem; } inline Qt3DCore::QNodeId lastKeyboardInputRequester() const { return m_lastRequester; } -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) override; - private: void setButtonValue(int key, bool value); diff --git a/src/input/backend/keyboardhandler.cpp b/src/input/backend/keyboardhandler.cpp index ae1e6d03c..66af527c9 100644 --- a/src/input/backend/keyboardhandler.cpp +++ b/src/input/backend/keyboardhandler.cpp @@ -56,22 +56,12 @@ namespace Qt3DInput { namespace Input { KeyboardHandler::KeyboardHandler() - : QBackendNode(QBackendNode::ReadWrite) + : BackendNode(QBackendNode::ReadWrite) , m_inputHandler(nullptr) , m_focus(false) { } -void KeyboardHandler::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QKeyboardHandlerData>>(change); - const auto &data = typedChange->data; - setSourcerDevice(data.keyboardDeviceId); - m_focus = false; - if (data.focus) - requestFocus(); -} - Qt3DCore::QNodeId KeyboardHandler::keyboardDevice() const { return m_keyboardDevice; @@ -86,43 +76,32 @@ void KeyboardHandler::setInputHandler(InputHandler *handler) // Sends a change notification so that the frontend can update itself void KeyboardHandler::setFocus(bool focus) { - if (focus != m_focus) { + if (focus != m_focus) m_focus = focus; - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("focus"); - e->setValue(m_focus); - notifyObservers(e); - } } -void KeyboardHandler::keyEvent(const QKeyEventPtr &event) +void KeyboardHandler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("event"); - e->setValue(QVariant::fromValue(event)); - notifyObservers(e); -} + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QKeyboardHandler *node = qobject_cast<const Qt3DInput::QKeyboardHandler *>(frontEnd); + if (!node) + return; + + if (firstTime) + m_focus = false; -void KeyboardHandler::sceneChangeEvent(const QSceneChangePtr &e) -{ bool focusRequest = false; - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("sourceDevice")) { - const QNodeId newId = propertyChange->value().value<QNodeId>(); - if (m_keyboardDevice != newId) { - setSourcerDevice(newId); - focusRequest = m_focus; - } - } else if (propertyChange->propertyName() == QByteArrayLiteral("focus")) { - focusRequest = propertyChange->value().toBool(); - } + auto id = Qt3DCore::qIdForNode(node->sourceDevice()); + if (m_keyboardDevice != id) { + setSourcerDevice(id); + focusRequest = m_focus; } + + if (m_focus != node->focus()) + focusRequest = node->focus(); + if (focusRequest) requestFocus(); - QBackendNode::sceneChangeEvent(e); } void KeyboardHandler::requestFocus() diff --git a/src/input/backend/keyboardhandler_p.h b/src/input/backend/keyboardhandler_p.h index 317c33792..a5c13efbf 100644 --- a/src/input/backend/keyboardhandler_p.h +++ b/src/input/backend/keyboardhandler_p.h @@ -52,7 +52,7 @@ // #include <Qt3DInput/qkeyevent.h> -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -63,7 +63,7 @@ namespace Input { class InputHandler; -class Q_AUTOTEST_EXPORT KeyboardHandler : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT KeyboardHandler : public BackendNode { public: KeyboardHandler(); @@ -71,19 +71,16 @@ public: Qt3DCore::QNodeId keyboardDevice() const; void setInputHandler(InputHandler *handler); void setFocus(bool focus); - void keyEvent(const QKeyEventPtr &event); inline bool focus() const { return m_focus; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; protected: void requestFocus(); void setSourcerDevice(Qt3DCore::QNodeId device); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - InputHandler *m_inputHandler; Qt3DCore::QNodeId m_keyboardDevice; bool m_focus; diff --git a/src/input/backend/keyeventdispatcherjob.cpp b/src/input/backend/keyeventdispatcherjob.cpp index 6201453fc..26a35e885 100644 --- a/src/input/backend/keyeventdispatcherjob.cpp +++ b/src/input/backend/keyeventdispatcherjob.cpp @@ -38,7 +38,9 @@ ****************************************************************************/ #include "keyeventdispatcherjob_p.h" - +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DInput/qkeyboardhandler.h> +#include <Qt3DInput/private/qkeyboardhandler_p.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/job_common_p.h> @@ -49,13 +51,26 @@ QT_BEGIN_NAMESPACE namespace Qt3DInput { namespace Input { +class KeyEventDispatcherJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + KeyEventDispatcherJobPrivate() { } + ~KeyEventDispatcherJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Qt3DCore::QNodeId m_keyboardHandler; + QList<QT_PREPEND_NAMESPACE(QKeyEvent)> m_events; +}; + KeyEventDispatcherJob::KeyEventDispatcherJob(Qt3DCore::QNodeId input, const QList<QT_PREPEND_NAMESPACE(QKeyEvent)> &events) - : QAspectJob() + : QAspectJob(*new KeyEventDispatcherJobPrivate) , m_inputHandler(nullptr) - , m_keyboardHandler(input) - , m_events(events) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::KeyEventDispatcher, 0); + Q_D(KeyEventDispatcherJob); + d->m_keyboardHandler = input; + d->m_events = events; + SET_JOB_RUN_STAT_TYPE(this, JobTypes::KeyEventDispatcher, 0) } void KeyEventDispatcherJob::setInputHandler(InputHandler *handler) @@ -65,12 +80,22 @@ void KeyEventDispatcherJob::setInputHandler(InputHandler *handler) void KeyEventDispatcherJob::run() { - KeyboardHandler *input = m_inputHandler->keyboardInputManager()->lookupResource(m_keyboardHandler); - if (input) - for (const QT_PREPEND_NAMESPACE(QKeyEvent) &e : qAsConst(m_events)) { - // Send events to frontend - input->keyEvent(QKeyEventPtr::create(e)); - } + // NOP +} + +void KeyEventDispatcherJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + QKeyboardHandler *node = qobject_cast<QKeyboardHandler *>(manager->lookupNode(m_keyboardHandler)); + if (!node) + return; + + QKeyboardHandlerPrivate *dnode = static_cast<QKeyboardHandlerPrivate *>(QKeyboardHandlerPrivate::get(node)); + for (const auto &e: qAsConst(m_events)) { + QKeyEvent ke(e); + dnode->keyEvent(&ke); + } + + m_events.clear(); } } // namespace Input diff --git a/src/input/backend/keyeventdispatcherjob_p.h b/src/input/backend/keyeventdispatcherjob_p.h index be2364ac9..bd0c770d4 100644 --- a/src/input/backend/keyeventdispatcherjob_p.h +++ b/src/input/backend/keyeventdispatcherjob_p.h @@ -61,6 +61,7 @@ namespace Qt3DInput { namespace Input { class InputHandler; +class KeyEventDispatcherJobPrivate; class KeyEventDispatcherJob : public Qt3DCore::QAspectJob { @@ -70,9 +71,9 @@ public: void run() override; private: + Q_DECLARE_PRIVATE(KeyEventDispatcherJob) + InputHandler *m_inputHandler; - const Qt3DCore::QNodeId m_keyboardHandler; - const QList<QT_PREPEND_NAMESPACE(QKeyEvent)> m_events; }; } // namespace Input diff --git a/src/input/backend/loadproxydevicejob.cpp b/src/input/backend/loadproxydevicejob.cpp index 2ea29b4a9..69f14beae 100644 --- a/src/input/backend/loadproxydevicejob.cpp +++ b/src/input/backend/loadproxydevicejob.cpp @@ -38,7 +38,9 @@ ****************************************************************************/ #include "loadproxydevicejob_p.h" - +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p.h> +#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/job_common_p.h> @@ -48,12 +50,22 @@ QT_BEGIN_NAMESPACE namespace Qt3DInput { namespace Input { +class LoadProxyDeviceJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + LoadProxyDeviceJobPrivate() { } + ~LoadProxyDeviceJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<Qt3DCore::QNodeId, QAbstractPhysicalDevice *>> updates; +}; + LoadProxyDeviceJob::LoadProxyDeviceJob() - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new LoadProxyDeviceJobPrivate) , m_inputHandler(nullptr) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::DeviceProxyLoading, 0); - + SET_JOB_RUN_STAT_TYPE(this, JobTypes::DeviceProxyLoading, 0) } LoadProxyDeviceJob::~LoadProxyDeviceJob() @@ -82,6 +94,9 @@ QVector<Qt3DCore::QNodeId> LoadProxyDeviceJob::proxies() const void LoadProxyDeviceJob::run() { + Q_D(LoadProxyDeviceJob); + d->updates.reserve(m_proxies.size()); + Q_ASSERT(m_inputHandler); for (const Qt3DCore::QNodeId id : qAsConst(m_proxies)) { PhysicalDeviceProxy *proxy = m_inputHandler->physicalDeviceProxyManager()->lookupResource(id); @@ -89,9 +104,27 @@ void LoadProxyDeviceJob::run() if (device != nullptr) proxy->setDevice(device); } - m_proxies.clear(); } +void LoadProxyDeviceJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (const auto &res : qAsConst(updates)) { + QAbstractPhysicalDeviceProxy *node = qobject_cast<QAbstractPhysicalDeviceProxy *>(manager->lookupNode(res.first)); + if (!node) + continue; + + auto *device = res.second; + QAbstractPhysicalDeviceProxyPrivate *dnode = static_cast<QAbstractPhysicalDeviceProxyPrivate *>(QAbstractPhysicalDeviceProxyPrivate::get(node)); + QAbstractPhysicalDevice *oldDevice = dnode->m_device; + dnode->setDevice(device); + // Delete the old device if it existed + delete oldDevice; + } + + updates.clear(); +} + + } // namespace Input } // namespace Qt3DInput diff --git a/src/input/backend/loadproxydevicejob_p.h b/src/input/backend/loadproxydevicejob_p.h index f9b343b2e..0848c8529 100644 --- a/src/input/backend/loadproxydevicejob_p.h +++ b/src/input/backend/loadproxydevicejob_p.h @@ -60,6 +60,7 @@ namespace Qt3DInput { namespace Input { class InputHandler; +class LoadProxyDeviceJobPrivate; class Q_AUTOTEST_EXPORT LoadProxyDeviceJob : public Qt3DCore::QAspectJob { @@ -75,6 +76,8 @@ public: void run() final; private: + Q_DECLARE_PRIVATE(LoadProxyDeviceJob) + InputHandler *m_inputHandler; QVector<Qt3DCore::QNodeId> m_proxies; }; diff --git a/src/input/backend/logicaldevice.cpp b/src/input/backend/logicaldevice.cpp index 5fcfb07bb..17426922f 100644 --- a/src/input/backend/logicaldevice.cpp +++ b/src/input/backend/logicaldevice.cpp @@ -42,9 +42,6 @@ #include <Qt3DInput/qaction.h> #include <Qt3DInput/qaxis.h> #include <Qt3DInput/qlogicaldevice.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/qlogicaldevice_p.h> @@ -56,18 +53,10 @@ namespace Qt3DInput { namespace Input { LogicalDevice::LogicalDevice() - : QBackendNode() + : BackendNode() { } -void LogicalDevice::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLogicalDeviceData>>(change); - const auto &data = typedChange->data; - m_actions = data.actionIds; - m_axes = data.axisIds; -} - void LogicalDevice::cleanup() { QBackendNode::setEnabled(false); @@ -75,31 +64,15 @@ void LogicalDevice::cleanup() m_axes.clear(); } -void LogicalDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void LogicalDevice::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("axis")) - m_axes.push_back(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("action")) - m_actions.push_back(change->addedNodeId()); - break; - } - - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("axis")) - m_axes.removeOne(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("action")) - m_actions.removeOne(change->removedNodeId()); - break; - } - - default: - break; - } - QBackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QLogicalDevice *node = qobject_cast<const QLogicalDevice *>(frontEnd); + if (!node) + return; + + m_actions = Qt3DCore::qIdsForNodes(node->actions()); + m_axes = Qt3DCore::qIdsForNodes(node->axes()); } LogicalDeviceNodeFunctor::LogicalDeviceNodeFunctor(LogicalDeviceManager *manager) diff --git a/src/input/backend/logicaldevice_p.h b/src/input/backend/logicaldevice_p.h index 138a54777..292f2a5c3 100644 --- a/src/input/backend/logicaldevice_p.h +++ b/src/input/backend/logicaldevice_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -62,7 +62,7 @@ namespace Input { class LogicalDeviceManager; -class Q_AUTOTEST_EXPORT LogicalDevice : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT LogicalDevice : public BackendNode { public: LogicalDevice(); @@ -71,11 +71,9 @@ public: inline QVector<Qt3DCore::QNodeId> axes() const { return m_axes; } inline QVector<Qt3DCore::QNodeId> actions() const { return m_actions; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_axes; QVector<Qt3DCore::QNodeId> m_actions; }; diff --git a/src/input/backend/mousedevice.cpp b/src/input/backend/mousedevice.cpp index e285783b7..47045a1a1 100644 --- a/src/input/backend/mousedevice.cpp +++ b/src/input/backend/mousedevice.cpp @@ -42,7 +42,6 @@ #include <Qt3DInput/qmousedevice.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qnode.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/inputhandler_p.h> @@ -65,14 +64,6 @@ MouseDevice::~MouseDevice() { } -void MouseDevice::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMouseDeviceData>>(change); - const auto &data = typedChange->data; - m_sensitivity = data.sensitivity; - QAbstractPhysicalDeviceBackendNode::initializeFromPeer(change); -} - void MouseDevice::setInputHandler(InputHandler *handler) { m_inputHandler = handler; @@ -173,13 +164,14 @@ void MouseDevice::updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent } } -void MouseDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void MouseDevice::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("sensitivity")) - m_sensitivity = propertyChange->value().toFloat(); - } + QAbstractPhysicalDeviceBackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QMouseDevice *node = qobject_cast<const Qt3DInput::QMouseDevice *>(frontEnd); + if (!node) + return; + + m_sensitivity = node->sensitivity(); } MouseDeviceFunctor::MouseDeviceFunctor(QInputAspect *inputAspect, InputHandler *handler) diff --git a/src/input/backend/mousedevice_p.h b/src/input/backend/mousedevice_p.h index d49ea2502..283eeaeaf 100644 --- a/src/input/backend/mousedevice_p.h +++ b/src/input/backend/mousedevice_p.h @@ -108,11 +108,9 @@ public: bool wasPressed() const; float sensitivity() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - InputHandler *m_inputHandler; MouseState m_mouseState; diff --git a/src/input/backend/mouseeventdispatcherjob.cpp b/src/input/backend/mouseeventdispatcherjob.cpp index 4bd3e93c3..0ee6862fb 100644 --- a/src/input/backend/mouseeventdispatcherjob.cpp +++ b/src/input/backend/mouseeventdispatcherjob.cpp @@ -38,7 +38,9 @@ ****************************************************************************/ #include "mouseeventdispatcherjob_p.h" - +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DInput/qmousehandler.h> +#include <Qt3DInput/private/qmousehandler_p.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/job_common_p.h> @@ -49,21 +51,37 @@ QT_BEGIN_NAMESPACE namespace Qt3DInput { namespace Input { +class MouseEventDispatcherJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + MouseEventDispatcherJobPrivate() { } + ~MouseEventDispatcherJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Qt3DCore::QNodeId m_mouseInput; + QList<QT_PREPEND_NAMESPACE(QMouseEvent)> m_mouseEvents; +#if QT_CONFIG(wheelevent) + QList<QT_PREPEND_NAMESPACE(QWheelEvent)> m_wheelEvents; +#endif +}; + MouseEventDispatcherJob::MouseEventDispatcherJob(Qt3DCore::QNodeId input, const QList<QT_PREPEND_NAMESPACE (QMouseEvent)> &mouseEvents #if QT_CONFIG(wheelevent) , const QList<QT_PREPEND_NAMESPACE (QWheelEvent)> &wheelEvents #endif ) - : QAspectJob() + : QAspectJob(*new MouseEventDispatcherJobPrivate) , m_inputHandler(nullptr) - , m_mouseInput(input) - , m_mouseEvents(mouseEvents) +{ + Q_D(MouseEventDispatcherJob); + d->m_mouseInput = input; + d->m_mouseEvents = mouseEvents; #if QT_CONFIG(wheelevent) - , m_wheelEvents(wheelEvents) + d->m_wheelEvents = wheelEvents; #endif -{ - SET_JOB_RUN_STAT_TYPE(this, JobTypes::MouseEventDispatcher, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::MouseEventDispatcher, 0) } void MouseEventDispatcherJob::setInputHandler(InputHandler *handler) @@ -73,16 +91,25 @@ void MouseEventDispatcherJob::setInputHandler(InputHandler *handler) void MouseEventDispatcherJob::run() { - MouseHandler *input = m_inputHandler->mouseInputManager()->lookupResource(m_mouseInput); - if (input) { - // Send mouse and wheel events to frontend - for (const QT_PREPEND_NAMESPACE(QMouseEvent) &e : m_mouseEvents) - input->mouseEvent(QMouseEventPtr::create(e)); + // NOP +} + +void MouseEventDispatcherJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + QMouseHandler *node = qobject_cast<QMouseHandler *>(manager->lookupNode(m_mouseInput)); + if (!node) + return; + + QMouseHandlerPrivate *dnode = static_cast<QMouseHandlerPrivate *>(QMouseHandlerPrivate::get(node)); + + for (const QT_PREPEND_NAMESPACE(QMouseEvent) &e : m_mouseEvents) + dnode->mouseEvent(QMouseEventPtr::create(e)); #if QT_CONFIG(wheelevent) - for (const QT_PREPEND_NAMESPACE(QWheelEvent) &e : m_wheelEvents) - input->wheelEvent(QWheelEventPtr::create(e)); -#endif + for (const QT_PREPEND_NAMESPACE(QWheelEvent) &e : m_wheelEvents) { + QWheelEvent we(e); + emit node->wheel(&we); } +#endif } } // namespace Input diff --git a/src/input/backend/mouseeventdispatcherjob_p.h b/src/input/backend/mouseeventdispatcherjob_p.h index 8abeccfb4..696d60da4 100644 --- a/src/input/backend/mouseeventdispatcherjob_p.h +++ b/src/input/backend/mouseeventdispatcherjob_p.h @@ -61,6 +61,7 @@ namespace Qt3DInput { namespace Input { class InputHandler; +class MouseEventDispatcherJobPrivate; class MouseEventDispatcherJob : public Qt3DCore::QAspectJob { @@ -75,12 +76,9 @@ public: void run() final; private: + Q_DECLARE_PRIVATE(MouseEventDispatcherJob) + InputHandler *m_inputHandler; - const Qt3DCore::QNodeId m_mouseInput; - const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> m_mouseEvents; -#if QT_CONFIG(wheelevent) - const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> m_wheelEvents; -#endif }; } // namespace Input diff --git a/src/input/backend/mousehandler.cpp b/src/input/backend/mousehandler.cpp index c492dcf28..46bd273d6 100644 --- a/src/input/backend/mousehandler.cpp +++ b/src/input/backend/mousehandler.cpp @@ -56,7 +56,7 @@ namespace Qt3DInput { namespace Input { MouseHandler::MouseHandler() - : QBackendNode(ReadWrite) + : BackendNode(ReadWrite) , m_inputHandler(nullptr) { } @@ -65,13 +65,6 @@ MouseHandler::~MouseHandler() { } -void MouseHandler::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMouseHandlerData>>(change); - const auto &data = typedChange->data; - setDevice(data.mouseDeviceId); -} - Qt3DCore::QNodeId MouseHandler::mouseDevice() const { return m_mouseDevice; @@ -82,38 +75,16 @@ void MouseHandler::setInputHandler(InputHandler *handler) m_inputHandler = handler; } -void MouseHandler::mouseEvent(const QMouseEventPtr &event) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("mouse"); - e->setValue(QVariant::fromValue(event)); - notifyObservers(e); -} - -#if QT_CONFIG(wheelevent) -void MouseHandler::wheelEvent(const QWheelEventPtr &event) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("wheel"); - e->setValue(QVariant::fromValue(event)); - notifyObservers(e); -} -#endif - -void MouseHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void MouseHandler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("device")) { - const QNodeId newId = propertyChange->value().value<QNodeId>(); - if (m_mouseDevice != newId) { - setDevice(newId); - } - } - } - QBackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QMouseHandler *node = qobject_cast<const Qt3DInput::QMouseHandler *>(frontEnd); + if (!node) + return; + + const auto newId = Qt3DCore::qIdForNode(node->sourceDevice()); + if (m_mouseDevice != newId) + setDevice(newId); } void MouseHandler::setDevice(Qt3DCore::QNodeId device) diff --git a/src/input/backend/mousehandler_p.h b/src/input/backend/mousehandler_p.h index 6d748c068..693c42471 100644 --- a/src/input/backend/mousehandler_p.h +++ b/src/input/backend/mousehandler_p.h @@ -52,7 +52,7 @@ // #include <Qt3DInput/qmouseevent.h> -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> QT_BEGIN_NAMESPACE @@ -61,7 +61,7 @@ namespace Input { class InputHandler; -class MouseHandler : public Qt3DCore::QBackendNode +class MouseHandler : public BackendNode { public: MouseHandler(); @@ -69,18 +69,12 @@ public: Qt3DCore::QNodeId mouseDevice() const; void setInputHandler(InputHandler *handler); - void mouseEvent(const QMouseEventPtr &event); -#if QT_CONFIG(wheelevent) - void wheelEvent(const QWheelEventPtr &event); -#endif protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setDevice(Qt3DCore::QNodeId device); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_mouseDevice; InputHandler *m_inputHandler; }; diff --git a/src/input/backend/physicaldeviceproxy.cpp b/src/input/backend/physicaldeviceproxy.cpp index 9512296b8..390b525eb 100644 --- a/src/input/backend/physicaldeviceproxy.cpp +++ b/src/input/backend/physicaldeviceproxy.cpp @@ -40,10 +40,10 @@ #include "physicaldeviceproxy_p.h" #include <Qt3DInput/qabstractphysicaldevice.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtCore/QCoreApplication> #include <Qt3DInput/private/inputmanagers_p.h> +#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p.h> #include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h> QT_BEGIN_NAMESPACE @@ -53,7 +53,7 @@ namespace Qt3DInput { namespace Input { PhysicalDeviceProxy::PhysicalDeviceProxy() - : QBackendNode(QBackendNode::ReadWrite) + : BackendNode(QBackendNode::ReadWrite) , m_manager(nullptr) { } @@ -89,12 +89,6 @@ void PhysicalDeviceProxy::setDevice(QAbstractPhysicalDevice *device) m_physicalDeviceId = device->id(); device->moveToThread(QCoreApplication::instance()->thread()); } - - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("device"); - e->setValue(QVariant::fromValue(device)); - notifyObservers(e); } Qt3DCore::QNodeId PhysicalDeviceProxy::physicalDeviceId() const @@ -102,14 +96,20 @@ Qt3DCore::QNodeId PhysicalDeviceProxy::physicalDeviceId() const return m_physicalDeviceId; } -void PhysicalDeviceProxy::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void PhysicalDeviceProxy::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractPhysicalDeviceProxyData>>(change); - const QAbstractPhysicalDeviceProxyData &data = typedChange->data; - m_deviceName = data.deviceName; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) { + const QAbstractPhysicalDeviceProxy *node = qobject_cast<const QAbstractPhysicalDeviceProxy *>(frontEnd); + if (!node) + return; - // Request to load the actual device - m_manager->addPendingProxyToLoad(peerId()); + m_deviceName = node->deviceName(); + + // Request to load the actual device + m_manager->addPendingProxyToLoad(peerId()); + } } PhysicalDeviceProxyNodeFunctor::PhysicalDeviceProxyNodeFunctor(PhysicalDeviceProxyManager *manager) diff --git a/src/input/backend/physicaldeviceproxy_p.h b/src/input/backend/physicaldeviceproxy_p.h index 9500a4adb..6dd2a54be 100644 --- a/src/input/backend/physicaldeviceproxy_p.h +++ b/src/input/backend/physicaldeviceproxy_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -64,7 +64,7 @@ namespace Input { class PhysicalDeviceProxyManager; -class Q_AUTOTEST_EXPORT PhysicalDeviceProxy : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT PhysicalDeviceProxy : public BackendNode { public: PhysicalDeviceProxy(); @@ -79,9 +79,9 @@ public: void setDevice(QAbstractPhysicalDevice *device); Qt3DCore::QNodeId physicalDeviceId() const; -private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; +private: QString m_deviceName; PhysicalDeviceProxyManager *m_manager; Qt3DCore::QNodeId m_physicalDeviceId; diff --git a/src/input/backend/qabstractphysicaldevicebackendnode.cpp b/src/input/backend/qabstractphysicaldevicebackendnode.cpp index 5006d702a..6e6899e32 100644 --- a/src/input/backend/qabstractphysicaldevicebackendnode.cpp +++ b/src/input/backend/qabstractphysicaldevicebackendnode.cpp @@ -44,11 +44,9 @@ #include <Qt3DInput/qaxissetting.h> #include <Qt3DInput/qinputaspect.h> #include <Qt3DInput/qphysicaldevicecreatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <cmath> +#include <algorithm> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> @@ -132,51 +130,14 @@ Input::AxisSetting *QAbstractPhysicalDeviceBackendNodePrivate::getAxisSetting(Qt return axisSetting; } -QVector<Input::AxisIdSetting> QAbstractPhysicalDeviceBackendNodePrivate::convertToAxisIdSettingVector(Qt3DCore::QNodeId axisSettingId) const -{ - const auto axisSetting = getAxisSetting(axisSettingId); - const auto axisIds = axisSetting->axes(); - - auto result = QVector<Input::AxisIdSetting>(); - result.reserve(axisIds.size()); - std::transform(axisIds.constBegin(), axisIds.constEnd(), - std::back_inserter(result), - [axisSettingId] (int axisId) { - return Input::AxisIdSetting{ axisId, axisSettingId }; - }); - return result; -} - -void QAbstractPhysicalDeviceBackendNodePrivate::updatePendingAxisSettings() -{ - if (m_pendingAxisSettingIds.isEmpty()) - return; - - m_axisSettings = std::accumulate( - m_pendingAxisSettingIds.constBegin(), m_pendingAxisSettingIds.constEnd(), - QVector<Input::AxisIdSetting>(), - [this] (const QVector<Input::AxisIdSetting> ¤t, Qt3DCore::QNodeId axisSettingId) { - return current + convertToAxisIdSettingVector(axisSettingId); - }); - m_pendingAxisSettingIds.clear(); -} - QAbstractPhysicalDeviceBackendNode::QAbstractPhysicalDeviceBackendNode(QBackendNode::Mode mode) - : Qt3DCore::QBackendNode(*new QAbstractPhysicalDeviceBackendNodePrivate(mode)) + : Input::BackendNode(*new QAbstractPhysicalDeviceBackendNodePrivate(mode)) { } QAbstractPhysicalDeviceBackendNode::QAbstractPhysicalDeviceBackendNode(QAbstractPhysicalDeviceBackendNodePrivate &dd) - : Qt3DCore::QBackendNode(dd) -{ -} - -void QAbstractPhysicalDeviceBackendNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) + : Input::BackendNode(dd) { - const auto deviceChange = qSharedPointerCast<QPhysicalDeviceCreatedChangeBase>(change); - Q_D(QAbstractPhysicalDeviceBackendNode); - // Store the axis setting Ids. We will update the settings themselves when needed - d->m_pendingAxisSettingIds = deviceChange->axisSettingIds(); } void QAbstractPhysicalDeviceBackendNode::cleanup() @@ -188,33 +149,34 @@ void QAbstractPhysicalDeviceBackendNode::cleanup() d->m_inputAspect = nullptr; } -void QAbstractPhysicalDeviceBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void QAbstractPhysicalDeviceBackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { Q_D(QAbstractPhysicalDeviceBackendNode); - switch (e->type()) { - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("axisSettings")) { - const auto axisSettingId = change->addedNodeId(); - Input::AxisSetting *axisSetting = d->getAxisSetting(axisSettingId); - const auto axisIds = axisSetting->axes(); - for (int axisId : axisIds) - d->addAxisSetting(axisId, axisSettingId); - } - break; - } - - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("axisSettings")) - d->removeAxisSetting(change->removedNodeId()); - break; - } + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QAbstractPhysicalDevice *node = qobject_cast<const Qt3DInput::QAbstractPhysicalDevice *>(frontEnd); + if (!node) + return; - default: - break; + auto settings = Qt3DCore::qIdsForNodes(node->axisSettings()); + std::sort(std::begin(settings), std::end(settings)); + Qt3DCore::QNodeIdVector addedSettings; + Qt3DCore::QNodeIdVector removedSettings; + std::set_difference(std::begin(settings), std::end(settings), + std::begin(d->m_currentAxisSettingIds), std::end(d->m_currentAxisSettingIds), + std::inserter(addedSettings, addedSettings.end())); + std::set_difference(std::begin(d->m_currentAxisSettingIds), std::end(d->m_currentAxisSettingIds), + std::begin(settings), std::end(settings), + std::inserter(removedSettings, removedSettings.end())); + d->m_currentAxisSettingIds = settings; + + for (const auto &axisSettingId: qAsConst(addedSettings)) { + Input::AxisSetting *axisSetting = d->getAxisSetting(axisSettingId); + const auto axisIds = axisSetting->axes(); + for (int axisId : axisIds) + d->addAxisSetting(axisId, axisSettingId); } - QBackendNode::sceneChangeEvent(e); + for (const auto &axisSettingId: qAsConst(removedSettings)) + d->removeAxisSetting(axisSettingId); } void QAbstractPhysicalDeviceBackendNode::setInputAspect(QInputAspect *aspect) @@ -232,7 +194,6 @@ QInputAspect *QAbstractPhysicalDeviceBackendNode::inputAspect() const float QAbstractPhysicalDeviceBackendNode::processedAxisValue(int axisIdentifier) { Q_D(QAbstractPhysicalDeviceBackendNode); - d->updatePendingAxisSettings(); // Find axis settings for this axis (if any) Qt3DCore::QNodeId axisSettingId; diff --git a/src/input/backend/qabstractphysicaldevicebackendnode_p.h b/src/input/backend/qabstractphysicaldevicebackendnode_p.h index e8e397883..ff46cf814 100644 --- a/src/input/backend/qabstractphysicaldevicebackendnode_p.h +++ b/src/input/backend/qabstractphysicaldevicebackendnode_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DInput/private/qt3dinput_global_p.h> @@ -66,12 +66,12 @@ namespace Qt3DInput { class QInputAspect; class QAbstractPhysicalDeviceBackendNodePrivate; -class Q_3DINPUTSHARED_PRIVATE_EXPORT QAbstractPhysicalDeviceBackendNode : public Qt3DCore::QBackendNode +class Q_3DINPUTSHARED_PRIVATE_EXPORT QAbstractPhysicalDeviceBackendNode : public Input::BackendNode { public: explicit QAbstractPhysicalDeviceBackendNode(QBackendNode::Mode mode); virtual void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setInputAspect(QInputAspect *aspect); QInputAspect *inputAspect() const; @@ -83,8 +83,6 @@ public: protected: QAbstractPhysicalDeviceBackendNode(QAbstractPhysicalDeviceBackendNodePrivate &dd); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; - Q_DECLARE_PRIVATE(QAbstractPhysicalDeviceBackendNode) }; diff --git a/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h b/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h index 4b0c47b36..9156fc64d 100644 --- a/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h +++ b/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h @@ -97,10 +97,7 @@ public: Input::AxisSetting *getAxisSetting(Qt3DCore::QNodeId axisSettingId) const; - QVector<Input::AxisIdSetting> convertToAxisIdSettingVector(Qt3DCore::QNodeId axisSettingId) const; - void updatePendingAxisSettings(); - - Qt3DCore::QNodeIdVector m_pendingAxisSettingIds; + Qt3DCore::QNodeIdVector m_currentAxisSettingIds; QVector<Input::AxisIdSetting> m_axisSettings; QVector<Input::AxisIdFilter> m_axisFilters; QInputAspect *m_inputAspect; diff --git a/src/input/backend/updateaxisactionjob.cpp b/src/input/backend/updateaxisactionjob.cpp index 03690479a..58ed36639 100644 --- a/src/input/backend/updateaxisactionjob.cpp +++ b/src/input/backend/updateaxisactionjob.cpp @@ -38,7 +38,11 @@ ****************************************************************************/ #include "updateaxisactionjob_p.h" - +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DInput/qaction.h> +#include <Qt3DInput/qaxis.h> +#include <Qt3DInput/private/qaction_p.h> +#include <Qt3DInput/private/qaxis_p.h> #include <Qt3DInput/private/inputhandler_p.h> #include <Qt3DInput/private/inputmanagers_p.h> #include <Qt3DInput/private/job_common_p.h> @@ -49,13 +53,25 @@ namespace Qt3DInput { namespace Input { +class UpdateAxisActionJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + UpdateAxisActionJobPrivate() { } + ~UpdateAxisActionJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<Qt3DCore::QNodeId, bool>> m_triggeredActions; + QVector<QPair<Qt3DCore::QNodeId, float>> m_triggeredAxis; +}; + UpdateAxisActionJob::UpdateAxisActionJob(qint64 currentTime, InputHandler *handler, HLogicalDevice handle) - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new UpdateAxisActionJobPrivate()) , m_currentTime(currentTime) , m_handler(handler) , m_handle(handle) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateAxisAction, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateAxisAction, 0) } void UpdateAxisActionJob::run() @@ -73,7 +89,10 @@ void UpdateAxisActionJob::run() void UpdateAxisActionJob::updateAction(LogicalDevice *device) { + Q_D(UpdateAxisActionJob); const auto actionIds = device->actions(); + d->m_triggeredActions.reserve(actionIds.size()); + for (const Qt3DCore::QNodeId actionId : actionIds) { bool actionTriggered = false; Action *action = m_handler->actionManager()->lookupResource(actionId); @@ -82,7 +101,10 @@ void UpdateAxisActionJob::updateAction(LogicalDevice *device) for (const Qt3DCore::QNodeId actionInputId : actionInputIds) actionTriggered |= processActionInput(actionInputId); - action->setActionTriggered(actionTriggered); + if (action->isEnabled() && (action->actionTriggered() != actionTriggered)) { + action->setActionTriggered(actionTriggered); + d->m_triggeredActions.push_back({actionId, actionTriggered}); + } } } @@ -95,7 +117,10 @@ bool UpdateAxisActionJob::processActionInput(const Qt3DCore::QNodeId actionInput void UpdateAxisActionJob::updateAxis(LogicalDevice *device) { + Q_D(UpdateAxisActionJob); const auto axisIds = device->axes(); + d->m_triggeredAxis.reserve(axisIds.size()); + for (const Qt3DCore::QNodeId axisId : axisIds) { Axis *axis = m_handler->axisManager()->lookupResource(axisId); float axisValue = 0.0f; @@ -106,7 +131,11 @@ void UpdateAxisActionJob::updateAxis(LogicalDevice *device) // Clamp the axisValue -1/1 axisValue = qMin(1.0f, qMax(axisValue, -1.0f)); - axis->setAxisValue(axisValue); + + if (axis->isEnabled() && !qFuzzyCompare(axisValue, axis->axisValue())) { + axis->setAxisValue(axisValue); + d->m_triggeredAxis.push_back({axisId, axisValue}); + } } } @@ -124,6 +153,30 @@ float UpdateAxisActionJob::processAxisInput(const Qt3DCore::QNodeId axisInputId) return 0.0f; } +void UpdateAxisActionJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (const auto &data: qAsConst(m_triggeredActions)) { + Qt3DInput::QAction *action = qobject_cast<Qt3DInput::QAction *>(manager->lookupNode(data.first)); + if (!action) + continue; + + Qt3DInput::QActionPrivate *daction = static_cast<Qt3DInput::QActionPrivate *>(Qt3DCore::QNodePrivate::get(action)); + daction->setActive(data.second); + } + + for (const auto &data: qAsConst(m_triggeredAxis)) { + Qt3DInput::QAxis *axis = qobject_cast<Qt3DInput::QAxis *>(manager->lookupNode(data.first)); + if (!axis) + continue; + + Qt3DInput::QAxisPrivate *daxis = static_cast<Qt3DInput::QAxisPrivate *>(Qt3DCore::QNodePrivate::get(axis)); + daxis->setValue(data.second); + } + + m_triggeredActions.clear(); + m_triggeredAxis.clear(); +} + } // Input } // Qt3DInput diff --git a/src/input/backend/updateaxisactionjob_p.h b/src/input/backend/updateaxisactionjob_p.h index 719923a50..040ed9775 100644 --- a/src/input/backend/updateaxisactionjob_p.h +++ b/src/input/backend/updateaxisactionjob_p.h @@ -67,6 +67,7 @@ namespace Input { class AbstractAxisInput; class ButtonAxisInput; class InputHandler; +class UpdateAxisActionJobPrivate; class UpdateAxisActionJob : public Qt3DCore::QAspectJob { @@ -75,6 +76,8 @@ public: void run() final; private: + Q_DECLARE_PRIVATE(UpdateAxisActionJob) + void updateAction(LogicalDevice *device); bool processActionInput(const Qt3DCore::QNodeId actionInputId); void updateAxis(LogicalDevice *device); diff --git a/src/input/frontend/qabstractphysicaldevice.cpp b/src/input/frontend/qabstractphysicaldevice.cpp index 120ec43a2..8cadf95a1 100644 --- a/src/input/frontend/qabstractphysicaldevice.cpp +++ b/src/input/frontend/qabstractphysicaldevice.cpp @@ -42,9 +42,6 @@ #include <Qt3DInput/qaxissetting.h> #include <Qt3DInput/qphysicaldevicecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/private/qnode_p.h> @@ -168,12 +165,7 @@ void QAbstractPhysicalDevice::addAxisSetting(QAxisSetting *axisSetting) { Q_D(QAbstractPhysicalDevice); if (axisSetting && !d->m_axisSettings.contains(axisSetting)) { - if (d->m_changeArbiter) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), axisSetting); - change->setPropertyName("axisSettings"); - d->notifyObservers(change); - } - + d->update(); d->m_axisSettings.push_back(axisSetting); } } @@ -185,12 +177,7 @@ void QAbstractPhysicalDevice::removeAxisSetting(QAxisSetting *axisSetting) { Q_D(QAbstractPhysicalDevice); if (axisSetting && d->m_axisSettings.contains(axisSetting)) { - if (d->m_changeArbiter) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), axisSetting); - change->setPropertyName("axisSettings"); - d->notifyObservers(change); - } - + d->update(); d->m_axisSettings.removeOne(axisSetting); } } @@ -209,11 +196,8 @@ QVector<QAxisSetting *> QAbstractPhysicalDevice::axisSettings() const */ void QAbstractPhysicalDevicePrivate::postAxisEvent(int axis, qreal value) { - Q_Q(QAbstractPhysicalDevice); - Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(q->id())); - change->setPropertyName("axisEvent"); - change->setValue(QVariant::fromValue(QPair<int, qreal>(axis, value))); - notifyObservers(change); + m_pendingAxisEvents.push_back({axis, value}); + update(); } /* @@ -221,11 +205,8 @@ void QAbstractPhysicalDevicePrivate::postAxisEvent(int axis, qreal value) */ void QAbstractPhysicalDevicePrivate::postButtonEvent(int button, qreal value) { - Q_Q(QAbstractPhysicalDevice); - Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(q->id())); - change->setPropertyName("buttonEvent"); - change->setValue(QVariant::fromValue(QPair<int, qreal>(button, value))); - notifyObservers(change); + m_pendingButtonsEvents.push_back({button, value}); + update(); } /*! diff --git a/src/input/frontend/qabstractphysicaldevice_p.h b/src/input/frontend/qabstractphysicaldevice_p.h index 8fa72aa02..fc8ad561c 100644 --- a/src/input/frontend/qabstractphysicaldevice_p.h +++ b/src/input/frontend/qabstractphysicaldevice_p.h @@ -76,6 +76,9 @@ public: QHash<QString, int> m_axesHash; QHash<QString, int> m_buttonsHash; + QVector<QPair<int, qreal>> m_pendingAxisEvents; + QVector<QPair<int, qreal>> m_pendingButtonsEvents; + void postAxisEvent(int axis, qreal value); void postButtonEvent(int button, qreal value); }; diff --git a/src/input/frontend/qabstractphysicaldeviceproxy.cpp b/src/input/frontend/qabstractphysicaldeviceproxy.cpp index 34b7db2a4..a7930ed76 100644 --- a/src/input/frontend/qabstractphysicaldeviceproxy.cpp +++ b/src/input/frontend/qabstractphysicaldeviceproxy.cpp @@ -160,26 +160,6 @@ int QAbstractPhysicalDeviceProxy::buttonIdentifier(const QString &name) const /*! \internal */ -void QAbstractPhysicalDeviceProxy::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QAbstractPhysicalDeviceProxy); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("device")) { - QAbstractPhysicalDevice *device = e->value().value<Qt3DInput::QAbstractPhysicalDevice *>(); - QAbstractPhysicalDevice *oldDevice = d->m_device; - setDevice(device); - // Delete the old device if it existed - if (oldDevice != nullptr) - delete oldDevice; - } - } - QAbstractPhysicalDevice::sceneChangeEvent(change); -} - -/*! - \internal - */ QAbstractPhysicalDeviceProxy::QAbstractPhysicalDeviceProxy(QAbstractPhysicalDeviceProxyPrivate &dd, Qt3DCore::QNode *parent) : QAbstractPhysicalDevice(dd, parent) { @@ -202,32 +182,45 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractPhysicalDeviceProxy::createNodeCrea /*! \internal */ -void QAbstractPhysicalDeviceProxy::setDevice(QAbstractPhysicalDevice *device) +void QAbstractPhysicalDeviceProxyPrivate::setDevice(QAbstractPhysicalDevice *device) { - Q_D(QAbstractPhysicalDeviceProxy); + Q_Q(QAbstractPhysicalDeviceProxy); // Note: technically book keeping could be optional since we are the parent // of the device. But who knows if someone plays with the object tree... // Unset bookkeeper - if (d->m_device != nullptr) { + if (m_device != nullptr) { // Note: we cannot delete the device here as we don't how if we are // called by the bookkeeper (in which case we would do a double free) // or by the sceneChangeEvent - d->unregisterDestructionHelper(d->m_device); - d->setStatus(QAbstractPhysicalDeviceProxy::NotFound); + unregisterDestructionHelper(m_device); + setStatus(QAbstractPhysicalDeviceProxy::NotFound); } // Set parent so that node is created in the backend if (device != nullptr && device->parent() == nullptr) - device->setParent(this); + device->setParent(q); - d->m_device = device; + m_device = device; // Set bookkeeper if (device != nullptr) { - d->setStatus(QAbstractPhysicalDeviceProxy::Ready); - d->registerDestructionHelper(d->m_device, &QAbstractPhysicalDeviceProxy::setDevice, d->m_device); + setStatus(QAbstractPhysicalDeviceProxy::Ready); + registerPrivateDestructionHelper(m_device, &QAbstractPhysicalDeviceProxyPrivate::resetDevice); + } +} + +void QAbstractPhysicalDeviceProxyPrivate::resetDevice(QAbstractPhysicalDevice *device) +{ + if (m_device == device) { + // Note: we cannot delete the device here as we don't how if we are + // called by the bookkeeper (in which case we would do a double free) + // or by the sceneChangeEvent + unregisterDestructionHelper(m_device); + setStatus(QAbstractPhysicalDeviceProxy::NotFound); + + m_device = nullptr; } } diff --git a/src/input/frontend/qabstractphysicaldeviceproxy_p.h b/src/input/frontend/qabstractphysicaldeviceproxy_p.h index e250b9eb9..4a7b1dfc5 100644 --- a/src/input/frontend/qabstractphysicaldeviceproxy_p.h +++ b/src/input/frontend/qabstractphysicaldeviceproxy_p.h @@ -88,13 +88,10 @@ Q_SIGNALS: void statusChanged(QAbstractPhysicalDeviceProxy::DeviceStatus status); protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - QAbstractPhysicalDeviceProxy(QAbstractPhysicalDeviceProxyPrivate &dd, Qt3DCore::QNode *parent = nullptr); Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; private: - void setDevice(QAbstractPhysicalDevice *device); Q_DECLARE_PRIVATE(QAbstractPhysicalDeviceProxy) }; diff --git a/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h b/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h index 8f8d1bea3..fc8645272 100644 --- a/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h +++ b/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h @@ -73,6 +73,8 @@ public: QAbstractPhysicalDeviceProxy::DeviceStatus m_status; QAbstractPhysicalDevice *m_device; + void setDevice(QAbstractPhysicalDevice *device); + void resetDevice(QAbstractPhysicalDevice *device); void setStatus(QAbstractPhysicalDeviceProxy::DeviceStatus status); }; diff --git a/src/input/frontend/qaction.cpp b/src/input/frontend/qaction.cpp index 1006c0cec..8eccec9e4 100644 --- a/src/input/frontend/qaction.cpp +++ b/src/input/frontend/qaction.cpp @@ -42,8 +42,6 @@ #include <Qt3DInput/qabstractactioninput.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/qnodecreatedchange.h> #include <Qt3DCore/private/qnode_p.h> @@ -121,11 +119,7 @@ void QAction::addInput(QAbstractActionInput *input) // Ensures proper bookkeeping d->registerDestructionHelper(input, &QAction::removeInput, d->m_inputs); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input); - change->setPropertyName("input"); - d->notifyObservers(change); - } + d->update(); } } @@ -137,11 +131,7 @@ void QAction::removeInput(QAbstractActionInput *input) Q_D(QAction); if (d->m_inputs.contains(input)) { - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input); - change->setPropertyName("input"); - d->notifyObservers(change); - } + d->update(); d->m_inputs.removeOne(input); @@ -159,16 +149,6 @@ QVector<QAbstractActionInput *> QAction::inputs() const return d->m_inputs; } -/*! \internal */ -void QAction::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QAction); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("active")) { - d->setActive(e->value().toBool()); - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QAction::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QActionData>::create(this); diff --git a/src/input/frontend/qaction.h b/src/input/frontend/qaction.h index f15159f68..8175bab8e 100644 --- a/src/input/frontend/qaction.h +++ b/src/input/frontend/qaction.h @@ -67,9 +67,6 @@ public: Q_SIGNALS: void activeChanged(bool isActive); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - private: Q_DECLARE_PRIVATE(QAction) Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; diff --git a/src/input/frontend/qaxis.cpp b/src/input/frontend/qaxis.cpp index 082ad4f67..7c9998776 100644 --- a/src/input/frontend/qaxis.cpp +++ b/src/input/frontend/qaxis.cpp @@ -41,8 +41,6 @@ #include <Qt3DInput/qabstractaxisinput.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/qnodecreatedchange.h> QT_BEGIN_NAMESPACE @@ -170,16 +168,6 @@ float QAxis::value() const return d->m_value; } -/*! \internal */ -void QAxis::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QAxis); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("value")) { - d->setValue(e->value().toFloat()); - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QAxis::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAxisData>::create(this); diff --git a/src/input/frontend/qaxis.h b/src/input/frontend/qaxis.h index a4f7ea7d4..1a542cf22 100644 --- a/src/input/frontend/qaxis.h +++ b/src/input/frontend/qaxis.h @@ -66,9 +66,6 @@ public: Q_SIGNALS: void valueChanged(float value); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - private: Q_DECLARE_PRIVATE(QAxis) Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; diff --git a/src/input/frontend/qaxisaccumulator.cpp b/src/input/frontend/qaxisaccumulator.cpp index 0c156194b..7e9930f66 100644 --- a/src/input/frontend/qaxisaccumulator.cpp +++ b/src/input/frontend/qaxisaccumulator.cpp @@ -291,17 +291,6 @@ void QAxisAccumulator::setScale(float scale) } /*! \internal */ -void QAxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QAxisAccumulator); - auto e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("value")) - d->setValue(e->value().toFloat()); - else if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("velocity")) - d->setVelocity(e->value().toFloat()); -} - -/*! \internal */ Qt3DCore::QNodeCreatedChangeBasePtr QAxisAccumulator::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAxisAccumulatorData>::create(this); diff --git a/src/input/frontend/qaxisaccumulator.h b/src/input/frontend/qaxisaccumulator.h index e5f35a32f..bb2e2696b 100644 --- a/src/input/frontend/qaxisaccumulator.h +++ b/src/input/frontend/qaxisaccumulator.h @@ -87,9 +87,6 @@ Q_SIGNALS: void velocityChanged(float value); void scaleChanged(float scale); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - private: Q_DECLARE_PRIVATE(QAxisAccumulator) Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; diff --git a/src/input/frontend/qinputaspect.cpp b/src/input/frontend/qinputaspect.cpp index c063f2580..e109461f0 100644 --- a/src/input/frontend/qinputaspect.cpp +++ b/src/input/frontend/qinputaspect.cpp @@ -145,26 +145,26 @@ QInputAspect::QInputAspect(QInputAspectPrivate &dd, QObject *parent) qRegisterMetaType<Qt3DInput::QAbstractPhysicalDevice*>(); - registerBackendType<QKeyboardDevice>(QBackendNodeMapperPtr(new Input::KeyboardDeviceFunctor(this, d_func()->m_inputHandler.data()))); - registerBackendType<QKeyboardHandler>(QBackendNodeMapperPtr(new Input::KeyboardHandlerFunctor(d_func()->m_inputHandler.data()))); - registerBackendType<QMouseDevice>(QBackendNodeMapperPtr(new Input::MouseDeviceFunctor(this, d_func()->m_inputHandler.data()))); - registerBackendType<QMouseHandler>(QBackendNodeMapperPtr(new Input::MouseHandlerFunctor(d_func()->m_inputHandler.data()))); + registerBackendType<QKeyboardDevice, true>(QBackendNodeMapperPtr(new Input::KeyboardDeviceFunctor(this, d_func()->m_inputHandler.data()))); + registerBackendType<QKeyboardHandler, true>(QBackendNodeMapperPtr(new Input::KeyboardHandlerFunctor(d_func()->m_inputHandler.data()))); + registerBackendType<QMouseDevice, true>(QBackendNodeMapperPtr(new Input::MouseDeviceFunctor(this, d_func()->m_inputHandler.data()))); + registerBackendType<QMouseHandler, true>(QBackendNodeMapperPtr(new Input::MouseHandlerFunctor(d_func()->m_inputHandler.data()))); registerBackendType<QAxis, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Axis, Input::AxisManager>(d_func()->m_inputHandler->axisManager()))); - registerBackendType<QAxisAccumulator>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisAccumulator, Input::AxisAccumulatorManager>(d_func()->m_inputHandler->axisAccumulatorManager()))); - registerBackendType<QAnalogAxisInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AnalogAxisInput, Input::AnalogAxisInputManager>(d_func()->m_inputHandler->analogAxisInputManager()))); - registerBackendType<QButtonAxisInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ButtonAxisInput, Input::ButtonAxisInputManager>(d_func()->m_inputHandler->buttonAxisInputManager()))); - registerBackendType<QAxisSetting>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisSetting, Input::AxisSettingManager>(d_func()->m_inputHandler->axisSettingManager()))); - registerBackendType<Qt3DInput::QAction>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Action, Input::ActionManager>(d_func()->m_inputHandler->actionManager()))); - registerBackendType<QActionInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ActionInput, Input::ActionInputManager>(d_func()->m_inputHandler->actionInputManager()))); - registerBackendType<QInputChord>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputChord, Input::InputChordManager>(d_func()->m_inputHandler->inputChordManager()))); - registerBackendType<QInputSequence>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputSequence, Input::InputSequenceManager>(d_func()->m_inputHandler->inputSequenceManager()))); - registerBackendType<QLogicalDevice>(QBackendNodeMapperPtr(new Input::LogicalDeviceNodeFunctor(d_func()->m_inputHandler->logicalDeviceManager()))); - registerBackendType<QGenericInputDevice>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data()))); - registerBackendType<QInputSettings>(QBackendNodeMapperPtr(new Input::InputSettingsFunctor(d_func()->m_inputHandler.data()))); - registerBackendType<QAbstractPhysicalDeviceProxy>(QBackendNodeMapperPtr(new Input::PhysicalDeviceProxyNodeFunctor(d_func()->m_inputHandler->physicalDeviceProxyManager()))); + registerBackendType<QAxisAccumulator, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisAccumulator, Input::AxisAccumulatorManager>(d_func()->m_inputHandler->axisAccumulatorManager()))); + registerBackendType<QAnalogAxisInput, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AnalogAxisInput, Input::AnalogAxisInputManager>(d_func()->m_inputHandler->analogAxisInputManager()))); + registerBackendType<QButtonAxisInput, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ButtonAxisInput, Input::ButtonAxisInputManager>(d_func()->m_inputHandler->buttonAxisInputManager()))); + registerBackendType<QAxisSetting, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisSetting, Input::AxisSettingManager>(d_func()->m_inputHandler->axisSettingManager()))); + registerBackendType<Qt3DInput::QAction, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Action, Input::ActionManager>(d_func()->m_inputHandler->actionManager()))); + registerBackendType<QActionInput, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ActionInput, Input::ActionInputManager>(d_func()->m_inputHandler->actionInputManager()))); + registerBackendType<QInputChord, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputChord, Input::InputChordManager>(d_func()->m_inputHandler->inputChordManager()))); + registerBackendType<QInputSequence, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputSequence, Input::InputSequenceManager>(d_func()->m_inputHandler->inputSequenceManager()))); + registerBackendType<QLogicalDevice, true>(QBackendNodeMapperPtr(new Input::LogicalDeviceNodeFunctor(d_func()->m_inputHandler->logicalDeviceManager()))); + registerBackendType<QGenericInputDevice, true>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data()))); + registerBackendType<QInputSettings, true>(QBackendNodeMapperPtr(new Input::InputSettingsFunctor(d_func()->m_inputHandler.data()))); + registerBackendType<QAbstractPhysicalDeviceProxy, true>(QBackendNodeMapperPtr(new Input::PhysicalDeviceProxyNodeFunctor(d_func()->m_inputHandler->physicalDeviceProxyManager()))); #ifdef HAVE_QGAMEPAD - registerBackendType<QGamepadInput>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data()))); + registerBackendType<QGamepadInput, true>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data()))); #endif Q_D(QInputAspect); diff --git a/src/input/frontend/qinputchord.cpp b/src/input/frontend/qinputchord.cpp index 7c986f297..a64cc8961 100644 --- a/src/input/frontend/qinputchord.cpp +++ b/src/input/frontend/qinputchord.cpp @@ -41,9 +41,6 @@ #include <Qt3DInput/qabstractphysicaldevice.h> #include <Qt3DCore/qnodecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -157,11 +154,7 @@ void QInputChord::addChord(QAbstractActionInput *input) if (!input->parent()) input->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input); - change->setPropertyName("chord"); - d->notifyObservers(change); - } + d->update(); } } @@ -174,12 +167,7 @@ void QInputChord::removeChord(QAbstractActionInput *input) { Q_D(QInputChord); if (d->m_chords.contains(input)) { - - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input); - change->setPropertyName("chord"); - d->notifyObservers(change); - } + d->update(); d->m_chords.removeOne(input); diff --git a/src/input/frontend/qinputsequence.cpp b/src/input/frontend/qinputsequence.cpp index 766674840..5e0e36aba 100644 --- a/src/input/frontend/qinputsequence.cpp +++ b/src/input/frontend/qinputsequence.cpp @@ -42,9 +42,6 @@ #include <Qt3DInput/qabstractactioninput.h> #include <Qt3DInput/qabstractphysicaldevice.h> #include <Qt3DCore/qnodecreatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qnode_p.h> @@ -210,11 +207,7 @@ void QInputSequence::addSequence(QAbstractActionInput *input) if (!input->parent()) input->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input); - change->setPropertyName("sequence"); - d->notifyObservers(change); - } + d->update(); } } @@ -227,11 +220,7 @@ void QInputSequence::removeSequence(QAbstractActionInput *input) { Q_D(QInputSequence); if (d->m_sequences.contains(input)) { - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input); - change->setPropertyName("sequence"); - d->notifyObservers(change); - } + d->update(); d->m_sequences.removeOne(input); diff --git a/src/input/frontend/qkeyboardhandler.cpp b/src/input/frontend/qkeyboardhandler.cpp index 485959bcd..aff136a04 100644 --- a/src/input/frontend/qkeyboardhandler.cpp +++ b/src/input/frontend/qkeyboardhandler.cpp @@ -170,23 +170,6 @@ QKeyboardHandler::~QKeyboardHandler() { } -/*! \internal */ -void QKeyboardHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QKeyboardHandler); - QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change); - if (e->type() == PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("focus")) { - bool block = blockNotifications(true); - setFocus(e->value().toBool()); - blockNotifications(block); - } else if (e->propertyName() == QByteArrayLiteral("event")) { - QKeyEventPtr ev = e->value().value<QKeyEventPtr>(); - d->keyEvent(ev.data()); - } - } -} - /*! \qmlproperty KeyboardDevice Qt3D.Input::KeyboardHandler::sourceDevice */ diff --git a/src/input/frontend/qkeyboardhandler.h b/src/input/frontend/qkeyboardhandler.h index 056d7c7a4..d69476286 100644 --- a/src/input/frontend/qkeyboardhandler.h +++ b/src/input/frontend/qkeyboardhandler.h @@ -115,9 +115,6 @@ Q_SIGNALS: void pressed(Qt3DInput::QKeyEvent *event); void released(Qt3DInput::QKeyEvent *event); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - private: Q_DECLARE_PRIVATE(QKeyboardHandler) Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; diff --git a/src/input/frontend/qlogicaldevice.cpp b/src/input/frontend/qlogicaldevice.cpp index 1e7033962..2069be633 100644 --- a/src/input/frontend/qlogicaldevice.cpp +++ b/src/input/frontend/qlogicaldevice.cpp @@ -41,9 +41,6 @@ #include "qlogicaldevice_p.h" #include <Qt3DCore/qnodecreatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DInput/qaction.h> #include <Qt3DInput/qaxis.h> @@ -176,11 +173,7 @@ void QLogicalDevice::addAction(QAction *action) // Ensures proper bookkeeping d->registerDestructionHelper(action, &QLogicalDevice::removeAction, d->m_actions); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), action); - change->setPropertyName("action"); - d->notifyObservers(change); - } + d->update(); } } @@ -191,12 +184,7 @@ void QLogicalDevice::removeAction(QAction *action) { Q_D(QLogicalDevice); if (d->m_actions.contains(action)) { - - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), action); - change->setPropertyName("action"); - d->notifyObservers(change); - } + d->update(); d->m_actions.removeOne(action); @@ -236,11 +224,7 @@ void QLogicalDevice::addAxis(QAxis *axis) // Ensures proper bookkeeping d->registerDestructionHelper(axis, &QLogicalDevice::removeAxis, d->m_axes); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), axis); - change->setPropertyName("axis"); - d->notifyObservers(change); - } + d->update(); } } @@ -251,11 +235,7 @@ void QLogicalDevice::removeAxis(QAxis *axis) { Q_D(QLogicalDevice); if (d->m_axes.contains(axis)) { - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), axis); - change->setPropertyName("axis"); - d->notifyObservers(change); - } + d->update(); d->m_axes.removeOne(axis); diff --git a/src/input/frontend/qmousehandler.cpp b/src/input/frontend/qmousehandler.cpp index c36ac50f1..944ca391a 100644 --- a/src/input/frontend/qmousehandler.cpp +++ b/src/input/frontend/qmousehandler.cpp @@ -335,24 +335,6 @@ void QMouseHandler::setContainsMouse(bool contains) } } -/*! \internal */ -void QMouseHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QMouseHandler); - QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change); - if (e->type() == PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("mouse")) { - QMouseEventPtr ev = e->value().value<QMouseEventPtr>(); - d->mouseEvent(ev); -#if QT_CONFIG(wheelevent) - } else if (e->propertyName() == QByteArrayLiteral("wheel")) { - QWheelEventPtr ev = e->value().value<QWheelEventPtr>(); - emit wheel(ev.data()); -#endif - } - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QMouseHandler::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QMouseHandlerData>::create(this); diff --git a/src/input/frontend/qmousehandler.h b/src/input/frontend/qmousehandler.h index aec450cb9..5331893b2 100644 --- a/src/input/frontend/qmousehandler.h +++ b/src/input/frontend/qmousehandler.h @@ -87,7 +87,6 @@ Q_SIGNALS: #endif protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; void setContainsMouse(bool contains); private: diff --git a/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp index 1176d8e8e..2b967f2d2 100644 --- a/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp +++ b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp @@ -40,8 +40,6 @@ #include "scene2dmanager_p.h" #include "scene2devent_p.h" -#include <Qt3DCore/QPropertyUpdatedChange> - QT_BEGIN_NAMESPACE using namespace Qt3DCore; diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp index 1dd798d94..cb9973f0a 100644 --- a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp +++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp @@ -41,8 +41,6 @@ #include "scene2devent_p.h" #include "scene2dsharedobject_p.h" -#include <Qt3DCore/QPropertyUpdatedChange> - QT_BEGIN_NAMESPACE using namespace Qt3DCore; diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp index 188e017e6..642f6e44d 100644 --- a/src/render/backend/backendnode.cpp +++ b/src/render/backend/backendnode.cpp @@ -56,6 +56,12 @@ BackendNode::BackendNode(Mode mode) { } +BackendNode::BackendNode(Qt3DCore::QBackendNodePrivate &dd) + : QBackendNode(dd) + , m_renderer(nullptr) +{ +} + BackendNode::~BackendNode() { } diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h index 167cb87f2..37f8305af 100644 --- a/src/render/backend/backendnode_p.h +++ b/src/render/backend/backendnode_p.h @@ -58,6 +58,12 @@ QT_BEGIN_NAMESPACE +namespace Qt3DCore { + +class QBackendNodePrivate; + +} + namespace Qt3DRender { namespace Render { @@ -78,6 +84,7 @@ public: QSharedPointer<RenderBackendResourceAccessor> resourceAccessor(); protected: + explicit BackendNode(Qt3DCore::QBackendNodePrivate &dd); void markDirty(AbstractRenderer::BackendNodeDirtySet changes); AbstractRenderer *m_renderer; }; diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp index 7a5c1f7e6..85c5e9656 100644 --- a/src/render/backend/cameralens.cpp +++ b/src/render/backend/cameralens.cpp @@ -47,7 +47,6 @@ #include <Qt3DRender/private/sphere_p.h> #include <Qt3DRender/private/computefilteredboundingvolumejob_p.h> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qtransform.h> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/computecommand.cpp b/src/render/backend/computecommand.cpp index 386c25fec..df79dcbe8 100644 --- a/src/render/backend/computecommand.cpp +++ b/src/render/backend/computecommand.cpp @@ -102,6 +102,9 @@ void ComputeCommand::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firs m_frameCount = d->m_frameCount; markDirty(AbstractRenderer::ComputeDirty); } + + if (firstTime) + markDirty(AbstractRenderer::ComputeDirty); } // Called from buildComputeRenderCommands in a job diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 8be58dd46..682dc000e 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "entity_p.h" +#include "entity_p_p.h" #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/qabstractlight.h> @@ -59,10 +60,7 @@ #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/qarmature.h> -#include <Qt3DCore/qcomponentaddedchange.h> -#include <Qt3DCore/qcomponentremovedchange.h> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qtransform.h> #include <Qt3DCore/private/qentity_p.h> #include <Qt3DCore/qnodecreatedchange.h> @@ -77,8 +75,33 @@ using namespace Qt3DCore; namespace Qt3DRender { namespace Render { + +EntityPrivate::EntityPrivate() + : Qt3DCore::QBackendNodePrivate(Entity::ReadOnly) +{ +} + +EntityPrivate *EntityPrivate::get(Entity *node) +{ + return node->d_func(); +} + +void EntityPrivate::componentAdded(Qt3DCore::QNode *frontend) +{ + Q_Q(Entity); + const auto componentIdAndType = QNodeIdTypePair(frontend->id(), QNodePrivate::findStaticMetaObject(frontend->metaObject())); + q->addComponent(componentIdAndType); +} + +void EntityPrivate::componentRemoved(Qt3DCore::QNode *frontend) +{ + Q_Q(Entity); + q->removeComponent(frontend->id()); +} + + Entity::Entity() - : BackendNode() + : BackendNode(*new EntityPrivate) , m_nodeManagers(nullptr) , m_boundingDirty(false) , m_treeEnabled(true) @@ -160,31 +183,6 @@ void Entity::setHandle(HEntity handle) m_handle = handle; } -void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - - case ComponentAdded: { - QComponentAddedChangePtr change = qSharedPointerCast<QComponentAddedChange>(e); - const auto componentIdAndType = QNodeIdTypePair(change->componentId(), change->componentMetaObject()); - addComponent(componentIdAndType); - qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Added. Id =" << change->componentId(); - break; - } - - case ComponentRemoved: { - QComponentRemovedChangePtr change = qSharedPointerCast<QComponentRemovedChange>(e); - removeComponent(change->componentId()); - qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Removed. Id =" << change->componentId(); - break; - } - - default: - break; - } - BackendNode::sceneChangeEvent(e); -} - void Entity::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { const Qt3DCore::QEntity *node = qobject_cast<const Qt3DCore::QEntity *>(frontEnd); @@ -265,16 +263,6 @@ void Entity::removeFromParentChildHandles() p->removeChildHandle(m_handle); } -void Entity::appendChildHandle(HEntity childHandle) -{ - if (!m_childrenHandles.contains(childHandle)) { - m_childrenHandles.append(childHandle); - Entity *child = m_nodeManagers->renderNodesManager()->data(childHandle); - if (child != nullptr) - child->m_parentHandle = m_handle; - } -} - QVector<Entity *> Entity::children() const { QVector<Entity *> childrenVector; diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 403f5568c..d13d96784 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -79,6 +79,7 @@ namespace Render { class Sphere; class Renderer; class NodeManagers; +class EntityPrivate; class Q_AUTOTEST_EXPORT Entity : public BackendNode { @@ -89,7 +90,6 @@ public: void setParentHandle(HEntity parentHandle); void setNodeManagers(NodeManagers *manager); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void dump() const; @@ -176,6 +176,9 @@ public: return containsComponentsOfType<T>() && containsComponentsOfType<Ts, Ts2...>(); } +protected: + Q_DECLARE_PRIVATE(Entity) + private: NodeManagers *m_nodeManagers; HEntity m_handle; diff --git a/src/render/renderers/opengl/renderer/glcommands.cpp b/src/render/backend/entity_p_p.h index fd7ee9fe8..4ac6ab978 100644 --- a/src/render/renderers/opengl/renderer/glcommands.cpp +++ b/src/render/backend/entity_p_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,31 +38,50 @@ ** ****************************************************************************/ -#include "glcommands_p.h" -#include <Qt3DRender/private/renderer_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> +#ifndef QT3DRENDER_RENDER_ENTITY_P_P_H +#define QT3DRENDER_RENDER_ENTITY_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DCore/private/qbackendnode_p.h> QT_BEGIN_NAMESPACE +namespace Qt3DCore { +class QNode; +} + namespace Qt3DRender { +class QRenderAspect; + namespace Render { -LoadShaderCommand::LoadShaderCommand(Shader *shader) - : m_shader(shader) -{ - Q_ASSERT(m_shader); -} +class Q_AUTOTEST_EXPORT EntityPrivate : public Qt3DCore::QBackendNodePrivate { +public: + EntityPrivate(); -void LoadShaderCommand::execute(Renderer *renderer, GraphicsContext *ctx) -{ - NodeManagers *nodeManagers = renderer->nodeManagers(); - ctx->loadShader(m_shader, nodeManagers->shaderManager()); -} + Q_DECLARE_PUBLIC(Entity) -} // Render + static EntityPrivate *get(Entity *node); -} // Qt3DRender + void componentAdded(Qt3DCore::QNode *frontend) override; + void componentRemoved(Qt3DCore::QNode *frontend) override; +}; + +} // namespace Render +} // namespace Qt3DRender QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_ENTITY_P_P_H diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp index f0c844906..f1b6d2fc6 100644 --- a/src/render/backend/layer.cpp +++ b/src/render/backend/layer.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/qlayer.h> #include <Qt3DRender/private/qlayer_p.h> #include <Qt3DRender/private/stringtoint_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QVariant> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/levelofdetail.cpp b/src/render/backend/levelofdetail.cpp index 08410edf9..7f528a9d5 100644 --- a/src/render/backend/levelofdetail.cpp +++ b/src/render/backend/levelofdetail.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/QLevelOfDetail> #include <Qt3DRender/private/qlevelofdetail_p.h> #include <Qt3DRender/private/stringtoint_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/QCamera> #include <QVariant> @@ -111,14 +110,8 @@ void LevelOfDetail::cleanup() void LevelOfDetail::setCurrentIndex(int currentIndex) { - if (m_currentIndex != currentIndex) { + if (m_currentIndex != currentIndex) m_currentIndex = currentIndex; - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("currentIndex"); - e->setValue(m_currentIndex); - notifyObservers(e); - } } } // namespace Render diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri index 6b60dfcda..9510b9530 100644 --- a/src/render/backend/render-backend.pri +++ b/src/render/backend/render-backend.pri @@ -11,6 +11,7 @@ HEADERS += \ $$PWD/platformsurfacefilter_p.h \ $$PWD/cameralens_p.h \ $$PWD/entity_p.h \ + $$PWD/entity_p_p.h \ $$PWD/entityvisitor_p.h \ $$PWD/entityaccumulator_p.h \ $$PWD/layer_p.h \ diff --git a/src/render/backend/rendersettings.cpp b/src/render/backend/rendersettings.cpp index 702be9c60..487f6e11a 100644 --- a/src/render/backend/rendersettings.cpp +++ b/src/render/backend/rendersettings.cpp @@ -43,7 +43,6 @@ #include <Qt3DRender/private/abstractrenderer_p.h> #include <Qt3DRender/private/qrendersettings_p.h> #include <Qt3DCore/qnodecommand.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/rendertarget.cpp b/src/render/backend/rendertarget.cpp index 206f64e4e..088818c94 100644 --- a/src/render/backend/rendertarget.cpp +++ b/src/render/backend/rendertarget.cpp @@ -41,9 +41,6 @@ #include <Qt3DRender/qrendertarget.h> #include <Qt3DRender/private/qrendertarget_p.h> #include <Qt3DRender/qrendertargetoutput.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <QVariant> QT_BEGIN_NAMESPACE diff --git a/src/render/backend/rendertargetoutput.cpp b/src/render/backend/rendertargetoutput.cpp index edfc7132e..e98acf3b8 100644 --- a/src/render/backend/rendertargetoutput.cpp +++ b/src/render/backend/rendertargetoutput.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include <Qt3DRender/private/rendertargetoutput_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtexture.h> #include <Qt3DRender/private/qrendertargetoutput_p.h> #include <QVariant> diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp index 6659657fa..8e98801b7 100644 --- a/src/render/backend/transform.cpp +++ b/src/render/backend/transform.cpp @@ -88,28 +88,6 @@ QVector3D Transform::translation() const return m_translation; } -// TODOSYNC remove once we've found a way to propagate animation changes -void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - // TODO: Flag the matrix as dirty and update all matrices batched in a job - if (e->type() == PropertyUpdated) { - const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("scale3D")) { - m_scale = propertyChange->value().value<QVector3D>(); - updateMatrix(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) { - m_rotation = propertyChange->value().value<QQuaternion>(); - updateMatrix(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) { - m_translation = propertyChange->value().value<QVector3D>(); - updateMatrix(); - } - } - markDirty(AbstractRenderer::TransformDirty); - - BackendNode::sceneChangeEvent(e); -} - void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { const Qt3DCore::QTransform *transform = qobject_cast<const Qt3DCore::QTransform *>(frontEnd); @@ -131,15 +109,6 @@ void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) BackendNode::syncFromFrontEnd(frontEnd, firstTime); } -void Transform::notifyWorldTransformChanged(const Matrix4x4 &worldMatrix) -{ - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("worldMatrix"); - change->setValue(convertToQMatrix4x4(worldMatrix)); - notifyObservers(change); -} - void Transform::updateMatrix() { QMatrix4x4 m; diff --git a/src/render/backend/transform_p.h b/src/render/backend/transform_p.h index 50857ac94..8c0cd826a 100644 --- a/src/render/backend/transform_p.h +++ b/src/render/backend/transform_p.h @@ -76,9 +76,7 @@ public: QQuaternion rotation() const; QVector3D translation() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final; - void notifyWorldTransformChanged(const Matrix4x4 &worldMatrix); private: void updateMatrix(); diff --git a/src/render/framegraph/blitframebuffer.cpp b/src/render/framegraph/blitframebuffer.cpp index c45d3fdbc..0ecfbf5c4 100644 --- a/src/render/framegraph/blitframebuffer.cpp +++ b/src/render/framegraph/blitframebuffer.cpp @@ -39,7 +39,6 @@ #include <Qt3DRender/private/qblitframebuffer_p.h> #include <Qt3DRender/private/blitframebuffer_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/buffercapture.cpp b/src/render/framegraph/buffercapture.cpp index 4e89150df..b5e80eb29 100644 --- a/src/render/framegraph/buffercapture.cpp +++ b/src/render/framegraph/buffercapture.cpp @@ -40,7 +40,6 @@ #include <Qt3DRender/private/qbuffercapture_p.h> #include <Qt3DRender/private/buffercapture_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/cameraselectornode.cpp b/src/render/framegraph/cameraselectornode.cpp index 482429b00..3beb0ef71 100644 --- a/src/render/framegraph/cameraselectornode.cpp +++ b/src/render/framegraph/cameraselectornode.cpp @@ -40,9 +40,7 @@ #include "cameraselectornode_p.h" #include <Qt3DRender/private/qcameraselector_p.h> #include <Qt3DRender/private/renderer_p.h> -#include <Qt3DCore/private/qchangearbiter_p.h> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/renderlogging_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/clearbuffers.cpp b/src/render/framegraph/clearbuffers.cpp index 7d018c935..3f99e0e20 100644 --- a/src/render/framegraph/clearbuffers.cpp +++ b/src/render/framegraph/clearbuffers.cpp @@ -39,7 +39,6 @@ #include "clearbuffers_p.h" #include <Qt3DRender/private/qclearbuffers_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -52,16 +51,16 @@ static QVector4D vec4dFromColor(const QColor &color) { if (!color.isValid()) return QVector4D(0.0f, 0.0f, 0.0f, 1.0f); - return QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + return QVector4D(float(color.redF()), float(color.greenF()), float(color.blueF()), float(color.alphaF())); } ClearBuffers::ClearBuffers() : FrameGraphNode(FrameGraphNode::ClearBuffers) , m_type(QClearBuffers::None) + , m_clearColor(vec4dFromColor(m_clearColorAsColor)) + , m_clearColorAsColor(Qt::black) , m_clearDepthValue(1.f) , m_clearStencilValue(0) - , m_clearColorAsColor(Qt::black) - , m_clearColor(vec4dFromColor(m_clearColorAsColor)) { } @@ -79,7 +78,7 @@ void ClearBuffers::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::FrameGraphDirty); } - if (m_clearDepthValue != node->clearDepthValue()) { + if (!qFuzzyCompare(m_clearDepthValue, node->clearDepthValue())) { m_clearDepthValue = node->clearDepthValue(); markDirty(AbstractRenderer::FrameGraphDirty); } diff --git a/src/render/framegraph/dispatchcompute.cpp b/src/render/framegraph/dispatchcompute.cpp index 5eae75bc6..4161d37b5 100644 --- a/src/render/framegraph/dispatchcompute.cpp +++ b/src/render/framegraph/dispatchcompute.cpp @@ -39,7 +39,6 @@ #include "dispatchcompute_p.h" #include <Qt3DRender/private/qdispatchcompute_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp index 93531fd7d..58ff05dc0 100644 --- a/src/render/framegraph/framegraphnode.cpp +++ b/src/render/framegraph/framegraphnode.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/frustumculling.cpp b/src/render/framegraph/frustumculling.cpp index 9f38d6be9..cf3a4ec57 100644 --- a/src/render/framegraph/frustumculling.cpp +++ b/src/render/framegraph/frustumculling.cpp @@ -39,7 +39,6 @@ #include "frustumculling_p.h" #include <Qt3DRender/qfrustumculling.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp index 5c53fa681..f50fc1306 100644 --- a/src/render/framegraph/layerfilternode.cpp +++ b/src/render/framegraph/layerfilternode.cpp @@ -40,9 +40,6 @@ #include "layerfilternode_p.h" #include "qlayerfilter.h" #include <Qt3DRender/private/qlayerfilter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/memorybarrier.cpp b/src/render/framegraph/memorybarrier.cpp index 6bfaedda7..bcc81464a 100644 --- a/src/render/framegraph/memorybarrier.cpp +++ b/src/render/framegraph/memorybarrier.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "memorybarrier_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qmemorybarrier_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/nodraw.cpp b/src/render/framegraph/nodraw.cpp index f2020d7ce..f64eb92d7 100644 --- a/src/render/framegraph/nodraw.cpp +++ b/src/render/framegraph/nodraw.cpp @@ -39,7 +39,6 @@ #include "nodraw_p.h" #include <Qt3DRender/qnodraw.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/proximityfilter.cpp b/src/render/framegraph/proximityfilter.cpp index 593e541bc..03dd2a7ec 100644 --- a/src/render/framegraph/proximityfilter.cpp +++ b/src/render/framegraph/proximityfilter.cpp @@ -39,7 +39,6 @@ #include "proximityfilter_p.h" #include <Qt3DRender/private/qproximityfilter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qblitframebuffer.cpp b/src/render/framegraph/qblitframebuffer.cpp index bf9e547cb..3a26e3d56 100644 --- a/src/render/framegraph/qblitframebuffer.cpp +++ b/src/render/framegraph/qblitframebuffer.cpp @@ -40,7 +40,6 @@ #include "qblitframebuffer.h" #include "qblitframebuffer_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp index d1d301077..0c12a3aff 100644 --- a/src/render/framegraph/qbuffercapture.cpp +++ b/src/render/framegraph/qbuffercapture.cpp @@ -40,7 +40,6 @@ #include <Qt3DRender/qbuffercapture.h> #include <Qt3DRender/private/qbuffercapture_p.h> #include <Qt3DCore/QSceneChange> -#include <Qt3DCore/QPropertyUpdatedChange> #include <Qt3DRender/QFrameGraphNodeCreatedChange> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qcameraselector.cpp b/src/render/framegraph/qcameraselector.cpp index 45abf638e..af293dc56 100644 --- a/src/render/framegraph/qcameraselector.cpp +++ b/src/render/framegraph/qcameraselector.cpp @@ -41,7 +41,6 @@ #include "qcameraselector_p.h" #include <Qt3DCore/qentity.h> #include <Qt3DCore/private/qentity_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qclearbuffers.cpp b/src/render/framegraph/qclearbuffers.cpp index 4cc4c98b6..31a31420c 100644 --- a/src/render/framegraph/qclearbuffers.cpp +++ b/src/render/framegraph/qclearbuffers.cpp @@ -39,7 +39,6 @@ #include "qclearbuffers.h" #include "qclearbuffers_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp index 1ef81a081..2390cb1c9 100644 --- a/src/render/framegraph/qframegraphnode.cpp +++ b/src/render/framegraph/qframegraphnode.cpp @@ -40,7 +40,6 @@ #include "qframegraphnode.h" #include "qframegraphnode_p.h" #include <Qt3DRender/qframegraphnodecreatedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/QNode> diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp index 8b0dd5669..5080012fd 100644 --- a/src/render/framegraph/qlayerfilter.cpp +++ b/src/render/framegraph/qlayerfilter.cpp @@ -40,9 +40,6 @@ #include "qlayerfilter.h" #include "qlayerfilter_p.h" #include "qlayer.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp index 4ef7e6d2d..778d3fa1f 100644 --- a/src/render/framegraph/qrenderpassfilter.cpp +++ b/src/render/framegraph/qrenderpassfilter.cpp @@ -42,9 +42,6 @@ #include <Qt3DRender/qfilterkey.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp index d558a939e..8c2c6ee7f 100644 --- a/src/render/framegraph/qrenderstateset.cpp +++ b/src/render/framegraph/qrenderstateset.cpp @@ -41,9 +41,6 @@ #include "qrenderstateset_p.h" #include <Qt3DRender/qrenderstate.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qrendersurfaceselector.cpp b/src/render/framegraph/qrendersurfaceselector.cpp index 765aa1824..df30663cb 100644 --- a/src/render/framegraph/qrendersurfaceselector.cpp +++ b/src/render/framegraph/qrendersurfaceselector.cpp @@ -44,7 +44,6 @@ #include <QtGui/QScreen> #include <QtGui/QOffscreenSurface> #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qrendersettings.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> @@ -252,17 +251,17 @@ void QRenderSurfaceSelector::setSurface(QObject *surfaceObject) d->m_surfaceEventFilter->setSurface(window); if (window) { - d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int width) { + d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int) { d->update(); }); - d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int height) { + d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int) { d->update(); }); d->m_screenConn = QObject::connect(window, &QWindow::screenChanged, [=] (QScreen *screen) { - if (screen && surfacePixelRatio() != screen->devicePixelRatio()) - setSurfacePixelRatio(screen->devicePixelRatio()); + if (screen && !qFuzzyCompare(surfacePixelRatio(), float(screen->devicePixelRatio()))) + setSurfacePixelRatio(float(screen->devicePixelRatio())); }); - setSurfacePixelRatio(window->devicePixelRatio()); + setSurfacePixelRatio(float(window->devicePixelRatio())); } break; @@ -292,7 +291,7 @@ QSize QRenderSurfaceSelector::externalRenderTargetSize() const void QRenderSurfaceSelector::setSurfacePixelRatio(float ratio) { Q_D(QRenderSurfaceSelector); - if (d->m_surfacePixelRatio == ratio) + if (qFuzzyCompare(d->m_surfacePixelRatio, ratio)) return; d->m_surfacePixelRatio = ratio; emit surfacePixelRatioChanged(ratio); diff --git a/src/render/framegraph/qrendertargetselector.cpp b/src/render/framegraph/qrendertargetselector.cpp index f4d95d507..c997c23cc 100644 --- a/src/render/framegraph/qrendertargetselector.cpp +++ b/src/render/framegraph/qrendertargetselector.cpp @@ -40,7 +40,6 @@ #include "qrendertargetselector.h" #include "qrendertargetselector_p.h" #include <Qt3DRender/qrendertarget.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderpass_p.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> diff --git a/src/render/framegraph/qsortpolicy.cpp b/src/render/framegraph/qsortpolicy.cpp index c8e3d23c5..a24dd5eae 100644 --- a/src/render/framegraph/qsortpolicy.cpp +++ b/src/render/framegraph/qsortpolicy.cpp @@ -102,6 +102,8 @@ QSortPolicyPrivate::QSortPolicyPrivate() \value FrontToBack sort the objects from front to back. The opposite of BackToFront. + + \value [since 5.14] Texture sort the objects to minimize texture changes. */ /*! @@ -124,6 +126,7 @@ QSortPolicyPrivate::QSortPolicyPrivate() \li Material - sort the objects based on their material value \li FrontToBack - sort the objects from front to back. The opposite of BackToFront. + \li [since 5.14] Texture - sort the objects to minimize texture changes. \endlist */ diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp index 28b151fc7..03e6a8ca7 100644 --- a/src/render/framegraph/qtechniquefilter.cpp +++ b/src/render/framegraph/qtechniquefilter.cpp @@ -41,9 +41,6 @@ #include "qtechniquefilter_p.h" #include <Qt3DRender/qfilterkey.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/qviewport.cpp b/src/render/framegraph/qviewport.cpp index 539e02d65..34716c5b5 100644 --- a/src/render/framegraph/qviewport.cpp +++ b/src/render/framegraph/qviewport.cpp @@ -40,7 +40,6 @@ #include "qviewport.h" #include "qviewport_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/renderpassfilternode.cpp b/src/render/framegraph/renderpassfilternode.cpp index afc49a563..bcec38fb6 100644 --- a/src/render/framegraph/renderpassfilternode.cpp +++ b/src/render/framegraph/renderpassfilternode.cpp @@ -42,9 +42,6 @@ #include "qrenderpassfilter.h" #include <Qt3DRender/private/qrenderpassfilter_p.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/rendersurfaceselector.cpp b/src/render/framegraph/rendersurfaceselector.cpp index ed8a79eac..a1e639df5 100644 --- a/src/render/framegraph/rendersurfaceselector.cpp +++ b/src/render/framegraph/rendersurfaceselector.cpp @@ -40,7 +40,6 @@ #include "rendersurfaceselector_p.h" #include <Qt3DRender/qrendersurfaceselector.h> #include <Qt3DRender/private/qrendersurfaceselector_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <QtGui/qwindow.h> #include <QtGui/qscreen.h> diff --git a/src/render/framegraph/rendertargetselectornode.cpp b/src/render/framegraph/rendertargetselectornode.cpp index 871a00154..614a749a5 100644 --- a/src/render/framegraph/rendertargetselectornode.cpp +++ b/src/render/framegraph/rendertargetselectornode.cpp @@ -43,7 +43,6 @@ #include <Qt3DRender/qrendertargetselector.h> #include <Qt3DRender/private/qrendertargetselector_p.h> #include <Qt3DRender/qrendertarget.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/renderlogging_p.h> #include <Qt3DRender/qrendertargetoutput.h> diff --git a/src/render/framegraph/sortpolicy.cpp b/src/render/framegraph/sortpolicy.cpp index 3c7975945..5c61966c0 100644 --- a/src/render/framegraph/sortpolicy.cpp +++ b/src/render/framegraph/sortpolicy.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "sortpolicy_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qsortpolicy_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/statesetnode.cpp b/src/render/framegraph/statesetnode.cpp index 32ac5e569..c494c572b 100644 --- a/src/render/framegraph/statesetnode.cpp +++ b/src/render/framegraph/statesetnode.cpp @@ -43,9 +43,6 @@ #include <Qt3DRender/private/qrenderstateset_p.h> #include <Qt3DRender/private/genericstate_p.h> #include <Qt3DRender/private/renderstateset_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/techniquefilternode.cpp b/src/render/framegraph/techniquefilternode.cpp index 8739143e6..b3b70e9cb 100644 --- a/src/render/framegraph/techniquefilternode.cpp +++ b/src/render/framegraph/techniquefilternode.cpp @@ -43,9 +43,6 @@ #include <Qt3DRender/private/qtechniquefilter_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/qparameter.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/viewportnode.cpp b/src/render/framegraph/viewportnode.cpp index c37278817..5396d97e2 100644 --- a/src/render/framegraph/viewportnode.cpp +++ b/src/render/framegraph/viewportnode.cpp @@ -40,7 +40,6 @@ #include "viewportnode_p.h" #include <Qt3DRender/qviewport.h> #include <Qt3DRender/private/qviewport_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/framegraph/waitfence.cpp b/src/render/framegraph/waitfence.cpp index 68ddda3d7..829730bbf 100644 --- a/src/render/framegraph/waitfence.cpp +++ b/src/render/framegraph/waitfence.cpp @@ -39,7 +39,6 @@ #include "waitfence_p.h" #include <Qt3DRender/private/qwaitfence_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> // // W A R N I N G diff --git a/src/render/frontend/qcameralens_p.h b/src/render/frontend/qcameralens_p.h index 01fcac0e5..5c5a6a42a 100644 --- a/src/render/frontend/qcameralens_p.h +++ b/src/render/frontend/qcameralens_p.h @@ -57,8 +57,6 @@ #include "qcameralens.h" -#include <Qt3DCore/qpropertyupdatedchange.h> - #include <QtGui/qmatrix4x4.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp index b0bec42d4..d040150d5 100644 --- a/src/render/frontend/qcomputecommand.cpp +++ b/src/render/frontend/qcomputecommand.cpp @@ -39,7 +39,6 @@ #include "qcomputecommand.h" #include "qcomputecommand_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp index a3596a518..3d0cb9553 100644 --- a/src/render/frontend/qlevelofdetail.cpp +++ b/src/render/frontend/qlevelofdetail.cpp @@ -40,7 +40,6 @@ #include "qlevelofdetail.h" #include "qlevelofdetail_p.h" #include "qcamera.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -55,6 +54,15 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate() { } +void QLevelOfDetailPrivate::setCurrentIndex(int currentIndex) +{ + Q_Q(QLevelOfDetail); + if (m_currentIndex != currentIndex) { + m_currentIndex = currentIndex; + emit q->currentIndexChanged(m_currentIndex); + } +} + /*! \class Qt3DRender::QLevelOfDetail \inmodule Qt3DRender @@ -317,20 +325,6 @@ Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() c return creationChange; } -/*! \internal */ -void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QLevelOfDetail); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("currentIndex")) { - int ndx = e->value().value<int>(); - d->m_currentIndex = ndx; - emit currentIndexChanged(ndx); - } - } -} - QCamera *QLevelOfDetail::camera() const { Q_D(const QLevelOfDetail); @@ -367,10 +361,7 @@ int QLevelOfDetail::currentIndex() const void QLevelOfDetail::setCurrentIndex(int currentIndex) { Q_D(QLevelOfDetail); - if (d->m_currentIndex != currentIndex) { - d->m_currentIndex = currentIndex; - emit currentIndexChanged(d->m_currentIndex); - } + d->setCurrentIndex(currentIndex); } QLevelOfDetail::ThresholdType QLevelOfDetail::thresholdType() const diff --git a/src/render/frontend/qlevelofdetail.h b/src/render/frontend/qlevelofdetail.h index 308a4d3c0..f6c09a287 100644 --- a/src/render/frontend/qlevelofdetail.h +++ b/src/render/frontend/qlevelofdetail.h @@ -97,7 +97,6 @@ Q_SIGNALS: protected: explicit QLevelOfDetail(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr); Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QLevelOfDetail) diff --git a/src/render/frontend/qlevelofdetail_p.h b/src/render/frontend/qlevelofdetail_p.h index 7b409e4ca..429128427 100644 --- a/src/render/frontend/qlevelofdetail_p.h +++ b/src/render/frontend/qlevelofdetail_p.h @@ -72,6 +72,8 @@ public: void _q_radiusChanged(float radius); void _q_centerChanged(const QVector3D ¢er); + virtual void setCurrentIndex(int currentIndex); + QCamera *m_camera; int m_currentIndex; QLevelOfDetail::ThresholdType m_thresholdType; diff --git a/src/render/frontend/qlevelofdetailswitch.cpp b/src/render/frontend/qlevelofdetailswitch.cpp index 845fdd5a6..7b888fe98 100644 --- a/src/render/frontend/qlevelofdetailswitch.cpp +++ b/src/render/frontend/qlevelofdetailswitch.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qlevelofdetailswitch.h" +#include "qlevelofdetailswitch_p.h" #include "qlevelofdetail_p.h" #include "qglobal.h" #include <Qt3DCore/QEntity> @@ -47,6 +48,38 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +QLevelOfDetailSwitchPrivate::QLevelOfDetailSwitchPrivate() + : QLevelOfDetailPrivate() +{ + +} + +void QLevelOfDetailSwitchPrivate::setCurrentIndex(int currentIndex) +{ + Q_Q(QLevelOfDetailSwitch); + + bool changed = m_currentIndex != currentIndex; + QLevelOfDetailPrivate::setCurrentIndex(currentIndex); + + if (!changed) + return; + + int entityIndex = 0; + const auto entities = q->entities(); + for (Qt3DCore::QEntity *entity : entities) { + const auto childNodes = entity->childNodes(); + for (Qt3DCore::QNode *childNode : childNodes) { + Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode); + if (childEntity) { + childEntity->setEnabled(entityIndex == currentIndex); + entityIndex++; + } + } + + break; // only work on the first entity, LOD should not be shared + } +} + /*! \class Qt3DRender::QLevelOfDetailSwitch \inmodule Qt3DRender @@ -84,9 +117,9 @@ namespace Qt3DRender { Constructs a new QLevelOfDetailSwitch with the specified \a parent. */ QLevelOfDetailSwitch::QLevelOfDetailSwitch(QNode *parent) - : QLevelOfDetail(parent) + : QLevelOfDetail(*new QLevelOfDetailSwitchPrivate(), parent) { - Q_D(QLevelOfDetail); + Q_D(QLevelOfDetailSwitch); d->m_currentIndex = -1; } @@ -101,34 +134,6 @@ QLevelOfDetailSwitch::QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, QNode *par { } -/*! \internal */ -void QLevelOfDetailSwitch::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QLevelOfDetail); - Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("currentIndex")) { - int ndx = e->value().value<int>(); - d->m_currentIndex = ndx; - emit currentIndexChanged(ndx); - - int entityIndex = 0; - const auto entities = this->entities(); - for (Qt3DCore::QEntity *entity : entities) { - const auto childNodes = entity->childNodes(); - for (Qt3DCore::QNode *childNode : childNodes) { - Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode); - if (childEntity) { - childEntity->setEnabled(entityIndex == ndx); - entityIndex++; - } - } - break; // only work on the first entity, LOD should not be shared - } - } - } -} - } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/render/frontend/qlevelofdetailswitch.h b/src/render/frontend/qlevelofdetailswitch.h index 1615d16e6..90f4ee3e2 100644 --- a/src/render/frontend/qlevelofdetailswitch.h +++ b/src/render/frontend/qlevelofdetailswitch.h @@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +class QLevelOfDetailSwitchPrivate; class Q_3DRENDERSHARED_EXPORT QLevelOfDetailSwitch : public QLevelOfDetail { @@ -56,10 +57,9 @@ public: protected: explicit QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: - Q_DECLARE_PRIVATE(QLevelOfDetail) + Q_DECLARE_PRIVATE(QLevelOfDetailSwitch) }; } // namespace Qt3DRender diff --git a/src/render/renderers/opengl/renderer/glcommands_p.h b/src/render/frontend/qlevelofdetailswitch_p.h index 5ed360759..51321c986 100644 --- a/src/render/renderers/opengl/renderer/glcommands_p.h +++ b/src/render/frontend/qlevelofdetailswitch_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QT3DRENDER_RENDER_GLCOMMANDS_P_H -#define QT3DRENDER_RENDER_GLCOMMANDS_P_H +#ifndef QT3DRENDER_QLEVELOFDETAILSWITCH_P_H +#define QT3DRENDER_QLEVELOFDETAILSWITCH_P_H // // W A R N I N G @@ -51,39 +51,27 @@ // We mean it. // -#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/private/qlevelofdetail_p.h> +#include <Qt3DRender/qlevelofdetailswitch.h> -QT_BEGIN_NAMESPACE +#include <QVector3D> +QT_BEGIN_NAMESPACE namespace Qt3DRender { -namespace Render { - -class GraphicsContext; -class Renderer; -class Shader; - -class GLCommand +class Q_3DRENDERSHARED_PRIVATE_EXPORT QLevelOfDetailSwitchPrivate : public QLevelOfDetailPrivate { public: - virtual void execute(Renderer *renderer, GraphicsContext *ctx) = 0; -}; + QLevelOfDetailSwitchPrivate(); -class Q_AUTOTEST_EXPORT LoadShaderCommand : public GLCommand -{ -public: - explicit LoadShaderCommand(Shader *shader); - Shader *shader() const { return m_shader; } - void execute(Renderer *renderer, GraphicsContext *ctx) Q_DECL_OVERRIDE; + Q_DECLARE_PUBLIC(QLevelOfDetailSwitch) -private: - Shader *m_shader = nullptr; + void setCurrentIndex(int currentIndex) override; }; -} // Render -} // Qt3DRender +} // namespace Qt3DRender QT_END_NAMESPACE -#endif // QT3DRENDER_RENDER_GLCOMMANDS_P_H +#endif // QT3DRENDER_QLEVELOFDETAILSWITCH_P_H diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 70ec70b2b..159c11981 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -288,7 +288,7 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QMaterial, true>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer)); q->registerBackendType<QParameter, true>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer)); q->registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer)); - q->registerBackendType<QShaderData>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<QShaderData, true>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<QShaderProgram, true>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer)); q->registerBackendType<QShaderProgramBuilder, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer)); q->registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp index 2a74db775..7269a8067 100644 --- a/src/render/frontend/qrendertarget.cpp +++ b/src/render/frontend/qrendertarget.cpp @@ -40,9 +40,6 @@ #include "qrendertarget.h" #include "qrendertarget_p.h" #include "qrendertargetoutput.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/qrendertargetoutput.cpp b/src/render/frontend/qrendertargetoutput.cpp index 14ac9c817..8c0d86134 100644 --- a/src/render/frontend/qrendertargetoutput.cpp +++ b/src/render/frontend/qrendertargetoutput.cpp @@ -40,7 +40,6 @@ #include "qrendertargetoutput.h" #include "qrendertargetoutput_p.h" #include "qtexture.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri index 1fafcc294..0153e9c97 100644 --- a/src/render/frontend/render-frontend.pri +++ b/src/render/frontend/render-frontend.pri @@ -9,6 +9,7 @@ HEADERS += \ $$PWD/qlevelofdetail.h \ $$PWD/qlevelofdetail_p.h \ $$PWD/qlevelofdetailswitch.h \ + $$PWD/qlevelofdetailswitch_p.h \ $$PWD/qrendertarget.h \ $$PWD/qrendertarget_p.h \ $$PWD/sphere_p.h \ diff --git a/src/render/geometry/armature.cpp b/src/render/geometry/armature.cpp index cfa2e572a..6e417952b 100644 --- a/src/render/geometry/armature.cpp +++ b/src/render/geometry/armature.cpp @@ -38,7 +38,6 @@ #include <Qt3DCore/qarmature.h> #include <Qt3DCore/qabstractskeleton.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qarmature_p.h> diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp index f241a85e5..de44c5fe3 100644 --- a/src/render/geometry/attribute.cpp +++ b/src/render/geometry/attribute.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "attribute_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qbuffer.h> #include <Qt3DRender/private/qattribute_p.h> #include <Qt3DRender/private/stringtoint_p.h> diff --git a/src/render/geometry/geometry.cpp b/src/render/geometry/geometry.cpp index cb401df5b..56ea936be 100644 --- a/src/render/geometry/geometry.cpp +++ b/src/render/geometry/geometry.cpp @@ -42,8 +42,6 @@ #include <Qt3DRender/qgeometry.h> #include <Qt3DRender/private/qgeometry_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp index b5c741659..3b460f48c 100644 --- a/src/render/geometry/geometryrenderer.cpp +++ b/src/render/geometry/geometryrenderer.cpp @@ -43,8 +43,6 @@ #include <Qt3DRender/private/qgeometryrenderer_p.h> #include <Qt3DRender/private/qmesh_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qtypedpropertyupdatechange_p.h> #include <Qt3DCore/private/qservicelocator_p.h> @@ -148,7 +146,7 @@ void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::GeometryDirty); } -void GeometryRenderer::executeFunctor() +GeometryFunctorResult GeometryRenderer::executeFunctor() { Q_ASSERT(m_geometryFactory); @@ -169,7 +167,8 @@ void GeometryRenderer::executeFunctor() } // Load geometry - std::unique_ptr<QGeometry> geometry((*m_geometryFactory)()); + QGeometry *geometry = (*m_geometryFactory)(); + QMesh::Status meshLoaderStatus = QMesh::None; // If the geometry is null, then we were either unable to load it (Error) // or the mesh is located at a remote url and needs to be downloaded first (Loading) @@ -178,24 +177,15 @@ void GeometryRenderer::executeFunctor() // corresponding QGeometryRenderer const auto appThread = QCoreApplication::instance()->thread(); geometry->moveToThread(appThread); - - auto e = QGeometryChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - e->setPropertyName("geometry"); - e->data = std::move(geometry); - notifyObservers(e); } // Send Status if (isQMeshFunctor) { QSharedPointer<MeshLoaderFunctor> meshLoader = qSharedPointerCast<MeshLoaderFunctor>(m_geometryFactory); - - auto e = QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - e->setPropertyName("status"); - e->setValue(meshLoader->status()); - notifyObservers(e); + meshLoaderStatus = meshLoader->status(); } + + return { geometry, meshLoaderStatus }; } void GeometryRenderer::unsetDirty() diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h index da538a00d..d2ddad4bb 100644 --- a/src/render/geometry/geometryrenderer_p.h +++ b/src/render/geometry/geometryrenderer_p.h @@ -54,6 +54,7 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/qgeometryfactory.h> +#include <Qt3DRender/qmesh.h> QT_BEGIN_NAMESPACE @@ -66,6 +67,12 @@ namespace Render { class GeometryRendererManager; +struct GeometryFunctorResult +{ + QGeometry *geometry; + QMesh::Status status; +}; + class Q_AUTOTEST_EXPORT GeometryRenderer : public BackendNode { public: @@ -75,7 +82,7 @@ public: void cleanup(); void setManager(GeometryRendererManager *manager); void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; - void executeFunctor(); + GeometryFunctorResult executeFunctor(); inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; } inline int instanceCount() const { return m_instanceCount; } diff --git a/src/render/geometry/joint.cpp b/src/render/geometry/joint.cpp index 86d583f51..9791f6c52 100644 --- a/src/render/geometry/joint.cpp +++ b/src/render/geometry/joint.cpp @@ -41,9 +41,6 @@ #include <Qt3DRender/private/managers_p.h> #include <Qt3DCore/QJoint> #include <Qt3DCore/private/qjoint_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <algorithm> @@ -72,69 +69,24 @@ void Joint::cleanup() setEnabled(false); } -// TODOSYNC remove once animation changes don't use messages anymore -void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("scale")) { - m_localPose.scale = propertyChange->value().value<QVector3D>(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) { - m_localPose.rotation = propertyChange->value().value<QQuaternion>(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) { - m_localPose.translation = propertyChange->value().value<QVector3D>(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("inverseBindMatrix")) { - // Setting the inverse bind matrix should be a rare operation. Usually it is - // set once and then remains constant for the duration of the skeleton. So just - // trigger a rebuild of the skeleton's SkeletonData which will include obtaining - // the inverse bind matrix. - m_inverseBindMatrix = propertyChange->value().value<QMatrix4x4>(); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton); - } else if (propertyChange->propertyName() == QByteArrayLiteral("name")) { - // Joint name doesn't affect anything in the render aspect so no need - // to mark anything as dirty. - m_name = propertyChange->value().toString(); - - // TODO: Notify other aspects (animation) about the name change. - } - } else if (e->type() == PropertyValueAdded) { - const auto addedChange = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (addedChange->propertyName() == QByteArrayLiteral("childJoint")) - m_childJointIds.push_back(addedChange->addedNodeId()); - } else if (e->type() == PropertyValueRemoved) { - const auto removedChange = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (removedChange->propertyName() == QByteArrayLiteral("childJoint")) - m_childJointIds.removeOne(removedChange->removedNodeId()); - } - BackendNode::sceneChangeEvent(e); -} - void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { const Qt3DCore::QJoint *joint = qobject_cast<const Qt3DCore::QJoint *>(frontEnd); if (!joint) return; + bool jointDirty = firstTime; if (m_localPose.scale != joint->scale()) { m_localPose.scale = joint->scale(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); + jointDirty = true; } if (m_localPose.rotation != joint->rotation()) { m_localPose.rotation = joint->rotation(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); + jointDirty = true; } if (m_localPose.translation != joint->translation()) { m_localPose.translation = joint->translation(); - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); + jointDirty = true; } if (m_inverseBindMatrix != joint->inverseBindMatrix()) { // Setting the inverse bind matrix should be a rare operation. Usually it is @@ -154,11 +106,10 @@ void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) Qt3DCore::QNodeIdVector childIds = qIdsForNodes(joint->childJoints()); std::sort(std::begin(childIds), std::end(childIds)); - if (m_childJointIds != childIds) { + if (m_childJointIds != childIds) m_childJointIds = childIds; - } - if (firstTime) { + if (jointDirty) { markDirty(AbstractRenderer::JointDirty); m_jointManager->addDirtyJoint(peerId()); } diff --git a/src/render/geometry/joint_p.h b/src/render/geometry/joint_p.h index d0530ac04..de875459e 100644 --- a/src/render/geometry/joint_p.h +++ b/src/render/geometry/joint_p.h @@ -69,7 +69,6 @@ public: Joint(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::Sqt localPose() const { return m_localPose; } diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp index a28d0baa6..84d14cfe1 100644 --- a/src/render/geometry/qattribute.cpp +++ b/src/render/geometry/qattribute.cpp @@ -41,8 +41,6 @@ #include "qattribute_p.h" #include <Qt3DRender/qbuffer.h> -#include <Qt3DCore/qpropertyupdatedchange.h> - QT_BEGIN_NAMESPACE namespace Qt3DRender { diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp index 47fad4302..4b0bca3b3 100644 --- a/src/render/geometry/qgeometry.cpp +++ b/src/render/geometry/qgeometry.cpp @@ -43,8 +43,6 @@ #include <private/qnode_p.h> #include <Qt3DRender/qattribute.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp index ddea873a7..6e0a24f61 100644 --- a/src/render/geometry/qgeometryrenderer.cpp +++ b/src/render/geometry/qgeometryrenderer.cpp @@ -41,9 +41,6 @@ #include "qgeometryrenderer_p.h" #include <private/qcomponent_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -483,19 +480,6 @@ void QGeometryRenderer::setGeometryFactory(const QGeometryFactoryPtr &factory) d->update(); } -/*! - \internal - */ -void QGeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - auto change = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(e); - if (change->type() == PropertyUpdated && change->propertyName() == QByteArrayLiteral("geometry")) { - auto typedChange = qSharedPointerCast<QGeometryChange>(e); - auto geometry = std::move(typedChange->data); - setGeometry(geometry.release()); - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QGeometryRenderer::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QGeometryRendererData>::create(this); diff --git a/src/render/geometry/qgeometryrenderer.h b/src/render/geometry/qgeometryrenderer.h index 81bd1ff67..eceeb9173 100644 --- a/src/render/geometry/qgeometryrenderer.h +++ b/src/render/geometry/qgeometryrenderer.h @@ -134,7 +134,6 @@ Q_SIGNALS: protected: explicit QGeometryRenderer(QGeometryRendererPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QGeometryRenderer) diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp index 66c4a69bc..1d7d33f9a 100644 --- a/src/render/geometry/qmesh.cpp +++ b/src/render/geometry/qmesh.cpp @@ -215,18 +215,6 @@ QMesh::QMesh(QMeshPrivate &dd, QNode *parent) { } -/*! \internal */ -void QMesh::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QMesh); - if (change->type() == Qt3DCore::PropertyUpdated) { - const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->propertyName() == QByteArrayLiteral("status")) - d->setStatus(e->value().value<QMesh::Status>()); - } - Qt3DRender::QGeometryRenderer::sceneChangeEvent(change); -} - void QMesh::setSource(const QUrl& source) { Q_D(QMesh); diff --git a/src/render/geometry/qmesh.h b/src/render/geometry/qmesh.h index 458a21fa4..04fdedc20 100644 --- a/src/render/geometry/qmesh.h +++ b/src/render/geometry/qmesh.h @@ -88,7 +88,6 @@ Q_SIGNALS: protected: explicit QMesh(QMeshPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QMesh) diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp index d4af1fe3c..839a1a056 100644 --- a/src/render/geometry/skeleton.cpp +++ b/src/render/geometry/skeleton.cpp @@ -36,24 +36,19 @@ #include "skeleton_p.h" -#include <Qt3DCore/qjoint.h> -#include <Qt3DCore/qpropertyupdatedchange.h> - #include <QCoreApplication> #include <QFile> #include <QFileInfo> +#include <Qt3DCore/qjoint.h> #include <Qt3DRender/private/abstractrenderer_p.h> -#include <Qt3DRender/private/gltfskeletonloader_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DRender/private/qurlhelper_p.h> #include <Qt3DCore/private/qskeletoncreatedchange_p.h> #include <Qt3DCore/private/qskeleton_p.h> #include <Qt3DCore/private/qskeletonloader_p.h> #include <Qt3DCore/private/qmath3d_p.h> -#include <Qt3DCore/private/qabstractnodefactory_p.h> QT_BEGIN_NAMESPACE @@ -119,9 +114,9 @@ void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) } m_createJoints = loaderNode->isCreateJointsEnabled(); - if ((loaderNode->rootJoint() && loaderNode->rootJoint()->id() != m_rootJointId) || - (!loaderNode->rootJoint() && !m_rootJointId.isNull())) { - m_rootJointId = loaderNode->rootJoint() ? loaderNode->rootJoint()->id() : Qt3DCore::QNodeId{}; + auto newJointId = Qt3DCore::qIdForNode(loaderNode->rootJoint()); + if (newJointId != m_rootJointId) { + m_rootJointId = newJointId; // If using a QSkeletonLoader to create frontend QJoints, when those joints are // set on the skeleton, we end up here. In order to allow the subsequent call @@ -139,239 +134,15 @@ void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) } } } -} - -// TODOSYNC remove once animation aspect no longer requires messages -void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("localPoses")) { - // When the animation aspect sends us a new set of local poses, all we - // need to do is copy them into place. The existing jobs will then update - // the skinning matrix palette. - m_skeletonData.localPoses = change->value().value<QVector<Qt3DCore::Sqt>>(); - } - - break; - } - default: - break; - } - QBackendNode::sceneChangeEvent(e); + auto d = Qt3DCore::QAbstractSkeletonPrivate::get(node); + m_skeletonData.localPoses = d->m_localPoses; } void Skeleton::setStatus(QSkeletonLoader::Status status) { - if (status != m_status) { + if (status != m_status) m_status = status; - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("status"); - e->setValue(QVariant::fromValue(m_status)); - notifyObservers(e); - } -} - -void Skeleton::notifyJointCount() -{ - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("jointCount"); - e->setValue(jointCount()); - notifyObservers(e); -} - -void Skeleton::notifyJointNamesAndPoses() -{ - auto e = QPropertyUpdatedChangePtr::create(peerId()); - JointNamesAndLocalPoses payload{m_skeletonData.jointNames, m_skeletonData.localPoses}; - e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes); - e->setPropertyName("jointNamesAndLocalPoses"); - e->setValue(QVariant::fromValue(payload)); - notifyObservers(e); -} - -void Skeleton::loadSkeleton() -{ - qCDebug(Jobs) << Q_FUNC_INFO << m_source; - clearData(); - - // Load the data - switch (m_dataType) { - case File: - loadSkeletonFromUrl(); - break; - - case Data: - loadSkeletonFromData(); - break; - - default: - Q_UNREACHABLE(); - } - - // If using a loader inform the frontend of the status change. - // Don't bother if asked to create frontend joints though. When - // the backend gets notified of those joints we'll update the - // status at that point. - if (m_dataType == File && !m_createJoints) { - if (jointCount() == 0) - setStatus(QSkeletonLoader::Error); - else - setStatus(QSkeletonLoader::Ready); - } - notifyJointCount(); - notifyJointNamesAndPoses(); - - qCDebug(Jobs) << "Loaded skeleton data:" << *this; -} - -void Skeleton::loadSkeletonFromUrl() -{ - // TODO: Handle remote files - QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source); - QFileInfo info(filePath); - if (!info.exists()) { - qWarning() << "Could not open skeleton file:" << filePath; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Could not open skeleton file:" << filePath; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - - // TODO: Make plugin based for more file type support. For now gltf or native - const QString ext = info.suffix(); - if (ext == QLatin1String("gltf")) { - GLTFSkeletonLoader loader; - loader.load(&file); - m_skeletonData = loader.createSkeleton(m_name); - - // If the user has requested it, create the frontend nodes for the joints - // and send them to the (soon to be owning) QSkeletonLoader. - if (m_createJoints) { - std::unique_ptr<QJoint> rootJoint(createFrontendJoints(m_skeletonData)); - if (!rootJoint) { - qWarning() << "Failed to create frontend joints"; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - - // Move the QJoint tree to the main thread and notify the - // corresponding QSkeletonLoader - const auto appThread = QCoreApplication::instance()->thread(); - rootJoint->moveToThread(appThread); - - auto e = QJointChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - e->setPropertyName("rootJoint"); - e->data = std::move(rootJoint); - notifyObservers(e); - - // Clear the skeleton data. It will be recreated from the - // frontend joints. A little bit inefficient but ensures - // that joints created this way and via QSkeleton go through - // the same code path. - m_skeletonData = SkeletonData(); - } - } else if (ext == QLatin1String("json")) { - // TODO: Support native skeleton type - } else { - qWarning() << "Unknown skeleton file type:" << ext; - setStatus(Qt3DCore::QSkeletonLoader::Error); - return; - } - m_skinningPalette.resize(m_skeletonData.joints.size()); -} - -void Skeleton::loadSkeletonFromData() -{ - // Recurse down through the joint hierarchy and process it into - // the vector of joints used within SkeletonData. The recursion - // ensures that a parent always appears before its children in - // the vector of JointInfo objects. - // - // In addition, we set up a mapping from the joint ids to the - // index of the corresponding JointInfo object in the vector. - // This will allow us to easily update entries in the vector of - // JointInfos when a Joint node marks itself as dirty. - const int rootParentIndex = -1; - processJointHierarchy(m_rootJointId, rootParentIndex, m_skeletonData); - m_skinningPalette.resize(m_skeletonData.joints.size()); -} - -Qt3DCore::QJoint *Skeleton::createFrontendJoints(const SkeletonData &skeletonData) const -{ - if (skeletonData.joints.isEmpty()) - return nullptr; - - // Create frontend joints from the joint info objects - QVector<QJoint *> frontendJoints; - const int jointCount = skeletonData.joints.size(); - frontendJoints.reserve(jointCount); - for (int i = 0; i < jointCount; ++i) { - const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose; - const QString &jointName = skeletonData.jointNames[i]; - const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i]; - frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix)); - } - - // Now go through and resolve the parent for each joint - for (int i = 0; i < frontendJoints.size(); ++i) { - const auto parentIndex = skeletonData.joints[i].parentIndex; - if (parentIndex == -1) - continue; - - // It's not enough to just set up the QObject parent-child relationship. - // We need to explicitly add the child to the parent's list of joints so - // that information is then propagated to the backend. - frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]); - } - - return frontendJoints[0]; -} - -Qt3DCore::QJoint *Skeleton::createFrontendJoint(const QString &jointName, - const Qt3DCore::Sqt &localPose, - const QMatrix4x4 &inverseBindMatrix) const -{ - auto joint = QAbstractNodeFactory::createNode<QJoint>("QJoint"); - joint->setTranslation(localPose.translation); - joint->setRotation(localPose.rotation); - joint->setScale(localPose.scale); - joint->setInverseBindMatrix(inverseBindMatrix); - joint->setName(jointName); - return joint; -} - -void Skeleton::processJointHierarchy(Qt3DCore::QNodeId jointId, - int parentJointIndex, - SkeletonData &skeletonData) -{ - // Lookup the joint, create a JointInfo, and add an entry to the index map - Joint *joint = m_renderer->nodeManagers()->jointManager()->lookupResource(jointId); - Q_ASSERT(joint); - joint->setOwningSkeleton(m_skeletonHandle); - const JointInfo jointInfo(joint, parentJointIndex); - skeletonData.joints.push_back(jointInfo); - skeletonData.localPoses.push_back(joint->localPose()); - skeletonData.jointNames.push_back(joint->name()); - - const int jointIndex = skeletonData.joints.size() - 1; - const HJoint jointHandle = m_jointManager->lookupHandle(jointId); - skeletonData.jointIndices.insert(jointHandle, jointIndex); - - // Recurse to the children - const auto childIds = joint->childJointIds(); - for (const auto childJointId : childIds) - processJointHierarchy(childJointId, jointIndex, skeletonData); } void Skeleton::clearData() @@ -383,6 +154,12 @@ void Skeleton::clearData() m_skeletonData.jointIndices.clear(); } +void Skeleton::setSkeletonData(const SkeletonData &data) +{ + m_skeletonData = data; + m_skinningPalette.resize(m_skeletonData.joints.size()); +} + // Called from UpdateSkinningPaletteJob void Skeleton::setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose) { diff --git a/src/render/geometry/skeleton_p.h b/src/render/geometry/skeleton_p.h index d71b404e5..eb9551f07 100644 --- a/src/render/geometry/skeleton_p.h +++ b/src/render/geometry/skeleton_p.h @@ -75,6 +75,12 @@ class SkeletonManager; class Q_AUTOTEST_EXPORT Skeleton : public BackendNode { public: + enum SkeletonDataType { + Unknown, + File, + Data + }; + Skeleton(); void setSkeletonManager(SkeletonManager *skeletonManager) { m_skeletonManager = skeletonManager; } @@ -84,52 +90,40 @@ public: JointManager *jointManager() const { return m_jointManager; } void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setStatus(Qt3DCore::QSkeletonLoader::Status status); Qt3DCore::QSkeletonLoader::Status status() const { return m_status; } QUrl source() const { return m_source; } + SkeletonDataType dataType() const { return m_dataType; } + bool createJoints() const { return m_createJoints; } void setName(const QString &name) { m_name = name; } QString name() const { return m_name; } int jointCount() const { return m_skeletonData.joints.size(); } - void notifyJointCount(); - void notifyJointNamesAndPoses(); QVector<JointInfo> joints() const { return m_skeletonData.joints; } + QVector<QString> jointNames() const { return m_skeletonData.jointNames; } + QVector<Qt3DCore::Sqt> localPoses() const { return m_skeletonData.localPoses; } Qt3DCore::QNodeId rootJointId() const { return m_rootJointId; } // Called from jobs - void loadSkeleton(); void setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose); QVector<QMatrix4x4> calculateSkinningMatrixPalette(); + void clearData(); + void setSkeletonData(const SkeletonData &data); + const SkeletonData &skeletonData() const { return m_skeletonData; } + SkeletonData skeletonData() { return m_skeletonData; } + // Allow unit tests to set the data type -#if !defined(QT_BUILD_INTERNAL) -private: -#endif - enum SkeletonDataType { - Unknown, - File, - Data - }; #if defined(QT_BUILD_INTERNAL) public: void setDataType(SkeletonDataType dataType) { m_dataType = dataType; } #endif private: - void loadSkeletonFromUrl(); - void loadSkeletonFromData(); - Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const; - Qt3DCore::QJoint *createFrontendJoint(const QString &jointName, - const Qt3DCore::Sqt &localPose, - const QMatrix4x4 &inverseBindMatrix) const; - void processJointHierarchy(Qt3DCore::QNodeId jointId, int parentJointIndex, SkeletonData &skeletonData); - void clearData(); - QVector<QMatrix4x4> m_skinningPalette; // QSkeletonLoader Properties diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp index d66fe3080..cf1e45355 100644 --- a/src/render/io/qsceneloader.cpp +++ b/src/render/io/qsceneloader.cpp @@ -219,6 +219,27 @@ void QSceneLoaderPrivate::setStatus(QSceneLoader::Status status) } } +void QSceneLoaderPrivate::setSceneRoot(QEntity *root) +{ + // If we already have a scene sub tree, delete it + if (m_subTreeRoot) { + delete m_subTreeRoot; + m_subTreeRoot = nullptr; + } + + // If we have successfully loaded a scene, graft it in + if (root) { + // Get the entity to which this component is attached + const Qt3DCore::QNodeIdVector entities = m_scene->entitiesForComponent(m_id); + Q_ASSERT(entities.size() == 1); + Qt3DCore::QNodeId parentEntityId = entities.first(); + QEntity *parentEntity = qobject_cast<QEntity *>(m_scene->lookupNode(parentEntityId)); + root->setParent(parentEntity); + m_subTreeRoot = root; + populateEntityMap(m_subTreeRoot); + } +} + /*! The constructor creates an instance with the specified \a parent. */ @@ -238,38 +259,6 @@ QSceneLoader::QSceneLoader(QSceneLoaderPrivate &dd, QNode *parent) { } -// Called in main thread -/*! \internal */ -void QSceneLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QSceneLoader); - QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change); - if (e->type() == PropertyUpdated) { - if (e->propertyName() == QByteArrayLiteral("scene")) { - // If we already have a scene sub tree, delete it - if (d->m_subTreeRoot) { - delete d->m_subTreeRoot; - d->m_subTreeRoot = nullptr; - } - - // If we have successfully loaded a scene, graft it in - auto *subTreeRoot = e->value().value<Qt3DCore::QEntity *>(); - if (subTreeRoot) { - // Get the entity to which this component is attached - const Qt3DCore::QNodeIdVector entities = d->m_scene->entitiesForComponent(d->m_id); - Q_ASSERT(entities.size() == 1); - Qt3DCore::QNodeId parentEntityId = entities.first(); - QEntity *parentEntity = qobject_cast<QEntity *>(d->m_scene->lookupNode(parentEntityId)); - subTreeRoot->setParent(parentEntity); - d->m_subTreeRoot = subTreeRoot; - d->populateEntityMap(d->m_subTreeRoot); - } - } else if (e->propertyName() == QByteArrayLiteral("status")) { - d->setStatus(e->value().value<QSceneLoader::Status>()); - } - } -} - QUrl QSceneLoader::source() const { Q_D(const QSceneLoader); diff --git a/src/render/io/qsceneloader.h b/src/render/io/qsceneloader.h index 4cb743333..6842a6926 100644 --- a/src/render/io/qsceneloader.h +++ b/src/render/io/qsceneloader.h @@ -60,7 +60,6 @@ public: explicit QSceneLoader(Qt3DCore::QNode *parent = nullptr); ~QSceneLoader(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; enum Status { None = 0, Loading, diff --git a/src/render/io/qsceneloader_p.h b/src/render/io/qsceneloader_p.h index 50745c66f..213bc1104 100644 --- a/src/render/io/qsceneloader_p.h +++ b/src/render/io/qsceneloader_p.h @@ -67,6 +67,7 @@ public: QSceneLoaderPrivate(); void setStatus(QSceneLoader::Status status); + void setSceneRoot(Qt3DCore::QEntity *root); Q_DECLARE_PUBLIC(QSceneLoader) diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp index e7f289f8a..089091701 100644 --- a/src/render/io/scene.cpp +++ b/src/render/io/scene.cpp @@ -66,16 +66,6 @@ void Scene::cleanup() m_source.clear(); } -void Scene::setStatus(QSceneLoader::Status status) -{ - // Send the new subtree to the frontend or notify failure - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("status"); - e->setValue(QVariant::fromValue(status)); - notifyObservers(e); -} - void Scene::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { const QSceneLoader *node = qobject_cast<const QSceneLoader *>(frontEnd); @@ -99,22 +89,6 @@ QUrl Scene::source() const return m_source; } -void Scene::setSceneSubtree(Qt3DCore::QEntity *subTree) -{ - if (subTree) { - // Move scene sub tree to the application thread so that it can be grafted in. - const auto appThread = QCoreApplication::instance()->thread(); - subTree->moveToThread(appThread); - } - - // Send the new subtree to the frontend or notify failure - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("scene"); - e->setValue(QVariant::fromValue(subTree)); - notifyObservers(e); -} - void Scene::setSceneManager(SceneManager *manager) { if (m_sceneManager != manager) diff --git a/src/render/io/scene_p.h b/src/render/io/scene_p.h index 04b9bba1a..bf625b369 100644 --- a/src/render/io/scene_p.h +++ b/src/render/io/scene_p.h @@ -74,7 +74,6 @@ public: void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QUrl source() const; - void setSceneSubtree(Qt3DCore::QEntity *subTree); void setSceneManager(SceneManager *manager); void cleanup(); diff --git a/src/render/jobs/abstractpickingjob.cpp b/src/render/jobs/abstractpickingjob.cpp index 74e6a7f80..35e658535 100644 --- a/src/render/jobs/abstractpickingjob.cpp +++ b/src/render/jobs/abstractpickingjob.cpp @@ -58,13 +58,24 @@ namespace Qt3DRender { namespace Render { AbstractPickingJob::AbstractPickingJob() - : m_manager(nullptr) + : Qt3DCore::QAspectJob() + , m_manager(nullptr) , m_node(nullptr) , m_frameGraphRoot(nullptr) , m_renderSettings(nullptr) { } +AbstractPickingJob::AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd) + : Qt3DCore::QAspectJob(dd) + , m_manager(nullptr) + , m_node(nullptr) + , m_frameGraphRoot(nullptr) + , m_renderSettings(nullptr) +{ + +} + void AbstractPickingJob::setRoot(Entity *root) { m_node = root; diff --git a/src/render/jobs/abstractpickingjob_p.h b/src/render/jobs/abstractpickingjob_p.h index 059c87aa7..c0c6ed7e9 100644 --- a/src/render/jobs/abstractpickingjob_p.h +++ b/src/render/jobs/abstractpickingjob_p.h @@ -90,6 +90,8 @@ public: const QRect &viewport); protected: + AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd); + void run() final; NodeManagers *m_manager; diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h index d72975761..4d93f0f8d 100644 --- a/src/render/jobs/genericlambdajob_p.h +++ b/src/render/jobs/genericlambdajob_p.h @@ -84,6 +84,49 @@ private: template<typename T> using GenericLambdaJobPtr = QSharedPointer<GenericLambdaJob<T>>; +template<typename T, typename U> +class GenericLambdaJobAndPostFramePrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + explicit GenericLambdaJobAndPostFramePrivate(U postFrameCallable) + : m_postFrameCallable(postFrameCallable) + {} + + ~GenericLambdaJobAndPostFramePrivate() override {} + + void postFrame(Qt3DCore::QAspectManager *manager) override + { + m_postFrameCallable(manager); + } + +private: + U m_postFrameCallable; +}; + +template<typename T, typename U> +class GenericLambdaJobAndPostFrame : public Qt3DCore::QAspectJob +{ +public: + explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda) + : Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable)) + , m_runCallable(runCallable) + { + SET_JOB_RUN_STAT_TYPE(this, type, 0); + } + + // QAspectJob interface + void run() final + { + m_runCallable(); + } + +private: + T m_runCallable; +}; + +template<typename T, typename U> +using GenericLambdaJobAndPostFramePtr = QSharedPointer<GenericLambdaJobAndPostFrame<T, U>>; + } // Render } // Qt3DRender diff --git a/src/render/jobs/loadgeometryjob.cpp b/src/render/jobs/loadgeometryjob.cpp index d28b15a7c..88930038a 100644 --- a/src/render/jobs/loadgeometryjob.cpp +++ b/src/render/jobs/loadgeometryjob.cpp @@ -41,6 +41,8 @@ #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/geometryrenderermanager_p.h> #include <Qt3DRender/private/job_common_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DRender/private/qmesh_p.h> QT_BEGIN_NAMESPACE @@ -48,8 +50,19 @@ namespace Qt3DRender { namespace Render { +class LoadGeometryJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + LoadGeometryJobPrivate() {} + ~LoadGeometryJobPrivate() {} + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<std::pair<Qt3DCore::QNodeId, GeometryFunctorResult>> m_updates; +}; + LoadGeometryJob::LoadGeometryJob(const HGeometryRenderer &handle) - : QAspectJob() + : QAspectJob(*new LoadGeometryJobPrivate) , m_handle(handle) , m_nodeManagers(nullptr) { @@ -62,9 +75,27 @@ LoadGeometryJob::~LoadGeometryJob() void LoadGeometryJob::run() { + Q_D(LoadGeometryJob); GeometryRenderer *geometryRenderer = m_nodeManagers->geometryRendererManager()->data(m_handle); if (geometryRenderer != nullptr) - geometryRenderer->executeFunctor(); + d->m_updates.push_back({ geometryRenderer->peerId(), geometryRenderer->executeFunctor() }); +} + +void LoadGeometryJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + const auto updates = std::move(m_updates); + for (const auto &update : updates) { + QGeometryRenderer *gR = static_cast<decltype(gR)>(manager->lookupNode(update.first)); + const GeometryFunctorResult &result = update.second; + gR->setGeometry(result.geometry); + + // Set status if gR is a QMesh instance + QMesh *mesh = qobject_cast<QMesh *>(gR); + if (mesh) { + QMeshPrivate *dMesh = static_cast<decltype(dMesh)>(Qt3DCore::QNodePrivate::get(mesh)); + dMesh->setStatus(result.status); + } + } } } // namespace Render diff --git a/src/render/jobs/loadgeometryjob_p.h b/src/render/jobs/loadgeometryjob_p.h index c02739647..998d543ac 100644 --- a/src/render/jobs/loadgeometryjob_p.h +++ b/src/render/jobs/loadgeometryjob_p.h @@ -62,6 +62,7 @@ namespace Qt3DRender { namespace Render { class NodeManagers; +class LoadGeometryJobPrivate; class Q_AUTOTEST_EXPORT LoadGeometryJob : public Qt3DCore::QAspectJob { @@ -75,6 +76,9 @@ protected: void run() override; HGeometryRenderer m_handle; NodeManagers *m_nodeManagers; + +private: + Q_DECLARE_PRIVATE(LoadGeometryJob) }; typedef QSharedPointer<LoadGeometryJob> LoadGeometryJobPtr; diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp index 9885d3225..f858f82e3 100644 --- a/src/render/jobs/loadscenejob.cpp +++ b/src/render/jobs/loadscenejob.cpp @@ -42,10 +42,12 @@ #include <private/nodemanagers_p.h> #include <private/scenemanager_p.h> #include <Qt3DCore/qentity.h> +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/private/job_common_p.h> #include <Qt3DRender/private/qsceneimporter_p.h> #include <Qt3DRender/private/qurlhelper_p.h> #include <Qt3DRender/qsceneloader.h> +#include <Qt3DRender/private/qsceneloader_p.h> #include <Qt3DRender/private/renderlogging_p.h> #include <QFileInfo> #include <QMimeDatabase> @@ -55,10 +57,10 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId m_sceneComponent) - : QAspectJob() +LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent) + : QAspectJob(*new LoadSceneJobPrivate(this)) , m_source(source) - , m_sceneComponent(m_sceneComponent) + , m_sceneComponent(sceneComponent) , m_managers(nullptr) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0); @@ -97,7 +99,6 @@ void LoadSceneJob::run() Q_ASSERT(scene); // Reset status - scene->setStatus(QSceneLoader::None); QSceneLoader::Status finalStatus = QSceneLoader::None; // Perform the loading only if the source wasn't explicitly set to empty @@ -110,8 +111,7 @@ void LoadSceneJob::run() qCDebug(SceneLoaders) << Q_FUNC_INFO << "Attempting to load" << finfo.filePath(); if (finfo.exists()) { const QStringList extensions(finfo.suffix()); - sceneSubTree = tryLoadScene(scene, - finalStatus, + sceneSubTree = tryLoadScene(finalStatus, extensions, [this] (QSceneImporter *importer) { importer->setSource(m_source); @@ -131,8 +131,7 @@ void LoadSceneJob::run() const QString basePath = m_source.adjusted(QUrl::RemoveFilename).toString(); - sceneSubTree = tryLoadScene(scene, - finalStatus, + sceneSubTree = tryLoadScene(finalStatus, extensions, [this, basePath] (QSceneImporter *importer) { importer->setData(m_data, basePath); @@ -140,19 +139,18 @@ void LoadSceneJob::run() } } - // If the sceneSubTree is null it will trigger the frontend to unload - // any subtree it may hold - // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree - // to the QCoreApplication thread which is where the frontend object tree lives. - scene->setSceneSubtree(sceneSubTree); + Q_D(LoadSceneJob); + d->m_sceneSubtree = sceneSubTree; + d->m_status = finalStatus; - // Note: the status is set after the subtree so that bindinds depending on the status - // in the frontend will be consistent - scene->setStatus(finalStatus); + if (d->m_sceneSubtree) { + // Move scene sub tree to the application thread so that it can be grafted in. + const auto appThread = QCoreApplication::instance()->thread(); + d->m_sceneSubtree->moveToThread(appThread); + } } -Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene, - QSceneLoader::Status &finalStatus, +Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(QSceneLoader::Status &finalStatus, const QStringList &extensions, const std::function<void (QSceneImporter *)> &importerSetupFunc) { @@ -165,9 +163,6 @@ Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene, foundSuitableLoggerPlugin = true; - // If the file type is supported -> enter Loading status - scene->setStatus(QSceneLoader::Loading); - // Set source file or data on importer importerSetupFunc(sceneImporter); @@ -188,6 +183,27 @@ Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene, return sceneSubTree; } +void LoadSceneJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + Q_Q(LoadSceneJob); + QSceneLoader *node = + qobject_cast<QSceneLoader *>(manager->lookupNode(q->sceneComponentId())); + if (!node) + return; + Qt3DRender::QSceneLoaderPrivate *dNode = + static_cast<decltype(dNode)>(Qt3DCore::QNodePrivate::get(node)); + + // If the sceneSubTree is null it will trigger the frontend to unload + // any subtree it may hold + // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree + // to the QCoreApplication thread which is where the frontend object tree lives. + dNode->setSceneRoot(m_sceneSubtree); + + // Note: the status is set after the subtree so that bindinds depending on the status + // in the frontend will be consistent + dNode->setStatus(m_status); +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/jobs/loadscenejob_p.h b/src/render/jobs/loadscenejob_p.h index 0c77dc6e8..3675d94c1 100644 --- a/src/render/jobs/loadscenejob_p.h +++ b/src/render/jobs/loadscenejob_p.h @@ -52,6 +52,7 @@ // #include <Qt3DCore/qaspectjob.h> +#include <Qt3DCore/private/qaspectjob_p.h> #include <Qt3DCore/qnodeid.h> #include <Qt3DRender/qsceneloader.h> #include <QSharedPointer> @@ -69,6 +70,24 @@ namespace Render { class Scene; class NodeManagers; +class LoadSceneJob; + +class Q_AUTOTEST_EXPORT LoadSceneJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + explicit LoadSceneJobPrivate(LoadSceneJob *q): q_ptr(q) {} + ~LoadSceneJobPrivate() override {} + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Qt3DCore::QEntity *m_sceneSubtree = nullptr; + QSceneLoader::Status m_status = QSceneLoader::None; + + Q_DECLARE_PUBLIC(LoadSceneJob) +private: + LoadSceneJob *q_ptr; +}; + class Q_AUTOTEST_EXPORT LoadSceneJob : public Qt3DCore::QAspectJob { public: @@ -91,10 +110,10 @@ private: NodeManagers *m_managers; QList<QSceneImporter *> m_sceneImporters; - Qt3DCore::QEntity *tryLoadScene(Scene *scene, - QSceneLoader::Status &finalStatus, + Qt3DCore::QEntity *tryLoadScene(QSceneLoader::Status &finalStatus, const QStringList &extensions, const std::function<void (QSceneImporter *)> &importerSetupFunc); + Q_DECLARE_PRIVATE(LoadSceneJob) }; typedef QSharedPointer<LoadSceneJob> LoadSceneJobPtr; diff --git a/src/render/jobs/loadskeletonjob.cpp b/src/render/jobs/loadskeletonjob.cpp index 413afc5b5..8d0d47fb9 100644 --- a/src/render/jobs/loadskeletonjob.cpp +++ b/src/render/jobs/loadskeletonjob.cpp @@ -35,32 +35,263 @@ ****************************************************************************/ #include "loadskeletonjob_p.h" -#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qabstractskeleton.h> +#include <Qt3DCore/qskeletonloader.h> +#include <Qt3DCore/private/qabstractskeleton_p.h> +#include <Qt3DCore/private/qabstractnodefactory_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DCore/private/qskeletonloader_p.h> #include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/qurlhelper_p.h> +#include <Qt3DRender/private/gltfskeletonloader_p.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { +class LoadSkeletonJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + LoadSkeletonJobPrivate() : m_backendSkeleton(nullptr), m_loadedRootJoint(nullptr) { } + ~LoadSkeletonJobPrivate() override { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + Skeleton *m_backendSkeleton; + Qt3DCore::QJoint* m_loadedRootJoint; +}; + LoadSkeletonJob::LoadSkeletonJob(const HSkeleton &handle) - : QAspectJob() + : QAspectJob(*new LoadSkeletonJobPrivate) , m_handle(handle) , m_nodeManagers(nullptr) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadSkeleton, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadSkeleton, 0) } -LoadSkeletonJob::~LoadSkeletonJob() +void LoadSkeletonJob::run() { + Q_D(LoadSkeletonJob); + d->m_backendSkeleton = nullptr; + + Skeleton *skeleton = m_nodeManagers->skeletonManager()->data(m_handle); + if (skeleton != nullptr) { + d->m_backendSkeleton = skeleton; + loadSkeleton(skeleton); + } } -void LoadSkeletonJob::run() +void LoadSkeletonJob::loadSkeleton(Skeleton *skeleton) { - Skeleton *skeleton = m_nodeManagers->skeletonManager()->data(m_handle); - if (skeleton != nullptr) - skeleton->loadSkeleton(); + qCDebug(Jobs) << Q_FUNC_INFO << skeleton->source(); + skeleton->clearData(); + + // Load the data + switch (skeleton->dataType()) { + case Skeleton::File: + loadSkeletonFromUrl(skeleton); + break; + + case Skeleton::Data: + loadSkeletonFromData(skeleton); + break; + + default: + Q_UNREACHABLE(); + } + + // If using a loader inform the frontend of the status change. + // Don't bother if asked to create frontend joints though. When + // the backend gets notified of those joints we'll update the + // status at that point. + if (skeleton->dataType() == Skeleton::File && !skeleton->createJoints()) { + if (skeleton->jointCount() == 0) + skeleton->setStatus(Qt3DCore::QSkeletonLoader::Error); + else + skeleton->setStatus(Qt3DCore::QSkeletonLoader::Ready); + } + + qCDebug(Jobs) << "Loaded skeleton data:" << *skeleton; +} + +void LoadSkeletonJob::loadSkeletonFromUrl(Skeleton *skeleton) +{ + Q_D(LoadSkeletonJob); + + using namespace Qt3DCore; + + // TODO: Handle remote files + QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(skeleton->source()); + QFileInfo info(filePath); + if (!info.exists()) { + qWarning() << "Could not open skeleton file:" << filePath; + skeleton->setStatus(Qt3DCore::QSkeletonLoader::Error); + return; + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open skeleton file:" << filePath; + skeleton->setStatus(QSkeletonLoader::Error); + return; + } + + // TODO: Make plugin based for more file type support. For now gltf or native + const QString ext = info.suffix(); + SkeletonData skeletonData; + if (ext == QLatin1String("gltf")) { + GLTFSkeletonLoader loader; + loader.load(&file); + skeletonData = loader.createSkeleton(skeleton->name()); + + // If the user has requested it, create the frontend nodes for the joints + // and send them to the (soon to be owning) QSkeletonLoader. + if (skeleton->createJoints()) { + QJoint *rootJoint = createFrontendJoints(skeletonData); + if (!rootJoint) { + qWarning() << "Failed to create frontend joints"; + skeleton->setStatus(QSkeletonLoader::Error); + return; + } + + // Move the QJoint tree to the main thread and notify the + // corresponding QSkeletonLoader + const auto appThread = QCoreApplication::instance()->thread(); + rootJoint->moveToThread(appThread); + + d->m_loadedRootJoint = rootJoint; + + // Clear the skeleton data. It will be recreated from the + // frontend joints. A little bit inefficient but ensures + // that joints created this way and via QSkeleton go through + // the same code path. + skeletonData = SkeletonData(); + } + } else if (ext == QLatin1String("json")) { + // TODO: Support native skeleton type + } else { + qWarning() << "Unknown skeleton file type:" << ext; + skeleton->setStatus(QSkeletonLoader::Error); + return; + } + + skeleton->setSkeletonData(skeletonData); +} + +void LoadSkeletonJob::loadSkeletonFromData(Skeleton *skeleton) +{ + // Recurse down through the joint hierarchy and process it into + // the vector of joints used within SkeletonData. The recursion + // ensures that a parent always appears before its children in + // the vector of JointInfo objects. + // + // In addition, we set up a mapping from the joint ids to the + // index of the corresponding JointInfo object in the vector. + // This will allow us to easily update entries in the vector of + // JointInfos when a Joint node marks itself as dirty. + const int rootParentIndex = -1; + auto skeletonData = skeleton->skeletonData(); + processJointHierarchy(skeleton->rootJointId(), rootParentIndex, skeletonData); + skeleton->setSkeletonData(skeletonData); +} + +Qt3DCore::QJoint *LoadSkeletonJob::createFrontendJoints(const SkeletonData &skeletonData) const +{ + if (skeletonData.joints.isEmpty()) + return nullptr; + + // Create frontend joints from the joint info objects + QVector<Qt3DCore::QJoint *> frontendJoints; + const int jointCount = skeletonData.joints.size(); + frontendJoints.reserve(jointCount); + for (int i = 0; i < jointCount; ++i) { + const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose; + const QString &jointName = skeletonData.jointNames[i]; + const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i]; + frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix)); + } + + // Now go through and resolve the parent for each joint + for (int i = 0; i < frontendJoints.size(); ++i) { + const auto parentIndex = skeletonData.joints[i].parentIndex; + if (parentIndex == -1) + continue; + + // It's not enough to just set up the QObject parent-child relationship. + // We need to explicitly add the child to the parent's list of joints so + // that information is then propagated to the backend. + frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]); + } + + return frontendJoints[0]; +} + +Qt3DCore::QJoint *LoadSkeletonJob::createFrontendJoint(const QString &jointName, + const Qt3DCore::Sqt &localPose, + const QMatrix4x4 &inverseBindMatrix) const +{ + auto joint = Qt3DCore::QAbstractNodeFactory::createNode<Qt3DCore::QJoint>("QJoint"); + joint->setTranslation(localPose.translation); + joint->setRotation(localPose.rotation); + joint->setScale(localPose.scale); + joint->setInverseBindMatrix(inverseBindMatrix); + joint->setName(jointName); + return joint; +} + +void LoadSkeletonJob::processJointHierarchy(Qt3DCore::QNodeId jointId, + int parentJointIndex, + SkeletonData &skeletonData) +{ + // Lookup the joint, create a JointInfo, and add an entry to the index map + Joint *joint = m_nodeManagers->jointManager()->lookupResource(jointId); + Q_ASSERT(joint); + joint->setOwningSkeleton(m_handle); + const JointInfo jointInfo(joint, parentJointIndex); + skeletonData.joints.push_back(jointInfo); + skeletonData.localPoses.push_back(joint->localPose()); + skeletonData.jointNames.push_back(joint->name()); + + const int jointIndex = skeletonData.joints.size() - 1; + const HJoint jointHandle = m_nodeManagers->jointManager()->lookupHandle(jointId); + skeletonData.jointIndices.insert(jointHandle, jointIndex); + + // Recurse to the children + const auto childIds = joint->childJointIds(); + for (const auto &childJointId : childIds) + processJointHierarchy(childJointId, jointIndex, skeletonData); +} + +void LoadSkeletonJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + if (!m_backendSkeleton) + return; + + using namespace Qt3DCore; + QAbstractSkeleton *node = qobject_cast<QAbstractSkeleton *>(manager->lookupNode(m_backendSkeleton->peerId())); + if (!node) + return; + + QAbstractSkeletonPrivate *dnode = QAbstractSkeletonPrivate::get(node); + dnode->m_jointCount = m_backendSkeleton->jointCount(); + dnode->m_jointNames = m_backendSkeleton->jointNames(); + dnode->m_localPoses = m_backendSkeleton->localPoses(); + dnode->update(); + + QSkeletonLoader *loaderNode = qobject_cast<QSkeletonLoader *>(node); + if (loaderNode) { + QSkeletonLoaderPrivate *dloaderNode = static_cast<QSkeletonLoaderPrivate *>(QSkeletonLoaderPrivate::get(loaderNode)); + dloaderNode->setStatus(m_backendSkeleton->status()); + + if (m_loadedRootJoint) { + dloaderNode->m_rootJoint = m_loadedRootJoint; + m_loadedRootJoint = nullptr; + } + } } } // namespace Render diff --git a/src/render/jobs/loadskeletonjob_p.h b/src/render/jobs/loadskeletonjob_p.h index 2cd9fa8bf..0cc09da3d 100644 --- a/src/render/jobs/loadskeletonjob_p.h +++ b/src/render/jobs/loadskeletonjob_p.h @@ -51,28 +51,46 @@ #include <Qt3DCore/qaspectjob.h> #include <QtCore/qsharedpointer.h> - +#include <Qt3DRender/private/skeletondata_p.h> #include <Qt3DRender/private/handle_types_p.h> QT_BEGIN_NAMESPACE +namespace Qt3DCore { +class QJoint; +} + namespace Qt3DRender { namespace Render { class NodeManagers; +class LoadSkeletonJobPrivate; class LoadSkeletonJob : public Qt3DCore::QAspectJob { public: explicit LoadSkeletonJob(const HSkeleton &handle); - ~LoadSkeletonJob(); void setNodeManagers(NodeManagers *nodeManagers) { m_nodeManagers = nodeManagers; } protected: void run() override; + void loadSkeleton(Skeleton *skeleton); + void loadSkeletonFromUrl(Skeleton *skeleton); + void loadSkeletonFromData(Skeleton *skeleton); + Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const; + Qt3DCore::QJoint *createFrontendJoint(const QString &jointName, + const Qt3DCore::Sqt &localPose, + const QMatrix4x4 &inverseBindMatrix) const; + void processJointHierarchy(Qt3DCore::QNodeId jointId, + int parentJointIndex, + SkeletonData &skeletonData); + HSkeleton m_handle; NodeManagers *m_nodeManagers; + +private: + Q_DECLARE_PRIVATE(LoadSkeletonJob) }; typedef QSharedPointer<LoadSkeletonJob> LoadSkeletonJobPtr; diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp index f3571c210..380447873 100644 --- a/src/render/jobs/raycastingjob.cpp +++ b/src/render/jobs/raycastingjob.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "raycastingjob_p.h" +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/geometryrenderer_p.h> @@ -51,6 +52,7 @@ #include <Qt3DRender/private/rendersettings_p.h> #include <Qt3DRender/private/trianglesvisitor_p.h> #include <Qt3DRender/private/entityvisitor_p.h> +#include <Qt3DRender/private/qabstractraycaster_p.h> QT_BEGIN_NAMESPACE @@ -82,11 +84,43 @@ public: } // anonymous +class Qt3DRender::Render::RayCastingJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + RayCastingJobPrivate() { } + ~RayCastingJobPrivate() override { Q_ASSERT(dispatches.isEmpty()); } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<RayCaster *, QAbstractRayCaster::Hits>> dispatches; +}; + + +void RayCastingJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (auto res: qAsConst(dispatches)) { + QAbstractRayCaster *node = qobject_cast<QAbstractRayCaster *>(manager->lookupNode(res.first->peerId())); + if (!node) + continue; + + QAbstractRayCasterPrivate *d = QAbstractRayCasterPrivate::get(node); + d->dispatchHits(res.second); + + if (node->runMode() == QAbstractRayCaster::SingleShot) { + node->setEnabled(false); + res.first->setEnabled(false); + } + } + + dispatches.clear(); +} + + RayCastingJob::RayCastingJob() - : AbstractPickingJob() + : AbstractPickingJob(*new RayCastingJobPrivate()) , m_castersDirty(true) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0) } void RayCastingJob::markCastersDirty() @@ -239,7 +273,8 @@ void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitLi }; } - rayCaster->dispatchHits(hits); + Q_D(RayCastingJob); + d->dispatches.push_back({rayCaster, hits}); } QT_END_NAMESPACE diff --git a/src/render/jobs/raycastingjob_p.h b/src/render/jobs/raycastingjob_p.h index 0bd8d445a..4b8b91ad5 100644 --- a/src/render/jobs/raycastingjob_p.h +++ b/src/render/jobs/raycastingjob_p.h @@ -68,6 +68,8 @@ namespace PickingUtils { typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList; } +class RayCastingJobPrivate; + class Q_AUTOTEST_EXPORT RayCastingJob : public AbstractPickingJob { public: @@ -80,6 +82,8 @@ protected: void dispatchHits(RayCaster *rayCaster, const PickingUtils::HitList &sphereHits); private: + Q_DECLARE_PRIVATE(RayCastingJob) + bool m_castersDirty; bool m_oneEnabledAtLeast; }; diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp index b5349a2c1..0a28b7628 100644 --- a/src/render/jobs/updatelevelofdetailjob.cpp +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "updatelevelofdetailjob_p.h" +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/QLevelOfDetail> #include <Qt3DRender/private/entityvisitor_p.h> #include <Qt3DRender/private/job_common_p.h> @@ -66,9 +67,11 @@ public: , m_filterValue(filterValue) , m_frameGraphRoot(frameGraphRoot) { + m_updatedIndices.reserve(manager->levelOfDetailManager()->count()); } double filterValue() const { return m_filterValue; } + const QVector<QPair<Qt3DCore::QNodeId, int>> &updatedIndices() const { return m_updatedIndices; } Operation visit(Qt3DRender::Render::Entity *entity = nullptr) override { using namespace Qt3DRender; @@ -102,6 +105,7 @@ public: private: double m_filterValue = 0.; Qt3DRender::Render::FrameGraphNode *m_frameGraphRoot; + QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices; void updateEntityLodByDistance(Qt3DRender::Render::Entity *entity, Qt3DRender::Render::LevelOfDetail *lod) { @@ -128,8 +132,10 @@ private: if (dist <= thresholds[i] || i == n -1) { m_filterValue = approxRollingAverage<30>(m_filterValue, i); i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1); - if (lod->currentIndex() != i) + if (lod->currentIndex() != i) { lod->setCurrentIndex(i); + m_updatedIndices.push_back({lod->peerId(), i}); + } break; } } @@ -172,8 +178,10 @@ private: if (thresholds[i] < area || i == n -1) { m_filterValue = approxRollingAverage<30>(m_filterValue, i); i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1); - if (lod->currentIndex() != i) + if (lod->currentIndex() != i) { lod->setCurrentIndex(i); + m_updatedIndices.push_back({lod->peerId(), i}); + } break; } } @@ -199,13 +207,24 @@ private: namespace Qt3DRender { namespace Render { +class UpdateLevelOfDetailJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + UpdateLevelOfDetailJobPrivate() { } + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices; +}; + UpdateLevelOfDetailJob::UpdateLevelOfDetailJob() - : m_manager(nullptr) + : Qt3DCore::QAspectJob(*new UpdateLevelOfDetailJobPrivate) + , m_manager(nullptr) , m_frameGraphRoot(nullptr) , m_root(nullptr) , m_filterValue(0.) { - SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0); + SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0) } UpdateLevelOfDetailJob::~UpdateLevelOfDetailJob() @@ -229,23 +248,32 @@ void UpdateLevelOfDetailJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) void UpdateLevelOfDetailJob::run() { + Q_D(UpdateLevelOfDetailJob); + Q_ASSERT(m_frameGraphRoot && m_root && m_manager); // short-circuit if no LoDs exist if (m_manager->levelOfDetailManager()->count() == 0) return; - - if (m_manager->levelOfDetailManager()->count() == 0) - return; // no LODs, lets bail out early - LODUpdateVisitor visitor(m_filterValue, m_frameGraphRoot, m_manager); visitor.apply(m_root); m_filterValue = visitor.filterValue(); + d->m_updatedIndices = visitor.updatedIndices(); } -} // Render +void UpdateLevelOfDetailJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + for (const auto &updatedNode: qAsConst(m_updatedIndices)) { + QLevelOfDetail *node = qobject_cast<QLevelOfDetail *>(manager->lookupNode(updatedNode.first)); + if (!node) + continue; + node->setCurrentIndex(updatedNode.second); + } +} + +} // Render } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/jobs/updatelevelofdetailjob_p.h b/src/render/jobs/updatelevelofdetailjob_p.h index 3c7d00d2c..9ac5cf0e9 100644 --- a/src/render/jobs/updatelevelofdetailjob_p.h +++ b/src/render/jobs/updatelevelofdetailjob_p.h @@ -65,6 +65,7 @@ class Entity; class NodeManagers; class LevelOfDetail; class FrameGraphNode; +class UpdateLevelOfDetailJobPrivate; class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateLevelOfDetailJob : public Qt3DCore::QAspectJob { @@ -81,6 +82,8 @@ public: Entity *root() const { return m_root; } private: + Q_DECLARE_PRIVATE(UpdateLevelOfDetailJob) + NodeManagers *m_manager; FrameGraphNode *m_frameGraphRoot; Entity *m_root; diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp index 6b8bccec2..13e14442f 100644 --- a/src/render/jobs/updateworldtransformjob.cpp +++ b/src/render/jobs/updateworldtransformjob.cpp @@ -39,6 +39,9 @@ #include "updateworldtransformjob_p.h" +#include <Qt3DCore/qtransform.h> +#include <Qt3DCore/private/qtransform_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/transform_p.h> @@ -56,10 +59,17 @@ namespace Render { namespace { -void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform) +struct TransformUpdate +{ + Qt3DCore::QNodeId peerId; + QMatrix4x4 worldTransformMatrix; +}; + +QVector<TransformUpdate> updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform) { Matrix4x4 worldTransform(parentTransform); Transform *nodeTransform = node->renderComponent<Transform>(); + QVector<TransformUpdate> updatedTransforms; const bool hasTransformComponent = nodeTransform != nullptr && nodeTransform->isEnabled(); if (hasTransformComponent) @@ -68,21 +78,33 @@ void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Ma if (*(node->worldTransform()) != worldTransform) { *(node->worldTransform()) = worldTransform; if (hasTransformComponent) - nodeTransform->notifyWorldTransformChanged(worldTransform); + updatedTransforms.push_back({nodeTransform->peerId(), convertToQMatrix4x4(worldTransform)}); } const auto childrenHandles = node->childrenHandles(); for (const HEntity &handle : childrenHandles) { Entity *child = manager->renderNodesManager()->data(handle); if (child) - updateWorldTransformAndBounds(manager, child, worldTransform); + updatedTransforms += updateWorldTransformAndBounds(manager, child, worldTransform); } + return updatedTransforms; } } +class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + UpdateWorldTransformJobPrivate() {} + ~UpdateWorldTransformJobPrivate() override {} + + void postFrame(Qt3DCore::QAspectManager *manager) override; + + QVector<TransformUpdate> m_updatedTransforms; +}; + UpdateWorldTransformJob::UpdateWorldTransformJob() - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new UpdateWorldTransformJobPrivate()) , m_node(nullptr) , m_manager(nullptr) { @@ -108,17 +130,32 @@ void UpdateWorldTransformJob::run() // TODO: Parallelise this on each level using a parallel_for // implementation. + Q_D(UpdateWorldTransformJob); qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread(); Matrix4x4 parentTransform; Entity *parent = m_node->parent(); if (parent != nullptr) parentTransform = *(parent->worldTransform()); - updateWorldTransformAndBounds(m_manager, m_node, parentTransform); + d->m_updatedTransforms = updateWorldTransformAndBounds(m_manager, m_node, parentTransform); qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread(); } +void UpdateWorldTransformJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + const QVector<TransformUpdate> updatedTransforms = std::move(m_updatedTransforms); + for (const TransformUpdate &t : updatedTransforms) { + Qt3DCore::QTransform *node = + qobject_cast<Qt3DCore::QTransform *>(manager->lookupNode(t.peerId)); + if (!node) + continue; + Qt3DCore::QTransformPrivate *dNode = + static_cast<Qt3DCore::QTransformPrivate *>(Qt3DCore::QNodePrivate::get(node)); + dNode->setWorldMatrix(t.worldTransformMatrix); + } +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/jobs/updateworldtransformjob_p.h b/src/render/jobs/updateworldtransformjob_p.h index 2689fe45a..e7ff592de 100644 --- a/src/render/jobs/updateworldtransformjob_p.h +++ b/src/render/jobs/updateworldtransformjob_p.h @@ -63,6 +63,7 @@ namespace Render { class Entity; class NodeManagers; +class UpdateWorldTransformJobPrivate; class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJob : public Qt3DCore::QAspectJob { @@ -77,6 +78,7 @@ public: private: Entity *m_node; NodeManagers *m_manager; + Q_DECLARE_PRIVATE(UpdateWorldTransformJob) }; typedef QSharedPointer<UpdateWorldTransformJob> UpdateWorldTransformJobPtr; diff --git a/src/render/lights/light.cpp b/src/render/lights/light.cpp index 30d71082b..3bdab0457 100644 --- a/src/render/lights/light.cpp +++ b/src/render/lights/light.cpp @@ -40,7 +40,6 @@ #include "light_p.h" #include "qabstractlight.h" #include "qabstractlight_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <private/abstractrenderer_p.h> #include <private/nodemanagers_p.h> #include <private/qbackendnode_p.h> diff --git a/src/render/lights/qdirectionallight.cpp b/src/render/lights/qdirectionallight.cpp index 9b6e580de..13fb78843 100644 --- a/src/render/lights/qdirectionallight.cpp +++ b/src/render/lights/qdirectionallight.cpp @@ -39,7 +39,6 @@ #include "qdirectionallight.h" #include "qdirectionallight_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/lights/qspotlight.cpp b/src/render/lights/qspotlight.cpp index c4deaf817..eddafbe61 100644 --- a/src/render/lights/qspotlight.cpp +++ b/src/render/lights/qspotlight.cpp @@ -40,7 +40,6 @@ #include "qspotlight.h" #include "qspotlight_p.h" #include "shaderdata_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/effect.cpp b/src/render/materialsystem/effect.cpp index 76036bd1f..035cf4746 100644 --- a/src/render/materialsystem/effect.cpp +++ b/src/render/materialsystem/effect.cpp @@ -43,10 +43,6 @@ #include <Qt3DRender/qparameter.h> #include <Qt3DRender/private/qeffect_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - #include <QVariant> #include <algorithm> diff --git a/src/render/materialsystem/filterkey.cpp b/src/render/materialsystem/filterkey.cpp index d51a06eec..e6c37b241 100644 --- a/src/render/materialsystem/filterkey.cpp +++ b/src/render/materialsystem/filterkey.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "filterkey_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qfilterkey_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/material.cpp b/src/render/materialsystem/material.cpp index 07764c207..6fda17ccd 100644 --- a/src/render/materialsystem/material.cpp +++ b/src/render/materialsystem/material.cpp @@ -46,10 +46,6 @@ #include "qeffect.h" #include <Qt3DRender/private/qmaterial_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - using namespace Qt3DCore; QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/parameter.cpp b/src/render/materialsystem/parameter.cpp index d32e60a2d..3360aebef 100644 --- a/src/render/materialsystem/parameter.cpp +++ b/src/render/materialsystem/parameter.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "parameter_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/private/qparameter_p.h> #include <Qt3DRender/qtexture.h> @@ -68,6 +67,7 @@ void Parameter::cleanup() m_nameId = -1; m_name.clear(); m_uniformValue = UniformValue(); + m_backendValue = {}; } void Parameter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) diff --git a/src/render/materialsystem/parameter_p.h b/src/render/materialsystem/parameter_p.h index 9deaa11f3..258834ff3 100644 --- a/src/render/materialsystem/parameter_p.h +++ b/src/render/materialsystem/parameter_p.h @@ -76,6 +76,7 @@ public: QString name() const; int nameId() const Q_DECL_NOTHROW { return m_nameId; } const UniformValue &uniformValue() const { return m_uniformValue; } + QVariant backendValue() const { return m_backendValue; } private: QString m_name; diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp index 35ac662fb..35f4d64a9 100644 --- a/src/render/materialsystem/qeffect.cpp +++ b/src/render/materialsystem/qeffect.cpp @@ -42,10 +42,6 @@ #include "qtechnique.h" #include "qparameter.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -172,7 +168,7 @@ QEffect::QEffect(QEffectPrivate &dd, QNode *parent) */ /*! - * Adds \a parameter to the effect. It sends a QPropertyNodeAddedChange to the backend. + * Adds \a parameter to the effect. It sends an update to the backend. * The \a parameter will be used to set a corresponding uniform value in the shader used * by this effect. */ @@ -219,7 +215,7 @@ QVector<QParameter *> QEffect::parameters() const } /*! - * Adds a new technique \a t to the effect. It sends a QPropertyNodeAddedChange to the backend. + * Adds a new technique \a t to the effect. It sends an update to the backend. */ void QEffect::addTechnique(QTechnique *t) { diff --git a/src/render/materialsystem/qfilterkey.cpp b/src/render/materialsystem/qfilterkey.cpp index 547c56d26..dc968400b 100644 --- a/src/render/materialsystem/qfilterkey.cpp +++ b/src/render/materialsystem/qfilterkey.cpp @@ -40,7 +40,6 @@ #include "qfilterkey.h" #include "qfilterkey_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp index db523a700..db286de6b 100644 --- a/src/render/materialsystem/qmaterial.cpp +++ b/src/render/materialsystem/qmaterial.cpp @@ -43,9 +43,6 @@ #include "qeffect.h" #include <Qt3DRender/private/renderlogging_p.h> #include "qparameter.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> /*! \qmltype Material diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp index afaf42158..77eda8c8e 100644 --- a/src/render/materialsystem/qparameter.cpp +++ b/src/render/materialsystem/qparameter.cpp @@ -40,7 +40,6 @@ #include "qparameter.h" #include "qparameter_p.h" #include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtexture.h> diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp index d0821c49c..e9dd50325 100644 --- a/src/render/materialsystem/qrenderpass.cpp +++ b/src/render/materialsystem/qrenderpass.cpp @@ -43,9 +43,6 @@ #include "qparameter.h" #include "qfilterkey.h" #include "qrenderstate.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/private/qnode_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp index dadeb98bd..2b96aa285 100644 --- a/src/render/materialsystem/qtechnique.cpp +++ b/src/render/materialsystem/qtechnique.cpp @@ -41,9 +41,6 @@ #include "qtechnique_p.h" #include "qparameter.h" #include "qgraphicsapifilter.h" -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -376,7 +373,6 @@ QVector<QParameter *> QTechnique::parameters() const return d->m_parameters; } -// TODO Qt 6 -> Remove QGraphicsApiFilter *QTechnique::graphicsApiFilter() { Q_D(QTechnique); diff --git a/src/render/materialsystem/qtechnique.h b/src/render/materialsystem/qtechnique.h index f0c857c2b..b9887b6a2 100644 --- a/src/render/materialsystem/qtechnique.h +++ b/src/render/materialsystem/qtechnique.h @@ -76,7 +76,7 @@ public: void removeRenderPass(QRenderPass *pass); QVector<QRenderPass *> renderPasses() const; - Q_DECL_DEPRECATED QGraphicsApiFilter *graphicsApiFilter(); + QGraphicsApiFilter *graphicsApiFilter(); const QGraphicsApiFilter *graphicsApiFilter() const; protected: diff --git a/src/render/materialsystem/renderpass.cpp b/src/render/materialsystem/renderpass.cpp index aaeca3bb4..19e2a427e 100644 --- a/src/render/materialsystem/renderpass.cpp +++ b/src/render/materialsystem/renderpass.cpp @@ -48,10 +48,6 @@ #include <Qt3DRender/private/renderstates_p.h> #include <Qt3DRender/private/renderstateset_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> - #include <algorithm> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp index b80a66a50..6116ca56b 100644 --- a/src/render/materialsystem/shaderbuilder.cpp +++ b/src/render/materialsystem/shaderbuilder.cpp @@ -39,6 +39,8 @@ #include "shaderbuilder_p.h" +#include <Qt3DCore/qpropertyupdatedchange.h> + #include <Qt3DRender/private/qshaderprogrambuilder_p.h> #include <Qt3DRender/qshaderprogram.h> #include <Qt3DRender/private/qshaderprogram_p.h> diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h index 12234bb6c..6b92d3114 100644 --- a/src/render/materialsystem/shaderbuilder_p.h +++ b/src/render/materialsystem/shaderbuilder_p.h @@ -53,7 +53,6 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/private/qgraphicsapifilter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp index 130333898..34d4641e9 100644 --- a/src/render/materialsystem/shaderdata.cpp +++ b/src/render/materialsystem/shaderdata.cpp @@ -64,8 +64,6 @@ const int qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); } -QVector<Qt3DCore::QNodeId> ShaderData::m_updatedShaderData; - ShaderData::ShaderData() : m_managers(nullptr) { @@ -80,51 +78,82 @@ void ShaderData::setManagers(NodeManagers *managers) m_managers = managers; } -void ShaderData::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderDataData>>(change); - const QShaderDataData &data = typedChange->data; - - m_propertyReader = data.propertyReader; - - for (const QPair<QByteArray, QVariant> &entry : data.properties) { - if (entry.first == QByteArrayLiteral("data") || - entry.first == QByteArrayLiteral("childNodes")) // We don't handle default Node properties - continue; - const QVariant &propertyValue = entry.second; - const QString propertyName = QString::fromLatin1(entry.first); - - m_originalProperties.insert(propertyName, propertyValue); - - // We check if the property is a QNodeId or QVector<QNodeId> so that we can - // check nested QShaderData for update - if (propertyValue.userType() == qNodeIdTypeId) { - m_nestedShaderDataProperties.insert(propertyName, propertyValue); - } else if (propertyValue.userType() == QMetaType::QVariantList) { - QVariantList list = propertyValue.value<QVariantList>(); - if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId) - m_nestedShaderDataProperties.insert(propertyName, propertyValue); - } - } + const QShaderData *node = qobject_cast<const QShaderData *>(frontEnd); + if (!node) + return; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) { + m_propertyReader = node->propertyReader(); + + const QMetaObject *metaObj = node->metaObject(); + const int propertyOffset = QShaderData::staticMetaObject.propertyOffset(); + const int propertyCount = metaObj->propertyCount(); + // Dynamic properties names + const auto dynamicPropertyNames = node->dynamicPropertyNames(); - // We look for transformed properties once the complete hash of - // originalProperties is available - QHash<QString, QVariant>::iterator it = m_originalProperties.begin(); - const QHash<QString, QVariant>::iterator end = m_originalProperties.end(); - - while (it != end) { - if (it.value().type() == QVariant::Vector3D) { - // if there is a matching QShaderData::TransformType propertyTransformed - QVariant value = m_originalProperties.value(it.key() + QLatin1String("Transformed")); - // if that's the case, we apply a space transformation to the property - if (value.isValid() && value.type() == QVariant::Int) - m_transformedProperties.insert(it.key(), static_cast<TransformType>(value.toInt())); + QVector<QString> propertyNames; + propertyNames.reserve(propertyCount - propertyOffset + dynamicPropertyNames.size()); + + // Statiically defined properties + for (int i = propertyOffset; i < propertyCount; ++i) { + const QMetaProperty pro = metaObj->property(i); + if (pro.isWritable()) + propertyNames.push_back(QString::fromLatin1(pro.name())); + } + // Dynamic properties + for (const QByteArray &propertyName : dynamicPropertyNames) + propertyNames.push_back(QString::fromLatin1(propertyName)); + + for (const QString &propertyName : propertyNames) { + if (propertyName == QStringLiteral("data") || + propertyName == QStringLiteral("childNodes")) // We don't handle default Node properties + continue; + + const QVariant &propertyValue = m_propertyReader->readProperty(node->property(propertyName.toLatin1())); + bool isNested = false; + bool isTransformed = false; + + // We check if the property is a QNodeId + isNested = (propertyValue.userType() == qNodeIdTypeId); + // We check if QVector<QNodeId> + if (propertyValue.userType() == QMetaType::QVariantList) { + QVariantList list = propertyValue.value<QVariantList>(); + if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId) + isNested = true; + } + + // We check if property is a Transformed property + if (propertyValue.userType() == QVariant::Vector3D) { + // if there is a matching QShaderData::TransformType propertyTransformed + isTransformed = propertyNames.contains(propertyName + QLatin1String("Transformed")); + } + m_originalProperties.insert(propertyName, { propertyValue, isNested, isTransformed }); + } + BackendNode::markDirty(AbstractRenderer::ParameterDirty); + } else { + // Updates + if (!m_propertyReader.isNull()) { + auto it = m_originalProperties.begin(); + const auto end = m_originalProperties.end(); + + while (it != end) { + const QVariant newValue = m_propertyReader->readProperty(node->property(it.key().toLatin1())); + PropertyValue &propValue = it.value(); + if (propValue.value != newValue) { + // Note we aren't notified about nested QShaderData in this call + // only scalar / vec properties + propValue.value = newValue; + BackendNode::markDirty(AbstractRenderer::ParameterDirty); + } + ++it; + } } - ++it; } } - ShaderData *ShaderData::lookupResource(NodeManagers *managers, QNodeId id) { return managers->shaderDataManager()->lookupResource(id); @@ -135,120 +164,62 @@ ShaderData *ShaderData::lookupResource(QNodeId id) return ShaderData::lookupResource(m_managers, id); } -// Call by cleanup job (single thread) -void ShaderData::clearUpdatedProperties() -{ - // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7 - // const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end(); - // QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin(); - - // while (it != end) { - // if (it.value().userType() == QMetaType::QVariantList) { - // const auto values = it.value().value<QVariantList>(); - // for (const QVariant &v : values) { - // ShaderData *nested = lookupResource(v.value<QNodeId>()); - // if (nested != nullptr) - // nested->clearUpdatedProperties(); - // } - // } else { - // ShaderData *nested = lookupResource(it.value().value<QNodeId>()); - // if (nested != nullptr) - // nested->clearUpdatedProperties(); - // } - // ++it; - // } -} - void ShaderData::cleanup(NodeManagers *managers) { Q_UNUSED(managers) - // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7 - // for (Qt3DCore::QNodeId id : qAsConst(m_updatedShaderData)) { - // ShaderData *shaderData = ShaderData::lookupResource(managers, id); - // if (shaderData) - // shaderData->clearUpdatedProperties(); - // } - m_updatedShaderData.clear(); } +// RenderCommand updater jobs QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) { // Note protecting m_worldMatrix at this point as we assume all world updates // have been performed when reaching this point - auto it = m_transformedProperties.find(name); - if (it != m_transformedProperties.end()) { - const TransformType transformType = it.value(); - switch (transformType) { - case ModelToEye: - return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(m_originalProperties.value(name).value<QVector3D>())); - case ModelToWorld: - return QVariant::fromValue(m_worldMatrix * Vector3D(m_originalProperties.value(it.key()).value<QVector3D>())); - case ModelToWorldDirection: - return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f))); - case NoTransform: - break; + const auto it = m_originalProperties.constFind(name); + if (it != m_originalProperties.constEnd()) { + const PropertyValue &propertyValue = it.value(); + if (propertyValue.isTransformed) { + const auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed")); + if (transformedIt != m_originalProperties.constEnd()) { + const PropertyValue &transformedValue = transformedIt.value(); + const TransformType transformType = static_cast<TransformType>(transformedValue.value.toInt()); + switch (transformType) { + case ModelToEye: + return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>())); + case ModelToWorld: + return QVariant::fromValue(m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>())); + case ModelToWorldDirection: + return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(propertyValue.value.value<QVector3D>(), 0.0f))); + case NoTransform: + break; + } + } } + return propertyValue.value; } return QVariant(); } -// Called by FramePreparationJob or by RenderView when dealing with lights -void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix) -{ - QMutexLocker lock(&m_mutex); - if (m_worldMatrix != worldMatrix) { - m_worldMatrix = worldMatrix; - } -} - -// This will add the ShaderData to be cleared from updates at the end of the frame -// by the cleanup job -// Called by renderview jobs (several concurrent threads) -void ShaderData::markDirty() -{ - QMutexLocker lock(&m_mutex); - if (!ShaderData::m_updatedShaderData.contains(peerId())) - ShaderData::m_updatedShaderData.append(peerId()); -} - -/*! - \internal - Lookup if the current ShaderData or a nested ShaderData has updated properties. - UpdateProperties contains either the value of the propertie of a QNodeId if it's another ShaderData. - Transformed properties are updated for all of ShaderData that have ones at the point. - - \note This needs to be performed for every top level ShaderData every time it is used. - As we don't know if the transformed properties use the same viewMatrix for all RenderViews. - */ - +// Unit tests only ShaderData::TransformType ShaderData::propertyTransformType(const QString &name) const { - return m_transformedProperties.value(name, TransformType::NoTransform); + const auto it = m_originalProperties.constFind(name); + if (it != m_originalProperties.constEnd()) { + const PropertyValue &propertyValue = it.value(); + if (propertyValue.isTransformed) { + auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed")); + if (transformedIt != m_originalProperties.end()) + return static_cast<TransformType>(transformedIt.value().value.toInt()); + } + } + return NoTransform; } -void ShaderData::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +// Called by FramePreparationJob or by RenderView when dealing with lights +void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix) { - if (!m_propertyReader.isNull() && e->type() == PropertyUpdated) { - QString propertyName; - QVariant propertyValue; - - if (auto propertyChange = qSharedPointerDynamicCast<QPropertyUpdatedChange>(e)) { - propertyName = QString::fromLatin1(propertyChange->propertyName()); - propertyValue = m_propertyReader->readProperty(propertyChange->value()); - } else if (auto propertyChange = qSharedPointerDynamicCast<QDynamicPropertyUpdatedChange>(e)) { - propertyName = QString::fromLatin1(propertyChange->propertyName()); - propertyValue = m_propertyReader->readProperty(propertyChange->value()); - } else { - Q_UNREACHABLE(); - } - - // Note we aren't notified about nested QShaderData in this call - // only scalar / vec properties - m_originalProperties.insert(propertyName, propertyValue); - BackendNode::markDirty(AbstractRenderer::ParameterDirty); + if (m_worldMatrix != worldMatrix) { + m_worldMatrix = worldMatrix; } - - BackendNode::sceneChangeEvent(e); } RenderShaderDataFunctor::RenderShaderDataFunctor(AbstractRenderer *renderer, NodeManagers *managers) diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h index f9c3ecc79..c9cc22939 100644 --- a/src/render/materialsystem/shaderdata_p.h +++ b/src/render/materialsystem/shaderdata_p.h @@ -76,49 +76,42 @@ public: ModelToWorld, ModelToWorldDirection }; + struct PropertyValue { + QVariant value; + bool isNested; + bool isTransformed; + }; ShaderData(); ~ShaderData(); - QHash<QString, QVariant> properties() const { return m_originalProperties; } + QHash<QString, PropertyValue> properties() const { return m_originalProperties; } // Called by FramePreparationJob void updateWorldTransform(const Matrix4x4 &worldMatrix); - // Call by RenderViewJob - void markDirty(); + QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix); + // Unit tests purposes only TransformType propertyTransformType(const QString &name) const; - QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix); // Called by FrameCleanupJob static void cleanup(NodeManagers *managers); void setManagers(NodeManagers *managers); -protected: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; +protected: PropertyReaderInterfacePtr m_propertyReader; - // 1 to 1 match with frontend properties, modified only by sceneChangeEvent - QHash<QString, QVariant> m_originalProperties; - - // Contains properties thar are of type ShaderData - QHash<QString, QVariant> m_nestedShaderDataProperties; - - // Contains property that are defined like: postionTransformed: ModelToEye - QHash<QString, TransformType> m_transformedProperties; + // 1 to 1 match with frontend properties + QHash<QString, PropertyValue> m_originalProperties; - QMutex m_mutex; - static QVector<Qt3DCore::QNodeId> m_updatedShaderData; Matrix4x4 m_worldMatrix; - Matrix4x4 m_viewMatrix; NodeManagers *m_managers; - void clearUpdatedProperties(); static ShaderData *lookupResource(NodeManagers *managers, Qt3DCore::QNodeId id); ShaderData *lookupResource(Qt3DCore::QNodeId id); diff --git a/src/render/materialsystem/shaderimage.cpp b/src/render/materialsystem/shaderimage.cpp index c1fb72bfd..65a4cf761 100644 --- a/src/render/materialsystem/shaderimage.cpp +++ b/src/render/materialsystem/shaderimage.cpp @@ -39,7 +39,6 @@ #include "shaderimage_p.h" #include <Qt3DRender/private/qshaderimage_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qabstracttexture.h> diff --git a/src/render/materialsystem/technique.cpp b/src/render/materialsystem/technique.cpp index d4199b7e3..10e9af990 100644 --- a/src/render/materialsystem/technique.cpp +++ b/src/render/materialsystem/technique.cpp @@ -48,9 +48,6 @@ #include <Qt3DRender/private/qtechnique_p.h> #include <Qt3DRender/private/shader_p.h> #include <Qt3DCore/private/qchangearbiter_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/techniquemanager_p.h> #include <Qt3DRender/private/nodemanagers_p.h> diff --git a/src/render/picking/qraycaster.cpp b/src/render/picking/qraycaster.cpp index 27307d2a8..f32ea32f1 100644 --- a/src/render/picking/qraycaster.cpp +++ b/src/render/picking/qraycaster.cpp @@ -40,7 +40,6 @@ #include "qraycaster.h" #include "qabstractraycaster_p.h" #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> diff --git a/src/render/picking/qscreenraycaster.cpp b/src/render/picking/qscreenraycaster.cpp index ef87632b4..3e47c2a01 100644 --- a/src/render/picking/qscreenraycaster.cpp +++ b/src/render/picking/qscreenraycaster.cpp @@ -40,7 +40,6 @@ #include "qscreenraycaster.h" #include "qabstractraycaster_p.h" #include <Qt3DCore/qentity.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp index 34bbaefd9..3a79204c7 100644 --- a/src/render/picking/raycaster.cpp +++ b/src/render/picking/raycaster.cpp @@ -45,8 +45,6 @@ #include <Qt3DRender/private/qabstractraycaster_p.h> #include <Qt3DRender/private/raycastingjob_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE @@ -179,24 +177,6 @@ void RayCaster::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime } } -void RayCaster::dispatchHits(const QAbstractRayCaster::Hits &hits) -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("hits"); - e->setValue(QVariant::fromValue(hits)); - notifyObservers(e); - - if (m_runMode == QAbstractRayCaster::SingleShot) { - setEnabled(false); - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("enabled"); - e->setValue(false); - notifyObservers(e); - } -} - void RayCaster::notifyJob() { if (m_renderer && m_renderer->rayCastingJob()) diff --git a/src/render/picking/raycaster_p.h b/src/render/picking/raycaster_p.h index 2be87ec3c..865d40365 100644 --- a/src/render/picking/raycaster_p.h +++ b/src/render/picking/raycaster_p.h @@ -83,8 +83,6 @@ public: void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void cleanup(); - void dispatchHits(const QAbstractRayCaster::Hits &hits); - private: void notifyJob(); diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp index bedc7f61c..4b4199820 100644 --- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp @@ -1572,7 +1572,8 @@ void SubmissionContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId, const GLenum mode = interpolationMethod ? GL_NEAREST : GL_LINEAR; m_glHelper->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - GL_COLOR_BUFFER_BIT, mode); + GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, + mode); // Reset draw buffer bindFramebuffer(lastDrawFboId, GraphicsHelperInterface::FBOReadAndDraw); diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp index c70f82dea..fee1cc4b5 100644 --- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp +++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp @@ -512,27 +512,24 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * // If the property needs to be transformed, we transform it here as // the shaderdata cannot hold transformed properties for multiple // thread contexts at once - if (currentShaderData->propertyTransformType(qmlPropertyName) != ShaderData::NoTransform) - activeUniformNamesToValue.insert(StringToInt::lookupId(varName), - currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix)); - else - activeUniformNamesToValue.insert(StringToInt::lookupId(varName), value); + activeUniformNamesToValue.insert(StringToInt::lookupId(varName), + currentShaderData->getTransformedProperty(qmlPropertyName.toLatin1(), viewMatrix)); } } } void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName) { - const QHash<QString, QVariant> &properties = rShaderData->properties(); - QHash<QString, QVariant>::const_iterator it = properties.begin(); - const QHash<QString, QVariant>::const_iterator end = properties.end(); + const QHash<QString, ShaderData::PropertyValue> &properties = rShaderData->properties(); + auto it = properties.begin(); + const auto end = properties.end(); while (it != end) { const auto prefix = qmlPropertyName.isEmpty() ? QLatin1String("") : QLatin1String("."); buildActiveUniformNameValueMapHelper(rShaderData, blockName + prefix + qmlPropertyName, it.key(), - it.value()); + it.value().value); ++it; } } diff --git a/src/render/renderers/opengl/renderer/commandthread.cpp b/src/render/renderers/opengl/renderer/commandthread.cpp deleted file mode 100644 index a518d3b68..000000000 --- a/src/render/renderers/opengl/renderer/commandthread.cpp +++ /dev/null @@ -1,204 +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: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 "commandthread_p.h" -#include <Qt3DRender/private/glcommands_p.h> -#include <Qt3DRender/private/offscreensurfacehelper_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/shadercache_p.h> -#include <QOpenGLContext> -#include <QOffscreenSurface> -#include <QDebug> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -CommandThread::CommandThread(Renderer *renderer) - : QThread() - , m_renderer(renderer) - , m_waitForStartSemaphore(0) - , m_initializedSemaphore(0) - , m_commandRequestedSemaphore(0) - , m_commandExecutionSemaphore(0) - , m_mainContext(nullptr) - , m_shaderCache(nullptr) - , m_offsreenSurfaceHelper(nullptr) - , m_currentCommand(nullptr) - , m_running(0) -{ -} - -CommandThread::~CommandThread() -{ - Q_ASSERT(!isRunning()); -} - -void CommandThread::setShaderCache(ShaderCache *shaderCache) -{ - m_shaderCache = shaderCache; -} - -// Called by RenderThread or MainThread (Scene3d) -void CommandThread::initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper) -{ - // Start the thread - start(); - - // Wait for thread to be started - m_waitForStartSemaphore.acquire(); - - m_mainContext = mainContext; - m_offsreenSurfaceHelper = offsreenSurfaceHelper; - Q_ASSERT(m_mainContext && offsreenSurfaceHelper); - - // Initialize shared context and resources for the thread. This must be - // done here since some platforms do not allow context sharing to be set up - // with contexts created on different threads. (Windows with WGL, in - // particular; resource sharing works fine later on, what matters is the - // thread the wglShareLists call is made on) - m_localContext.reset(new QOpenGLContext()); - m_localContext->setFormat(m_mainContext->format()); - m_localContext->setShareContext(m_mainContext); - if (!m_localContext->create()) - qWarning("CommandThread: Failed to create local context"); - m_localContext->moveToThread(this); - - m_running.fetchAndStoreOrdered(1); - - // Allow thread to proceed - m_initializedSemaphore.release(); -} - -// Called by RenderThread or MainThread (Scene3D) -void CommandThread::shutdown() -{ - m_running.fetchAndStoreOrdered(0); - - // Unblock thread - m_commandRequestedSemaphore.release(1); - - // Wait for thread to exit - wait(); - - // Reset semaphores (in case we ever want to restart) - m_waitForStartSemaphore.acquire(m_waitForStartSemaphore.available()); - m_initializedSemaphore.acquire(m_initializedSemaphore.available()); - m_commandRequestedSemaphore.acquire(m_commandRequestedSemaphore.available()); - m_commandExecutionSemaphore.acquire(m_commandExecutionSemaphore.available()); - m_localContext.reset(); -} - -// Any thread can call this, this is a blocking command -void CommandThread::executeCommand(GLCommand *command) -{ - if (!isRunning()) - return; - - // We lock to prevent any other call to executeCommand to be executed - // before we have received the result of our command - m_blockingCallerMutex.lock(); - - // Store command to be executed - m_currentCommand = command; - - // Allow thread to proceed and execute command - m_commandRequestedSemaphore.release(); - - // Wait for thread to be done - m_commandExecutionSemaphore.acquire(); - - // Reset command - m_currentCommand = nullptr; - - // Unlock blocking semaphore so that other calls to executeCommand - // can proceed - m_blockingCallerMutex.unlock(); -} - -void CommandThread::run() -{ - // Allow initialize to proceed - m_waitForStartSemaphore.release(); - - // Wait for initialize to be completed - m_initializedSemaphore.acquire(); - - Q_ASSERT(m_mainContext && m_shaderCache); - - // Initialize GraphicsContext - m_graphicsContext.reset(new GraphicsContext()); - m_graphicsContext->setShaderCache(m_shaderCache); - m_graphicsContext->setOpenGLContext(m_localContext.data()); - - bool initialized = false; - while (true) { - - // Wait for command - m_commandRequestedSemaphore.acquire(); - - // Are we still running? - if (!m_running.loadRelaxed()) { - m_graphicsContext->doneCurrent(); - // to prevent executeCommand being locked - m_commandExecutionSemaphore.release(); - break; - } - - if (Q_UNLIKELY(!initialized)) { - QOffscreenSurface *offscreenSurface = m_offsreenSurfaceHelper->offscreenSurface(); - Q_ASSERT(offscreenSurface); - m_graphicsContext->makeCurrent(offscreenSurface); - initialized = true; - } - - m_currentCommand->execute(m_renderer, m_graphicsContext.data()); - - // Allow caller to proceed as we are done with the command - m_commandExecutionSemaphore.release(); - } -} - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/renderers/opengl/renderer/commandthread_p.h b/src/render/renderers/opengl/renderer/commandthread_p.h deleted file mode 100644 index 0508675c4..000000000 --- a/src/render/renderers/opengl/renderer/commandthread_p.h +++ /dev/null @@ -1,115 +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: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$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_COMMANDTHREAD_P_H -#define QT3DRENDER_RENDER_COMMANDTHREAD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QThread> -#include <QtCore/QSemaphore> -#include <QtCore/QMutex> - -QT_BEGIN_NAMESPACE - -class QOpenGLContext; - -namespace Qt3DRender { - -namespace Render { - -class Renderer; -class GLCommand; -class OffscreenSurfaceHelper; -class GraphicsContext; -class ShaderCache; - -class CommandThread : public QThread -{ - Q_OBJECT -public: - explicit CommandThread(Renderer *renderer); - ~CommandThread(); - - Render::Renderer* renderer() const { return m_renderer; } - - void setShaderCache(ShaderCache *shaderCache); - ShaderCache *shaderCache() const { return m_shaderCache; } - - void initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper); - void shutdown(); - - void executeCommand(GLCommand *command); - -private: - void run() override; - void executeCommandInternal(Qt3DRender::Render::GLCommand *command); - -private: - Renderer* m_renderer; - QSemaphore m_waitForStartSemaphore; - QSemaphore m_initializedSemaphore; - QSemaphore m_commandRequestedSemaphore; - QSemaphore m_commandExecutionSemaphore; - QMutex m_blockingCallerMutex; - QOpenGLContext *m_mainContext; - ShaderCache *m_shaderCache; - OffscreenSurfaceHelper *m_offsreenSurfaceHelper; - QScopedPointer<QOpenGLContext> m_localContext; - QScopedPointer<GraphicsContext> m_graphicsContext; - GLCommand *m_currentCommand; - QAtomicInt m_running; -}; - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_COMMANDTHREAD_P_H diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 45f13c424..42af03d11 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -89,14 +89,13 @@ #include <Qt3DRender/private/buffercapture_p.h> #include <Qt3DRender/private/offscreensurfacehelper_p.h> #include <Qt3DRender/private/renderviewbuilder_p.h> -#include <Qt3DRender/private/commandthread_p.h> -#include <Qt3DRender/private/glcommands_p.h> #include <Qt3DRender/private/setfence_p.h> #include <Qt3DRender/private/subtreeenabler_p.h> #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/private/qeventfilterservice_p.h> #include <Qt3DCore/private/qabstractaspectjobmanager_p.h> +#include <Qt3DCore/private/qaspectmanager_p.h> #if QT_CONFIG(qt3d_profile_jobs) #include <Qt3DCore/private/aspectcommanddebugger_p.h> @@ -165,7 +164,6 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_submissionContext(nullptr) , m_renderQueue(new RenderQueue()) , m_renderThread(type == QRenderAspect::Threaded ? new RenderThread(this) : nullptr) - , m_commandThread(new CommandThread(this)) , m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService(m_renderThread != nullptr)) , m_waitForInitializationToBeCompleted(0) , m_hasBeenInitializedMutex() @@ -196,7 +194,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) - , m_sendTextureChangesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendTextureChangesToFrontend(); }, JobTypes::SendTextureChangesToFrontend)) + , m_sendTextureChangesToFrontendJob(decltype(m_sendTextureChangesToFrontendJob)::create([] {}, + [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); }, + JobTypes::SendTextureChangesToFrontend)) , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) , m_sendDisablesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend)) , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) @@ -331,18 +331,11 @@ QOpenGLContext *Renderer::shareContext() const : nullptr); } -// Executed in the command thread +// Executed in the reloadDirtyShader job void Renderer::loadShader(Shader *shader, HShader shaderHandle) { -#ifdef SHADER_LOADING_IN_COMMAND_THREAD - Q_UNUSED(shaderHandle); - Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload); - LoadShaderCommand cmd(shader); - m_commandThread->executeCommand(&cmd); -#else Q_UNUSED(shader); m_dirtyShaders.push_back(shaderHandle); -#endif } void Renderer::setOpenGLContext(QOpenGLContext *context) @@ -403,7 +396,6 @@ void Renderer::initialize() // Set shader cache on submission context and command thread m_submissionContext->setShaderCache(m_shaderCache); - m_commandThread->setShaderCache(m_shaderCache); // Note: we don't have a surface at this point // The context will be made current later on (at render time) @@ -416,13 +408,6 @@ void Renderer::initialize() // (MS Windows), an offscreen surface is just a hidden QWindow. m_format = ctx->format(); QMetaObject::invokeMethod(m_offscreenHelper, "createOffscreenSurface"); - - // Initialize command thread (uses the offscreen surface to make its own ctx current) - m_commandThread->initialize(ctx, m_offscreenHelper); - // Note: the offscreen surface is also used at shutdown time to release resources - // of the submission gl context (when the window is already gone). - // By that time (in releaseGraphicResources), the commandThread has been destroyed - // and the offscreenSurface can be reused } // Awake setScenegraphRoot in case it was waiting @@ -454,8 +439,6 @@ void Renderer::shutdown() m_renderQueue->reset(); lockRenderQueue.unlock(); - m_commandThread->shutdown(); - if (!m_renderThread) { releaseGraphicsResources(); } else { @@ -1167,24 +1150,39 @@ void Renderer::reloadDirtyShaders() } } -// Executed in a job -void Renderer::sendTextureChangesToFrontend() +// Executed in a job (as postFrame) +void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager) { const QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties); for (const auto &pair : updateTextureProperties) { - // Prepare change notification - const Qt3DCore::QNodeIdVector targetIds = pair.second; for (const Qt3DCore::QNodeId targetId: targetIds) { + // Lookup texture Texture *t = m_nodesManager->textureManager()->lookupResource(targetId); + // If backend texture is Dirty, some property has changed and the properties we are + // about to send are already outdate + if (t == nullptr || t->dirtyFlags() != Texture::NotDirty) + continue; - // Texture might have been deleted between previous and current frame - if (t == nullptr) + QAbstractTexture *texture = static_cast<QAbstractTexture *>(manager->lookupNode(targetId)); + if (!texture) continue; + const TextureProperties &properties = pair.first.properties; + + const bool blocked = texture->blockNotifications(true); + texture->setWidth(properties.width); + texture->setHeight(properties.height); + texture->setDepth(properties.depth); + texture->setLayers(properties.layers); + texture->setFormat(properties.format); + texture->blockNotifications(blocked); + + QAbstractTexturePrivate *dTexture = static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(texture)); - // Send change and update backend - t->updatePropertiesAndNotify(pair.first); + dTexture->setStatus(properties.status); + dTexture->setHandleType(pair.first.handleType); + dTexture->setHandle(pair.first.handle); } } } @@ -1807,11 +1805,12 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() const bool frameGraphDirty = dirtyBitsForFrame & AbstractRenderer::FrameGraphDirty; const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty; + const bool shadersDirty = dirtyBitsForFrame & AbstractRenderer::ShadersDirty; const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; const bool lightsDirty = dirtyBitsForFrame & AbstractRenderer::LightsDirty; const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty; const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty; - const bool materialCacheNeedsToBeRebuilt = materialDirty || frameGraphDirty; + const bool materialCacheNeedsToBeRebuilt = shadersDirty || materialDirty || frameGraphDirty; // Rebuild Entity Layers list if layers are dirty if (layersDirty) diff --git a/src/render/renderers/opengl/renderer/renderer.pri b/src/render/renderers/opengl/renderer/renderer.pri index 34f6064bd..849bac702 100644 --- a/src/render/renderers/opengl/renderer/renderer.pri +++ b/src/render/renderers/opengl/renderer/renderer.pri @@ -1,8 +1,6 @@ INCLUDEPATH += $$PWD SOURCES += \ - $$PWD/commandthread.cpp \ - $$PWD/glcommands.cpp \ $$PWD/openglvertexarrayobject.cpp \ $$PWD/rendercommand.cpp \ $$PWD/renderer.cpp \ @@ -12,8 +10,6 @@ SOURCES += \ $$PWD/shaderparameterpack.cpp HEADERS += \ - $$PWD/commandthread_p.h \ - $$PWD/glcommands_p.h \ $$PWD/openglvertexarrayobject_p.h \ $$PWD/renderercache_p.h \ $$PWD/rendercommand_p.h \ diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index c7b4f8805..41a071290 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -144,7 +144,6 @@ class RenderView; class Effect; class RenderPass; class RenderThread; -class CommandThread; class RenderStateSet; class VSyncFrameAdvanceService; class PickEventFilter; @@ -320,7 +319,6 @@ private: RenderQueue *m_renderQueue; QScopedPointer<RenderThread> m_renderThread; - QScopedPointer<CommandThread> m_commandThread; QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService; QSemaphore m_submitRenderViewsSemaphore; @@ -379,7 +377,7 @@ private: GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; - GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob; + GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>> m_sendTextureChangesToFrontendJob; GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob; GenericLambdaJobPtr<std::function<void ()>> m_sendDisablesToFrontendJob; IntrospectShadersJobPtr m_introspectShaderJob; @@ -391,7 +389,7 @@ private: void lookForDownloadableBuffers(); void lookForDirtyTextures(); void reloadDirtyShaders(); - void sendTextureChangesToFrontend(); + void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager); void sendSetFenceHandlesToFrontend(); void sendDisablesToFrontend(); diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index 420b32325..8fbe8e188 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -849,56 +849,6 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, uniformPack.setUniformBuffer(std::move(uniformBlockUBO)); // Buffer update to GL buffer will be done at render time } - - - //ShaderData *shaderData = nullptr; - // if ((shaderData = m_manager->shaderDataManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != nullptr) { - // UBO are indexed by <ShaderId, ShaderDataId> so that a same QShaderData can be used among different shaders - // while still making sure that if they have a different layout everything will still work - // If two shaders define the same block with the exact same layout, in that case the UBO could be shared - // but how do we know that ? We'll need to compare ShaderUniformBlocks - - // Note: we assume that if a buffer is shared across multiple shaders - // then it implies that they share the same layout - - // Temporarly disabled - - // BufferShaderKey uboKey(shaderData->peerId(), - // shader->peerId()); - - // BlockToUBO uniformBlockUBO; - // uniformBlockUBO.m_blockIndex = block.m_index; - // uniformBlockUBO.m_shaderDataID = shaderData->peerId(); - // bool uboNeedsUpdate = false; - - // // build UBO at uboId if not created before - // if (!m_manager->glBufferManager()->contains(uboKey)) { - // m_manager->glBufferManager()->getOrCreateResource(uboKey); - // uboNeedsUpdate = true; - // } - - // // If shaderData has been updated (property has changed or one of the nested properties has changed) - // // foreach property defined in the QShaderData, we try to fill the value of the corresponding active uniform(s) - // // for all the updated properties (all the properties if the UBO was just created) - // if (shaderData->updateViewTransform(*m_data->m_viewMatrix) || uboNeedsUpdate) { - // // Clear previous values remaining in the hash - // m_data->m_uniformBlockBuilder.activeUniformNamesToValue.clear(); - // // Update only update properties if uboNeedsUpdate is true, otherwise update the whole block - // m_data->m_uniformBlockBuilder.updatedPropertiesOnly = uboNeedsUpdate; - // // Retrieve names and description of each active uniforms in the uniform block - // m_data->m_uniformBlockBuilder.uniforms = shader->activeUniformsForUniformBlock(block.m_index); - // // Builds the name-value map for the block - // m_data->m_uniformBlockBuilder.buildActiveUniformNameValueMapStructHelper(shaderData, block.m_name); - // if (!uboNeedsUpdate) - // shaderData->markDirty(); - // // copy the name-value map into the BlockToUBO - // uniformBlockUBO.m_updatedProperties = m_data->m_uniformBlockBuilder.activeUniformNamesToValue; - // uboNeedsUpdate = true; - // } - - // uniformBlockUBO.m_needsUpdate = uboNeedsUpdate; - // uniformPack.setUniformBuffer(std::move(uniformBlockUBO)); - // } } } diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp index 11d2c2be9..1b5a972ec 100644 --- a/src/render/renderers/opengl/textures/gltexture.cpp +++ b/src/render/renderers/opengl/textures/gltexture.cpp @@ -54,9 +54,6 @@ #include <Qt3DRender/private/qabstracttexture_p.h> #include <Qt3DRender/private/renderbuffer_p.h> #include <Qt3DRender/private/qtextureimagedata_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #if !defined(QT_OPENGL_ES_2) #include <QOpenGLFunctions_3_1> diff --git a/src/render/renderstates/qdithering.cpp b/src/render/renderstates/qdithering.cpp index ae77ced97..a449be508 100644 --- a/src/render/renderstates/qdithering.cpp +++ b/src/render/renderstates/qdithering.cpp @@ -41,7 +41,6 @@ #include "qdithering.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qmultisampleantialiasing.cpp b/src/render/renderstates/qmultisampleantialiasing.cpp index bb5136846..249dcd4bd 100644 --- a/src/render/renderstates/qmultisampleantialiasing.cpp +++ b/src/render/renderstates/qmultisampleantialiasing.cpp @@ -40,7 +40,6 @@ #include "qmultisampleantialiasing.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qnodepthmask.cpp b/src/render/renderstates/qnodepthmask.cpp index 7be7f24f4..241751a26 100644 --- a/src/render/renderstates/qnodepthmask.cpp +++ b/src/render/renderstates/qnodepthmask.cpp @@ -41,7 +41,6 @@ #include "qnodepthmask.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qrastermode.cpp b/src/render/renderstates/qrastermode.cpp index fc255b717..c432f1063 100644 --- a/src/render/renderstates/qrastermode.cpp +++ b/src/render/renderstates/qrastermode.cpp @@ -45,6 +45,100 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +/*! + \class Qt3DRender::QRasterMode + \brief The QRasterMode render state allows to control the type of + rasterization to be performed + \since 5.14 + \inmodule Qt3DRender + \ingroup renderstates + + The QRasterMode class is used to control the rasterization step of the + primitives at render time. This can be used to choose whether we only + want to show points, edges or fill a primitive. + + \note This is not supported when rendering on OpenGL ES 2.0 platforms. + + \sa QAlphaTest, QStencilTest + */ + +/*! + \qmltype RasterMode + \brief The RasterMode render state allows to control the type of + rasterization to be performed + \since 5.14 + \inqmlmodule Qt3D.Render + \inherits RenderState + \instantiates Qt3DRender::QRasterMode + \ingroup renderstates + + The QRasterMode class is used to control the rasterization step of the + primitives at render time. This can be used to choose whether we only + want to show points, edges or fill a primitive. + + \note This is not supported when rendering on OpenGL ES 2.0 platforms. + + \sa AlphaTest, StencilTest + */ + +/*! + \enum Qt3DRender::QRasterMode::RasterMode + + Enumeration for raster mode values + \value Points Vertices at the start of an edge are drawn as points. + \value Lines Edges of a polygon are draw as line segments. + \value Fill Fills the interior of the primitive. +*/ + +/*! + \enum Qt3DRender::QRasterMode::FaceMode + + Enumeration for face mode values + \value Front Applies to front faces only + \value Back Applies to back faces only + \value FrontAndBack Applies to front and back faces +*/ + +/*! + \property QRasterMode::rasterMode + + Holds the raster mode to be used. +*/ + +/*! + \property QRasterMode::faceMode + + Holds the face mode to be used. Controls on which face the raster mode is + to be applied. +*/ + +/*! + \qmlproperty enumeration RasterMode::rasterMode + + Holds the raster mode to be used. + + \list + \li Points Vertices at the start of an edge are drawn as points. + \li Lines Edges of a polygon are draw as line segments. + \li Fill Fills the interior of the primitive. + \endlist +*/ + +/*! + \qmlproperty enumeration RasterMode::faceMode + + Holds the face mode to be used. Controls on which face the raster mode is + to be applied. + + \list + \li Front Applies to front faces only + \li Back Applies to back faces only + \li FrontAndBack Applies to front and back faces + \endlist +*/ + + + QRasterMode::QRasterMode(QNode *parent) : QRenderState(*new QRasterModePrivate, parent) { diff --git a/src/render/renderstates/qseamlesscubemap.cpp b/src/render/renderstates/qseamlesscubemap.cpp index 860b36450..8458aded8 100644 --- a/src/render/renderstates/qseamlesscubemap.cpp +++ b/src/render/renderstates/qseamlesscubemap.cpp @@ -40,7 +40,6 @@ #include "qseamlesscubemap.h" #include "qrenderstate_p.h" #include <private/qnode_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qstenciloperation.cpp b/src/render/renderstates/qstenciloperation.cpp index 86b4c706b..34f95c03d 100644 --- a/src/render/renderstates/qstenciloperation.cpp +++ b/src/render/renderstates/qstenciloperation.cpp @@ -40,7 +40,6 @@ #include "qstenciloperation.h" #include "qstenciloperation_p.h" #include "qstenciloperationarguments.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/qstenciltest.cpp b/src/render/renderstates/qstenciltest.cpp index 8f6738e54..7284af140 100644 --- a/src/render/renderstates/qstenciltest.cpp +++ b/src/render/renderstates/qstenciltest.cpp @@ -41,7 +41,6 @@ #include "qstenciltest.h" #include "qstenciltest_p.h" #include "qstenciltestarguments.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> QT_BEGIN_NAMESPACE diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp index bd218c803..3040c5aaa 100644 --- a/src/render/renderstates/renderstatenode.cpp +++ b/src/render/renderstates/renderstatenode.cpp @@ -37,7 +37,6 @@ #include "renderstatenode_p.h" #include <Qt3DRender/qrenderstate.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qalphacoverage.h> #include <Qt3DRender/qalphatest.h> diff --git a/src/render/renderstates/renderstates.cpp b/src/render/renderstates/renderstates.cpp index bd4a209a1..5e238c010 100644 --- a/src/render/renderstates/renderstates.cpp +++ b/src/render/renderstates/renderstates.cpp @@ -40,7 +40,6 @@ #include "renderstates_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qrenderstate.h> #include <Qt3DRender/qcullface.h> #include <Qt3DRender/qpointsize.h> diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index 229d773ad..ab9f01d39 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -85,6 +85,39 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat } } +void QAbstractTexturePrivate::setStatus(QAbstractTexture::Status status) +{ + Q_Q(QAbstractTexture); + if (m_status != status) { + m_status = status; + const bool blocked = q->blockNotifications(true); + q->statusChanged(status); + q->blockNotifications(blocked); + } +} + +void QAbstractTexturePrivate::setHandle(const QVariant &handle) +{ + Q_Q(QAbstractTexture); + if (m_handle != handle) { + m_handle = handle; + const bool blocked = q->blockNotifications(true); + emit q->handleChanged(handle); + q->blockNotifications(blocked); + } +} + +void QAbstractTexturePrivate::setHandleType(QAbstractTexture::HandleType type) +{ + Q_Q(QAbstractTexture); + if (m_handleType != type) { + m_handleType = type; + const bool blocked = q->blockNotifications(true); + emit q->handleTypeChanged(type); + q->blockNotifications(blocked); + } +} + /*! \class Qt3DRender::QAbstractTexture \inmodule Qt3DRender @@ -564,7 +597,9 @@ void QAbstractTexture::setStatus(Status status) Q_D(QAbstractTexture); if (status != d->m_status) { d->m_status = status; + const bool blocked = blockNotifications(true); emit statusChanged(status); + blockNotifications(blocked); } } @@ -673,11 +708,7 @@ void QAbstractTexture::addTextureImage(QAbstractTextureImage *textureImage) if (!textureImage->parent()) textureImage->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), textureImage); - change->setPropertyName("textureImage"); - d->notifyObservers(change); - } + d->updateNode(textureImage, "textureImage", PropertyValueAdded); } } @@ -688,11 +719,7 @@ void QAbstractTexture::removeTextureImage(QAbstractTextureImage *textureImage) { Q_ASSERT(textureImage); Q_D(QAbstractTexture); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), textureImage); - change->setPropertyName("textureImage"); - d->notifyObservers(change); - } + d->updateNode(textureImage, "textureImage", PropertyValueRemoved); d->m_textureImages.removeOne(textureImage); // Remove bookkeeping connection d->unregisterDestructionHelper(textureImage); diff --git a/src/render/texture/qabstracttexture.h b/src/render/texture/qabstracttexture.h index 5a32b8487..b3d5efb34 100644 --- a/src/render/texture/qabstracttexture.h +++ b/src/render/texture/qabstracttexture.h @@ -350,6 +350,7 @@ protected: explicit QAbstractTexture(QAbstractTexturePrivate &dd, Qt3DCore::QNode *parent = nullptr); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; + // TO DO Qt6, should be on private class void setStatus(Status status); void setHandle(const QVariant &handle); void setHandleType(HandleType type); diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h index 573eac8c7..5b2945f73 100644 --- a/src/render/texture/qabstracttexture_p.h +++ b/src/render/texture/qabstracttexture_p.h @@ -96,6 +96,10 @@ public : QTextureGeneratorPtr dataFunctor() const; void setDataFunctor(const QTextureGeneratorPtr &generator); + void setStatus(QAbstractTexture::Status status); + void setHandle(const QVariant &handle); + void setHandleType(QAbstractTexture::HandleType type); + QVector<QTextureDataUpdate> m_pendingDataUpdates; private: diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp index a5d342d83..9ca4599c5 100644 --- a/src/render/texture/qabstracttextureimage.cpp +++ b/src/render/texture/qabstracttextureimage.cpp @@ -39,7 +39,6 @@ #include "qabstracttextureimage.h" #include "qabstracttextureimage_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtextureimagedatagenerator.h> QT_BEGIN_NAMESPACE diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp index 53216d27d..d120c2b39 100644 --- a/src/render/texture/texture.cpp +++ b/src/render/texture/texture.cpp @@ -93,20 +93,6 @@ void Texture::unsetDirty() m_dirty = Texture::NotDirty; } -void Texture::addTextureImage(Qt3DCore::QNodeId id) -{ - if (!m_textureImageIds.contains(id)) { - m_textureImageIds.push_back(id); - addDirtyFlag(DirtyImageGenerators); - } -} - -void Texture::removeTextureImage(Qt3DCore::QNodeId id) -{ - m_textureImageIds.removeAll(id); - addDirtyFlag(DirtyImageGenerators); -} - // This is called by Renderer::updateGLResources // when the texture has been marked for cleanup void Texture::cleanup() @@ -125,38 +111,6 @@ void Texture::cleanup() m_dirty = NotDirty; } -// ChangeArbiter/Aspect Thread -void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - DirtyFlags dirty; - - switch (e->type()) { - - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("textureImage")) { - addTextureImage(change->addedNodeId()); - } - } - break; - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("textureImage")) { - removeTextureImage(change->removedNodeId()); - } - } - break; - - default: - break; - - } - - addDirtyFlag(dirty); - BackendNode::sceneChangeEvent(e); -} - void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { BackendNode::syncFromFrontEnd(frontEnd, firstTime); @@ -203,8 +157,12 @@ void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) addTextureDataUpdate(pendingUpdate); dnode->m_pendingDataUpdates.clear(); - for (const auto imgNode : dnode->m_textureImages) - addTextureImage(imgNode->id()); + auto ids = Qt3DCore::qIdsForNodes(dnode->m_textureImages); + std::sort(std::begin(ids), std::end(ids)); + if (ids != m_textureImageIds) { + m_textureImageIds = ids; + addDirtyFlag(DirtyImageGenerators); + } } if (dnode->m_sharedTextureId != m_sharedTextureId) { @@ -220,88 +178,6 @@ void Texture::setDataGenerator(const QTextureGeneratorPtr &generator) addDirtyFlag(DirtyDataGenerator); } -// Called by sendTextureChangesToFrontendJob once GLTexture and sharing -// has been performed -void Texture::updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo) -{ - // If we are Dirty, some property has changed and the properties we have - // received are potentially already outdated - if (m_dirty != NotDirty) - return; - - // Note we don't update target has it is constant for frontend nodes - - if (updateInfo.properties.width != m_properties.width) { - m_properties.width = updateInfo.properties.width; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("width"); - change->setValue(updateInfo.properties.width); - notifyObservers(change); - } - - if (updateInfo.properties.height != m_properties.height) { - m_properties.height = updateInfo.properties.height; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("height"); - change->setValue(updateInfo.properties.height); - notifyObservers(change); - } - - if (updateInfo.properties.depth != m_properties.depth) { - m_properties.depth = updateInfo.properties.depth; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("depth"); - change->setValue(updateInfo.properties.depth); - notifyObservers(change); - } - - if (updateInfo.properties.layers != m_properties.layers) { - m_properties.layers = updateInfo.properties.layers; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("layers"); - change->setValue(updateInfo.properties.layers); - notifyObservers(change); - } - - if (updateInfo.properties.format != m_properties.format) { - m_properties.format = updateInfo.properties.format; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("format"); - change->setValue(updateInfo.properties.format); - notifyObservers(change); - } - - if (updateInfo.properties.status != m_properties.status) { - m_properties.status = updateInfo.properties.status; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("status"); - change->setValue(updateInfo.properties.status); - notifyObservers(change); - } - - { - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("handleType"); - change->setValue(updateInfo.handleType); - notifyObservers(change); - } - - { - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - change->setPropertyName("handle"); - change->setValue(updateInfo.handle); - notifyObservers(change); - } -} - bool Texture::isValid(TextureImageManager *manager) const { for (const QNodeId &id : m_textureImageIds) { @@ -336,8 +212,9 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan m_dataFunctor = data.dataFunctor; m_sharedTextureId = data.sharedTextureId; - for (const QNodeId &imgId : data.textureImageIds) - addTextureImage(imgId); + m_textureImageIds = data.textureImageIds; + if (m_textureImageIds.size()) + addDirtyFlag(DirtyImageGenerators); const QVector<QTextureDataUpdate> initialDataUpdates = data.initialDataUpdates; for (const QTextureDataUpdate &initialUpdate : initialDataUpdates) diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h index 967b2a44a..9e347243e 100644 --- a/src/render/texture/texture_p.h +++ b/src/render/texture/texture_p.h @@ -156,14 +156,11 @@ public: DirtyFlags dirtyFlags(); void unsetDirty(); - void addTextureImage(Qt3DCore::QNodeId id); - void removeTextureImage(Qt3DCore::QNodeId id); void cleanup(); void addTextureDataUpdate(const QTextureDataUpdate &update); QVector<QTextureDataUpdate> takePendingTextureDataUpdates() { return std::move(m_pendingTextureDataUpdates); } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline const TextureProperties& properties() const { return m_properties; } @@ -173,7 +170,6 @@ public: inline int sharedTextureId() const { return m_sharedTextureId; } void setDataGenerator(const QTextureGeneratorPtr &generator); - void updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo); bool isValid(TextureImageManager *manager) const; private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp index 512949d91..25001b9df 100644 --- a/src/render/texture/textureimage.cpp +++ b/src/render/texture/textureimage.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "textureimage_p.h" -#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qtextureimage.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/qabstracttextureimage_p.h> |