UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

124 lines (97 loc) 3.9 kB
import { computeFileExtension } from "../../../../core/path/computeFileExtension.js"; import { convertTexture2Sampler2D } from "../../../graphics/texture/sampler/convertTexture2Sampler2D.js"; import { GameAssetType } from "../../GameAssetType.js"; import { ArrayBufferLoader } from "../ArrayBufferLoader.js"; import { AssetLoader } from "../AssetLoader.js"; import { CodecWithFallback } from "./codec/CodecWithFallback.js"; import { NativeImageDecoder } from "./codec/NativeImageDecoder.js"; import { ThreadedImageDecoder } from "./codec/ThreadedImageDecoder.js"; import { ImageRGBADataAsset } from "./ImageRGBADataAsset.js"; const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer"; export class ImageRGBADataLoader extends AssetLoader { /** * * @param {string} [worker_path] Path to decoder worker, allows flexibility in deployment */ constructor({ worker_path } = {}) { super(); /** * * @type {CodecWithFallback<{data, width:number, height:number, itemSize:number, bitDepth:number}>} */ this.decoder = new CodecWithFallback( new ThreadedImageDecoder({ worker_path }), new NativeImageDecoder() ); } async link(assetManager, engine) { if (assetManager.getLoaderByType(ASSET_TYPE_ARRAY_BUFFER) === undefined) { await assetManager.registerLoader(ASSET_TYPE_ARRAY_BUFFER, new ArrayBufferLoader()); } await super.link(assetManager, engine); } /** * * @param {string} path * @param {AssetRequestScope} scope * @returns {Promise<{data:ArrayBuffer, width: number, height:number, itemSize: number, bitDepth:number}>} * @private */ async __decode_via_worker(path, scope) { const asset = await this.assetManager.promise(path, ASSET_TYPE_ARRAY_BUFFER, { scope }); /** * @type {ArrayBuffer} */ const array_buffer = asset.create(); return await this.decoder.decode(new Uint8Array(array_buffer)); } /** * * @param {String} path * @param {AssetRequestScope} scope * @return {Promise<ImageRGBADataAsset>} * @private */ async __standard(path, scope) { const bitmap = await this.__decode_via_worker(path, scope); let data; const bitDepth = bitmap.bitDepth; switch (bitDepth) { case 8: data = new Uint8Array(bitmap.data); break case 16: data = new Uint16Array(bitmap.data); break; default: throw new Error(`Unsupported bit depth '${bitDepth}'. path='${path}'`); } return new ImageRGBADataAsset(data, bitmap.width, bitmap.height, bitmap.itemSize); } load(scope, path, success, failure, progress) { const extension = computeFileExtension(path); if (extension === 'dds') { //compressed texture this.assetManager.get({ path: path, scope, type: GameAssetType.Texture, callback: asset => { /** * * @type {Texture} */ const texture = asset.create(); const sampler2D = convertTexture2Sampler2D(texture); texture.dispose(); const f = new ImageRGBADataAsset(sampler2D.data, sampler2D.width, sampler2D.height, sampler2D.itemSize); success(f); }, failure: failure, progress: progress }); } else { this.__standard(path, scope).then(success, failure); } } }