summaryrefslogtreecommitdiffstats
path: root/src/runtime/q3dsscenemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/q3dsscenemanager.cpp')
-rw-r--r--src/runtime/q3dsscenemanager.cpp53
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);