diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-09-19 21:55:16 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-09-19 21:55:23 +0200 |
commit | d51dad630e0afb6ddca19ee61dd1ddf424fb49c2 (patch) | |
tree | 1ca0630bfb8af983950621399dbd4d0863afa568 /src | |
parent | c8dab9f129ba838988e2c0ae67071a0197e75045 (diff) | |
parent | 471ea347fde07cf5e48c586c47bf066220dc78c2 (diff) |
Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
Diffstat (limited to 'src')
73 files changed, 691 insertions, 944 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index 92e614236..24c484dc2 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -453,6 +453,7 @@ 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); @@ -469,6 +470,7 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim 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"); @@ -479,6 +481,7 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim // 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"); diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp index 6d1a8ca30..426741a61 100644 --- a/src/core/aspects/qaspectengine.cpp +++ b/src/core/aspects/qaspectengine.cpp @@ -275,6 +275,7 @@ void QAspectEnginePrivate::initialize() arbiter->setPostman(m_postman); arbiter->setScene(m_scene); m_initialized = true; + m_aspectManager->setPostConstructorInit(m_scene->postConstructorInit()); #if QT_CONFIG(qt3d_profile_jobs) m_commandDebugger->setAspectEngine(q_func()); m_commandDebugger->initialize(); diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp index 6bca77a9e..a33f771e9 100644 --- a/src/core/aspects/qaspectmanager.cpp +++ b/src/core/aspects/qaspectmanager.cpp @@ -374,6 +374,11 @@ QServiceLocator *QAspectManager::serviceLocator() const return m_serviceLocator.data(); } +void QAspectManager::setPostConstructorInit(NodePostConstructorInit *postConstructorInit) +{ + m_postConstructorInit = postConstructorInit; +} + /*! \internal \brief Drives the Qt3D simulation loop in the main thread @@ -429,6 +434,10 @@ void QAspectManager::processFrame() changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); #endif + // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of + // tree changes + m_postConstructorInit->processNodes(); + // Add and Remove Nodes const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges); for (const NodeTreeChange &change : nodeTreeChanges) { diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h index b39ad1f89..38ddbc55d 100644 --- a/src/core/aspects/qaspectmanager_p.h +++ b/src/core/aspects/qaspectmanager_p.h @@ -74,6 +74,7 @@ class QChangeArbiter; class QAbstractAspect; class QAbstractAspectJobManager; class QServiceLocator; +class NodePostConstructorInit; struct NodeTreeChange; class Q_3DCORE_PRIVATE_EXPORT QAspectManager : public QObject @@ -105,6 +106,7 @@ public: QAbstractAspectJobManager *jobManager() const; QChangeArbiter *changeArbiter() const; QServiceLocator *serviceLocator() const; + void setPostConstructorInit(NodePostConstructorInit *postConstructorInit); private: bool event(QEvent *event) override; @@ -121,6 +123,8 @@ private: bool m_simulationLoopRunning; QAspectEngine::RunMode m_driveMode; QVector<NodeTreeChange> m_nodeTreeChanges; + NodePostConstructorInit* m_postConstructorInit; + }; } // namespace Qt3DCore diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp index 0e9af58dd..a9f4e7a31 100644 --- a/src/core/jobs/qthreadpooler.cpp +++ b/src/core/jobs/qthreadpooler.cpp @@ -183,7 +183,7 @@ int QThreadPooler::currentCount() const { // The caller have to set the mutex - return m_taskCount.load(); + return m_taskCount.loadRelaxed(); } int QThreadPooler::maxThreadCount() const diff --git a/src/core/jobs/task.cpp b/src/core/jobs/task.cpp index 4291a4779..091aabfd6 100644 --- a/src/core/jobs/task.cpp +++ b/src/core/jobs/task.cpp @@ -118,7 +118,7 @@ void SyncTaskRunnable::run() m_atomicCount->deref(); // Wait for the other worker threads to be done - while (m_atomicCount->load() > 0) + while (m_atomicCount->loadRelaxed() > 0) QThread::currentThread()->yieldCurrentThread(); if (m_pooler) diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp index 546f1d670..0ff8c4646 100644 --- a/src/core/nodes/qentity.cpp +++ b/src/core/nodes/qentity.cpp @@ -295,13 +295,7 @@ void QEntity::onParentChanged(QObject *) if (!d->m_hasBackendNode) return; - const auto parentID = parentEntity() ? parentEntity()->id() : Qt3DCore::QNodeId(); - auto parentChange = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); - parentChange->setPropertyName("parentEntityUpdated"); - parentChange->setValue(QVariant::fromValue(parentID)); - const bool blocked = blockNotifications(false); - notifyObservers(parentChange); - blockNotifications(blocked); + d->update(); } } // namespace Qt3DCore diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index 491059ff9..d8310731c 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -194,7 +194,7 @@ public: void removeNode(QNode *node); void addNode(QNode *node); -private Q_SLOTS: +public Q_SLOTS: void processNodes(); private: diff --git a/src/core/transforms/qjoint.cpp b/src/core/transforms/qjoint.cpp index 017773ff6..553fbd654 100644 --- a/src/core/transforms/qjoint.cpp +++ b/src/core/transforms/qjoint.cpp @@ -352,11 +352,8 @@ void QJoint::addChildJoint(QJoint *joint) // Ensures proper bookkeeping d->registerDestructionHelper(joint, &QJoint::removeChildJoint, d->m_childJoints); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), joint); - change->setPropertyName("childJoint"); - d->notifyObservers(change); - } + if (d->m_changeArbiter != nullptr) + d->update(); } } @@ -369,11 +366,8 @@ void QJoint::removeChildJoint(QJoint *joint) Q_D(QJoint); if (d->m_childJoints.contains(joint)) { - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), joint); - change->setPropertyName("childJoint"); - d->notifyObservers(change); - } + if (d->m_changeArbiter != nullptr) + d->update(); d->m_childJoints.removeOne(joint); diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp index bedf108f2..e5902f11f 100644 --- a/src/core/transforms/qtransform.cpp +++ b/src/core/transforms/qtransform.cpp @@ -239,12 +239,13 @@ QTransform::QTransform(QTransformPrivate &dd, QNode *parent) */ void QTransform::sceneChangeEvent(const QSceneChangePtr &change) { + Q_D(QTransform); switch (change->type()) { case PropertyUpdated: { Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); if (propertyChange->propertyName() == QByteArrayLiteral("worldMatrix")) { const bool blocked = blockNotifications(true); - setWorldMatrix(propertyChange->value().value<QMatrix4x4>()); + d->setWorldMatrix(propertyChange->value().value<QMatrix4x4>()); blockNotifications(blocked); } break; @@ -254,13 +255,13 @@ void QTransform::sceneChangeEvent(const QSceneChangePtr &change) } } -void QTransform::setWorldMatrix(const QMatrix4x4 &worldMatrix) +void QTransformPrivate::setWorldMatrix(const QMatrix4x4 &worldMatrix) { - Q_D(QTransform); - if (d->m_worldMatrix == worldMatrix) + Q_Q(QTransform); + if (m_worldMatrix == worldMatrix) return; - d->m_worldMatrix = worldMatrix; - emit worldMatrixChanged(worldMatrix); + m_worldMatrix = worldMatrix; + emit q->worldMatrixChanged(worldMatrix); } void QTransform::setMatrix(const QMatrix4x4 &m) diff --git a/src/core/transforms/qtransform.h b/src/core/transforms/qtransform.h index 527760df7..503ea4d4a 100644 --- a/src/core/transforms/qtransform.h +++ b/src/core/transforms/qtransform.h @@ -120,7 +120,6 @@ Q_SIGNALS: protected: explicit QTransform(QTransformPrivate &dd, QNode *parent = nullptr); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - void setWorldMatrix(const QMatrix4x4 &worldMatrix); private: Q_DECLARE_PRIVATE(QTransform) diff --git a/src/core/transforms/qtransform_p.h b/src/core/transforms/qtransform_p.h index d44e5e157..028a9aba7 100644 --- a/src/core/transforms/qtransform_p.h +++ b/src/core/transforms/qtransform_p.h @@ -77,6 +77,8 @@ public: mutable bool m_matrixDirty; QMatrix4x4 m_worldMatrix; + + void setWorldMatrix(const QMatrix4x4 &worldMatrix); }; struct QTransformData diff --git a/src/extras/defaults/qforwardrenderer.cpp b/src/extras/defaults/qforwardrenderer.cpp index 22a471cec..dd3c872cc 100644 --- a/src/extras/defaults/qforwardrenderer.cpp +++ b/src/extras/defaults/qforwardrenderer.cpp @@ -239,11 +239,13 @@ QColor QForwardRenderer::clearColor() const \qmlproperty color ForwardRenderer::clearBuffers Holds the current buffers to be cleared. Default value is ColorDepthBuffer + \since 5.14 */ /*! \property QForwardRenderer::clearBuffers Holds the current buffers to be cleared. Default value is ColorDepthBuffer + \since 5.14 */ QClearBuffers::BufferType QForwardRenderer::clearBuffers() const { diff --git a/src/extras/defaults/qforwardrenderer.h b/src/extras/defaults/qforwardrenderer.h index 6d01a0ded..0b53a094b 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) + Q_PROPERTY(Qt3DRender::QClearBuffers::BufferType clearBuffers READ clearBuffers WRITE setClearBuffers NOTIFY clearBuffersChanged 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) diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp index 91ec85795..b675ec283 100644 --- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp +++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp @@ -87,6 +87,7 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri) // Framegraphs qmlRegisterType<Qt3DExtras::QForwardRenderer>(uri, 2, 0, "ForwardRenderer"); qmlRegisterType<Qt3DExtras::QForwardRenderer, 9>(uri, 2, 9, "ForwardRenderer"); + qmlRegisterType<Qt3DExtras::QForwardRenderer, 14>(uri, 2, 14, "ForwardRenderer"); // Entities qmlRegisterType<Qt3DExtras::QSkyboxEntity>(uri, 2, 0, "SkyboxEntity"); diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp index ce19d35ed..e16314c8e 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp @@ -239,6 +239,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DRender::QObjectPicker, 9>(uri, 2, 9, "ObjectPicker"); qmlRegisterType<Qt3DRender::QObjectPicker, 13>(uri, 2, 13, "ObjectPicker"); qmlRegisterUncreatableType<Qt3DRender::QPickEvent>(uri, 2, 0, "PickEvent", QStringLiteral("Events cannot be created")); + qmlRegisterUncreatableType<Qt3DRender::QPickEvent, 14>(uri, 2, 14, "PickEvent", QStringLiteral("Events cannot be created")); qmlRegisterType<Qt3DRender::Render::Quick::Quick3DRayCaster>(uri, 2, 11, "RayCaster"); qmlRegisterType<Qt3DRender::Render::Quick::Quick3DScreenRayCaster>(uri, 2, 11, "ScreenRayCaster"); @@ -297,7 +298,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DRender::QBlendEquationArguments>(uri, 2, 0, "BlendEquationArguments"); qmlRegisterType<Qt3DRender::QBlendEquation>(uri, 2, 0, "BlendEquation"); qmlRegisterType<Qt3DRender::QAlphaTest>(uri, 2, 0, "AlphaTest"); - qmlRegisterType<Qt3DRender::QDepthRange>(uri, 2, 13, "DepthRange"); + qmlRegisterType<Qt3DRender::QDepthRange>(uri, 2, 14, "DepthRange"); qmlRegisterType<Qt3DRender::QDepthTest>(uri, 2, 0, "DepthTest"); qmlRegisterType<Qt3DRender::QMultiSampleAntiAliasing>(uri, 2, 0, "MultiSampleAntiAliasing"); qmlRegisterType<Qt3DRender::QNoDepthMask>(uri, 2, 0, "NoDepthMask"); diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp index 27ab7f010..562f0d2c7 100644 --- a/src/quick3d/quick3dscene2d/items/scene2d.cpp +++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp @@ -443,7 +443,7 @@ void Scene2D::cleanup() } if (m_renderThread) { renderThreadClientCount->fetchAndSubAcquire(1); - if (renderThreadClientCount->load() == 0) + if (renderThreadClientCount->loadRelaxed() == 0) renderThread->quit(); } } diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index bf128b508..d8520a97e 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -145,44 +145,6 @@ void Entity::setHandle(HEntity handle) m_handle = handle; } -void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<QNodeCreatedChange<Qt3DCore::QEntityData>>(change); - const auto &data = typedChange->data; - - // Note this is *not* the parentId as that is the ID of the parent QNode, which is not - // necessarily the same as the parent QEntity (which may be further up the tree). - m_parentEntityId = data.parentEntityId; - qCDebug(Render::RenderNodes) << "Creating Entity id =" << peerId() << "parentId =" << m_parentEntityId; - - // TODO: Store string id instead and only in debug mode - //m_objectName = peer->objectName(); - m_worldTransform = m_nodeManagers->worldMatrixManager()->getOrAcquireHandle(peerId()); - - // TODO: Suboptimal -> Maybe have a Hash<QComponent, QEntityList> instead - m_transformComponent = QNodeId(); - m_materialComponent = QNodeId(); - m_cameraComponent = QNodeId(); - m_geometryRendererComponent = QNodeId(); - m_objectPickerComponent = QNodeId(); - m_boundingVolumeDebugComponent = QNodeId(); - m_computeComponent = QNodeId(); - m_layerComponents.clear(); - m_levelOfDetailComponents.clear(); - m_rayCasterComponents.clear(); - m_shaderDataComponents.clear(); - m_lightComponents.clear(); - m_environmentLightComponents.clear(); - m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId()); - m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId()); - m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId()); - - for (const auto &idAndType : qAsConst(data.componentIdsAndTypes)) - addComponent(idAndType); - - markDirty(AbstractRenderer::EntityHierarchyDirty); -} - void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { switch (e->type()) { @@ -192,7 +154,6 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) const auto componentIdAndType = QNodeIdTypePair(change->componentId(), change->componentMetaObject()); addComponent(componentIdAndType); qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Added. Id =" << change->componentId(); - markDirty(AbstractRenderer::AllDirty); break; } @@ -200,27 +161,6 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QComponentRemovedChangePtr change = qSharedPointerCast<QComponentRemovedChange>(e); removeComponent(change->componentId()); qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Removed. Id =" << change->componentId(); - markDirty(AbstractRenderer::AllDirty); - break; - } - - case PropertyUpdated: { - QPropertyUpdatedChangePtr change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("enabled")) { - // We only mark as dirty the renderer - markDirty(AbstractRenderer::EntityEnabledDirty); - // We let QBackendNode::sceneChangeEvent change the enabled property - } else if (change->propertyName() == QByteArrayLiteral("parentEntityUpdated")) { - auto newParent = change->value().value<Qt3DCore::QNodeId>(); - qCDebug(Render::RenderNodes) << "Setting parent for " << peerId() << ", new parentId =" << newParent; - if (m_parentEntityId != newParent) { - m_parentEntityId = newParent; - // TODO: change to EventHierarchyDirty and update renderer to - // ensure all jobs are run that depend on Entity hierarchy. - markDirty(AbstractRenderer::AllDirty); - } - } - break; } @@ -230,6 +170,58 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Entity::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + const Qt3DCore::QEntity *node = qobject_cast<const Qt3DCore::QEntity *>(frontEnd); + if (!node) + return; + + if (this->isEnabled() != node->isEnabled()) { + markDirty(AbstractRenderer::EntityEnabledDirty); + // We let QBackendNode::syncFromFrontEnd change the enabled property + } + + const auto parentID = node->parentEntity() ? node->parentEntity()->id() : Qt3DCore::QNodeId(); + if (m_parentEntityId != parentID) { + m_parentEntityId = parentID; + // TODO: change to EventHierarchyDirty and update renderer to + // ensure all jobs are run that depend on Entity hierarchy. + markDirty(AbstractRenderer::AllDirty); + } + + if (firstTime) { + m_worldTransform = m_nodeManagers->worldMatrixManager()->getOrAcquireHandle(peerId()); + + // TODO: Suboptimal -> Maybe have a Hash<QComponent, QEntityList> instead + m_transformComponent = QNodeId(); + m_materialComponent = QNodeId(); + m_cameraComponent = QNodeId(); + m_geometryRendererComponent = QNodeId(); + m_objectPickerComponent = QNodeId(); + m_boundingVolumeDebugComponent = QNodeId(); + m_computeComponent = QNodeId(); + m_layerComponents.clear(); + m_levelOfDetailComponents.clear(); + m_rayCasterComponents.clear(); + m_shaderDataComponents.clear(); + m_lightComponents.clear(); + m_environmentLightComponents.clear(); + m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId()); + m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId()); + m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId()); + + const QComponentVector &components = node->components(); + for (QComponent *c : components) { + const auto idAndType = QNodeIdTypePair(c->id(), QNodePrivate::findStaticMetaObject(c->metaObject())); + addComponent(idAndType); + } + + markDirty(AbstractRenderer::EntityHierarchyDirty); + } + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); +} + void Entity::dump() const { static int depth = 0; @@ -358,6 +350,7 @@ void Entity::addComponent(Qt3DCore::QNodeIdTypePair idAndType) } else if (type->inherits(&QArmature::staticMetaObject)) { m_armatureComponent = id; } + markDirty(AbstractRenderer::AllDirty); } void Entity::removeComponent(Qt3DCore::QNodeId nodeId) @@ -392,6 +385,7 @@ void Entity::removeComponent(Qt3DCore::QNodeId nodeId) } else if (m_armatureComponent == nodeId) { m_armatureComponent = QNodeId(); } + markDirty(AbstractRenderer::AllDirty); } bool Entity::isBoundingVolumeDirty() const diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index b4c9541f2..493774feb 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -90,6 +90,7 @@ 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; @@ -178,10 +179,7 @@ public: return containsComponentsOfType<T>() && containsComponentsOfType<Ts, Ts2...>(); } - private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - NodeManagers *m_nodeManagers; HEntity m_handle; HEntity m_parentHandle; diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp index 390ed4f05..6659657fa 100644 --- a/src/render/backend/transform.cpp +++ b/src/render/backend/transform.cpp @@ -68,17 +68,6 @@ void Transform::cleanup() QBackendNode::setEnabled(false); } -void Transform::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTransformData>>(change); - const auto &data = typedChange->data; - m_rotation = data.rotation; - m_scale = data.scale; - m_translation = data.translation; - updateMatrix(); - markDirty(AbstractRenderer::TransformDirty); -} - Matrix4x4 Transform::transformMatrix() const { return m_transformMatrix; @@ -99,6 +88,7 @@ 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 @@ -120,6 +110,27 @@ void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + const Qt3DCore::QTransform *transform = qobject_cast<const Qt3DCore::QTransform *>(frontEnd); + if (!transform) + return; + + bool dirty = m_rotation != transform->rotation(); + m_rotation = transform->rotation(); + dirty |= m_scale != transform->scale3D(); + m_scale = transform->scale3D(); + dirty |= m_translation != transform->translation(); + m_translation = transform->translation(); + + if (dirty || firstTime) { + updateMatrix(); + markDirty(AbstractRenderer::TransformDirty); + } + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); +} + void Transform::notifyWorldTransformChanged(const Matrix4x4 &worldMatrix) { auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); diff --git a/src/render/backend/transform_p.h b/src/render/backend/transform_p.h index e3bcad317..50857ac94 100644 --- a/src/render/backend/transform_p.h +++ b/src/render/backend/transform_p.h @@ -77,12 +77,11 @@ public: 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(); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Matrix4x4 m_transformMatrix; QQuaternion m_rotation; QVector3D m_scale; diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 35eff052b..f33af9ebd 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -252,8 +252,8 @@ void QRenderAspectPrivate::registerBackendTypes() qRegisterMetaType<Qt3DRender::QViewport*>(); qRegisterMetaType<Qt3DCore::QJoint*>(); - q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); - q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer)); + q->registerBackendType<Qt3DCore::QEntity, true>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<Qt3DCore::QTransform, true>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer)); q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q)); q->registerBackendType<QLayer>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer)); @@ -266,32 +266,32 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QRenderState>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer)); // Geometry + Compute - q->registerBackendType<QAttribute>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer)); - q->registerBackendType<QBuffer>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager())); + q->registerBackendType<QAttribute, true>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer)); + q->registerBackendType<QBuffer, true>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager())); q->registerBackendType<QComputeCommand>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer)); - q->registerBackendType<QGeometry>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer)); - q->registerBackendType<QGeometryRenderer>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager())); - q->registerBackendType<Qt3DCore::QArmature>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer)); - q->registerBackendType<Qt3DCore::QAbstractSkeleton>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager())); - q->registerBackendType<Qt3DCore::QJoint>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager())); + q->registerBackendType<QGeometry, true>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer)); + q->registerBackendType<QGeometryRenderer, true>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager())); + q->registerBackendType<Qt3DCore::QArmature, true>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer)); + q->registerBackendType<Qt3DCore::QAbstractSkeleton, true>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager())); + q->registerBackendType<Qt3DCore::QJoint, true>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager())); // Textures - q->registerBackendType<QAbstractTexture>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager())); + q->registerBackendType<QAbstractTexture, true>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager())); q->registerBackendType<QAbstractTextureImage>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer, m_nodeManagers->textureImageManager())); // Material system - q->registerBackendType<QEffect>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer)); + q->registerBackendType<QEffect, true>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer)); q->registerBackendType<QFilterKey>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer)); - q->registerBackendType<QAbstractLight>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers)); - q->registerBackendType<QEnvironmentLight>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer)); - q->registerBackendType<QMaterial>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer)); - q->registerBackendType<QParameter>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer)); - q->registerBackendType<QRenderPass>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer)); + q->registerBackendType<QAbstractLight, true>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<QEnvironmentLight, true>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer)); + 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<QShaderProgram>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer)); q->registerBackendType<QShaderProgramBuilder>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer)); - q->registerBackendType<QTechnique>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<QShaderImage>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer)); // Framegraph diff --git a/src/render/geometry/armature.cpp b/src/render/geometry/armature.cpp index 15a26c9ec..cfa2e572a 100644 --- a/src/render/geometry/armature.cpp +++ b/src/render/geometry/armature.cpp @@ -36,6 +36,8 @@ #include "armature_p.h" +#include <Qt3DCore/qarmature.h> +#include <Qt3DCore/qabstractskeleton.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qarmature_p.h> @@ -52,32 +54,20 @@ Armature::Armature() { } -void Armature::cleanup() +void Armature::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - m_skeletonId = Qt3DCore::QNodeId(); - setEnabled(false); -} + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QArmature *node = qobject_cast<const QArmature *>(frontEnd); + if (!node) + return; -void Armature::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<QNodeCreatedChange<QArmatureData>>(change); - m_skeletonId = typedChange->data.skeletonId; + m_skeletonId = node->skeleton() ? node->skeleton()->id() : QNodeId{}; } -void Armature::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Armature::cleanup() { - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("skeleton")) - m_skeletonId = change->value().value<QNodeId>(); - break; - } - - default: - break; - } - QBackendNode::sceneChangeEvent(e); + m_skeletonId = Qt3DCore::QNodeId(); + setEnabled(false); } } // namespace Render diff --git a/src/render/geometry/armature_p.h b/src/render/geometry/armature_p.h index 3e6e52a3f..39baa4a79 100644 --- a/src/render/geometry/armature_p.h +++ b/src/render/geometry/armature_p.h @@ -63,7 +63,7 @@ class Q_AUTOTEST_EXPORT Armature : public BackendNode public: Armature(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void cleanup(); Qt3DCore::QNodeId skeletonId() const { return m_skeletonId; } @@ -73,8 +73,6 @@ public: const UniformValue &skinningPaletteUniform() const { return m_skinningPaletteUniform; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_skeletonId; UniformValue m_skinningPaletteUniform; }; diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp index bc6b27851..f241a85e5 100644 --- a/src/render/geometry/attribute.cpp +++ b/src/render/geometry/attribute.cpp @@ -83,78 +83,54 @@ void Attribute::cleanup() m_nameId = 0; } -void Attribute::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Attribute::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAttributeData>>(change); - const auto &data = typedChange->data; - m_bufferId = data.bufferId; - m_name = data.name; - m_nameId = StringToInt::lookupId(m_name); - m_vertexBaseType = data.vertexBaseType; - m_vertexSize = data.vertexSize; - m_count = data.count; - m_byteStride = data.byteStride; - m_byteOffset = data.byteOffset; - m_divisor = data.divisor; - m_attributeType = data.attributeType; - m_attributeDirty = true; -} - -/*! - \fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize) - - The signal is emitted with \a vertexSize when the dataSize changes. - -*/ -/*! - \fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType) - - The signal is emitted with \a vertexBaseType when the dataType changed. -*/ -void Attribute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - - if (propertyName == QByteArrayLiteral("name")) { - m_name = propertyChange->value().toString(); - m_nameId = StringToInt::lookupId(m_name); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("vertexBaseType")) { - m_vertexBaseType = static_cast<QAttribute::VertexBaseType>(propertyChange->value().value<int>()); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("vertexSize")) { - m_vertexSize = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("count")) { - m_count = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("byteStride")) { - m_byteStride = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("byteOffset")) { - m_byteOffset = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("divisor")) { - m_divisor = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("attributeType")) { - m_attributeType = static_cast<QAttribute::AttributeType>(propertyChange->value().value<int>()); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("buffer")) { - m_bufferId = propertyChange->value().value<QNodeId>(); - m_attributeDirty = true; - } - markDirty(AbstractRenderer::AllDirty); - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAttribute *node = qobject_cast<const QAttribute *>(frontEnd); + if (!node) + return; + + m_attributeDirty = firstTime; + if (m_name != node->name()) { + m_name = node->name(); + m_nameId = StringToInt::lookupId(m_name); + m_attributeDirty = true; } - - default: - break; + if (m_vertexBaseType != node->vertexBaseType()) { + m_vertexBaseType = node->vertexBaseType(); + m_attributeDirty = true; } - BackendNode::sceneChangeEvent(e); + if (m_vertexSize != node->vertexSize()) { + m_vertexSize = node->vertexSize(); + m_attributeDirty = true; + } + if (m_count != node->count()) { + m_count = node->count(); + m_attributeDirty = true; + } + if (m_byteStride != node->byteStride()) { + m_byteStride = node->byteStride(); + m_attributeDirty = true; + } + if (m_byteOffset != node->byteOffset()) { + m_byteOffset = node->byteOffset(); + m_attributeDirty = true; + } + if (m_divisor != node->divisor()) { + m_divisor = node->divisor(); + m_attributeDirty = true; + } + if (m_attributeType != node->attributeType()) { + m_attributeType = node->attributeType(); + m_attributeDirty = true; + } + const auto bufferId = node->buffer() ? node->buffer()->id() : QNodeId{}; + if (bufferId != m_bufferId) { + m_bufferId = bufferId; + m_attributeDirty = true; + } + + markDirty(AbstractRenderer::AllDirty); } void Attribute::unsetDirty() diff --git a/src/render/geometry/attribute_p.h b/src/render/geometry/attribute_p.h index e01537605..4b47146e1 100644 --- a/src/render/geometry/attribute_p.h +++ b/src/render/geometry/attribute_p.h @@ -68,7 +68,7 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline Qt3DCore::QNodeId bufferId() const { return m_bufferId; } inline QString name() const { return m_name; } @@ -84,8 +84,6 @@ public: void unsetDirty(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_bufferId; QString m_name; int m_nameId; diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp index d60f89c7d..998db3640 100644 --- a/src/render/geometry/buffer.cpp +++ b/src/render/geometry/buffer.cpp @@ -113,28 +113,6 @@ void Buffer::updateDataFromGPUToCPU(QByteArray data) notifyObservers(e); } -void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBufferData>>(change); - const auto &data = typedChange->data; - m_data = data.data; - m_usage = data.usage; - m_syncData = data.syncData; - m_access = data.access; - m_bufferDirty = true; - - if (!m_data.isEmpty()) - forceDataUpload(); - - m_functor = data.functor; - Q_ASSERT(m_manager); - if (m_functor) - m_manager->addDirtyBuffer(peerId()); - - m_manager->addBufferReference(peerId()); - markDirty(AbstractRenderer::BuffersDirty); -} - void Buffer::forceDataUpload() { // We push back an update with offset = -1 @@ -145,40 +123,50 @@ void Buffer::forceDataUpload() m_bufferUpdates.push_back(updateNewData); } -void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - if (propertyName == QByteArrayLiteral("data")) { - QByteArray newData = propertyChange->value().toByteArray(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QBuffer *node = qobject_cast<const QBuffer *>(frontEnd); + if (!node) + return; + + if (firstTime && m_manager != nullptr) + m_manager->addBufferReference(peerId()); + + m_syncData = node->isSyncData(); + m_access = node->accessType(); + if (m_usage != node->usage()) { + m_usage = node->usage(); + m_bufferDirty = true; + } + { + QBufferDataGeneratorPtr newGenerator = node->dataGenerator(); + bool dirty = (newGenerator && m_functor && !(*newGenerator == *m_functor)) || + (newGenerator.isNull() && !m_functor.isNull()) || + (!newGenerator.isNull() && m_functor.isNull()); + m_bufferDirty |= dirty; + m_functor = newGenerator; + if (m_functor && m_manager != nullptr) + m_manager->addDirtyBuffer(peerId()); + } + { + QVariant v = node->property("QT3D_updateData"); + if (v.isValid()) { + Qt3DRender::QBufferUpdate updateData = v.value<Qt3DRender::QBufferUpdate>(); + m_data.replace(updateData.offset, updateData.data.size(), updateData.data); + m_bufferUpdates.push_back(updateData); + m_bufferDirty = true; + const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {}); + } else { + QByteArray newData = node->data(); bool dirty = m_data != newData; m_bufferDirty |= dirty; m_data = newData; - if (dirty) + if (dirty && !m_data.isEmpty()) forceDataUpload(); - } else if (propertyName == QByteArrayLiteral("updateData")) { - Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>(); - m_data.replace(updateData.offset, updateData.data.size(), updateData.data); - m_bufferUpdates.push_back(updateData); - m_bufferDirty = true; - } else if (propertyName == QByteArrayLiteral("usage")) { - m_usage = static_cast<QBuffer::UsageType>(propertyChange->value().value<int>()); - m_bufferDirty = true; - } else if (propertyName == QByteArrayLiteral("accessType")) { - m_access = static_cast<QBuffer::AccessType>(propertyChange->value().value<int>()); - } else if (propertyName == QByteArrayLiteral("dataGenerator")) { - QBufferDataGeneratorPtr newGenerator = propertyChange->value().value<QBufferDataGeneratorPtr>(); - m_bufferDirty |= !(newGenerator && m_functor && *newGenerator == *m_functor); - m_functor = newGenerator; - if (m_functor && m_manager != nullptr) - m_manager->addDirtyBuffer(peerId()); - } else if (propertyName == QByteArrayLiteral("syncData")) { - m_syncData = propertyChange->value().toBool(); } - markDirty(AbstractRenderer::BuffersDirty); } - BackendNode::sceneChangeEvent(e); + markDirty(AbstractRenderer::BuffersDirty); } // Called by Renderer once the buffer has been uploaded to OpenGL diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h index 9a171599d..a3f52d1b3 100644 --- a/src/render/geometry/buffer_p.h +++ b/src/render/geometry/buffer_p.h @@ -73,7 +73,7 @@ public: ~Buffer(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setManager(BufferManager *manager); void executeFunctor(); @@ -88,7 +88,6 @@ public: void unsetDirty(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void forceDataUpload(); QBuffer::UsageType m_usage; diff --git a/src/render/geometry/geometry.cpp b/src/render/geometry/geometry.cpp index 4ee02a74d..cb401df5b 100644 --- a/src/render/geometry/geometry.cpp +++ b/src/render/geometry/geometry.cpp @@ -45,6 +45,8 @@ #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> +#include <algorithm> + QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -76,51 +78,29 @@ void Geometry::cleanup() m_shouldNotifyMaxExtentChanged = false; } -void Geometry::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QGeometryData>>(change); - const auto &data = typedChange->data; - m_attributes = data.attributeIds; - m_boundingPositionAttribute = data.boundingVolumePositionAttributeId; - m_geometryDirty = true; - markDirty(AbstractRenderer::GeometryDirty); -} - -void Geometry::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Geometry::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("attribute")) { - m_attributes.push_back(change->addedNodeId()); - m_geometryDirty = true; - } - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("attribute")) { - m_attributes.removeOne(change->removedNodeId()); - m_geometryDirty = true; - } - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QGeometry *node = qobject_cast<const QGeometry *>(frontEnd); + if (!node) + return; + + m_geometryDirty |= firstTime; + + QNodeIdVector attribs = qIdsForNodes(node->attributes()); + std::sort(std::begin(attribs), std::end(attribs)); + if (m_attributes != attribs) { + m_attributes = attribs; + m_geometryDirty = true; } - case PropertyUpdated: { + if ((node->boundingVolumePositionAttribute() && node->boundingVolumePositionAttribute()->id() != m_boundingPositionAttribute) || // Note: doesn't set dirtyness as this parameter changing doesn't need a new VAO update. - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("boundingVolumePositionAttribute")) { - m_boundingPositionAttribute = change->value().value<QNodeId>(); - break; - } + (!node->boundingVolumePositionAttribute() && !m_boundingPositionAttribute.isNull())) { + m_boundingPositionAttribute = node->boundingVolumePositionAttribute() ? node->boundingVolumePositionAttribute()->id() : QNodeId{}; } - default: - break; - } markDirty(AbstractRenderer::GeometryDirty); - BackendNode::sceneChangeEvent(e); } void Geometry::unsetDirty() diff --git a/src/render/geometry/geometry_p.h b/src/render/geometry/geometry_p.h index e66524787..429a577b0 100644 --- a/src/render/geometry/geometry_p.h +++ b/src/render/geometry/geometry_p.h @@ -68,7 +68,7 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline QVector<Qt3DCore::QNodeId> attributes() const { return m_attributes; } inline bool isDirty() const { return m_geometryDirty; } @@ -82,8 +82,6 @@ public: void notifyExtentChanged(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_attributes; bool m_geometryDirty; Qt3DCore::QNodeId m_boundingPositionAttribute; diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp index ea059c6ee..b5c741659 100644 --- a/src/render/geometry/geometryrenderer.cpp +++ b/src/render/geometry/geometryrenderer.cpp @@ -105,95 +105,47 @@ void GeometryRenderer::setManager(GeometryRendererManager *manager) m_manager = manager; } -void GeometryRenderer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QGeometryRendererData>>(change); - const auto &data = typedChange->data; - m_geometryId = data.geometryId; - m_instanceCount = data.instanceCount; - m_vertexCount = data.vertexCount; - m_indexOffset = data.indexOffset; - m_firstInstance = data.firstInstance; - m_firstVertex = data.firstVertex; - m_indexBufferByteOffset = data.indexBufferByteOffset; - m_restartIndexValue = data.restartIndexValue; - m_verticesPerPatch = data.verticesPerPatch; - m_primitiveRestartEnabled = data.primitiveRestart; - m_primitiveType = data.primitiveType; - - Q_ASSERT(m_manager); - m_geometryFactory = data.geometryFactory; - if (m_geometryFactory) - m_manager->addDirtyGeometryRenderer(peerId()); - - m_dirty = true; - markDirty(AbstractRenderer::GeometryDirty); -} - -void GeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - - if (propertyName == QByteArrayLiteral("instanceCount")) { - m_instanceCount = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("vertexCount")) { - m_vertexCount = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("indexOffset")) { - m_indexOffset = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("firstInstance")) { - m_firstInstance = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("firstVertex")) { - m_firstVertex = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("indexBufferByteOffset")) { - m_indexBufferByteOffset = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("restartIndexValue")) { - m_restartIndexValue = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("verticesPerPatch")) { - m_verticesPerPatch = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("primitiveRestartEnabled")) { - m_primitiveRestartEnabled = propertyChange->value().toBool(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("primitiveType")) { - m_primitiveType = static_cast<QGeometryRenderer::PrimitiveType>(propertyChange->value().value<int>()); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("geometryFactory")) { - QGeometryFactoryPtr newFunctor = propertyChange->value().value<QGeometryFactoryPtr>(); - const bool functorDirty = ((m_geometryFactory && !newFunctor) - || (!m_geometryFactory && newFunctor) - || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory))); - m_dirty |= functorDirty; - if (functorDirty) { - m_geometryFactory = newFunctor; - if (m_geometryFactory && m_manager != nullptr) - m_manager->addDirtyGeometryRenderer(peerId()); - } - } else if (propertyName == QByteArrayLiteral("geometry")) { - m_geometryId = propertyChange->value().value<Qt3DCore::QNodeId>(); - m_dirty = true; - } - break; - } - - default: - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QGeometryRenderer *node = qobject_cast<const QGeometryRenderer *>(frontEnd); + if (!node) + return; + + m_dirty |= m_instanceCount != node->instanceCount(); + m_instanceCount = node->instanceCount(); + m_dirty |= m_vertexCount != node->vertexCount(); + m_vertexCount = node->vertexCount(); + m_dirty |= m_indexOffset != node->indexOffset(); + m_indexOffset = node->indexOffset(); + m_dirty |= m_firstInstance != node->firstInstance(); + m_firstInstance = node->firstInstance(); + m_dirty |= m_firstVertex != node->firstVertex(); + m_firstVertex = node->firstVertex(); + m_dirty |= m_indexBufferByteOffset != node->indexBufferByteOffset(); + m_indexBufferByteOffset = node->indexBufferByteOffset(); + m_dirty |= m_restartIndexValue != node->restartIndexValue(); + m_restartIndexValue = node->restartIndexValue(); + m_dirty |= m_verticesPerPatch != node->verticesPerPatch(); + m_verticesPerPatch = node->verticesPerPatch(); + m_dirty |= m_primitiveRestartEnabled != node->primitiveRestartEnabled(); + m_primitiveRestartEnabled = node->primitiveRestartEnabled(); + m_dirty |= m_primitiveType != node->primitiveType(); + m_primitiveType = node->primitiveType(); + m_dirty |= (node->geometry() && m_geometryId != node->geometry()->id()) || (!node->geometry() && !m_geometryId.isNull()); + m_geometryId = node->geometry() ? node->geometry()->id() : Qt3DCore::QNodeId(); + QGeometryFactoryPtr newFunctor = node->geometryFactory(); + const bool functorDirty = ((m_geometryFactory && !newFunctor) + || (!m_geometryFactory && newFunctor) + || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory))); + if (functorDirty) { + m_dirty = true; + m_geometryFactory = newFunctor; + if (m_geometryFactory && m_manager != nullptr) + m_manager->addDirtyGeometryRenderer(peerId()); } markDirty(AbstractRenderer::GeometryDirty); - - BackendNode::sceneChangeEvent(e); - - // Add to dirty list in manager } void GeometryRenderer::executeFunctor() diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h index 57d1ca0be..da538a00d 100644 --- a/src/render/geometry/geometryrenderer_p.h +++ b/src/render/geometry/geometryrenderer_p.h @@ -74,7 +74,7 @@ public: void cleanup(); void setManager(GeometryRendererManager *manager); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void executeFunctor(); inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; } @@ -98,8 +98,6 @@ public: QVector<RayCasting::QBoundingVolume *> triangleData() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_geometryId; int m_instanceCount; int m_vertexCount; diff --git a/src/render/geometry/joint.cpp b/src/render/geometry/joint.cpp index c770564f9..86d583f51 100644 --- a/src/render/geometry/joint.cpp +++ b/src/render/geometry/joint.cpp @@ -39,11 +39,14 @@ #include "joint_p.h" #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> + QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -69,21 +72,7 @@ void Joint::cleanup() setEnabled(false); } -void Joint::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - Q_ASSERT(m_jointManager); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QJointData>>(change); - const auto &data = typedChange->data; - m_inverseBindMatrix = data.inverseBindMatrix; - m_localPose.rotation = data.rotation; - m_localPose.scale = data.scale; - m_localPose.translation = data.translation; - m_childJointIds = data.childJointIds; - m_name = data.name; - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); -} - +// TODOSYNC remove once animation changes don't use messages anymore void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { if (e->type() == PropertyUpdated) { @@ -123,10 +112,60 @@ void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &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; + + if (m_localPose.scale != joint->scale()) { + m_localPose.scale = joint->scale(); + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + if (m_localPose.rotation != joint->rotation()) { + m_localPose.rotation = joint->rotation(); + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + if (m_localPose.translation != joint->translation()) { + m_localPose.translation = joint->translation(); + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + if (m_inverseBindMatrix != joint->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 = joint->inverseBindMatrix(); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton); + } + if (m_name != joint->name()) { + // Joint name doesn't affect anything in the render aspect so no need + // to mark anything as dirty. + m_name = joint->name(); + + // TODO: Notify other aspects (animation) about the name change. + } + + Qt3DCore::QNodeIdVector childIds = qIdsForNodes(joint->childJoints()); + std::sort(std::begin(childIds), std::end(childIds)); + if (m_childJointIds != childIds) { + m_childJointIds = childIds; + } + + if (firstTime) { + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); +} + JointFunctor::JointFunctor(AbstractRenderer *renderer, JointManager *jointManager, diff --git a/src/render/geometry/joint_p.h b/src/render/geometry/joint_p.h index e144ac489..d0530ac04 100644 --- a/src/render/geometry/joint_p.h +++ b/src/render/geometry/joint_p.h @@ -70,6 +70,7 @@ public: 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; } QMatrix4x4 inverseBindMatrix() const { return m_inverseBindMatrix; } @@ -90,8 +91,6 @@ public: SkeletonManager *skeletonManager() const { return m_skeletonManager; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QMatrix4x4 m_inverseBindMatrix; Qt3DCore::Sqt m_localPose; QVector<Qt3DCore::QNodeId> m_childJointIds; diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp index ca467fda9..a28d0baa6 100644 --- a/src/render/geometry/qattribute.cpp +++ b/src/render/geometry/qattribute.cpp @@ -505,6 +505,19 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAttribute::createNodeCreationChange() const return creationChange; } + +/*! +\fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize) + +The signal is emitted with \a vertexSize when the dataSize changes. +*/ +/*! +\fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType) + +The signal is emitted with \a vertexBaseType when the dataType changed. +*/ + + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp index e0574a4c5..f27005f2b 100644 --- a/src/render/geometry/qbuffer.cpp +++ b/src/render/geometry/qbuffer.cpp @@ -329,7 +329,7 @@ void QBuffer::setData(const QByteArray &bytes) Q_D(QBuffer); if (bytes != d->m_data) { d->m_data = bytes; - Qt3DCore::QNodePrivate::get(this)->notifyPropertyChange("data", QVariant::fromValue(d->m_data)); + Qt3DCore::QNodePrivate::get(this)->update(); emit dataChanged(bytes); } } @@ -351,11 +351,8 @@ void QBuffer::updateData(int offset, const QByteArray &bytes) QBufferUpdate updateData; updateData.offset = offset; updateData.data = bytes; - - auto e = QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("updateData"); - e->setValue(QVariant::fromValue(updateData)); - notifyObservers(e); + setProperty("QT3D_updateData", QVariant::fromValue(updateData)); + d->update(); } /*! @@ -409,12 +406,7 @@ void QBuffer::setDataGenerator(const QBufferDataGeneratorPtr &functor) if (functor && d->m_functor && *functor == *d->m_functor) return; d->m_functor = functor; - if (d->m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("dataGenerator"); - change->setValue(QVariant::fromValue(d->m_functor)); - d->notifyObservers(change); - } + d->update(); } /*! diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp index ec80e2657..47fad4302 100644 --- a/src/render/geometry/qgeometry.cpp +++ b/src/render/geometry/qgeometry.cpp @@ -196,11 +196,7 @@ void QGeometry::addAttribute(QAttribute *attribute) if (!attribute->parent()) attribute->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } + d->update(); } } @@ -212,14 +208,10 @@ void QGeometry::removeAttribute(QAttribute *attribute) { Q_ASSERT(attribute); Q_D(QGeometry); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } d->m_attributes.removeOne(attribute); // Remove bookkeeping connection d->unregisterDestructionHelper(attribute); + d->update(); } void QGeometry::setBoundingVolumePositionAttribute(QAttribute *boundingVolumePositionAttribute) diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp index 6bff3462f..ddea873a7 100644 --- a/src/render/geometry/qgeometryrenderer.cpp +++ b/src/render/geometry/qgeometryrenderer.cpp @@ -480,12 +480,7 @@ void QGeometryRenderer::setGeometryFactory(const QGeometryFactoryPtr &factory) if (factory && d->m_geometryFactory && *factory == *d->m_geometryFactory) return; d->m_geometryFactory = factory; - if (d->m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("geometryFactory"); - change->setValue(QVariant::fromValue(d->m_geometryFactory)); - d->notifyObservers(change); - } + d->update(); } /*! diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp index 615b76c88..d4af1fe3c 100644 --- a/src/render/geometry/skeleton.cpp +++ b/src/render/geometry/skeleton.cpp @@ -80,39 +80,68 @@ void Skeleton::cleanup() setEnabled(false); } -void Skeleton::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - Q_ASSERT(m_skeletonManager); - m_skeletonHandle = m_skeletonManager->lookupHandle(peerId()); - - const auto skeletonCreatedChange = qSharedPointerCast<QSkeletonCreatedChangeBase>(change); - switch (skeletonCreatedChange->type()) { - case QSkeletonCreatedChangeBase::SkeletonLoader: { - const auto loaderTypedChange = qSharedPointerCast<QSkeletonCreatedChange<QSkeletonLoaderData>>(change); - const auto &data = loaderTypedChange->data; - m_dataType = File; - m_source = data.source; - m_createJoints = data.createJoints; - if (!m_source.isEmpty()) { - markDirty(AbstractRenderer::SkeletonDataDirty); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractSkeleton *node = qobject_cast<const QAbstractSkeleton *>(frontEnd); + if (!node) + return; + const QSkeleton *skeletonNode = qobject_cast<const QSkeleton *>(frontEnd); + const QSkeletonLoader *loaderNode = qobject_cast<const QSkeletonLoader *>(frontEnd); + + if (firstTime) { + m_skeletonHandle = m_skeletonManager->lookupHandle(peerId()); + + if (skeletonNode) { + m_dataType = Data; + m_rootJointId = skeletonNode->rootJoint()->id(); + if (!m_rootJointId.isNull()) { + markDirty(AbstractRenderer::SkeletonDataDirty); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + } + } + + if (loaderNode) { + m_dataType = File; + m_source = loaderNode->source(); + if (!m_source.isEmpty()) { + markDirty(AbstractRenderer::SkeletonDataDirty); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + } } - break; } - case QSkeletonCreatedChangeBase::Skeleton: - const auto typedChange = qSharedPointerCast<QSkeletonCreatedChange<QSkeletonData>>(change); - const auto &data = typedChange->data; - m_dataType = Data; - m_rootJointId = data.rootJointId; - if (!m_rootJointId.isNull()) { + if (loaderNode) { + if (loaderNode->source() != m_source) { + m_source = loaderNode->source(); markDirty(AbstractRenderer::SkeletonDataDirty); m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); } - break; + 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{}; + + // 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 + // to loadSkeleton(), see below, to build the internal data from the frontend + // joints rather than from the source url again, we need to change the data type + // to Data. + m_dataType = Data; + + // If the joint changes, we need to rebuild our internal SkeletonData and + // the relationships between joints and skeleton. Mark the skeleton data as + // dirty so that we get a loadSkeletonJob executed to process this skeleton. + if (!m_rootJointId.isNull()) { + markDirty(AbstractRenderer::SkeletonDataDirty); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + } + } } } +// TODOSYNC remove once animation aspect no longer requires messages void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { switch (e->type()) { @@ -123,31 +152,6 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) // 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>>(); - } else if (change->propertyName() == QByteArrayLiteral("source")) { - Q_ASSERT(m_dataType == File); - const auto source = change->value().toUrl(); - if (source != m_source) { - m_source = source; - markDirty(AbstractRenderer::SkeletonDataDirty); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); - } - } else if (change->propertyName() == QByteArrayLiteral("createJointsEnabled")) { - m_createJoints = change->value().toBool(); - } else if (change->propertyName() == QByteArrayLiteral("rootJoint")) { - m_rootJointId = change->value().value<QNodeId>(); - - // 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 - // to loadSkeleton(), see below, to build the internal data from the frontend - // joints rather than from the source url again, we need to change the data type - // to Data. - m_dataType = Data; - - // If the joint changes, we need to rebuild our internal SkeletonData and - // the relationships between joints and skeleton. Mark the skeleton data as - // dirty so that we get a loadSkeletonJob executed to process this skeleton. - markDirty(AbstractRenderer::SkeletonDataDirty); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); } break; diff --git a/src/render/geometry/skeleton_p.h b/src/render/geometry/skeleton_p.h index 4a14e5c1c..d71b404e5 100644 --- a/src/render/geometry/skeleton_p.h +++ b/src/render/geometry/skeleton_p.h @@ -85,6 +85,7 @@ public: 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; } @@ -120,7 +121,6 @@ public: #endif private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void loadSkeletonFromUrl(); void loadSkeletonFromData(); Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const; diff --git a/src/render/lights/environmentlight.cpp b/src/render/lights/environmentlight.cpp index d4245fb6e..20364fdfa 100644 --- a/src/render/lights/environmentlight.cpp +++ b/src/render/lights/environmentlight.cpp @@ -53,11 +53,17 @@ QNodeId EnvironmentLight::shaderData() const return m_shaderDataId; } -void EnvironmentLight::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void EnvironmentLight::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEnvironmentLightData>>(change); - const auto &data = typedChange->data; - m_shaderDataId = data.shaderDataId; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QEnvironmentLight *node = qobject_cast<const QEnvironmentLight *>(frontEnd); + if (!node) + return; + + if (firstTime) { + QEnvironmentLightPrivate *d = static_cast<QEnvironmentLightPrivate *>(QEnvironmentLightPrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd))); + m_shaderDataId = d->m_shaderData ? d->m_shaderData->id() : QNodeId{}; + } } } // namespace Render diff --git a/src/render/lights/environmentlight_p.h b/src/render/lights/environmentlight_p.h index 00d49d298..92f6ce100 100644 --- a/src/render/lights/environmentlight_p.h +++ b/src/render/lights/environmentlight_p.h @@ -63,10 +63,9 @@ class Q_AUTOTEST_EXPORT EnvironmentLight : public BackendNode { public: Qt3DCore::QNodeId shaderData() const; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_shaderDataId; }; diff --git a/src/render/lights/light.cpp b/src/render/lights/light.cpp index e8474b728..30d71082b 100644 --- a/src/render/lights/light.cpp +++ b/src/render/lights/light.cpp @@ -58,14 +58,18 @@ QNodeId Light::shaderData() const return m_shaderDataId; } -void Light::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void Light::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractLightData>>(change); - const auto &data = typedChange->data; - m_shaderDataId = data.shaderDataId; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractLight *node = qobject_cast<const QAbstractLight *>(frontEnd); + if (!node) + return; - Q_ASSERT(m_renderer); - BackendNode::markDirty(AbstractRenderer::LightsDirty); + if (firstTime) { + QAbstractLightPrivate *d = static_cast<QAbstractLightPrivate *>(QAbstractLightPrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd))); + m_shaderDataId = d->m_shaderData ? d->m_shaderData->id() : QNodeId{}; + BackendNode::markDirty(AbstractRenderer::LightsDirty); + } } RenderLightFunctor::RenderLightFunctor(AbstractRenderer *renderer, NodeManagers *managers) diff --git a/src/render/lights/light_p.h b/src/render/lights/light_p.h index 8ecc87585..5f5f8140e 100644 --- a/src/render/lights/light_p.h +++ b/src/render/lights/light_p.h @@ -66,9 +66,9 @@ class Q_AUTOTEST_EXPORT Light : public BackendNode public: Qt3DCore::QNodeId shaderData() const; -private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; +private: Qt3DCore::QNodeId m_shaderDataId; }; diff --git a/src/render/materialsystem/effect.cpp b/src/render/materialsystem/effect.cpp index 29d05ed01..76036bd1f 100644 --- a/src/render/materialsystem/effect.cpp +++ b/src/render/materialsystem/effect.cpp @@ -48,6 +48,7 @@ #include <Qt3DCore/qpropertynoderemovedchange.h> #include <QVariant> +#include <algorithm> QT_BEGIN_NAMESPACE @@ -73,41 +74,25 @@ void Effect::cleanup() m_techniques.clear(); } -void Effect::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Effect::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEffectData>>(change); - const auto &data = typedChange->data; - m_techniques = data.techniqueIds; - m_parameterPack.setParameters(data.parameterIds); -} - -void Effect::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("technique")) - appendRenderTechnique(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.appendParameter(change->addedNodeId()); - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("technique")) - m_techniques.removeOne(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.removeParameter(change->removedNodeId()); - break; - } - - default: - break; - } - - markDirty(AbstractRenderer::AllDirty); - BackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QEffect *node = qobject_cast<const QEffect *>(frontEnd); + if (!node) + return; + + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) + m_parameterPack.setParameters(parameters); + + auto techniques = qIdsForNodes(node->techniques()); + std::sort(std::begin(techniques), std::end(techniques)); + if (m_techniques != techniques) + m_techniques = techniques; + + if (!firstTime) + markDirty(AbstractRenderer::AllDirty); } void Effect::appendRenderTechnique(Qt3DCore::QNodeId technique) diff --git a/src/render/materialsystem/effect_p.h b/src/render/materialsystem/effect_p.h index 87ff4a803..e81be2b8d 100644 --- a/src/render/materialsystem/effect_p.h +++ b/src/render/materialsystem/effect_p.h @@ -70,15 +70,13 @@ public: ~Effect(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void appendRenderTechnique(Qt3DCore::QNodeId t); QVector<Qt3DCore::QNodeId> techniques() const; QVector<Qt3DCore::QNodeId> parameters() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_techniques; ParameterPack m_parameterPack; }; diff --git a/src/render/materialsystem/material.cpp b/src/render/materialsystem/material.cpp index a69ff8a13..07764c207 100644 --- a/src/render/materialsystem/material.cpp +++ b/src/render/materialsystem/material.cpp @@ -73,47 +73,26 @@ void Material::cleanup() m_parameterPack.clear(); } -void Material::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Material::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMaterialData>>(change); - const auto &data = typedChange->data; - m_effectUuid = data.effectId; - m_parameterPack.setParameters(data.parameterIds); - - markDirty(AbstractRenderer::MaterialDirty); -} - -void Material::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - - switch (e->type()) { - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("effect")) - m_effectUuid = change->value().value<QNodeId>(); - break; - } - - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.appendParameter(change->addedNodeId()); - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.removeParameter(change->removedNodeId()); - break; - } - - default: - break; - } - markDirty(AbstractRenderer::AllDirty); - - BackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QMaterial *node = qobject_cast<const QMaterial *>(frontEnd); + if (!node) + return; + + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) + m_parameterPack.setParameters(parameters); + + const auto effectId = node->effect() ? node->effect()->id() : QNodeId{}; + if (effectId != m_effectUuid) + m_effectUuid = effectId; + + if (firstTime) + markDirty(AbstractRenderer::MaterialDirty); + else + markDirty(AbstractRenderer::AllDirty); } QVector<Qt3DCore::QNodeId> Material::parameters() const diff --git a/src/render/materialsystem/material_p.h b/src/render/materialsystem/material_p.h index 3b55dc657..7a02c6691 100644 --- a/src/render/materialsystem/material_p.h +++ b/src/render/materialsystem/material_p.h @@ -79,14 +79,12 @@ public: ~Material(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QVector<Qt3DCore::QNodeId> parameters() const; Qt3DCore::QNodeId effect() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - ParameterPack m_parameterPack; Qt3DCore::QNodeId m_effectUuid; }; diff --git a/src/render/materialsystem/parameter.cpp b/src/render/materialsystem/parameter.cpp index 86ca418aa..d32e60a2d 100644 --- a/src/render/materialsystem/parameter.cpp +++ b/src/render/materialsystem/parameter.cpp @@ -70,34 +70,33 @@ void Parameter::cleanup() m_uniformValue = UniformValue(); } -void Parameter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Parameter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QParameterData>>(change); - const auto &data = typedChange->data; - m_name = data.name; - m_nameId = StringToInt::lookupId(m_name); - m_uniformValue = UniformValue::fromVariant(data.backendValue); - markDirty(AbstractRenderer::ParameterDirty); -} + const QParameter *node = qobject_cast<const QParameter *>(frontEnd); + if (!node) + return; -void Parameter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - - if (e->type() == PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("name")) { - m_name = propertyChange->value().toString(); - m_nameId = StringToInt::lookupId(m_name); - markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("value")) { - m_uniformValue = UniformValue::fromVariant(propertyChange->value()); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) { - markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); - } + AbstractRenderer::BackendNodeDirtySet dirty = firstTime ? AbstractRenderer::ParameterDirty : static_cast<AbstractRenderer::BackendNodeDirtyFlag>(0); + if (node->isEnabled() != isEnabled()) + dirty |= (AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); + + if (node->name() != m_name) { + m_name = node->name(); + m_nameId = StringToInt::lookupId(m_name); + dirty |= (AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); } - BackendNode::sceneChangeEvent(e); + QParameterPrivate* d = static_cast<QParameterPrivate *>(QParameterPrivate::get(const_cast<QParameter *>(node))); + if (d->m_backendValue != m_backendValue) { + m_backendValue = d->m_backendValue; + m_uniformValue = UniformValue::fromVariant(m_backendValue); + dirty |= (AbstractRenderer::ParameterDirty); + } + + if (dirty) + markDirty(dirty); + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); } QString Parameter::name() const diff --git a/src/render/materialsystem/parameter_p.h b/src/render/materialsystem/parameter_p.h index 4ab04bc8e..9deaa11f3 100644 --- a/src/render/materialsystem/parameter_p.h +++ b/src/render/materialsystem/parameter_p.h @@ -71,16 +71,15 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QString name() const; int nameId() const Q_DECL_NOTHROW { return m_nameId; } const UniformValue &uniformValue() const { return m_uniformValue; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QString m_name; + QVariant m_backendValue; UniformValue m_uniformValue; int m_nameId; }; diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp index b611657c4..35ac662fb 100644 --- a/src/render/materialsystem/qeffect.cpp +++ b/src/render/materialsystem/qeffect.cpp @@ -192,11 +192,7 @@ void QEffect::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -207,14 +203,10 @@ void QEffect::removeParameter(QParameter *parameter) { Q_D(QEffect); - if (parameter && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); + d->update(); } /*! @@ -246,11 +238,7 @@ void QEffect::addTechnique(QTechnique *t) if (!t->parent()) t->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), t); - change->setPropertyName("technique"); - d->notifyObservers(change); - } + d->update(); } } @@ -260,11 +248,8 @@ void QEffect::addTechnique(QTechnique *t) void QEffect::removeTechnique(QTechnique *t) { Q_D(QEffect); - if (t && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), t); - change->setPropertyName("technique"); - d->notifyObservers(change); - } + if (t) + d->update(); d->m_techniques.removeOne(t); // Remove bookkeeping connection d->unregisterDestructionHelper(t); diff --git a/src/render/materialsystem/qgraphicsapifilter.cpp b/src/render/materialsystem/qgraphicsapifilter.cpp index 70f329172..9b5557930 100644 --- a/src/render/materialsystem/qgraphicsapifilter.cpp +++ b/src/render/materialsystem/qgraphicsapifilter.cpp @@ -107,6 +107,11 @@ QGraphicsApiFilterPrivate *QGraphicsApiFilterPrivate::get(QGraphicsApiFilter *q) return q->d_func(); } +const QGraphicsApiFilterPrivate *QGraphicsApiFilterPrivate::get(const QGraphicsApiFilter *q) +{ + return q->d_func(); +} + /*! \class Qt3DRender::QGraphicsApiFilter \inmodule Qt3DRender diff --git a/src/render/materialsystem/qgraphicsapifilter_p.h b/src/render/materialsystem/qgraphicsapifilter_p.h index 3961d4f93..435451c27 100644 --- a/src/render/materialsystem/qgraphicsapifilter_p.h +++ b/src/render/materialsystem/qgraphicsapifilter_p.h @@ -84,6 +84,7 @@ public: } static QGraphicsApiFilterPrivate *get(QGraphicsApiFilter *q); + static const QGraphicsApiFilterPrivate *get(const QGraphicsApiFilter *q); Q_DECLARE_PUBLIC(QGraphicsApiFilter) GraphicsApiFilterData m_data; diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp index c6913441e..db523a700 100644 --- a/src/render/materialsystem/qmaterial.cpp +++ b/src/render/materialsystem/qmaterial.cpp @@ -275,11 +275,7 @@ void QMaterial::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -290,11 +286,7 @@ void QMaterial::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QMaterial); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); } diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp index 111bb7b5f..d0821c49c 100644 --- a/src/render/materialsystem/qrenderpass.cpp +++ b/src/render/materialsystem/qrenderpass.cpp @@ -231,12 +231,6 @@ void QRenderPass::setShaderProgram(QShaderProgram *shaderProgram) Q_D(QRenderPass); if (d->m_shader != shaderProgram) { - if (d->m_shader != nullptr && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), d->m_shader); - change->setPropertyName("shaderProgram"); - d->notifyObservers(change); - } - if (d->m_shader) d->unregisterDestructionHelper(d->m_shader); @@ -283,11 +277,7 @@ void QRenderPass::addFilterKey(QFilterKey *filterKey) if (!filterKey->parent()) filterKey->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); } } @@ -298,11 +288,7 @@ void QRenderPass::removeFilterKey(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QRenderPass); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); d->m_filterKeyList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); @@ -339,11 +325,7 @@ void QRenderPass::addRenderState(QRenderState *state) if (!state->parent()) state->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), state); - change->setPropertyName("renderState"); - d->notifyObservers(change); - } + d->update(); } } @@ -354,11 +336,7 @@ void QRenderPass::removeRenderState(QRenderState *state) { Q_ASSERT(state); Q_D(QRenderPass); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), state); - change->setPropertyName("renderState"); - d->notifyObservers(change); - } + d->update(); d->m_renderStates.removeOne(state); // Remove bookkeeping connection d->unregisterDestructionHelper(state); @@ -394,11 +372,7 @@ void QRenderPass::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -409,11 +383,7 @@ void QRenderPass::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QRenderPass); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp index b668eb25f..dadeb98bd 100644 --- a/src/render/materialsystem/qtechnique.cpp +++ b/src/render/materialsystem/qtechnique.cpp @@ -234,12 +234,7 @@ QTechnique::QTechnique(QTechniquePrivate &dd, QNode *parent) /*! \internal */ void QTechniquePrivate::_q_graphicsApiFilterChanged() { - if (m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(m_id); - change->setPropertyName("graphicsApiFilterData"); - change->setValue(QVariant::fromValue(QGraphicsApiFilterPrivate::get(const_cast<QGraphicsApiFilter *>(&m_graphicsApiFilter))->m_data)); - notifyObservers(change); - } + update(); } /*! @@ -262,11 +257,7 @@ void QTechnique::addFilterKey(QFilterKey *filterKey) if (!filterKey->parent()) filterKey->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); } } @@ -277,11 +268,7 @@ void QTechnique::removeFilterKey(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QTechnique); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); d->m_filterKeys.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); @@ -317,11 +304,7 @@ void QTechnique::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -332,11 +315,7 @@ void QTechnique::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QTechnique); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); @@ -362,11 +341,7 @@ void QTechnique::addRenderPass(QRenderPass *pass) if (!pass->parent()) pass->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), pass); - change->setPropertyName("pass"); - d->notifyObservers(change); - } + d->update(); } } @@ -377,11 +352,7 @@ void QTechnique::removeRenderPass(QRenderPass *pass) { Q_ASSERT(pass); Q_D(QTechnique); - if (d->m_changeArbiter) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), pass); - change->setPropertyName("pass"); - d->notifyObservers(change); - } + d->update(); d->m_renderPasses.removeOne(pass); // Remove bookkeeping connection d->unregisterDestructionHelper(pass); @@ -405,12 +376,19 @@ QVector<QParameter *> QTechnique::parameters() const return d->m_parameters; } +// TODO Qt 6 -> Remove QGraphicsApiFilter *QTechnique::graphicsApiFilter() { Q_D(QTechnique); return &d->m_graphicsApiFilter; } +const QGraphicsApiFilter *QTechnique::graphicsApiFilter() const +{ + Q_D(const QTechnique); + return &d->m_graphicsApiFilter; +} + Qt3DCore::QNodeCreatedChangeBasePtr QTechnique::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QTechniqueData>::create(this); diff --git a/src/render/materialsystem/qtechnique.h b/src/render/materialsystem/qtechnique.h index 7711cd67f..f0c857c2b 100644 --- a/src/render/materialsystem/qtechnique.h +++ b/src/render/materialsystem/qtechnique.h @@ -76,7 +76,8 @@ public: void removeRenderPass(QRenderPass *pass); QVector<QRenderPass *> renderPasses() const; - QGraphicsApiFilter *graphicsApiFilter(); + Q_DECL_DEPRECATED QGraphicsApiFilter *graphicsApiFilter(); + const QGraphicsApiFilter *graphicsApiFilter() const; protected: explicit QTechnique(QTechniquePrivate &dd, Qt3DCore::QNode *parent = nullptr); diff --git a/src/render/materialsystem/renderpass.cpp b/src/render/materialsystem/renderpass.cpp index e0fadddd9..aaeca3bb4 100644 --- a/src/render/materialsystem/renderpass.cpp +++ b/src/render/materialsystem/renderpass.cpp @@ -52,6 +52,8 @@ #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> +#include <algorithm> + QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -77,58 +79,33 @@ void RenderPass::cleanup() m_shaderUuid = Qt3DCore::QNodeId(); } -void RenderPass::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderPassData>>(change); - const auto &data = typedChange->data; - m_filterKeyList = data.filterKeyIds; - m_parameterPack.setParameters(data.parameterIds); - for (const auto &renderStateId : qAsConst(data.renderStateIds)) - addRenderState(renderStateId); - m_shaderUuid = data.shaderId; -} - -void RenderPass::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void RenderPass::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("filterKeys")) - appendFilterKey(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderUuid = change->addedNodeId(); - else if (change->propertyName() == QByteArrayLiteral("renderState")) - addRenderState(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.appendParameter(change->addedNodeId()); - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QRenderPass *node = qobject_cast<const QRenderPass *>(frontEnd); + if (!node) + return; + + if ((node->shaderProgram() && node->shaderProgram()->id() != m_shaderUuid) || + (!node->shaderProgram() && !m_shaderUuid.isNull())) { + m_shaderUuid = node->shaderProgram() ? node->shaderProgram()->id() : QNodeId{}; } - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderUuid = change->value().value<Qt3DCore::QNodeId>(); - break; - } + auto filterList = qIdsForNodes(node->filterKeys()); + std::sort(std::begin(filterList), std::end(filterList)); + if (m_filterKeyList != filterList) + m_filterKeyList = filterList; - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("filterKeys")) - removeFilterKey(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderUuid = QNodeId(); - else if (change->propertyName() == QByteArrayLiteral("renderState")) - removeRenderState(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.removeParameter(change->removedNodeId()); - break; - } + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) + m_parameterPack.setParameters(parameters); - default: - break; - } + auto renderStates = qIdsForNodes(node->renderStates()); + std::sort(std::begin(renderStates), std::end(renderStates)); + if (m_renderStates != renderStates) + m_renderStates = renderStates; - BackendNode::sceneChangeEvent(e); markDirty(AbstractRenderer::AllDirty); } diff --git a/src/render/materialsystem/renderpass_p.h b/src/render/materialsystem/renderpass_p.h index 1ca02b1ad..314386ad1 100644 --- a/src/render/materialsystem/renderpass_p.h +++ b/src/render/materialsystem/renderpass_p.h @@ -79,7 +79,7 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId shaderProgram() const; QVector<Qt3DCore::QNodeId> filterKeys() const; @@ -95,8 +95,6 @@ private: void addRenderState(Qt3DCore::QNodeId renderStateId); void removeRenderState(Qt3DCore::QNodeId renderStateId); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_shaderUuid; QVector<Qt3DCore::QNodeId> m_filterKeyList; ParameterPack m_parameterPack; diff --git a/src/render/materialsystem/technique.cpp b/src/render/materialsystem/technique.cpp index 42430883e..d4199b7e3 100644 --- a/src/render/materialsystem/technique.cpp +++ b/src/render/materialsystem/technique.cpp @@ -85,72 +85,48 @@ void Technique::cleanup() m_isCompatibleWithRenderer = false; } -void Technique::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Technique::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTechniqueData>>(change); - const QTechniqueData &data = typedChange->data; - - m_graphicsApiFilterData = data.graphicsApiFilterData; - m_filterKeyList = data.filterKeyIds; - m_parameterPack.setParameters(data.parameterIds); - m_renderPasses = data.renderPassIds; - m_nodeManager->techniqueManager()->addDirtyTechnique(peerId()); - markDirty(AbstractRenderer::TechniquesDirty); -} + const QTechnique *node = qobject_cast<const QTechnique *>(frontEnd); -void Technique::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("enabled")) { - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("graphicsApiFilterData")) { - GraphicsApiFilterData filterData = change->value().value<GraphicsApiFilterData>(); - m_graphicsApiFilterData = filterData; - // Notify the manager that our graphicsApiFilterData has changed - // and that we therefore need to be check for compatibility again - m_isCompatibleWithRenderer = false; - m_nodeManager->techniqueManager()->addDirtyTechnique(peerId()); - markDirty(AbstractRenderer::TechniquesDirty); - } - break; + if (!node) + return; + + bool dirty = isEnabled() != frontEnd->isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + auto renderPasses = qIdsForNodes(node->renderPasses()); + std::sort(std::begin(renderPasses), std::end(renderPasses)); + if (m_renderPasses != renderPasses) { + m_renderPasses = renderPasses; + dirty = true; } - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("pass")) { - appendRenderPass(change->addedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.appendParameter(change->addedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("filterKeys")) { - appendFilterKey(change->addedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } - break; + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) { + m_parameterPack.setParameters(parameters); + dirty = true; } - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("pass")) { - removeRenderPass(change->removedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.removeParameter(change->removedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("filterKeys")) { - removeFilterKey(change->removedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } - break; + auto filterKeys = qIdsForNodes(node->filterKeys()); + std::sort(std::begin(filterKeys), std::end(filterKeys)); + if (m_filterKeyList != filterKeys) { + m_filterKeyList = filterKeys; + dirty = true; + } + + auto graphicsApiFilterData = QGraphicsApiFilterPrivate::get(node->graphicsApiFilter())->m_data; + if (m_graphicsApiFilterData != graphicsApiFilterData) { + m_graphicsApiFilterData = graphicsApiFilterData; + m_isCompatibleWithRenderer = false; + dirty = true; } - default: - break; + if (dirty) { + m_nodeManager->techniqueManager()->addDirtyTechnique(peerId()); + markDirty(AbstractRenderer::TechniquesDirty); } - BackendNode::sceneChangeEvent(e); } QVector<Qt3DCore::QNodeId> Technique::parameters() const diff --git a/src/render/materialsystem/technique_p.h b/src/render/materialsystem/technique_p.h index d885c1b87..1d0d0a9dd 100644 --- a/src/render/materialsystem/technique_p.h +++ b/src/render/materialsystem/technique_p.h @@ -80,7 +80,8 @@ public: ~Technique(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + QVector<Qt3DCore::QNodeId> parameters() const; void appendRenderPass(Qt3DCore::QNodeId renderPassId); @@ -102,7 +103,6 @@ public: NodeManagers *nodeManager() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; GraphicsApiFilterData m_graphicsApiFilterData; ParameterPack m_parameterPack; diff --git a/src/render/picking/qpickevent.cpp b/src/render/picking/qpickevent.cpp index a18c6ead8..ae5748082 100644 --- a/src/render/picking/qpickevent.cpp +++ b/src/render/picking/qpickevent.cpp @@ -309,14 +309,14 @@ int QPickEvent::modifiers() const * The viewport in which this event originated. A null value means the event originated from a frame graph branch without a Viewport. * If a frame graph branch has a Viewport inside a Viewport the property will contain the leaf viewport. * - * \since 5.13 + * \since 5.14 */ /*! * \property Qt3DRender::QPickEvent::viewport * The viewport in which this event originated. A null value means the event originated from a frame graph branch without a QViewport. * If a frame graph branch has a Viewport inside a Viewport the property will contain the leaf viewport. * - * \since 5.13 + * \since 5.14 */ QViewport *QPickEvent::viewport() const { @@ -332,7 +332,7 @@ QViewport *QPickEvent::viewport() const * If the object picker is not attached to a leaf node in the scene graph, * this is useful to find which child entity was actually picked. * - * \since 5.13 + * \since 5.14 */ /*! * \property Qt3DRender::QPickEvent::entity @@ -341,7 +341,7 @@ QViewport *QPickEvent::viewport() const * If the object picker is not attached to a leaf node in the scene graph, * this is useful to find which child entity was actually picked. * - * \since 5.13 + * \since 5.14 */ Qt3DCore::QEntity *QPickEvent::entity() const { diff --git a/src/render/picking/qpickevent.h b/src/render/picking/qpickevent.h index 21d072ffe..854008aaf 100644 --- a/src/render/picking/qpickevent.h +++ b/src/render/picking/qpickevent.h @@ -70,8 +70,8 @@ class Q_3DRENDERSHARED_EXPORT QPickEvent : public QObject Q_PROPERTY(Qt3DRender::QPickEvent::Buttons button READ button CONSTANT) Q_PROPERTY(int buttons READ buttons CONSTANT) Q_PROPERTY(int modifiers READ modifiers CONSTANT) - Q_PROPERTY(Qt3DRender::QViewport *viewport READ viewport CONSTANT) - Q_PROPERTY(Qt3DCore::QEntity *entity READ entity CONSTANT) + Q_PROPERTY(Qt3DRender::QViewport *viewport READ viewport CONSTANT REVISION 14) + Q_PROPERTY(Qt3DCore::QEntity *entity READ entity CONSTANT REVISION 14) public: enum Buttons { LeftButton = Qt::LeftButton, diff --git a/src/render/renderers/opengl/renderer/commandthread.cpp b/src/render/renderers/opengl/renderer/commandthread.cpp index dcaacadcc..a518d3b68 100644 --- a/src/render/renderers/opengl/renderer/commandthread.cpp +++ b/src/render/renderers/opengl/renderer/commandthread.cpp @@ -176,7 +176,7 @@ void CommandThread::run() m_commandRequestedSemaphore.acquire(); // Are we still running? - if (!m_running.load()) { + if (!m_running.loadRelaxed()) { m_graphicsContext->doneCurrent(); // to prevent executeCommand being locked m_commandExecutionSemaphore.release(); diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index e0d1f598f..845a4d8be 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -448,7 +448,7 @@ void Renderer::shutdown() QMutexLocker lock(&m_hasBeenInitializedMutex); qCDebug(Backend) << Q_FUNC_INFO << "Requesting renderer shutdown"; - m_running.store(0); + m_running.storeRelaxed(0); // We delete any renderqueue that we may not have had time to render // before the surface was destroyed @@ -619,7 +619,7 @@ void Renderer::render() // One scene description // One framegraph description - while (m_running.load() > 0) { + while (m_running.loadRelaxed() > 0) { doRender(); // TO DO: Restore windows exposed detection // Probably needs to happens some place else though @@ -789,7 +789,7 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder); locker.unlock(); // We're done protecting the queue at this point if (isQueueComplete) { - if (m_renderThread && m_running.load()) + if (m_renderThread && m_running.loadRelaxed()) Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0); m_submitRenderViewsSemaphore.release(1); } @@ -798,7 +798,7 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder bool Renderer::canRender() const { // Make sure that we've not been told to terminate - if (m_renderThread && !m_running.load()) { + if (m_renderThread && !m_running.loadRelaxed()) { qCDebug(Rendering) << "RenderThread termination requested whilst waiting"; return false; } @@ -817,7 +817,7 @@ bool Renderer::isReadyToSubmit() m_submitRenderViewsSemaphore.acquire(1); // Check if shutdown has been requested - if (m_running.load() == 0) + if (m_running.loadRelaxed() == 0) return false; // The semaphore should only @@ -1424,7 +1424,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren const int renderViewsCount = renderViews.size(); quint64 frameElapsed = queueElapsed; - m_lastFrameCorrect.store(1); // everything fine until now..... + m_lastFrameCorrect.storeRelaxed(1); // everything fine until now..... qCDebug(Memory) << Q_FUNC_INFO << "rendering frame "; @@ -1457,7 +1457,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // to use when surface is null. Or if we should instead expose an // offscreensurface to Qt3D. if (!surface || !surfaceLock.isSurfaceValid()) { - m_lastFrameCorrect.store(0); + m_lastFrameCorrect.storeRelaxed(0); continue; } @@ -1477,7 +1477,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // next RenderView. We won't get the full frame but we may get something if (!m_submissionContext->beginDrawing(surface)) { qWarning() << "Failed to make OpenGL context current on surface"; - m_lastFrameCorrect.store(0); + m_lastFrameCorrect.storeRelaxed(0); continue; } @@ -1578,7 +1578,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // Execute the render commands if (!executeCommandsSubmission(renderView)) - m_lastFrameCorrect.store(0); // something went wrong; make sure to render the next frame! + m_lastFrameCorrect.storeRelaxed(0); // something went wrong; make sure to render the next frame! // executeCommandsSubmission takes care of restoring the stateset to the value // of gc->currentContext() at the moment it was called (either @@ -1681,7 +1681,7 @@ bool Renderer::shouldRender() || m_renderThread == nullptr // <==> we use Scene3D || m_dirtyBits.marked != 0 || m_dirtyBits.remaining != 0 - || !m_lastFrameCorrect.load()); + || !m_lastFrameCorrect.loadRelaxed()); } void Renderer::skipNextFrame() diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index 6286f1bce..0f911236a 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -185,7 +185,7 @@ public: void doRender(bool swapBuffers = true) override; void cleanGraphicsResources() override; - bool isRunning() const override { return m_running.load(); } + bool isRunning() const override { return m_running.loadRelaxed(); } void setSceneRoot(Entity *sgRoot) override; Entity *sceneRoot() const override { return m_renderSceneRoot; } diff --git a/src/render/renderstates/qdepthrange.cpp b/src/render/renderstates/qdepthrange.cpp index 58b8b744a..ec5bbce9f 100644 --- a/src/render/renderstates/qdepthrange.cpp +++ b/src/render/renderstates/qdepthrange.cpp @@ -48,7 +48,7 @@ namespace Qt3DRender { /*! \class Qt3DRender::QDepthRange \inmodule Qt3DRender - \since 5.13 + \since 5.14 \ingroup renderstates \brief Enables remapping depth values written into the depth buffer. @@ -65,7 +65,7 @@ namespace Qt3DRender { \inherits RenderState \inqmlmodule Qt3D.Render \ingroup renderstates - \since 5.13 + \since 5.14 \brief Enables remapping depth values written into the depth buffer. By default, OpenGL writes scene depth information into the depth buffer in diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index 399314f24..229d773ad 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -81,10 +81,7 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat { if (generator != m_dataFunctor) { m_dataFunctor = generator; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); - change->setPropertyName("generator"); - change->setValue(QVariant::fromValue(generator)); - notifyObservers(change); + update(); } } @@ -811,24 +808,15 @@ void QAbstractTexture::setWrapMode(const QTextureWrapMode &wrapMode) Q_D(QAbstractTexture); if (d->m_wrapMode.x() != wrapMode.x()) { d->m_wrapMode.setX(wrapMode.x()); - auto e = QPropertyUpdatedChangePtr::create(d->m_id); - e->setPropertyName("wrapModeX"); - e->setValue(static_cast<int>(d->m_wrapMode.x())); - d->notifyObservers(e); + d->update(); } if (d->m_wrapMode.y() != wrapMode.y()) { d->m_wrapMode.setY(wrapMode.y()); - auto e = QPropertyUpdatedChangePtr::create(d->m_id); - e->setPropertyName("wrapModeY"); - e->setValue(static_cast<int>(d->m_wrapMode.y())); - d->notifyObservers(e); + d->update(); } if (d->m_wrapMode.z() != wrapMode.z()) { d->m_wrapMode.setZ(wrapMode.z()); - auto e = QPropertyUpdatedChangePtr::create(d->m_id); - e->setPropertyName("wrapModeZ"); - e->setValue(static_cast<int>(d->m_wrapMode.z())); - d->notifyObservers(e); + d->update(); } } @@ -983,16 +971,8 @@ void QAbstractTexture::updateData(const QTextureDataUpdate &update) { Q_D(QAbstractTexture); - // Send update to backend if we have the changeArbiter - if (d->m_changeArbiter != nullptr) { - auto e = QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("updateData"); - e->setValue(QVariant::fromValue(update)); - notifyObservers(e); - } else { - // If we have no arbiter (no backend), record the update as part of the creation changes - d->m_initialDataUpdates.push_back(update); - } + d->m_pendingDataUpdates.push_back(update); + d->update(); } Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() const @@ -1019,8 +999,8 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() data.samples = d->m_samples; data.dataFunctor = d->m_dataFunctor; data.sharedTextureId = d->m_sharedTextureId; - data.initialDataUpdates = d->m_initialDataUpdates; - return creationChange; + data.initialDataUpdates = d->m_pendingDataUpdates; + return std::move(creationChange); } /*! diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h index 072bd8159..573eac8c7 100644 --- a/src/render/texture/qabstracttexture_p.h +++ b/src/render/texture/qabstracttexture_p.h @@ -96,7 +96,7 @@ public : QTextureGeneratorPtr dataFunctor() const; void setDataFunctor(const QTextureGeneratorPtr &generator); - QVector<QTextureDataUpdate> m_initialDataUpdates; + QVector<QTextureDataUpdate> m_pendingDataUpdates; private: QTextureGeneratorPtr m_dataFunctor; diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp index a95e1fffd..42f8eb747 100644 --- a/src/render/texture/qabstracttextureimage.cpp +++ b/src/render/texture/qabstracttextureimage.cpp @@ -255,12 +255,7 @@ void QAbstractTextureImage::setFace(QAbstractTexture::CubeMapFace face) void QAbstractTextureImage::notifyDataGeneratorChanged() { Q_D(QAbstractTextureImage); - if (d->m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("dataGenerator"); - change->setValue(QVariant::fromValue(dataGenerator())); - d->notifyObservers(change); - } + d->update(); } /*! \internal */ diff --git a/src/render/texture/qtexturedataupdate.cpp b/src/render/texture/qtexturedataupdate.cpp index f196a6b7b..e3d5220f0 100644 --- a/src/render/texture/qtexturedataupdate.cpp +++ b/src/render/texture/qtexturedataupdate.cpp @@ -68,6 +68,7 @@ static bool operator==(const QTextureDataUpdatePrivate &lhs, const QTextureDataU as well as the eventual layer, mipLevel and face. \sa QAbstractTexture + \since 5.14 */ QTextureDataUpdate::QTextureDataUpdate() diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp index c7a739724..53216d27d 100644 --- a/src/render/texture/texture.cpp +++ b/src/render/texture/texture.cpp @@ -61,6 +61,7 @@ Texture::Texture() // We need backend -> frontend notifications to update the status of the texture : BackendNode(ReadWrite) , m_dirty(DirtyImageGenerators|DirtyProperties|DirtyParameters|DirtyDataGenerator) + , m_sharedTextureId(-1) { } @@ -130,67 +131,6 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) DirtyFlags dirty; switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("width")) { - m_properties.width = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("height")) { - m_properties.height = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("depth")) { - m_properties.depth = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("format")) { - m_properties.format = static_cast<QAbstractTexture::TextureFormat>(propertyChange->value().toInt()); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("target")) { - m_properties.target = static_cast<QAbstractTexture::Target>(propertyChange->value().toInt()); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("mipmaps")) { - m_properties.generateMipMaps = propertyChange->value().toBool(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("minificationFilter")) { - m_parameters.minificationFilter = static_cast<QAbstractTexture::Filter>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("magnificationFilter")) { - m_parameters.magnificationFilter = static_cast<QAbstractTexture::Filter>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeX")) { - m_parameters.wrapModeX = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeY")) { - m_parameters.wrapModeY = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeZ")) { - m_parameters.wrapModeZ =static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("maximumAnisotropy")) { - m_parameters.maximumAnisotropy = propertyChange->value().toFloat(); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonFunction")) { - m_parameters.comparisonFunction = propertyChange->value().value<QAbstractTexture::ComparisonFunction>(); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonMode")) { - m_parameters.comparisonMode = propertyChange->value().value<QAbstractTexture::ComparisonMode>(); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("layers")) { - m_properties.layers = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("samples")) { - m_properties.samples = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("generator")) { - setDataGenerator(propertyChange->value().value<QTextureGeneratorPtr>()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("textureId")) { - m_sharedTextureId = propertyChange->value().toInt(); - dirty = DirtySharedTextureId; - } else if (propertyChange->propertyName() == QByteArrayLiteral("updateData")) { - Qt3DRender::QTextureDataUpdate updateData = propertyChange->value().value<Qt3DRender::QTextureDataUpdate>(); - addTextureDataUpdate(updateData); - } - break; - } case PropertyValueAdded: { const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); @@ -217,6 +157,62 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractTexture *node = qobject_cast<const QAbstractTexture *>(frontEnd); + if (!node) + return; + + TextureProperties p = m_properties; + p.width = node->width(); + p.height = node->height(); + p.depth = node->depth(); + p.format = node->format(); + p.target = node->target(); + p.generateMipMaps = node->generateMipMaps(); + p.layers = node->layers(); + p.samples = node->samples(); + if (p != m_properties) { + m_properties = p; + addDirtyFlag(DirtyProperties); + } + + TextureParameters q = m_parameters; + q.magnificationFilter = node->magnificationFilter(); + q.minificationFilter = node->minificationFilter(); + q.wrapModeX = const_cast<QAbstractTexture *>(node)->wrapMode()->x(); + q.wrapModeY = const_cast<QAbstractTexture *>(node)->wrapMode()->y(); + q.wrapModeZ = const_cast<QAbstractTexture *>(node)->wrapMode()->z(); + q.maximumAnisotropy = node->maximumAnisotropy(); + q.comparisonFunction = node->comparisonFunction(); + q.comparisonMode = node->comparisonMode(); + if (q != m_parameters) { + m_parameters = q; + addDirtyFlag(DirtyParameters); + } + + auto newGenerator = node->dataGenerator(); + if (newGenerator != m_dataFunctor) { + setDataGenerator(newGenerator); + } + + QAbstractTexturePrivate *dnode = dynamic_cast<QAbstractTexturePrivate *>(QAbstractTexturePrivate::get(const_cast<QAbstractTexture *>(node))); + if (dnode) { + for (const QTextureDataUpdate &pendingUpdate : dnode->m_pendingDataUpdates) + addTextureDataUpdate(pendingUpdate); + dnode->m_pendingDataUpdates.clear(); + + for (const auto imgNode : dnode->m_textureImages) + addTextureImage(imgNode->id()); + } + + if (dnode->m_sharedTextureId != m_sharedTextureId) { + m_sharedTextureId = dnode->m_sharedTextureId; + addDirtyFlag(DirtySharedTextureId); + } +} + // Called by sceneChangeEvent or TextureDownloadRequest (both in AspectThread context) void Texture::setDataGenerator(const QTextureGeneratorPtr &generator) { @@ -308,7 +304,7 @@ void Texture::updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo) bool Texture::isValid(TextureImageManager *manager) const { - for (const QNodeId id : m_textureImageIds) { + for (const QNodeId &id : m_textureImageIds) { TextureImage *img = manager->lookupResource(id); if (img == nullptr) return false; @@ -340,7 +336,7 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan m_dataFunctor = data.dataFunctor; m_sharedTextureId = data.sharedTextureId; - for (const QNodeId imgId : data.textureImageIds) + for (const QNodeId &imgId : data.textureImageIds) addTextureImage(imgId); const QVector<QTextureDataUpdate> initialDataUpdates = data.initialDataUpdates; diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h index 28580c92a..967b2a44a 100644 --- a/src/render/texture/texture_p.h +++ b/src/render/texture/texture_p.h @@ -164,6 +164,7 @@ public: 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; } inline const TextureParameters& parameters() const { return m_parameters; } |