[SOLVED] Material cloned too soon after loading fails to clone texture

I’ve found a solution that works for my project. I’ve updated the example project with the workaround.
Basically, I check the loaded material to see if the diffuseMap is named placeholder. If so, I set a flag and keep checking on the update for it to change. Then I clone after that.

Here is the code…

var AssignClonedMaterial = pc.createScript('assignClonedMaterial');

AssignClonedMaterial.attributes.add('mat', {type: 'asset', assetType: 'material', title: 'Material'});
AssignClonedMaterial.attributes.add('cloneIt', {type: 'boolean', default: false, title: 'Clone it?'});
AssignClonedMaterial.attributes.add('useWorkAround', {type: 'boolean', default: false, title: 'Use work around?'});

// initialize code called once per entity
AssignClonedMaterial.prototype.initialize = function() {
    
    this.shape = this.entity.model.meshInstances[0];
    var self = this;
    this.checkIsMatLoaded = false;  // set to true in workaround below
    this.mat.ready(function (asset) {
        // asset loaded
        if(self.cloneIt){
            // use clone of material.
            if(self.useWorkAround){
                self.checkIsMatLoaded = true; // we'll clone later when the diffuseMap is no longer a placeholder.
            }else{
                // clone now. This fails because non-preloaded textures are still placeholders at this point
                self.shape.material = asset.resource.clone();
            }
        }else{
            // use freshly loaded material.
            self.shape.material = asset.resource;
            // note: the material is loaded but the textures are still being loaded.  
            //       OK for materials used directly, they will update automatically when fully loaded.
        }
    });
    this.app.assets.load(this.mat);
    
};

// update code called every frame
AssignClonedMaterial.prototype.update = function(dt) {
    if(this.checkIsMatLoaded){  // if true, we need to check to see if the texture has loaded.
        var map = this.mat.resource.diffuseMap;

        console.log("diffuseMap = " + map.name);
        
        if(map.name != "placeholder"){
            // no longer a placeholder.
            this.checkIsMatLoaded = false;
            this.shape.material = this.mat.resource.clone(); // OK to clone now, diffuseMap texture is loaded.*
            // * other textures should be checked but if you know that only a diffuseMap is being used then we are OK.
        }

    }
};