[SOLVED] Editor: How to relink materials with same names to a new version of imported model?

Here is the situation:

  1. We have imported a 3D model into the editor with all the materials.
  2. We have adjusted all materials (340+) inside the editor to fit our needs.
  3. The mesh need to be changed a bit. We need to reimport the 3D model.

Now, how can I link existing materials that we edited in the editor to the new imported model with old materials with the same name?

I don’t want to do that one by one each time the mesh need to change. Here how I need to do it actually, one by one:

Is there a way to automate the replacement in the editor or I’m forced to change all materials by code at runtime?

Hi, Mystik :grinning: ,that’s very annoying indeed,but if I remember correctly,there seems to have some editor settings to solve this problem,if not,you can write some editor scripts to solve it:

	// get the binding materials of the model
    // the modelID can be find at the asset inspector
    // return an array,useful when some meshs of this model have the same name,we just get an 
    // array which contains the material information so we can map the new modle meshes later.
	function getBindingMaterials(modelID) {
		return editor.call("assets:get", modelID).get("data.mapping") || [];
	}
	// similar to the getBindingMaterials function,but this time we create a map which map the 
    // meshe's name and it's material together.useful when the new model has new meshes.
	function getBindingMap(modelID) {
		var observer = editor.call("assets:get", modelID);
		if (!observer)
			return {};

		var bindingMaterials = observer.get("data.mapping");
		var mesheNames = observer.get("meta.meshInstancesNames");
		if (!bindingMaterials || !mesheNames)
			return {};

		var map = {};
		for (var i = 0; i < mesheNames .length; map[mesheNames [i]] = bindingMaterials[i++]);
		return map;
	}
	// use with the getBindingMaterials function
	function setBindingMaterials(modelID, bindingMaterials) {
		if (!bindingMaterials)
			return;

		editor.call("assets:get", modelID).set("data.mapping", bindingMaterials);
	}
	// use with the getBindingMap function
	function setBindingMap(modelID, bindingMap) {
		if (!bindingMap)
			return;

		var observer = editor.call("assets:get", modelID);
		if (!observer)
			return;

		var bindingMaterials = observer.get("data.mapping");
		var mesheNames = observer.get("meta.meshInstancesNames");
		if (!bindingMaterials || !mesheNames)
			return;

		var i = 0;
		var mat, materials = [];
		for (var mesh in mesheNames) {
			mat = bindingMap[mesheNames[mesh]];
			materials.push(mat ? mat : bindingMaterials[i]);
			i++;
		}
		observer.set("data.mapping", materials);
	}

open the console at the editor site and run these scripts.get the binding map of the old model before overwriting it,then import the new one and set the map.These scripts are unoffical,please make a backup before setting them.

you can take a look at this topic if you want to know more about the editor scripting:
https://forum.playcanvas.com/t/scripting-the-playcanvas-editor/2315
and some one has already made a very useful tool to make it easier:
https://forum.playcanvas.com/t/released-uranus-editor-scripting/15203

3 Likes

Hey this is working pretty well! Thank you very much for this code. This save me a lot of time. :slight_smile:

1 Like