UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

199 lines 14.8 kB
import { TgdEvent } from "./../event/index.js"; import { isWebglImage } from "./../types/index.js"; import { webglTextureParametersSet, } from "./../webgl/index.js"; export class TgdTexture2D { constructor(context, storage) { this.eventChange = new TgdEvent(); this._texture = null; this._width = 0; this._height = 0; const { gl } = context; this.gl = gl; this.name = `Texture2D/${TgdTexture2D.counter++}`; const texture = gl.createTexture(); if (!texture) throw new Error("Unable to create a WebGLTexture!"); this._texture = texture; this.setParams({ magFilter: "LINEAR", minFilter: "LINEAR", wrapS: "REPEAT", wrapT: "REPEAT", wrapR: "REPEAT", }); this.storage = Object.assign({ width: 1, height: 1, internalFormat: "RGBA8", levels: 1, flipY: false }, storage); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this.storage.flipY); if (typeof (storage === null || storage === void 0 ? void 0 : storage.width) === "number" && typeof (storage === null || storage === void 0 ? void 0 : storage.height) === "number") { this.resize(storage === null || storage === void 0 ? void 0 : storage.width, storage === null || storage === void 0 ? void 0 : storage.height); } } delete() { this.gl.deleteTexture(this.glTexture); } get width() { return this._width; } get height() { return this._height; } resize(width, height) { if (width === this.width && height === this.height) return; const { gl, storage } = this; this._width = storage.width = width; this._height = storage.height = height; const { internalFormat, levels } = this.storage; if (internalFormat.startsWith("COMPRESSED_")) { // We need to load an extension for that. const extension = gl.getExtension("WEBGL_compressed_texture_etc"); if (!extension) throw new Error('Your browser does not support extension "WEBGL_compressed_texture_etc" on this device!'); } this.bind(); gl.texStorage2D(gl.TEXTURE_2D, levels, gl[internalFormat], width, height); } get glTexture() { if (this._texture) return this._texture; throw new Error(`Texture "${this.name}" has been deleted!`); } bind() { this.gl.bindTexture(this.gl.TEXTURE_2D, this.glTexture); } loadBitmap(bmp, options = {}) { if (!bmp) return this; if (!isWebglImage(bmp)) { bmp.then(data => this.loadBitmap(data)).catch(error => console.error("Unable to load texture BMP:", error)); return this; } const { storage, gl } = this; const { level = 0 } = options; this._width = bmp.width; this._height = bmp.height; this.bind(); gl.texImage2D(gl.TEXTURE_2D, level, gl[storage.internalFormat], gl[figureOutCompatibleFormat(storage.internalFormat)], gl.UNSIGNED_BYTE, bmp); this.eventChange.dispatch(this); return this; } loadData(data, options) { const { level = 0, width, height, // internalFormat, // format, // offset = 0, } = options; const { gl } = this; this.bind(); gl.texImage2D(gl.TEXTURE_2D, level, gl.RGB, //gl[internalFormat], width, height, 0, gl.RGB, // gl[format], gl.UNSIGNED_BYTE, data // offset ); this.eventChange.dispatch(this); return this; } /** * * @param unit Unit to link the texture to * @param program The program that owns the uniform to update * @param uniformName The uniform that hold the texture */ activate(unit, program, uniformName) { const { gl } = this; gl.activeTexture(gl.TEXTURE0 + unit); this.bind(); if (program && uniformName) { program.uniform1i(uniformName, unit); } return this; } generateMipmap() { const { gl } = this; this.bind(); gl.generateMipmap(gl.TEXTURE_2D); return this; } setParams(parameters) { this.bind(); webglTextureParametersSet(this.gl, parameters); return this; } set textureBaseLevel(value) { const { gl } = this; this.bind(); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, value); } get textureBaseLevel() { const { gl } = this; this.bind(); return gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL); } set textureMaxLevel(value) { const { gl } = this; this.bind(); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, value); } get textureMaxLevel() { const { gl } = this; this.bind(); return gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL); } getParameter(parameter) { const { gl, glTexture } = this; gl.bindTexture(gl.TEXTURE_2D, glTexture); const value = gl.getTexParameter(gl.TEXTURE_2D, gl[parameter]); return value; } } TgdTexture2D.counter = 0; const COMPATIBLE_FORMATS = [ [ "RGB", new Set([ "RGB", "RGB8", "RGB565", "SRGB8", "RGB8_SNORM", "RGB565", "R11F_G11F_B10F", "RGB9_E5", "RGB16F", "R11F_G11F_B10F", "RGB9_E5", "RGB32F", "RGB16F", "R11F_G11F_B10F", "RGB9_E5", ]), ], [ "RGBA", new Set([ "RGBA", "RGBA8", "RGB5_A1", "RGBA4", "SRGB8_ALPHA8", "RGBA8_SNORM", "RGBA4", "RGB5_A1", "RGB10_A2", "RGB5_A1", "RGBA16F", "RGBA32F", "RGBA16F", ]), ], ["RG", new Set(["RG8"])], ["RED", new Set(["R8"])], ]; function figureOutCompatibleFormat(internalFormat) { for (const [format, internalFormats] of COMPATIBLE_FORMATS) { if (internalFormats.has(internalFormat)) return format; } throw new Error(`There is no compatible format for internalFormat "${internalFormat}" and type "UNSIGNED_BYTE"!`); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dHVyZTJkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RleHR1cmUvdGV4dHVyZTJkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFckMsT0FBTyxFQUFFLFlBQVksRUFBaUMsTUFBTSxZQUFZLENBQUE7QUFDeEUsT0FBTyxFQUdILHlCQUF5QixHQUM1QixNQUFNLFlBQVksQ0FBQTtBQTJDbkIsTUFBTSxPQUFPLFlBQVk7SUFZckIsWUFDSSxPQUF1QyxFQUN2QyxPQUFzQztRQVgxQixnQkFBVyxHQUFHLElBQUksUUFBUSxFQUFnQixDQUFBO1FBRXpDLGFBQVEsR0FBd0IsSUFBSSxDQUFBO1FBQzdDLFdBQU0sR0FBRyxDQUFDLENBQUE7UUFDVixZQUFPLEdBQUcsQ0FBQyxDQUFBO1FBU2YsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQTtRQUN0QixJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQTtRQUNaLElBQUksQ0FBQyxJQUFJLEdBQUcsYUFBYSxZQUFZLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQTtRQUNqRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDbEMsSUFBSSxDQUFDLE9BQU87WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUE7UUFFakUsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUE7UUFDdkIsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNYLFNBQVMsRUFBRSxRQUFRO1lBQ25CLFNBQVMsRUFBRSxRQUFRO1lBQ25CLEtBQUssRUFBRSxRQUFRO1lBQ2YsS0FBSyxFQUFFLFFBQVE7WUFDZixLQUFLLEVBQUUsUUFBUTtTQUNsQixDQUFDLENBQUE7UUFDRixJQUFJLENBQUMsT0FBTyxtQkFDUixLQUFLLEVBQUUsQ0FBQyxFQUNSLE1BQU0sRUFBRSxDQUFDLEVBQ1QsY0FBYyxFQUFFLE9BQU8sRUFDdkIsTUFBTSxFQUFFLENBQUMsRUFDVCxLQUFLLEVBQUUsS0FBSyxJQUNULE9BQU8sQ0FDYixDQUFBO1FBQ0QsRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMxRCxJQUNJLE9BQU8sQ0FBQSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsS0FBSyxDQUFBLEtBQUssUUFBUTtZQUNsQyxPQUFPLENBQUEsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLE1BQU0sQ0FBQSxLQUFLLFFBQVEsRUFDckMsQ0FBQztZQUNDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLEtBQUssRUFBRSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsTUFBTSxDQUFDLENBQUE7UUFDaEQsQ0FBQztJQUNMLENBQUM7SUFFRCxNQUFNO1FBQ0YsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQ3pDLENBQUM7SUFFRCxJQUFJLEtBQUs7UUFDTCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUE7SUFDdEIsQ0FBQztJQUVELElBQUksTUFBTTtRQUNOLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUN2QixDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQWEsRUFBRSxNQUFjO1FBQ2hDLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxLQUFLLElBQUksTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTTtRQUUxRCxNQUFNLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQTtRQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1FBQ25DLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDdEMsTUFBTSxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFBO1FBQy9DLElBQUksY0FBYyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQzNDLHlDQUF5QztZQUN6QyxNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLDhCQUE4QixDQUFDLENBQUE7WUFDakUsSUFBSSxDQUFDLFNBQVM7Z0JBQ1YsTUFBTSxJQUFJLEtBQUssQ0FDWCx3RkFBd0YsQ0FDM0YsQ0FBQTtRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7UUFDWCxFQUFFLENBQUMsWUFBWSxDQUNYLEVBQUUsQ0FBQyxVQUFVLEVBQ2IsTUFBTSxFQUNMLEVBQXdDLENBQUMsY0FBYyxDQUFDLEVBQ3pELEtBQUssRUFDTCxNQUFNLENBQ1QsQ0FBQTtJQUNMLENBQUM7SUFFRCxJQUFJLFNBQVM7UUFDVCxJQUFJLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFBO1FBRXZDLE1BQU0sSUFBSSxLQUFLLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxxQkFBcUIsQ0FBQyxDQUFBO0lBQy9ELENBQUM7SUFFRCxJQUFJO1FBQ0EsSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQzNELENBQUM7SUFFRCxVQUFVLENBQ04sR0FBbUQsRUFDbkQsVUFFSSxFQUFFO1FBRU4sSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLElBQUksQ0FBQTtRQUVyQixJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDckIsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FDbEQsT0FBTyxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsRUFBRSxLQUFLLENBQUMsQ0FDdEQsQ0FBQTtZQUNELE9BQU8sSUFBSSxDQUFBO1FBQ2YsQ0FBQztRQUVELE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQzVCLE1BQU0sRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEdBQUcsT0FBTyxDQUFBO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQTtRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUE7UUFDekIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ1gsRUFBRSxDQUFDLFVBQVUsQ0FDVCxFQUFFLENBQUMsVUFBVSxFQUNiLEtBQUssRUFDSixFQUF3QyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsRUFDakUsRUFBRSxDQUFDLHlCQUF5QixDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBVyxFQUMvRCxFQUFFLENBQUMsYUFBYSxFQUNoQixHQUFHLENBQ04sQ0FBQTtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQy9CLE9BQU8sSUFBSSxDQUFBO0lBQ2YsQ0FBQztJQUVELFFBQVEsQ0FDSixJQUFvQyxFQUNwQyxPQWVDO1FBRUQsTUFBTSxFQUNGLEtBQUssR0FBRyxDQUFDLEVBQ1QsS0FBSyxFQUNMLE1BQU07UUFDTixrQkFBa0I7UUFDbEIsVUFBVTtRQUNWLGNBQWM7VUFDakIsR0FBRyxPQUFPLENBQUE7UUFDWCxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQ25CLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNYLEVBQUUsQ0FBQyxVQUFVLENBQ1QsRUFBRSxDQUFDLFVBQVUsRUFDYixLQUFLLEVBQ0wsRUFBRSxDQUFDLEdBQUcsRUFBRSxxQkFBcUI7UUFDN0IsS0FBSyxFQUNMLE1BQU0sRUFDTixDQUFDLEVBQ0QsRUFBRSxDQUFDLEdBQUcsRUFBRSxjQUFjO1FBQ3RCLEVBQUUsQ0FBQyxhQUFhLEVBQ2hCLElBQUk7UUFDSixTQUFTO1NBQ1osQ0FBQTtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQy9CLE9BQU8sSUFBSSxDQUFBO0lBQ2YsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsUUFBUSxDQUFDLElBQVksRUFBRSxPQUFvQixFQUFFLFdBQW9CO1FBQzdELE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDbkIsRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxDQUFBO1FBQ3BDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNYLElBQUksT0FBTyxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ3pCLE9BQU8sQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQ3hDLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFFRCxjQUFjO1FBQ1YsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQTtRQUNuQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7UUFDWCxFQUFFLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUNoQyxPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFFRCxTQUFTLENBQUMsVUFBa0M7UUFDeEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ1gseUJBQXlCLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQTtRQUM5QyxPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFFRCxJQUFJLGdCQUFnQixDQUFDLEtBQWE7UUFDOUIsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQTtRQUNuQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7UUFDWCxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ2pFLENBQUM7SUFFRCxJQUFJLGdCQUFnQjtRQUNoQixNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQ25CLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNYLE9BQU8sRUFBRSxDQUFDLGVBQWUsQ0FDckIsRUFBRSxDQUFDLFVBQVUsRUFDYixFQUFFLENBQUMsa0JBQWtCLENBQ2QsQ0FBQTtJQUNmLENBQUM7SUFFRCxJQUFJLGVBQWUsQ0FBQyxLQUFhO1FBQzdCLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDbkIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ1gsRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUNoRSxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2YsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQTtRQUNuQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7UUFDWCxPQUFPLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsaUJBQWlCLENBQVcsQ0FBQTtJQUM1RSxDQUFDO0lBRUQsWUFBWSxDQUFDLFNBQTRCO1FBQ3JDLE1BQU0sRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQzlCLEVBQUUsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQTtRQUN4QyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUduRCxDQUFBO1FBQ1YsT0FBTyxLQUFLLENBQUE7SUFDaEIsQ0FBQzs7QUFqT2Msb0JBQU8sR0FBRyxDQUFDLEFBQUosQ0FBSTtBQW9POUIsTUFBTSxrQkFBa0IsR0FBdUQ7SUFDM0U7UUFDSSxLQUFLO1FBQ0wsSUFBSSxHQUFHLENBQUM7WUFDSixLQUFLO1lBQ0wsTUFBTTtZQUNOLFFBQVE7WUFDUixPQUFPO1lBQ1AsWUFBWTtZQUNaLFFBQVE7WUFDUixnQkFBZ0I7WUFDaEIsU0FBUztZQUNULFFBQVE7WUFDUixnQkFBZ0I7WUFDaEIsU0FBUztZQUNULFFBQVE7WUFDUixRQUFRO1lBQ1IsZ0JBQWdCO1lBQ2hCLFNBQVM7U0FDWixDQUFDO0tBQ0w7SUFDRDtRQUNJLE1BQU07UUFDTixJQUFJLEdBQUcsQ0FBQztZQUNKLE1BQU07WUFDTixPQUFPO1lBQ1AsU0FBUztZQUNULE9BQU87WUFDUCxjQUFjO1lBQ2QsYUFBYTtZQUNiLE9BQU87WUFDUCxTQUFTO1lBQ1QsVUFBVTtZQUNWLFNBQVM7WUFDVCxTQUFTO1lBQ1QsU0FBUztZQUNULFNBQVM7U0FDWixDQUFDO0tBQ0w7SUFDRCxDQUFDLElBQUksRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDeEIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0NBQzNCLENBQUE7QUFFRCxTQUFTLHlCQUF5QixDQUM5QixjQUFzQjtJQUV0QixLQUFLLE1BQU0sQ0FBQyxNQUFNLEVBQUUsZUFBZSxDQUFDLElBQUksa0JBQWtCLEVBQUUsQ0FBQztRQUN6RCxJQUFJLGVBQWUsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQUUsT0FBTyxNQUFNLENBQUE7SUFDMUQsQ0FBQztJQUNELE1BQU0sSUFBSSxLQUFLLENBQ1gscURBQXFELGNBQWMsNkJBQTZCLENBQ25HLENBQUE7QUFDTCxDQUFDIn0=