UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

270 lines (267 loc) 8.56 kB
import { ADDRESS_CLAMP_TO_EDGE, PIXELFORMAT_RGB8, PIXELFORMAT_RGBA8, TEXTURETYPE_RGBM, TEXTURETYPE_DEFAULT } from '../../platform/graphics/constants.js'; import { Texture } from '../../platform/graphics/texture.js'; import { Asset } from '../asset/asset.js'; import { ResourceHandler } from './handler.js'; class CubemapHandler extends ResourceHandler { load(url, callback, asset) { this.loadAssets(asset, callback); } open(url, data, asset) { return asset ? asset.resource : null; } patch(asset, registry) { this.loadAssets(asset, (err, result)=>{ if (err) { registry.fire('error', asset); registry.fire("error:" + asset.id, err, asset); asset.fire('error', asset); } }); } getAssetIds(cubemapAsset) { var result = []; result[0] = cubemapAsset.file; if ((cubemapAsset.loadFaces || !cubemapAsset.file) && cubemapAsset.data && cubemapAsset.data.textures) { for(var i = 0; i < 6; ++i){ result[i + 1] = cubemapAsset.data.textures[i]; } } else { result[1] = result[2] = result[3] = result[4] = result[5] = result[6] = null; } return result; } compareAssetIds(assetIdA, assetIdB) { if (assetIdA && assetIdB) { if (parseInt(assetIdA, 10) === assetIdA || typeof assetIdA === 'string') { return assetIdA === assetIdB; } return assetIdA.url === assetIdB.url; } return assetIdA !== null === (assetIdB !== null); } update(cubemapAsset, assetIds, assets) { var assetData = cubemapAsset.data || {}; var oldAssets = cubemapAsset._handlerState.assets; var oldResources = cubemapAsset._resources; var tex, mip, i; var resources = [ null, null, null, null, null, null, null ]; var getType = function getType() { if (assetData.hasOwnProperty('type')) { return assetData.type; } if (assetData.hasOwnProperty('rgbm')) { return assetData.rgbm ? TEXTURETYPE_RGBM : TEXTURETYPE_DEFAULT; } return null; }; if (!cubemapAsset.loaded || assets[0] !== oldAssets[0]) { if (assets[0]) { tex = assets[0].resource; if (tex.cubemap) { for(i = 0; i < 6; ++i){ resources[i + 1] = new Texture(this._device, { name: cubemapAsset.name + "_prelitCubemap" + (tex.width >> i), cubemap: true, type: getType() || tex.type, width: tex.width >> i, height: tex.height >> i, format: tex.format, levels: [ tex._levels[i] ], addressU: ADDRESS_CLAMP_TO_EDGE, addressV: ADDRESS_CLAMP_TO_EDGE, mipmaps: i === 0 }); } } else { resources[1] = tex; } } } else { resources[1] = oldResources[1] || null; resources[2] = oldResources[2] || null; resources[3] = oldResources[3] || null; resources[4] = oldResources[4] || null; resources[5] = oldResources[5] || null; resources[6] = oldResources[6] || null; } var faceAssets = assets.slice(1); if (!cubemapAsset.loaded || !this.cmpArrays(faceAssets, oldAssets.slice(1))) { if (faceAssets.indexOf(null) === -1) { var faceTextures = faceAssets.map((asset)=>{ return asset.resource; }); var faceLevels = []; for(mip = 0; mip < faceTextures[0]._levels.length; ++mip){ faceLevels.push(faceTextures.map((faceTexture)=>{ return faceTexture._levels[mip]; })); } var format = faceTextures[0].format; var _assetData_mipmaps; var faces = new Texture(this._device, { name: "" + cubemapAsset.name + "_faces", cubemap: true, type: getType() || faceTextures[0].type, width: faceTextures[0].width, height: faceTextures[0].height, format: format === PIXELFORMAT_RGB8 ? PIXELFORMAT_RGBA8 : format, mipmaps: (_assetData_mipmaps = assetData.mipmaps) != null ? _assetData_mipmaps : true, levels: faceLevels, minFilter: assetData.hasOwnProperty('minFilter') ? assetData.minFilter : faceTextures[0].minFilter, magFilter: assetData.hasOwnProperty('magFilter') ? assetData.magFilter : faceTextures[0].magFilter, anisotropy: assetData.hasOwnProperty('anisotropy') ? assetData.anisotropy : 1, addressU: ADDRESS_CLAMP_TO_EDGE, addressV: ADDRESS_CLAMP_TO_EDGE }); resources[0] = faces; } } else { resources[0] = oldResources[0] || null; } if (!this.cmpArrays(resources, oldResources)) { cubemapAsset.resources = resources; cubemapAsset._handlerState.assetIds = assetIds; cubemapAsset._handlerState.assets = assets; for(i = 0; i < oldResources.length; ++i){ if (oldResources[i] !== null && resources.indexOf(oldResources[i]) === -1) { oldResources[i].destroy(); } } } for(i = 0; i < oldAssets.length; ++i){ if (oldAssets[i] !== null && assets.indexOf(oldAssets[i]) === -1) { oldAssets[i].unload(); } } } cmpArrays(arr1, arr2) { if (arr1.length !== arr2.length) { return false; } for(var i = 0; i < arr1.length; ++i){ if (arr1[i] !== arr2[i]) { return false; } } return true; } resolveId(value) { var valueInt = parseInt(value, 10); return valueInt === value || valueInt.toString() === value ? valueInt : value; } loadAssets(cubemapAsset, callback) { if (!cubemapAsset.hasOwnProperty('_handlerState')) { cubemapAsset._handlerState = { assetIds: [ null, null, null, null, null, null, null ], assets: [ null, null, null, null, null, null, null ] }; } var self = this; var assetIds = self.getAssetIds(cubemapAsset); var assets = [ null, null, null, null, null, null, null ]; var loadedAssetIds = cubemapAsset._handlerState.assetIds; var loadedAssets = cubemapAsset._handlerState.assets; var registry = self._registry; var awaiting = 7; var onLoad = function onLoad(index, asset) { assets[index] = asset; awaiting--; if (awaiting === 0) { self.update(cubemapAsset, assetIds, assets); callback(null, cubemapAsset.resources); } }; var onError = function onError(index, err, asset) { callback(err); }; var processTexAsset = function processTexAsset(index, texAsset) { if (texAsset.loaded) { onLoad(index, texAsset); } else { registry.once("load:" + texAsset.id, onLoad.bind(self, index)); registry.once("error:" + texAsset.id, onError.bind(self, index)); if (!texAsset.loading) { registry.load(texAsset); } } }; var texAsset; for(var i = 0; i < 7; ++i){ var assetId = this.resolveId(assetIds[i]); if (!assetId) { onLoad(i, null); } else if (self.compareAssetIds(assetId, loadedAssetIds[i])) { processTexAsset(i, loadedAssets[i]); } else if (parseInt(assetId, 10) === assetId) { texAsset = registry.get(assetId); if (texAsset) { processTexAsset(i, texAsset); } else { setTimeout(((index, assetId_)=>{ var texAsset = registry.get(assetId_); if (texAsset) { processTexAsset(index, texAsset); } else { onError(index, "failed to find dependent cubemap asset=" + assetId_); } }).bind(null, i, assetId)); } } else { var file = typeof assetId === 'string' ? { url: assetId, filename: assetId } : assetId; var data = file.url.search('.dds') === -1 ? { type: 'rgbp', addressu: 'clamp', addressv: 'clamp', mipmaps: false } : null; texAsset = new Asset(cubemapAsset.name + "_part_" + i, 'texture', file, data); registry.add(texAsset); processTexAsset(i, texAsset); } } } constructor(app){ super(app, 'cubemap'); this._device = app.graphicsDevice; this._registry = app.assets; this._loader = app.loader; } } export { CubemapHandler };