Change material properties with a button

Hello friends, I need a script with which I can control material properties (Textures, Colors, etc). The idea is that by pressing a button the material changes. Any advice?
Thanks.

Hey! For adding buttons to execute custom logic on click check the following tutorial:

On changing materials or material properties o runtime check the following tutorials:

Thanxs @Leonidas

Here I share the link of the project I have created for this new personal challenge:
https://playcanvas.com/editor/scene/984199

I have created these screenshots to visually explain what exactly I want to achieve



I have started with a script that I found in the forum, just as a starting point, but I don’t know if it is the right way. It doesn’t work at all. I think I need a lot of help and a lot of patience from some of the jedi masters on the forum (@LeXXik , @youstar , @Leonidas and more :thinking: :thinking: :grinning: :grinning:)

Now I am trying with this code, I am trying to make a call and get a response but it doesn’t work. I apply the script to the object (box), it says something like when the “Hills” button is pressed, the texture of the diffuse changes. But it doesn’t seem to work

var ButtonChangeMaterialDiffuseText = pc.createScript('ButtonChangeMaterialDiffuseText');

// Reference a list of textures that we can cycle through
ButtonChangeMaterialDiffuseText.attributes.add("textures", {type: "asset", assetType: "texture", array: true, title: "Textures"});

// initialize code called once per entity
ButtonChangeMaterialDiffuseText.prototype.initialize = function() {
    var self = this;
    
    // Keep track of which texture in the array we are currently using
    this.textureIndex = 0;

    // Change textures on button press
  var myHills = this.app.root.findByName('Hills');
    myHills.element.on('mouseup', this.onHillsBtnPressed, this);
    };
 

ButtonChangeMaterialDiffuseText.prototype.changeToNextTexture = function(dt) {
    // Index the next texture in the list, wrapping around if we reach the end
    this.textureIndex = (this.textureIndex + 1) % this.textures.length;

    // Reference the texture
    var texture = this.textures[this.textureIndex].resource;        

    // Go through all the mesh instances of the model and change the diffuse texture on the
    // material to our new one
    var meshInstances = this.entity.model.meshInstances;
    for (var i = 0; i < meshInstances.length; ++i) { 
        var mesh = meshInstances[i];
        mesh.material.diffuseMap = texture;
        mesh.material.update();
    }
};

The callback function this.onHillsBtnPressed doesn’t exist in this script.

Hello @yaustar , Does “not exist” mean that I should remove that part of the code? :thinking:

Hey, no you need to implement a method in your script named onHillsBtnPressed that will get executed on each button click.

If your changeToNextTexture method is meant to do that, then rename it to onHillsBtnPressed.

1 Like

ok @Leonidas, I try this way thanks

1 Like

I think this code should also work but it is not working, where is the fault?

var Change = pc.createScript('change');

Change.attributes.add('Texture', {
    type: 'asset',
    assetType: 'texture'
});
// initialize code called once per entity
Change.prototype.initialize = function() {
    
};

// update code called every frame
Change.prototype.update = function(dt) {
    if(this.onMoonsBtnPressed)
        this.changeDiffuse();
};


Change.prototype.changeDiffuse = function(){
    var meshes = this.entity.model.meshInstances;
    for(var i = 0; i < meshes.length; i++){
        meshes[i].material.diffuseMap = this.Texture.resource;
        //meshes[i].material.emissiveMap = this.Texture;
        meshes[i].material.update();
    }
    //this.entity.model.material.diffuseMapChannel = 'rgb';
    //this.entity.model.material._aoMapChannel = 'rgb';
    this.entity.model.material.update();
};

Can you tell me what the code is doing here?

Yes of course @yaustar, here the code should change the texture of the diffuse when the button “Moons” is pressed. But it doesn’t. You can enter the project if you want.

https://playcanvas.com/editor/scene/984199

I’m now using a code that I found in the forum, in this particular code the map of the diffuse changes when pressing the spacebar key, I want to modify it so that it changes when pressing a button. this is the original code created by @berdoffy

The original code by @berdoffy:

var Change = pc.createScript(‘change’);

Change.attributes.add(‘Texture’, {
type: ‘asset’,
assetType: ‘texture’
});
// initialize code called once per entity
Change.prototype.initialize = function() {

};

// update code called every frame
Change.prototype.update = function(dt) {
if(this.app.keyboard.wasPressed(pc.input.KEY_SPACE))
this.changeDiffuse();
};

Change.prototype.changeDiffuse = function(){
var meshes = this.entity.model.meshInstances;
for(var i = 0; i < meshes.length; i++){
meshes[i].material.diffuseMap = this.Texture.resource;
//meshes[i].material.emissiveMap = this.Texture;
meshes[i].material.update();
}
//this.entity.model.material.diffuseMapChannel = ‘rgb’;
//this.entity.model.material._aoMapChannel = ‘rgb’;
this.entity.model.material.update();
};
// swap method called for script hot-reloading
// inherit your script state here
// Change.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// http://developer.playcanvas.com/en/user-manual/scripting/

Let me put this another way.

What values can this.onMoonsBtnPressed be?

Where is variable assigned a value in your code?

I don’t know exactly where or how to put this variable, nor do I know where to put the value. I understand that the code is incomplete Script Attributes, any recommendations or help?

Going back to this version as it’s the closest.

Doesn’t exist means that you haven’t defined that function. So you either have to create that function or use a different function that is defined in the script.

Ok, let’s go back to that version then, what attribute is missing from that version to be able to work (variables and values)? I discarded that version because it seemed to me that it was very difficult to go that way, sorry, let’s go back to that version, can you continue to help me make it work? @Leonidas he had recommended me " If your changeToNextTexture method is meant to do that, then rename it to onHillsBtnPressed" I continue from this point ??

var ButtonChangeMaterialDiffuseText = pc.createScript('ButtonChangeMaterialDiffuseText');

// Reference a list of textures that we can cycle through
ButtonChangeMaterialDiffuseText.attributes.add("textures", {type: "asset", assetType: "texture", array: true, title: "Textures"});

// initialize code called once per entity
ButtonChangeMaterialDiffuseText.prototype.initialize = function() {
    var self = this;
    
    // Keep track of which texture in the array we are currently using
    this.textureIndex = 0;

    // Change textures on button press
  var myHills = this.app.root.findByName('Hills');
    myHills.element.on('mouseup', this.onHillsBtnPressed, this);
    };
 

ButtonChangeMaterialDiffuseText.prototype.onHillsBtnPressed = function(dt) {
    // Index the next texture in the list, wrapping around if we reach the end
    this.textureIndex = (this.textureIndex + 1) % this.textures.length;

    // Reference the texture
    var texture = this.textures[this.textureIndex].resource;        

    // Go through all the mesh instances of the model and change the diffuse texture on the
    // material to our new one
    var meshInstances = this.entity.model.meshInstances;
    for (var i = 0; i < meshInstances.length; ++i) { 
        var mesh = meshInstances[i];
        mesh.material.diffuseMap = texture;
        mesh.material.update();
    }
};

(Side note: please use the ``` around your code to nicely format it :slight_smile: )

Now that you have changed the code, have you tried it? Does it not work? What error comes up?

Is working now @yaustar ! Many thanks, check te proyect now ! i m happy

https://launch.playcanvas.com/984199?debug=true

Now my next goal is to change the color of the diffuse with the blue and red buttons. Any ideas??

1 Like

Same approach but instead of changing the material, you would change the diffuse colour on the material instead:

See line 50 here: PlayCanvas | HTML5 Game Engine