UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

295 lines 27.7 kB
import { TgdDataset } from "./../dataset/index.js"; import { TgdConsole } from "./../debug/index.js"; import { TgdProgram } from "./../program/index.js"; import { TgdShaderFragment, TgdShaderVertex, tgdCodeStringify, } from "./../shader/index.js"; import { ensureArray, tgdTextureRecordToUniforms, webglElementTypeFromTypedArray, webglLookup } from "./../utils/index.js"; import { TgdPainterLogic, TgdVertexArray } from "./../index.js"; import { TgdUniformBufferObject } from "./../uniform/uniform-buffer-object.js"; import { TgdPainter } from "./painter.js"; import { TgdPainterState } from "./state/index.js"; export class TgdPainterProgram extends TgdPainter { constructor(context, { onEnter, onDelete, uniforms = {}, textures = {}, varying, vert, frag, dataset, elements, drawMode, state, elementsCount, elementsOffset, instancesCount, }) { super(); this.context = context; this.elementsCount = 0; this.elementsOffset = 0; this.instancesCount = 0; this.uniformBlocks = []; this.uniformBlocksToDelete = []; this.internalPaint = (time, delta) => { const { context, onEnter, textures, uniformBlocks, prg, vao, elementsType, elementsCount, elementsOffset, instancesCount, drawMode: mode, } = this; const { gl } = context; prg.use(); let unit = 0; for (const name of Object.keys(textures)) { const texture = textures[name]; texture.activate(unit++, prg, name); } onEnter?.(time, delta); for (const block of uniformBlocks) { block.updateData(); } vao.bind(); if (this.hasElements) { if (instancesCount > 0) { gl.drawElementsInstanced(mode, elementsCount, elementsType, elementsOffset, instancesCount); } else { gl.drawElements(mode, elementsCount, elementsType, elementsOffset); } } else { if (instancesCount > 0) { gl.drawArraysInstanced(mode, elementsOffset, elementsCount, instancesCount); } else { gl.drawArrays(mode, elementsOffset, elementsCount); } } vao.unbind(); }; this.textures = textures; this.onEnter = onEnter; this.onDelete = onDelete; const datasets = ensureArray(dataset).map((item) => { if (item instanceof TgdDataset) return item; const attributesDefinition = {}; for (const attribName of Object.keys(item.attribs)) { attributesDefinition[attribName] = item.attribs[attribName].type; } const ds = new TgdDataset(attributesDefinition, item); for (const attribName of Object.keys(item.attribs)) { ds.set(attribName, item.attribs[attribName].data); } return ds; }); this.drawMode = typeof drawMode === "number" ? drawMode : context.gl[drawMode]; const uniformsHeader = ensureArray(this.uniformsToCode(uniforms)); const uniformsForTextures = tgdTextureRecordToUniforms(textures); const vertexShader = new TgdShaderVertex({ ...vert, uniforms: uniformsForTextures, attributes: resolveAttributesFromDataset(datasets), header: [...uniformsHeader, ...ensureArray(vert.header)], varying, }); const fragmentShader = new TgdShaderFragment({ ...frag, uniforms: uniformsForTextures, header: [...uniformsHeader, ...ensureArray(vert.header)], varying, }); const program = new TgdProgram(context.gl, { vert: vertexShader, frag: fragmentShader, }); this.prg = program; program.use(); const samplerNames = Object.keys(textures); for (let unit = 0; unit < samplerNames.length; unit++) { const uniformName = samplerNames[unit]; const texture = textures[uniformName]; texture.activate(unit, program, uniformName); } const vao = new TgdVertexArray(context.gl, program, datasets, elements); this.vao = vao; this.painterState = new TgdPainterState(context, { ...state, children: [new TgdPainterLogic(this.internalPaint)], }); this.elementsCount = elementsCount ?? resolveElementsCount(datasets, elements); this.elementsOffset = elementsOffset ?? 0; this.instancesCount = instancesCount ?? resolveInstancesCount(datasets); this.hasElements = !!elements; this.elementsType = elements ? webglElementTypeFromTypedArray(elements) : 0; const setBindingPoints = new Set(); Object.keys(uniforms).forEach((blockName, index) => { const block = this.uniformBlocks[index]; if (setBindingPoints.has(block.bindingPoint)) { const code = Object.keys(uniforms).map((blockName, index) => this.uniformBlocks[index].toShaderCode(blockName)); throw new Error(`[TgdPainterProgram] Uniform blocks must have distincts binding points!\n${tgdCodeStringify(code)}`); } setBindingPoints.add(block.bindingPoint); block.bindToProgram(program, blockName); }); } setElements(elements) { this.vao.updateElements(elements); this.elementsCount = elements.length; } /** * Update the values of an attribute of a dataset and resolve the counts. */ setAttributeValues(dataset, attribName, values) { try { dataset.set(attribName, values); this.vao.updateDataset(dataset); if (dataset.divisor > 0) { this.instancesCount = values.length; } else { const { gl } = this.context; switch (this.drawMode) { case gl.POINTS: return values.length; case gl.LINES: return Math.floor(values.length / 2); case gl.LINE_LOOP: return values.length; case gl.LINE_STRIP: return values.length - 1; case gl.TRIANGLES: return Math.floor(values.length / 3); case gl.TRIANGLE_FAN: case gl.TRIANGLE_STRIP: return values.length - 2; default: throw new Error(`Unknown drawMode: ${webglLookup(this.drawMode)}!`); } } } catch (error) { const message = error instanceof Error ? error.message : JSON.stringify(error); throw new Error(`[TgdPainterProgram] Unable to set attribute values of dataset "${dataset.name}" for "${this.name}"!\n${message}`); } } delete() { this.onDelete?.(); for (const block of this.uniformBlocksToDelete) { block.delete(); } this.prg.delete(); this.vao.delete(); } paint(time, delta) { this.painterState.paint(time, delta); } debug(caption) { console.debug(caption ?? this.name); console.debug({ drawMode: webglLookup(this.drawMode), elementsCount: this.elementsCount, elementsOffset: this.elementsOffset, instancesCount: this.instancesCount, }); this.vao.debug(); } uniformsToCode(uniforms) { const code = []; const setNames = new Set(); const setDuplicated = new Set(); const names = {}; for (const blockName of Object.keys(uniforms)) { const block = this.resolveUniformBlock(uniforms[blockName]); this.uniformBlocks.push(block); names[blockName] = block.names; code.push(...ensureArray(block.toShaderCode(blockName))); for (const name of block.names) { if (setNames.has(name)) setDuplicated.add(name); else setNames.add(name); } } if (setDuplicated.size > 0) { // There is a duplicate! const out = new TgdConsole({ text: "[TgdPainterProgram] You have duplicated names in your uniform blocks:\n", color: "#f33", }); for (const blockName of Object.keys(names)) { out.add(` ${blockName}`, { bold: true }).add(": "); names[blockName].forEach((name, index) => { if (index > 0) out.add(", "); out.add(name, setDuplicated.has(name) ? { bold: true, color: "#f33", } : undefined); }); out.nl(); } out.error(); } return code; } resolveUniformBlock(obj) { if (obj instanceof TgdUniformBufferObject) return obj; return new TgdUniformBufferObject(this.context, obj); } } function resolveAttributesFromDataset(datasets) { const attributes = {}; const setNames = new Set(); const setDuplicated = new Set(); for (const dataset of datasets) { for (const name of dataset.attributesNames) { if (setNames.has(name)) setDuplicated.add(name); else setNames.add(name); attributes[name] = dataset.getType(name); } } if (setDuplicated.size > 0) { // There is a duplicate! const out = new TgdConsole({ text: "[TgdPainterProgram] You have duplicated names in your datasets:\n", color: "#f33", }); for (const dataset of datasets) { out.add(` ${dataset.name}`, { bold: true }).add(": "); dataset.attributesNames.forEach((name, index) => { if (index > 0) out.add(", "); out.add(name, setDuplicated.has(name) ? { bold: true, color: "#f33", } : undefined); }); out.nl(); } out.error(); } return attributes; } function resolveElementsCount(datasets, elements) { if (elements) return elements.length; const counts = datasets.filter((ds) => ds.divisor === 0).map((ds) => ds.count); if (counts.length === 0) { throw new Error("[TgdPainterProgram] You must give at least one Dataset with divisor 0 in the constructor!\nOr you can specify elementsCount."); } if (counts.length === 1) return counts[0]; counts.sort(); const [first] = counts; const last = counts[counts.length - 1]; if (first === last) return first; throw new Error(`[TgdPainterPogram] I cannot resolve elementsCount because your datasets have different counts!\n${datasets .filter((ds) => ds.divisor === 0) .map((ds) => ` ${ds.name}: count == ${ds.count}`)}`); } function resolveInstancesCount(datasets) { const counts = datasets.filter((ds) => ds.divisor > 0).map((ds) => ds.count / ds.divisor); if (counts.length === 0) return 0; if (counts.length === 1) return counts[0]; counts.sort(); const [first] = counts; const last = counts[counts.length - 1]; if (first === last) return first; throw new Error(`[TgdPainterPogram] I cannot resolve elementsCount because your instance datasets have different counts!\n${datasets .filter((ds) => ds.divisor > 0) .map((ds) => ` ${ds.name}: count == ${ds.count} / ${ds.divisor} == ${ds.count / ds.divisor}`)}`); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3JhbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYWludGVyL3Byb2dyYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFVBQVUsRUFBMEUsTUFBTSxjQUFjLENBQUE7QUFDakgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUN2QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ3pDLE9BQU8sRUFJSCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLGdCQUFnQixHQUNuQixNQUFNLGFBQWEsQ0FBQTtBQUdwQixPQUFPLEVBQUUsV0FBVyxFQUFFLDBCQUEwQixFQUFFLDhCQUE4QixFQUFFLFdBQVcsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNqSCxPQUFPLEVBQUUsZUFBZSxFQUFnQyxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM5RixPQUFPLEVBQUUsc0JBQXNCLEVBQXNDLE1BQU0sb0NBQW9DLENBQUE7QUFDL0csT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsZUFBZSxFQUErQixNQUFNLFNBQVMsQ0FBQTtBQThEdEUsTUFBTSxPQUFPLGlCQUFrQixTQUFRLFVBQVU7SUFpQjdDLFlBQ29CLE9BQW1CLEVBQ25DLEVBQ0ksT0FBTyxFQUNQLFFBQVEsRUFDUixRQUFRLEdBQUcsRUFBRSxFQUNiLFFBQVEsR0FBRyxFQUFFLEVBQ2IsT0FBTyxFQUNQLElBQUksRUFDSixJQUFJLEVBQ0osT0FBTyxFQUNQLFFBQVEsRUFDUixRQUFRLEVBQ1IsS0FBSyxFQUNMLGFBQWEsRUFDYixjQUFjLEVBQ2QsY0FBYyxHQUNTO1FBRTNCLEtBQUssRUFBRSxDQUFBO1FBbEJTLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFqQmhDLGtCQUFhLEdBQUcsQ0FBQyxDQUFBO1FBQ2pCLG1CQUFjLEdBQUcsQ0FBQyxDQUFBO1FBQ2xCLG1CQUFjLEdBQUcsQ0FBQyxDQUFBO1FBR1Isa0JBQWEsR0FBNkIsRUFBRSxDQUFBO1FBQzVDLDBCQUFxQixHQUE2QixFQUFFLENBQUE7UUFzS3BELGtCQUFhLEdBQUcsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLEVBQUU7WUFDN0QsTUFBTSxFQUNGLE9BQU8sRUFDUCxPQUFPLEVBQ1AsUUFBUSxFQUNSLGFBQWEsRUFDYixHQUFHLEVBQ0gsR0FBRyxFQUNILFlBQVksRUFDWixhQUFhLEVBQ2IsY0FBYyxFQUNkLGNBQWMsRUFDZCxRQUFRLEVBQUUsSUFBSSxHQUNqQixHQUFHLElBQUksQ0FBQTtZQUNSLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUE7WUFDdEIsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFBO1lBQ1QsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFBO1lBQ1osS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDOUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDdkMsQ0FBQztZQUNELE9BQU8sRUFBRSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQTtZQUN0QixLQUFLLE1BQU0sS0FBSyxJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUNoQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUE7WUFDdEIsQ0FBQztZQUNELEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtZQUNWLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixJQUFJLGNBQWMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDckIsRUFBRSxDQUFDLHFCQUFxQixDQUFDLElBQUksRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxjQUFjLENBQUMsQ0FBQTtnQkFDL0YsQ0FBQztxQkFBTSxDQUFDO29CQUNKLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUE7Z0JBQ3RFLENBQUM7WUFDTCxDQUFDO2lCQUFNLENBQUM7Z0JBQ0osSUFBSSxjQUFjLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0JBQ3JCLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxjQUFjLENBQUMsQ0FBQTtnQkFDL0UsQ0FBQztxQkFBTSxDQUFDO29CQUNKLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxhQUFhLENBQUMsQ0FBQTtnQkFDdEQsQ0FBQztZQUNMLENBQUM7WUFDRCxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUE7UUFDaEIsQ0FBQyxDQUFBO1FBaExHLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBQ3hCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFBO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBQ3hCLE1BQU0sUUFBUSxHQUFpQixXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDN0QsSUFBSSxJQUFJLFlBQVksVUFBVTtnQkFBRSxPQUFPLElBQUksQ0FBQTtZQUMzQyxNQUFNLG9CQUFvQixHQUF5QixFQUFFLENBQUE7WUFDckQsS0FBSyxNQUFNLFVBQVUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNqRCxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQTtZQUNwRSxDQUFDO1lBQ0QsTUFBTSxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDckQsS0FBSyxNQUFNLFVBQVUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNqRCxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO1lBQ3JELENBQUM7WUFDRCxPQUFPLEVBQUUsQ0FBQTtRQUNiLENBQUMsQ0FBQyxDQUFBO1FBQ0YsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLFFBQVEsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM5RSxNQUFNLGNBQWMsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFBO1FBQ2pFLE1BQU0sbUJBQW1CLEdBQUcsMEJBQTBCLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDaEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxlQUFlLENBQUM7WUFDckMsR0FBRyxJQUFJO1lBQ1AsUUFBUSxFQUFFLG1CQUFtQjtZQUM3QixVQUFVLEVBQUUsNEJBQTRCLENBQUMsUUFBUSxDQUFDO1lBQ2xELE1BQU0sRUFBRSxDQUFDLEdBQUcsY0FBYyxFQUFFLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN4RCxPQUFPO1NBQ1YsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxjQUFjLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQztZQUN6QyxHQUFHLElBQUk7WUFDUCxRQUFRLEVBQUUsbUJBQW1CO1lBQzdCLE1BQU0sRUFBRSxDQUFDLEdBQUcsY0FBYyxFQUFFLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN4RCxPQUFPO1NBQ1YsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRTtZQUN2QyxJQUFJLEVBQUUsWUFBWTtZQUNsQixJQUFJLEVBQUUsY0FBYztTQUN2QixDQUFDLENBQUE7UUFDRixJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQTtRQUNsQixPQUFPLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDYixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQzFDLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUFFLElBQUksR0FBRyxZQUFZLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7WUFDcEQsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFBO1lBQ3RDLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQTtZQUNyQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUE7UUFDaEQsQ0FBQztRQUNELE1BQU0sR0FBRyxHQUFHLElBQUksY0FBYyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQTtRQUN2RSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQTtRQUNkLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxlQUFlLENBQUMsT0FBTyxFQUFFO1lBQzdDLEdBQUcsS0FBSztZQUNSLFFBQVEsRUFBRSxDQUFDLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUN0RCxDQUFDLENBQUE7UUFDRixJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDOUUsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLElBQUksQ0FBQyxDQUFBO1FBQ3pDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxJQUFJLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3ZFLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtRQUM3QixJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsOEJBQThCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUMzRSxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUE7UUFDMUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDL0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUN2QyxJQUFJLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztnQkFDM0MsTUFBTSxJQUFJLEdBQWdCLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQ3JFLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUNwRCxDQUFBO2dCQUNELE1BQU0sSUFBSSxLQUFLLENBQ1gsMkVBQTJFLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQ3RHLENBQUE7WUFDTCxDQUFDO1lBQ0QsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQTtZQUN4QyxLQUFLLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQTtRQUMzQyxDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUM7SUFFRCxXQUFXLENBQUMsUUFBa0I7UUFDMUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDakMsSUFBSSxDQUFDLGFBQWEsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFBO0lBQ3hDLENBQUM7SUFFRDs7T0FFRztJQUNILGtCQUFrQixDQUFDLE9BQW1CLEVBQUUsVUFBa0IsRUFBRSxNQUFvQjtRQUM1RSxJQUFJLENBQUM7WUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQTtZQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUMvQixJQUFJLE9BQU8sQ0FBQyxPQUFPLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLElBQUksQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQTtZQUN2QyxDQUFDO2lCQUFNLENBQUM7Z0JBQ0osTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUE7Z0JBQzNCLFFBQVEsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUNwQixLQUFLLEVBQUUsQ0FBQyxNQUFNO3dCQUNWLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQTtvQkFDeEIsS0FBSyxFQUFFLENBQUMsS0FBSzt3QkFDVCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtvQkFDeEMsS0FBSyxFQUFFLENBQUMsU0FBUzt3QkFDYixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUE7b0JBQ3hCLEtBQUssRUFBRSxDQUFDLFVBQVU7d0JBQ2QsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQTtvQkFDNUIsS0FBSyxFQUFFLENBQUMsU0FBUzt3QkFDYixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtvQkFDeEMsS0FBSyxFQUFFLENBQUMsWUFBWSxDQUFDO29CQUNyQixLQUFLLEVBQUUsQ0FBQyxjQUFjO3dCQUNsQixPQUFPLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFBO29CQUM1Qjt3QkFDSSxNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQTtnQkFDM0UsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNiLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDOUUsTUFBTSxJQUFJLEtBQUssQ0FDWCxrRUFBa0UsT0FBTyxDQUFDLElBQUksVUFBVSxJQUFJLENBQUMsSUFBSSxPQUFPLE9BQU8sRUFBRSxDQUNwSCxDQUFBO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFRCxNQUFNO1FBQ0YsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUE7UUFDakIsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUM3QyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUE7UUFDbEIsQ0FBQztRQUNELElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUE7UUFDakIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQTtJQUNyQixDQUFDO0lBRUQsS0FBSyxDQUFDLElBQVksRUFBRSxLQUFhO1FBQzdCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUN4QyxDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQWdCO1FBQ2xCLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNuQyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQ1YsUUFBUSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1lBQ3BDLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtZQUNqQyxjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWM7WUFDbkMsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjO1NBQ3RDLENBQUMsQ0FBQTtRQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUE7SUFDcEIsQ0FBQztJQTRDTyxjQUFjLENBQ2xCLFFBQXNHO1FBRXRHLE1BQU0sSUFBSSxHQUFnQixFQUFFLENBQUE7UUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQTtRQUNsQyxNQUFNLGFBQWEsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFBO1FBQ3ZDLE1BQU0sS0FBSyxHQUE2QixFQUFFLENBQUE7UUFDMUMsS0FBSyxNQUFNLFNBQVMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDNUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFBO1lBQzNELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQzlCLEtBQUssQ0FBQyxTQUFTLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFBO1lBQzlCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDeEQsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzdCLElBQUksUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUM7b0JBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQTs7b0JBQzFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDM0IsQ0FBQztRQUNMLENBQUM7UUFDRCxJQUFJLGFBQWEsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDekIsd0JBQXdCO1lBQ3hCLE1BQU0sR0FBRyxHQUFHLElBQUksVUFBVSxDQUFDO2dCQUN2QixJQUFJLEVBQUUseUVBQXlFO2dCQUMvRSxLQUFLLEVBQUUsTUFBTTthQUNoQixDQUFDLENBQUE7WUFDRixLQUFLLE1BQU0sU0FBUyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDekMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFBO2dCQUNuRCxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO29CQUNyQyxJQUFJLEtBQUssR0FBRyxDQUFDO3dCQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7b0JBQzVCLEdBQUcsQ0FBQyxHQUFHLENBQ0gsSUFBSSxFQUNKLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO3dCQUNuQixDQUFDLENBQUM7NEJBQ0ksSUFBSSxFQUFFLElBQUk7NEJBQ1YsS0FBSyxFQUFFLE1BQU07eUJBQ2hCO3dCQUNILENBQUMsQ0FBQyxTQUFTLENBQ2xCLENBQUE7Z0JBQ0wsQ0FBQyxDQUFDLENBQUE7Z0JBQ0YsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFBO1lBQ1osQ0FBQztZQUNELEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNmLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxHQUEyRDtRQUNuRixJQUFJLEdBQUcsWUFBWSxzQkFBc0I7WUFBRSxPQUFPLEdBQUcsQ0FBQTtRQUVyRCxPQUFPLElBQUksc0JBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQTtJQUN4RCxDQUFDO0NBQ0o7QUFFRCxTQUFTLDRCQUE0QixDQUFDLFFBQXNCO0lBQ3hELE1BQU0sVUFBVSxHQUF5QyxFQUFFLENBQUE7SUFDM0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQTtJQUNsQyxNQUFNLGFBQWEsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFBO0lBQ3ZDLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekMsSUFBSSxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztnQkFBRSxhQUFhLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFBOztnQkFDMUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUN2QixVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM1QyxDQUFDO0lBQ0wsQ0FBQztJQUNELElBQUksYUFBYSxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN6Qix3QkFBd0I7UUFDeEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxVQUFVLENBQUM7WUFDdkIsSUFBSSxFQUFFLG1FQUFtRTtZQUN6RSxLQUFLLEVBQUUsTUFBTTtTQUNoQixDQUFDLENBQUE7UUFDRixLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQzdCLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDdEQsT0FBTyxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7Z0JBQzVDLElBQUksS0FBSyxHQUFHLENBQUM7b0JBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDNUIsR0FBRyxDQUFDLEdBQUcsQ0FDSCxJQUFJLEVBQ0osYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUM7b0JBQ25CLENBQUMsQ0FBQzt3QkFDSSxJQUFJLEVBQUUsSUFBSTt3QkFDVixLQUFLLEVBQUUsTUFBTTtxQkFDaEI7b0JBQ0gsQ0FBQyxDQUFDLFNBQVMsQ0FDbEIsQ0FBQTtZQUNMLENBQUMsQ0FBQyxDQUFBO1lBQ0YsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFBO1FBQ1osQ0FBQztRQUNELEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtJQUNmLENBQUM7SUFDRCxPQUFPLFVBQVUsQ0FBQTtBQUNyQixDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxRQUFzQixFQUFFLFFBQTZDO0lBQy9GLElBQUksUUFBUTtRQUFFLE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQTtJQUNwQyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzlFLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksS0FBSyxDQUNYLDhIQUE4SCxDQUNqSSxDQUFBO0lBQ0wsQ0FBQztJQUNELElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDekMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sQ0FBQTtJQUN0QixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtJQUN0QyxJQUFJLEtBQUssS0FBSyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUE7SUFFaEMsTUFBTSxJQUFJLEtBQUssQ0FDWCxtR0FBbUcsUUFBUTtTQUN0RyxNQUFNLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDO1NBQ2hDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxjQUFjLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQzNELENBQUE7QUFDTCxDQUFDO0FBRUQsU0FBUyxxQkFBcUIsQ0FBQyxRQUFzQjtJQUNqRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDekYsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQTtJQUNqQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3pDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtJQUNiLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxNQUFNLENBQUE7SUFDdEIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDdEMsSUFBSSxLQUFLLEtBQUssSUFBSTtRQUFFLE9BQU8sS0FBSyxDQUFBO0lBRWhDLE1BQU0sSUFBSSxLQUFLLENBQ1gsNEdBQTRHLFFBQVE7U0FDL0csTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztTQUM5QixHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksY0FBYyxFQUFFLENBQUMsS0FBSyxNQUFNLEVBQUUsQ0FBQyxPQUFPLE9BQU8sRUFBRSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUN2RyxDQUFBO0FBQ0wsQ0FBQyJ9