summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2018-08-22 11:25:57 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2018-08-23 17:33:46 +0000
commit87a8a864327da7c64232ab44881310133107d29b (patch)
tree79184da6ecf9b15bd42cb8436bec5d92f1b4e1e9
parent10b0cabebd9f07725191f463e807ea815d68ceb2 (diff)
Make ReferencedMaterial more dynamic
The ill-named ReferencedMaterial lacked quite some of the dynamic property handling, meaning it was not possible to change the referencedmaterial property to a different target material instance. This is now corrected. Therefore, the following console command sequence generates a green sphere, where the Model's child is a ReferencedMaterial that points to a DefaultMaterial living somewhere else, not associated (in the object tree at least) with any model. object(mm,mm,DefaultMaterial,Layer,Slide1) object(kk,kk,Model,Layer,Slide1) set(kk,sourcepath,#Sphere) object(rm,rm,ReferencedMaterial,kk,Slide1) set(rm,referencedmaterial,#mm) set(mm, diffuse, 0 1 0) Note that we continue with the assumption that a ReferencedMaterial cannot reference another ReferencedMaterial, meaning the target is always a default or custom material (or unset). Change-Id: I2cebb9689167f0ecb409d1bf73ee3df2364f3e04 Reviewed-by: Christian Stromme <christian.stromme@qt.io>
-rw-r--r--src/runtime/q3dsscenemanager.cpp53
-rw-r--r--src/runtime/q3dsscenemanager_p.h5
-rw-r--r--src/runtime/q3dsuippresentation.cpp10
-rw-r--r--src/runtime/q3dsuippresentation_p.h9
4 files changed, 74 insertions, 3 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);
diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h
index 84c9cb9..4b2f4cd 100644
--- a/src/runtime/q3dsscenemanager_p.h
+++ b/src/runtime/q3dsscenemanager_p.h
@@ -567,6 +567,10 @@ public:
Qt3DRender::QParameter *lightProbeOffset = nullptr;
};
+class Q3DSReferencedMaterialAttached : public Q3DSGraphObjectAttached
+{
+};
+
class Q3DSEffectAttached : public Q3DSGraphObjectAttached
{
public:
@@ -854,6 +858,7 @@ private:
void initImage(Q3DSImage *image);
void initDefaultMaterial(Q3DSDefaultMaterial *m);
void initCustomMaterial(Q3DSCustomMaterialInstance *m);
+ void initReferencedMaterial(Q3DSReferencedMaterial *m);
void buildLayerQuadEntity(Q3DSLayerNode *layer3DS, Qt3DCore::QEntity *parentEntity, Qt3DRender::QLayer *tag,
BuildLayerQuadFlags flags, int layerDepth = 0);
diff --git a/src/runtime/q3dsuippresentation.cpp b/src/runtime/q3dsuippresentation.cpp
index b475c2a..1c32d94 100644
--- a/src/runtime/q3dsuippresentation.cpp
+++ b/src/runtime/q3dsuippresentation.cpp
@@ -2103,6 +2103,16 @@ void Q3DSReferencedMaterial::resolveReferences(Q3DSUipPresentation &pres)
resolveRef(m_lightProbe_unresolved, Q3DSGraphObject::Image, &m_lightProbe, pres);
}
+int Q3DSReferencedMaterial::mapChangeFlags(const Q3DSPropertyChangeList &changeList)
+{
+ int changeFlags = Q3DSGraphObject::mapChangeFlags(changeList);
+ for (auto it = changeList.cbegin(), itEnd = changeList.cend(); it != itEnd; ++it) {
+ if (it->nameStr() == QStringLiteral("referencedmaterial"))
+ changeFlags |= ReferenceChanges;
+ }
+ return changeFlags;
+}
+
Q3DSPropertyChange Q3DSReferencedMaterial::setReferencedMaterial(Q3DSGraphObject *v)
{
return createPropSetter(m_referencedMaterial, v, "referencedmaterial");
diff --git a/src/runtime/q3dsuippresentation_p.h b/src/runtime/q3dsuippresentation_p.h
index adc8191..b6623e9 100644
--- a/src/runtime/q3dsuippresentation_p.h
+++ b/src/runtime/q3dsuippresentation_p.h
@@ -211,7 +211,8 @@ public:
CustomMaterialDirty = 0x1000,
EffectDirty = 0x2000,
AliasDirty = 0x4000,
- BehaviorDirty = 0x8000
+ BehaviorDirty = 0x8000,
+ ReferencedMaterialDirty = 0x10000
};
Q_DECLARE_FLAGS(FrameDirtyFlags, FrameDirtyFlag)
@@ -1763,6 +1764,7 @@ private:
Q3DSImage *m_lightProbe = nullptr;
};
+// this should have been named Q3DSReferencingMaterialInstance or something like that
class Q3DSV_PRIVATE_EXPORT Q3DSReferencedMaterial : public Q3DSGraphObject
{
Q3DS_OBJECT
@@ -1772,11 +1774,16 @@ class Q3DSV_PRIVATE_EXPORT Q3DSReferencedMaterial : public Q3DSGraphObject
Q_PROPERTY(Q3DSImage * lightmapshadow READ lightmapShadowMap WRITE setLightmapShadowMap)
Q_PROPERTY(Q3DSImage * iblprobe READ lightProbe WRITE setLightProbe)
public:
+ enum ReferencedMaterialPropertyChanges {
+ ReferenceChanges = 1 << 0
+ };
+
Q3DSReferencedMaterial();
void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
void applyPropertyChanges(const Q3DSPropertyChangeList &changeList) override;
void resolveReferences(Q3DSUipPresentation &pres) override;
+ int mapChangeFlags(const Q3DSPropertyChangeList &changeList) override;
// Properties
Q3DSGraphObject *referencedMaterial() const { return m_referencedMaterial; }