UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

226 lines (223 loc) 7.57 kB
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 };