Я работаю над решением этой проблемы.У вашего кода есть пара проблем.
entityvar.components[j]=metal_mat;
это не будет работать, потому что qml хочет, чтобы вы заменили весь массив, вы не можете изменить его на месте
var entitynames=sceneLoader.entityNames();
for (var i = 0; i < entitynames.length; ++i) {
var entityname=entitynames[i];
var entityvar=sceneLoader.entity(entityname);
Это не будет работатьдля файлов, которые имеют сущности или подмодели с одинаковыми именами, например, вообще без имени.
Вот как я решил эти проблемы: SceneLoader загружает сцену из файла fbx или obj и помещает ее как childNodes в родительский объект,Таким образом, единственный способ пройтись по дереву - посмотреть массив childNodes родительского объекта.
import Qt3D.Render 2.12
import Qt3D.Extras 2.12
import Qt3D.Core 2.12
Entity {
id: rootEntity
property alias source: loader.source
property Transform transform: Transform{}
components:[ loader, transform ]
SceneLoader {
id: loader
Component {
id: pbrMatTemplate
MetalRoughMaterial { }
}
onStatusChanged: {
if(status == SceneLoader.Ready) {
instantiateMaterials();
}
}
}
function instantiateMaterials() {
// TODO create as many materials as you need here
var newmat = pbrMatTemplate.createObject(loader);
function traverseNodes(node) {
if(node.components) {
var comps = [];
for (var j = 0; j< node.components.length; ++j) {
var cmp = node.components[j];
var cmp_class = cmp.toString();
if(cmp_class.indexOf("QPhongMaterial")>=0) {
// TODO: look up material from list of materials you created instead of just using one
comps.push(newMat);
} else {
comps.push(cmp);
}
}
// replace whole list of components
node.components = comps;
}
if(node.childNodes) {
for(var i=0; i<node.childNodes.length; i++) {
if(node.childNodes[i] == null) continue;
traverseNodes(node.childNodes[i]);
}
}
} // traverseNodes()
traverseNodes(rootEntity);
}
}