I’m using a JSON file to create materials within the editor. The files contains about 17 materials so I loop through each one and use the editor hooks to create it.
My problem is that although 17 materials are created, changing the material’s name and adding a texture only works once.
The code should explain it better, but firing the event ‘assets:add’ with editor.once() changes the first material’s name/diffuseMap, and using editor.on() changes all of them but to the same values.
What I’m looking for is to either get the material that’s created by editor.call('assets:create:material', { parent: folder[1] }); or a way to wait until the event has fired and executed. Are there Promises in here at all?
In the end I created two separate buttons within the UI (I’m building a Chrome plugin). One creates a load of New Materials, the other applies textures to those materials. Not perfect but good enough for our needs.
Things I tried was forcing a hard wait, a while loop for searching for the new asset, moving the editor.once() call to before the call to create the asset, and creating a load of new materials before immediately applying textures.
None of these worked. It looks like there needs to be a stop in JS execution so that the New Materials can be found by editor.call('assets:findOne', a => a.get('type') == 'material' && a.get('name') == 'New Material');.
Another update on this. I managed to crack it in the end.
Instead of creating a New Material, then applying a texture, I do it all before creating the material:
// taken from editor.js, line 39,278
const createMaterialApplyTexture = (materialName, textureId, parent, colours, tiling) => {
var asset = {
name: materialName,
type: 'material',
source: false,
preload: true,
data: editor.call('schema:material:getDefaultData'),
parent: parent,
scope: {
type: 'project',
id: config.project.id
}
};
// overwrite the defaults (provided by editor.call('schema:material:getDefaultData'))
// with the texture, tiling and colour values
asset.data.diffuseMap = textureId;
asset.data.diffuseMapTint = true;
asset.data.diffuse = [colours.r, colours.g, colours.b];
asset.data.diffuseMapTiling = [tiling.x, tiling.y];
editor.call('assets:create', asset);
}
This method does away with two separate buttons to create the materials then apply the textures. I was using editor.call('assets:create:material'), but using the above is much easier.
I have over 50 projects to create, each with 50 - 200 entities and associated materials to create. All the data are in JSON files. This function saves us days in setup time.