diff options
Diffstat (limited to 'src/runtime/q3dsscenemanager.cpp')
-rw-r--r-- | src/runtime/q3dsscenemanager.cpp | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp index ea52921..ffef07c 100644 --- a/src/runtime/q3dsscenemanager.cpp +++ b/src/runtime/q3dsscenemanager.cpp @@ -3877,6 +3877,16 @@ void Q3DSSceneManager::initCustomMaterial(Q3DSCustomMaterialInstance *m) data->eventObserverIndex = m->addEventHandler(QString(), std::bind(&Q3DSSceneManager::handleEvent, this, std::placeholders::_1)); } +void Q3DSSceneManager::initReferencedMaterial(Q3DSReferencedMaterial *m) +{ + Q3DSReferencedMaterialAttached *data = new Q3DSReferencedMaterialAttached; + m->setAttached(data); + + data->propertyChangeObserverIndex = m->addPropertyChangeObserver( + std::bind(&Q3DSSceneManager::handlePropertyChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + data->eventObserverIndex = m->addEventHandler(QString(), std::bind(&Q3DSSceneManager::handleEvent, this, std::placeholders::_1)); +} + // Recursively builds the Qt3D scene for the given node tree under a layer. (or // sub-tree, when called in response to a dynamic scene change with DirtyNodeAdded). void Q3DSSceneManager::buildLayerScene(Q3DSGraphObject *obj, Q3DSLayerNode *layer3DS, Qt3DCore::QEntity *parent) @@ -3909,6 +3919,9 @@ void Q3DSSceneManager::buildLayerScene(Q3DSGraphObject *obj, Q3DSLayerNode *laye case Q3DSGraphObject::CustomMaterial: initCustomMaterial(static_cast<Q3DSCustomMaterialInstance *>(obj)); break; + case Q3DSGraphObject::ReferencedMaterial: + initReferencedMaterial(static_cast<Q3DSReferencedMaterial *>(obj)); + break; default: break; } @@ -4597,10 +4610,12 @@ void Q3DSSceneManager::rebuildModelSubMeshes(Q3DSModelNode *model3DS) sm.entity->addComponent(mesh); sm.material = material; sm.resolvedMaterial = material; - // follow the reference for ReferencedMaterial + // follow the reference for ReferencedMaterial (which is more like a referencING material...) if (sm.material->type() == Q3DSGraphObject::ReferencedMaterial) { Q3DSReferencedMaterial *matRef = static_cast<Q3DSReferencedMaterial *>(sm.material); sm.referencingMaterial = matRef; + // only if set (i.e. non-null), keep pointing to itself otherwise + // (resolvedMaterial must not be null no matter what) if (matRef->referencedMaterial()) sm.resolvedMaterial = matRef->referencedMaterial(); } @@ -4673,7 +4688,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS) } for (Q3DSModelAttached::SubMesh &sm : modelData->subMeshes) { - if (sm.resolvedMaterial && !sm.materialComponent) { + if (sm.resolvedMaterial && !sm.materialComponent && sm.resolvedMaterial->type() != Q3DSGraphObject::ReferencedMaterial) { Q_ASSERT(sm.resolvedMaterial->attached()); if (sm.resolvedMaterial->type() == Q3DSGraphObject::DefaultMaterial) { Q3DSDefaultMaterial *defaultMaterial = static_cast<Q3DSDefaultMaterial *>(sm.resolvedMaterial); @@ -7041,6 +7056,12 @@ void Q3DSSceneManager::handlePropertyChange(Q3DSGraphObject *obj, const QSet<QSt data->frameChangeFlags |= changeFlags; } break; + case Q3DSGraphObject::ReferencedMaterial: + { + data->frameDirty |= Q3DSGraphObjectAttached::ReferencedMaterialDirty; + data->frameChangeFlags |= changeFlags; + } + break; case Q3DSGraphObject::Effect: { data->frameDirty |= Q3DSGraphObjectAttached::EffectDirty; @@ -7346,6 +7367,7 @@ void Q3DSSceneManager::prepareNextFrame() static void markLayerForObjectDirty(Q3DSGraphObject *obj) { auto findLayersForMat = [](Q3DSGraphObject *obj) { + Q_ASSERT(obj->type() == Q3DSGraphObject::DefaultMaterial || obj->type() == Q3DSGraphObject::CustomMaterial); QVector<Q3DSLayerNode *> layers; Q3DSMaterialAttached *data = static_cast<Q3DSMaterialAttached *>(obj->attached()); if (data) { @@ -7376,6 +7398,12 @@ static void markLayerForObjectDirty(Q3DSGraphObject *obj) } else if (obj->type() == Q3DSGraphObject::DefaultMaterial || obj->type() == Q3DSGraphObject::CustomMaterial) { for (Q3DSLayerNode *layer3DS : findLayersForMat(obj)) markLayerDirty(layer3DS); + } else if (obj->type() == Q3DSGraphObject::ReferencedMaterial) { + Q3DSGraphObject *targetMat = static_cast<Q3DSReferencedMaterial *>(obj)->referencedMaterial(); + if (targetMat && targetMat->type() != Q3DSGraphObject::ReferencedMaterial) { + for (Q3DSLayerNode *layer3DS : findLayersForMat(targetMat)) + markLayerDirty(layer3DS); + } } else if (obj->type() == Q3DSGraphObject::Effect) { Q3DSEffectAttached *data = static_cast<Q3DSEffectAttached *>(obj->attached()); if (data && data->layer3DS) @@ -7540,6 +7568,27 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj) } } break; + case Q3DSGraphObject::ReferencedMaterial: + { + Q3DSReferencedMaterial *mat3DS = static_cast<Q3DSReferencedMaterial *>(obj); + Q3DSReferencedMaterialAttached *data = static_cast<Q3DSReferencedMaterialAttached *>(mat3DS->attached()); + if (data && (data->frameDirty & Q3DSGraphObjectAttached::ReferencedMaterialDirty)) { + const bool refChanges = data->frameChangeFlags & Q3DSReferencedMaterial::ReferenceChanges; + if (refChanges) { + mat3DS->resolveReferences(*m_presentation); + if (mat3DS->parent() && mat3DS->parent()->type() == Q3DSGraphObject::Model) { + Q3DSModelNode *model3DS = static_cast<Q3DSModelNode *>(mat3DS->parent()); + qCDebug(lcPerf, "Rebuilding submeshes for %s due to material reference change", + model3DS->id().constData()); + rebuildModelSubMeshes(model3DS); + rebuildModelMaterial(model3DS); + } + } + m_wasDirty = true; + markLayerForObjectDirty(mat3DS); + } + } + break; case Q3DSGraphObject::Effect: { Q3DSEffectInstance *eff3DS = static_cast<Q3DSEffectInstance *>(obj); |