playcanvas
Version:
PlayCanvas WebGL game engine
226 lines (223 loc) • 7.57 kB
JavaScript
import { http } from '../../platform/net/http.js';
import { standardMaterialTextureParameters, standardMaterialCubemapParameters } from '../../scene/materials/standard-material-parameters.js';
import { AssetReference } from '../asset/asset-reference.js';
import { JsonStandardMaterialParser } from '../parsers/material/json-standard-material.js';
import { ResourceHandler } from './handler.js';
import { getBuiltInTexture } from '../../platform/graphics/built-in-textures.js';
var PLACEHOLDER_MAP = {
aoMap: 'white',
aoDetailMap: 'white',
diffuseMap: 'gray',
diffuseDetailMap: 'gray',
specularMap: 'gray',
specularityFactorMap: 'white',
metalnessMap: 'black',
glossMap: 'gray',
sheenMap: 'black',
sheenGlossMap: 'gray',
clearCoatMap: 'black',
clearCoatGlossMap: 'gray',
clearCoatNormalMap: 'normal',
refractionMap: 'white',
emissiveMap: 'gray',
normalMap: 'normal',
normalDetailMap: 'normal',
heightMap: 'gray',
opacityMap: 'gray',
sphereMap: 'gray',
lightMap: 'white',
thicknessMap: 'black',
iridescenceMap: 'black',
iridescenceThicknessMap: 'black',
envAtlas: 'black'
};
class MaterialHandler extends ResourceHandler {
load(url, callback) {
if (typeof url === 'string') {
url = {
load: url,
original: url
};
}
http.get(url.load, {
retry: this.maxRetries > 0,
maxRetries: this.maxRetries
}, (err, response)=>{
if (!err) {
if (callback) {
response._engine = true;
callback(null, response);
}
} else {
if (callback) {
callback("Error loading material: " + url.original + " [" + err + "]");
}
}
});
}
open(url, data) {
var material = this._parser.parse(data);
if (data._engine) {
material._data = data;
delete data._engine;
}
return material;
}
patch(asset, assets) {
if (asset.resource._data) {
asset._data = asset.resource._data;
delete asset.resource._data;
}
asset.data.name = asset.name;
asset.resource.name = asset.name;
this._bindAndAssignAssets(asset, assets);
asset.off('unload', this._onAssetUnload, this);
asset.on('unload', this._onAssetUnload, this);
}
_onAssetUnload(asset) {
delete asset.data.parameters;
delete asset.data.chunks;
delete asset.data.name;
}
_assignTexture(parameterName, materialAsset, texture) {
materialAsset.resource[parameterName] = texture;
}
_getPlaceholderTexture(parameterName) {
var placeholder = PLACEHOLDER_MAP[parameterName];
return getBuiltInTexture(this._device, placeholder);
}
_assignPlaceholderTexture(parameterName, materialAsset) {
materialAsset.resource[parameterName] = this._getPlaceholderTexture(parameterName);
}
_onTextureLoad(parameterName, materialAsset, textureAsset) {
this._assignTexture(parameterName, materialAsset, textureAsset.resource);
materialAsset.resource.update();
}
_onTextureAdd(parameterName, materialAsset, textureAsset) {
this._assets.load(textureAsset);
}
_onTextureRemoveOrUnload(parameterName, materialAsset, textureAsset) {
var material = materialAsset.resource;
if (material) {
if (materialAsset.resource[parameterName] === textureAsset.resource) {
this._assignPlaceholderTexture(parameterName, materialAsset);
material.update();
}
}
}
_assignCubemap(parameterName, materialAsset, textures) {
materialAsset.resource[parameterName] = textures[0];
if (parameterName === 'cubeMap') {
var prefiltered = textures.slice(1);
if (prefiltered.every((t)=>t)) {
materialAsset.resource.prefilteredCubemaps = prefiltered;
} else if (prefiltered[0]) {
materialAsset.resource.envAtlas = prefiltered[0];
}
}
}
_onCubemapLoad(parameterName, materialAsset, cubemapAsset) {
this._assignCubemap(parameterName, materialAsset, cubemapAsset.resources);
this._parser.initialize(materialAsset.resource, materialAsset.data);
}
_onCubemapAdd(parameterName, materialAsset, cubemapAsset) {
this._assets.load(cubemapAsset);
}
_onCubemapRemoveOrUnload(parameterName, materialAsset, cubemapAsset) {
var material = materialAsset.resource;
if (materialAsset.data.prefilteredCubeMap128 === cubemapAsset.resources[1]) {
this._assignCubemap(parameterName, materialAsset, [
null,
null,
null,
null,
null,
null,
null
]);
material.update();
}
}
_bindAndAssignAssets(materialAsset, assets) {
var data = this._parser.migrate(materialAsset.data);
var material = materialAsset.resource;
var pathMapping = data.mappingFormat === 'path';
var TEXTURES = standardMaterialTextureParameters;
var i, name, assetReference;
for(i = 0; i < TEXTURES.length; i++){
name = TEXTURES[i];
assetReference = material._assetReferences[name];
var dataAssetId = data[name];
var materialTexture = material[name];
var isPlaceHolderTexture = materialTexture === this._getPlaceholderTexture(name);
var dataValidated = data.validated;
if (dataAssetId && (!materialTexture || !dataValidated || isPlaceHolderTexture)) {
if (!assetReference) {
assetReference = new AssetReference(name, materialAsset, assets, {
load: this._onTextureLoad,
add: this._onTextureAdd,
remove: this._onTextureRemoveOrUnload,
unload: this._onTextureRemoveOrUnload
}, this);
material._assetReferences[name] = assetReference;
}
if (pathMapping) {
assetReference.url = materialAsset.getAbsoluteUrl(dataAssetId);
} else {
assetReference.id = dataAssetId;
}
if (assetReference.asset) {
if (assetReference.asset.resource) {
this._assignTexture(name, materialAsset, assetReference.asset.resource);
} else {
this._assignPlaceholderTexture(name, materialAsset);
}
assets.load(assetReference.asset);
}
} else {
if (assetReference) {
if (pathMapping) {
assetReference.url = null;
} else {
assetReference.id = null;
}
}
}
}
var CUBEMAPS = standardMaterialCubemapParameters;
for(i = 0; i < CUBEMAPS.length; i++){
name = CUBEMAPS[i];
assetReference = material._assetReferences[name];
if (data[name] && !materialAsset.data.prefilteredCubeMap128) {
if (!assetReference) {
assetReference = new AssetReference(name, materialAsset, assets, {
load: this._onCubemapLoad,
add: this._onCubemapAdd,
remove: this._onCubemapRemoveOrUnload,
unload: this._onCubemapRemoveOrUnload
}, this);
material._assetReferences[name] = assetReference;
}
if (pathMapping) {
assetReference.url = data[name];
} else {
assetReference.id = data[name];
}
if (assetReference.asset) {
if (assetReference.asset.loaded) {
this._assignCubemap(name, materialAsset, assetReference.asset.resources);
}
assets.load(assetReference.asset);
}
}
}
this._parser.initialize(material, data);
}
constructor(app){
super(app, 'material');
this._assets = app.assets;
this._device = app.graphicsDevice;
this._parser = new JsonStandardMaterialParser();
}
}
export { MaterialHandler };