mondlich
Version:
cross-engine vfx library
1,216 lines • 379 kB
JavaScript
var aA = Object.defineProperty;
var _ = (r) => {
throw TypeError(r);
};
var nA = (r, t, A) => t in r ? aA(r, t, { enumerable: !0, configurable: !0, writable: !0, value: A }) : r[t] = A;
var g = (r, t, A) => nA(r, typeof t != "symbol" ? t + "" : t, A), $ = (r, t, A) => t.has(r) || _("Cannot " + A);
var a = (r, t, A) => ($(r, t, "read from private field"), A ? A.call(r) : t.get(r)), k = (r, t, A) => t.has(r) ? _("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, A), u = (r, t, A, e) => ($(r, t, "write to private field"), e ? e.call(r, A) : t.set(r, A), A);
import { vec3 as f, mat4 as E, glMatrix as cA, quat as AA, vec2 as BA } from "gl-matrix";
import { Renderer as fA } from "phaser";
import { RendererType as CA } from "pixi.js";
class hA {
constructor({ viewConfig: t, projectionConfig: A }) {
g(this, "_viewConfig");
g(this, "_projectionConfig");
g(this, "_worldMatrix");
g(this, "_viewMatrix");
g(this, "_projectionMatrix");
this._viewConfig = {
eye: f.clone(t.eye),
center: f.clone(t.center),
up: f.clone(t.up)
}, this._projectionConfig = { ...A }, this._worldMatrix = new Float32Array(16), this._viewMatrix = new Float32Array(16), this._projectionMatrix = new Float32Array(16), this.updateMatrices();
}
updateMatrices() {
E.identity(this._worldMatrix), E.lookAt(
this._viewMatrix,
this._viewConfig.eye,
this._viewConfig.center,
this._viewConfig.up
), E.perspective(
this._projectionMatrix,
this._projectionConfig.fovy,
this._projectionConfig.aspect,
this._projectionConfig.nearPlane,
this._projectionConfig.farPlane
);
}
setEyePosition(t) {
f.copy(this._viewConfig.eye, t), this.updateMatrices();
}
setLookAt(t) {
f.copy(this._viewConfig.center, t), this.updateMatrices();
}
setUpVector(t) {
f.copy(this._viewConfig.up, t), this.updateMatrices();
}
moveEye(t) {
f.add(this._viewConfig.eye, this._viewConfig.eye, t), this.updateMatrices();
}
moveLookAt(t) {
f.add(this._viewConfig.center, this._viewConfig.center, t), this.updateMatrices();
}
// Projection controls
setFovy(t) {
this._projectionConfig.fovy = t, this.updateMatrices();
}
setAspect(t) {
this._projectionConfig.aspect = t, this.updateMatrices();
}
setNearPlane(t) {
this._projectionConfig.nearPlane = t, this.updateMatrices();
}
setFarPlane(t) {
this._projectionConfig.farPlane = t, this.updateMatrices();
}
get worldMatrix() {
return this._worldMatrix;
}
get viewMatrix() {
return this._viewMatrix;
}
get projectionMatrix() {
return this._projectionMatrix;
}
get eyePosition() {
return this._viewConfig.eye;
}
get lookAtPoint() {
return this._viewConfig.center;
}
get upVector() {
return this._viewConfig.up;
}
}
const QA = {
eye: [0, 1500, 1e3],
center: [0, 1100, 0],
// lookAt
up: [0, 1, 0]
}, lA = {
fovy: cA.toRadian(100),
aspect: 1,
nearPlane: 0.1,
farPlane: 5e4
}, tA = 60, EA = {
alpha: !1,
// better performance
antialias: !0,
depth: !0,
// enable depth buffer
stencil: !1,
// disable stencil buffer
premultipliedAlpha: !1,
preserveDrawingBuffer: !1,
powerPreference: "high-performance"
};
class at {
constructor(t, A = {}) {
g(this, "camera");
g(this, "gl");
this.canvas = t;
const e = t.getContext("webgl2", {
...EA,
...A
});
if (!e) throw new Error("WebGL2 is not supported in this browser.");
this.gl = e, this.camera = new hA({
viewConfig: QA,
projectionConfig: {
...lA,
aspect: t.width / t.height
}
});
}
get viewportSize() {
return {
width: this.canvas.width,
height: this.canvas.height
};
}
}
class eA {
}
class nt {
constructor(t) {
this.engine = t;
}
get viewportSize() {
return this.engine.viewportSize;
}
get cameraWorldMatrix() {
return this.engine.camera.worldMatrix;
}
get cameraViewMatrix() {
return this.engine.camera.viewMatrix;
}
get cameraProjectionMatrix() {
return this.engine.camera.projectionMatrix;
}
get cameraMatrix() {
const t = new Float32Array(16);
return E.multiply(t, t, this.engine.camera.projectionMatrix), E.multiply(t, t, this.engine.camera.viewMatrix), E.copy(t, this.engine.camera.worldMatrix), t;
}
get gl() {
return this.engine.gl;
}
executeInGLContext(t) {
t(this.engine.gl);
}
}
class ct extends eA {
constructor(A, e) {
super();
g(this, "game");
g(this, "scene");
if (this.game = A, this.scene = e, !(this.game.renderer instanceof fA.WebGL.WebGLRenderer))
throw new Error("Phaser game must use WebGL renderer");
if (!(this.game.renderer.gl instanceof WebGL2RenderingContext))
throw new Error("Phaser game must be configured to use WebGL2");
}
get gl() {
return this.game.renderer.gl;
}
get cameraMatrix() {
const A = this.cameraViewMatrix, e = this.cameraProjectionMatrix, i = E.create();
return E.multiply(i, e, A), i;
}
get cameraWorldMatrix() {
const A = new Float32Array(16), e = this.cameraViewMatrix;
return E.invert(A, e), A;
}
get cameraViewMatrix() {
if (!this.scene.cameras.main)
throw new Error("Main camera not initialized");
const A = this.scene.cameras.main, e = new Float32Array(16);
return E.translate(e, e, [-A.scrollX, -A.scrollY, 0]), E.scale(e, e, [1 / A.zoom, 1 / A.zoom, 1]), e;
}
get cameraProjectionMatrix() {
const { width: A, height: e } = this.viewportSize, i = new Float32Array(16);
return E.ortho(i, 0, A, e, 0, -1e3, 1e3), i;
}
get viewportSize() {
return {
width: this.game.scale.width,
height: this.game.scale.height
};
}
executeInGLContext(A) {
A(this.gl);
}
}
class Bt extends eA {
constructor(A, e) {
super();
g(this, "app");
g(this, "gl");
if (this.app = A, this.app.renderer.type !== CA.WEBGL)
throw new Error("PixiJS application must use WebGL renderer");
this.gl = e;
}
get cameraMatrix() {
const A = this.cameraViewMatrix, e = this.cameraProjectionMatrix, i = new Float32Array(16);
return E.multiply(i, e, A), i;
}
get cameraWorldMatrix() {
const A = new Float32Array(16);
return E.identity(A), A;
}
get cameraViewMatrix() {
const A = new Float32Array(16);
return E.identity(A), A;
}
get cameraProjectionMatrix() {
const { width: A, height: e } = this.viewportSize, i = new Float32Array(16);
return E.ortho(i, 0, A, e, 0, -1e3, 1e3), i;
}
get viewportSize() {
return {
width: this.app.renderer.width,
height: this.app.renderer.height
};
}
executeInGLContext(A) {
A(this.gl);
}
}
class iA {
constructor(t = !0) {
g(this, "startTime");
g(this, "oldTime");
g(this, "elapsedTime");
g(this, "running");
this.startTime = 0, this.oldTime = 0, this.elapsedTime = 0, this.running = !1, t && this.start();
}
start() {
this.startTime = (typeof performance > "u" ? Date : performance).now(), this.oldTime = this.startTime, this.elapsedTime = 0, this.running = !0;
}
stop() {
this.getElapsedTime(), this.running = !1;
}
getElapsedTime() {
return this.getDelta(), this.elapsedTime;
}
getDelta() {
let t = 0;
const A = (typeof performance > "u" ? Date : performance).now();
return this.running && (t = (A - this.oldTime) / 1e3, this.elapsedTime += t, this.oldTime = A), t;
}
get isRunning() {
return this.running;
}
}
class SA {
}
class IA extends SA {
update(t, A, e) {
const i = A * 3, s = A * 3;
e.lives[A] -= t, e.sizes[A] -= t * e.decays[A];
const o = 0.47, n = 1.22, c = Math.PI / 1e4;
let C = -0.5 * o * c * n * e.velocities[s] * e.velocities[s] * e.velocities[s] / Math.abs(e.velocities[s]), B = -0.5 * o * c * n * e.velocities[s + 2] * e.velocities[s + 2] * e.velocities[s + 2] / Math.abs(e.velocities[s + 2]), Q = -0.5 * o * c * n * e.velocities[s + 1] * e.velocities[s + 1] * e.velocities[s + 1] / Math.abs(e.velocities[s + 1]);
C = isNaN(C) ? 0 : C, Q = isNaN(Q) ? 0 : Q, B = isNaN(B) ? 0 : B;
const P = C / e.masses[A], I = e.gravities[A] + Q / e.masses[A], v = B / e.masses[A];
e.velocities[s] += P * t, e.velocities[s + 1] += I * t, e.velocities[s + 2] += v * t, e.positions[i] += e.velocities[s] * t * 100, e.positions[i + 1] += e.velocities[s + 1] * t * 100, e.positions[i + 2] += e.velocities[s + 2] * t * 100;
}
reset(t, A) {
const e = t * 3, i = t * 3, s = t * 3;
A.positions[e] = 0, A.positions[e + 1] = 0, A.positions[e + 2] = 0, A.velocities[i] = 0, A.velocities[i + 1] = 0, A.velocities[i + 2] = 0, A.masses[t] = 1, A.aliveStatus[t] = 0, A.sizes[t] = 0, A.decays[t] = 0, A.lives[t] = 0, A.gravities[t] = -9.82, A.colors[s] = 1, A.colors[s + 1] = 1, A.colors[s + 2] = 1;
}
}
class vA {
}
function sA() {
return typeof SharedArrayBuffer < "u" && self.crossOriginIsolated;
}
class UA extends vA {
constructor(A) {
super();
g(this, "current");
g(this, "positions");
g(this, "velocities");
g(this, "sizes");
g(this, "masses");
g(this, "decays");
g(this, "lives");
g(this, "gravities");
g(this, "aliveStatus");
g(this, "colors");
g(this, "isActionTriggeredCallbacks");
g(this, "actions");
g(this, "persistentEffects");
g(this, "physics");
this.particlesCount = A, this.current = 0, this.isActionTriggeredCallbacks = /* @__PURE__ */ new Map(), this.actions = /* @__PURE__ */ new Map(), this.persistentEffects = /* @__PURE__ */ new Map(), this.physics = new IA();
const e = sA();
console.log(`Ininializing buffer: ${e ? "SharedArrayBuffer" : "ArrayBuffer"}`);
const i = e ? SharedArrayBuffer : ArrayBuffer;
this.positions = new Float32Array(new i(A * 3 * 4)), this.velocities = new Float32Array(new i(A * 3 * 4)), this.sizes = new Float32Array(new i(A * 4)), this.masses = new Float32Array(new i(A * 4)), this.decays = new Float32Array(new i(A * 4)), this.lives = new Float32Array(new i(A * 4)), this.gravities = new Float32Array(new i(A * 4)), this.aliveStatus = new Uint8Array(new i(A)), this.colors = new Float32Array(new i(A * 3 * 4)), this.initPool();
}
get data() {
return {
positions: this.positions,
colors: this.colors,
sizes: this.sizes,
velocities: this.velocities,
masses: this.masses,
decays: this.decays,
lives: this.lives,
gravities: this.gravities,
aliveStatus: this.aliveStatus
};
}
initPool() {
for (let A = 0; A < this.particlesCount; A++)
this.reset(A);
}
add(A) {
return this.current++, this.current === this.particlesCount && (this.current = 0), this.updateParticle(this.current, {
alive: !0,
x: A.x,
y: A.y,
z: A.z,
vx: A.vx || 0,
vy: A.vy || 0,
vz: A.vz || 0,
mass: A.mass || 1,
size: A.size || 1,
decay: A.decay || 10,
life: A.life || 1,
gravity: A.gravity || -9.82,
r: A.r || 1,
g: A.g || 1,
b: A.b || 1,
isActionTriggered: A.isActionTriggered || (() => !1),
action: A.action || (() => {
}),
persistentEffect: A.persistentEffect || (() => {
})
}), this.current;
}
getParticle(A) {
const e = A * 3, i = A * 3, s = A * 3;
return {
x: this.positions[e],
y: this.positions[e + 1],
z: this.positions[e + 2],
vx: this.velocities[i],
vy: this.velocities[i + 1],
vz: this.velocities[i + 2],
mass: this.masses[A],
alive: this.aliveStatus[A] === 1,
size: this.sizes[A],
r: this.colors[s],
g: this.colors[s + 1],
b: this.colors[s + 2],
decay: this.decays[A],
life: this.lives[A],
gravity: this.gravities[A]
};
}
getParticleCallbacks(A) {
return {
isActionTriggered: this.isActionTriggeredCallbacks.get(A) || (() => !1),
action: this.actions.get(A) || (() => {
}),
persistentEffect: this.persistentEffects.get(A) || (() => {
})
};
}
updateParticle(A, e) {
const i = A * 3, s = A * 3, o = A * 3;
e.x !== void 0 && (this.positions[i] = e.x), e.y !== void 0 && (this.positions[i + 1] = e.y), e.z !== void 0 && (this.positions[i + 2] = e.z), e.vx !== void 0 && (this.velocities[s] = e.vx), e.vy !== void 0 && (this.velocities[s + 1] = e.vy), e.vz !== void 0 && (this.velocities[s + 2] = e.vz), e.mass !== void 0 && (this.masses[A] = e.mass), e.alive !== void 0 && (this.aliveStatus[A] = e.alive ? 1 : 0), e.size !== void 0 && (this.sizes[A] = e.size), e.r !== void 0 && (this.colors[o] = e.r), e.g !== void 0 && (this.colors[o + 1] = e.g), e.b !== void 0 && (this.colors[o + 2] = e.b), e.decay !== void 0 && (this.decays[A] = e.decay), e.life !== void 0 && (this.lives[A] = e.life), e.gravity !== void 0 && (this.gravities[A] = e.gravity), e.isActionTriggered !== void 0 && this.isActionTriggeredCallbacks.set(A, e.isActionTriggered), e.action !== void 0 && this.actions.set(A, e.action), e.persistentEffect !== void 0 && this.persistentEffects.set(A, e.persistentEffect);
}
update(A, e) {
this.physics.update(A, e, this);
}
reset(A) {
this.physics.reset(A, this), this.isActionTriggeredCallbacks.set(A, () => !1), this.actions.set(A, () => {
}), this.persistentEffects.set(A, () => {
});
}
launchEffects(A, e, i) {
const s = this.getParticle(i), o = this.getParticleCallbacks(i);
o.isActionTriggered(s, A, e) && (o.action(s, A, e), this.reset(i)), o.persistentEffect(s, A, e), (this.lives[i] <= 0 || this.sizes[i] <= 0) && this.reset(i);
}
cleanup() {
this.positions = null, this.velocities = null, this.sizes = null, this.masses = null, this.decays = null, this.lives = null, this.gravities = null, this.aliveStatus = null, this.colors = null, this.isActionTriggeredCallbacks.clear(), this.actions.clear(), this.persistentEffects.clear();
}
}
class PA {
constructor({
particleSystem: t,
particlesCount: A,
spawnFramespan: e
}) {
g(this, "_isActive", !0);
// TODO: должно быть доступно только из партикл эффекта/воркера
g(this, "_activeParticlesCount", 0);
g(this, "pool");
g(this, "particleSystem");
// TODO: должно быть доступно только из партикл эффекта/воркера
g(this, "spawnFramespan");
g(this, "timer");
g(this, "particlesCount");
g(this, "frameDelta", 0);
g(this, "spawnCounter", 0);
this.particlesCount = A, this.pool = new UA(this.particlesCount), this.timer = new iA(!1), this.particleSystem = t, this.spawnFramespan = e;
}
get data() {
return this.pool.data;
}
set data(t) {
Object.entries(t).forEach(([A, e]) => {
e && (this.pool[A] = e);
});
}
async update(t, A) {
if (!this.timer.isRunning) return Promise.resolve();
const e = A ? A.time : Date.now() * 1e-3;
for (this.frameDelta += A ? A.delta : this.timer.getDelta(), this.spawnFramespan && (this.spawnCounter += 1, this.spawnCounter > this.spawnFramespan && (this.particleSystem.launch(this.pool), this.spawnCounter = 0)); this.frameDelta >= 1 / tA; )
await t.updateParticles(this, e), this.launchParticleEffects(this.frameDelta, e), this.frameDelta -= 1 / tA;
}
updateParticles(t) {
this._activeParticlesCount = 0;
for (let A = 0; A < this.particlesCount; A++) {
const e = this.pool.getParticle(A);
e.alive && (this.pool.update(this.frameDelta, A), e.alive && this._activeParticlesCount++);
}
}
launchParticleEffects(t, A) {
for (let e = 0; e < this.particlesCount; e++)
this.pool.getParticle(e).alive && this.pool.launchEffects(this.frameDelta, A, e);
}
start() {
this.timer.start();
}
stop() {
this.timer.stop();
}
// defines if effect is visible
get isActive() {
return this._isActive;
}
set isActive(t) {
if (this._isActive = t, t) {
this.start();
return;
}
this.stop();
}
get activeParticlesCount() {
return this._activeParticlesCount;
}
get settings() {
return this.particleSystem.settings;
}
cleanup() {
this.pool.cleanup();
}
}
class wA {
constructor({
gl: t,
shaderProgram: A,
elementsCount: e
}) {
g(this, "gl");
g(this, "shaderProgram");
g(this, "elementsCount");
g(this, "vertexBuffers", /* @__PURE__ */ new Map());
g(this, "indexBufferConfig", null);
g(this, "textures", /* @__PURE__ */ new Map());
this.gl = t, this.shaderProgram = A, this.elementsCount = e;
}
createVertexBuffer({
name: t,
getData: A,
attributeConfig: e,
usage: i = this.gl.STATIC_DRAW
}) {
const s = this.gl.createBuffer();
if (!s) throw new Error("Failed to create vertex buffer");
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, s), this.gl.bufferData(this.gl.ARRAY_BUFFER, A(), i), this.vertexBuffers.set(t, {
buffer: s,
getData: A,
attributeConfig: e,
usage: i
});
}
createVertexBuffers(t) {
t.forEach(({
name: A,
getData: e,
attributeConfig: i,
usage: s = this.gl.STATIC_DRAW
}) => {
this.createVertexBuffer({
name: A,
getData: e,
attributeConfig: i,
usage: s
});
});
}
createIndexBuffer({
data: t,
usage: A = this.gl.STATIC_DRAW
}) {
const e = this.gl.createBuffer();
if (!e) throw new Error("Failed to create index buffer");
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, e), this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, t, A), this.indexBufferConfig = {
buffer: e,
data: t,
usage: A
};
}
enableVertexBuffer(t) {
if (!this.shaderProgram.program) throw new Error("Shader program not found");
const A = this.vertexBuffers.get(t);
if (!A) throw new Error(`Vertex buffer ${t} not found`);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, A.buffer), this.gl.bufferData(this.gl.ARRAY_BUFFER, A.getData(), A.usage);
const e = this.gl.getAttribLocation(this.shaderProgram.program, t);
if (e === -1) {
console.log(`Attribute ${t} not found. Skipping...`);
return;
}
this.gl.enableVertexAttribArray(e), this.gl.vertexAttribPointer(
e,
A.attributeConfig.size,
A.attributeConfig.type,
A.attributeConfig.normalized,
A.attributeConfig.stride,
A.attributeConfig.offset
);
}
enableAllVertexBuffers() {
this.vertexBuffers.forEach((t, A) => {
this.enableVertexBuffer(A);
});
}
enableIndexBuffer() {
this.indexBufferConfig && (this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.indexBufferConfig.buffer), this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this.indexBufferConfig.data, this.indexBufferConfig.usage));
}
createTexture({
name: t,
unit: A,
source: e = null,
width: i = 1,
height: s = 1
}) {
const o = this.gl.createTexture();
if (!o) throw new Error("Failed to create texture");
this.gl.activeTexture(this.gl.TEXTURE0 + A), this.gl.bindTexture(this.gl.TEXTURE_2D, o), e ? this.gl.texImage2D(
this.gl.TEXTURE_2D,
0,
this.gl.RGBA,
this.gl.RGBA,
this.gl.UNSIGNED_BYTE,
e
) : this.gl.texImage2D(
this.gl.TEXTURE_2D,
0,
this.gl.RGBA,
i,
s,
0,
this.gl.RGBA,
this.gl.UNSIGNED_BYTE,
new Uint8Array([255, 255, 255, 255])
), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR), this.textures.set(t, {
texture: o,
unit: A
});
}
bindTextures() {
this.textures.forEach(({ texture: t, unit: A }, e) => {
this.gl.activeTexture(this.gl.TEXTURE0 + A), this.gl.bindTexture(this.gl.TEXTURE_2D, t), this.shaderProgram.setInt(e, A);
});
}
disableAllVertexBuffers() {
this.vertexBuffers.forEach((t, A) => {
const e = this.gl.getAttribLocation(this.shaderProgram.program, A);
e !== -1 && this.gl.disableVertexAttribArray(e);
});
}
disableIndexBuffer() {
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null);
}
disableTextures() {
this.textures.forEach(({ unit: t }) => {
this.gl.activeTexture(this.gl.TEXTURE0 + t), this.gl.bindTexture(this.gl.TEXTURE_2D, null);
});
}
dispose() {
this.vertexBuffers.forEach((t) => this.gl.deleteBuffer(t)), this.indexBufferConfig && this.gl.deleteBuffer(this.indexBufferConfig.buffer), this.textures.forEach(({ texture: t }) => this.gl.deleteTexture(t));
}
get hasIndexBuffer() {
return this.indexBufferConfig !== null;
}
get program() {
return this.shaderProgram;
}
}
class MA {
constructor(t) {
g(this, "_adapter");
t && this.setAdapter(t);
}
get adapter() {
return this._adapter;
}
setAdapter(t) {
console.log("Renderer adapter has been set"), this._adapter = t;
}
render(t) {
if (!this.adapter) throw new Error("Register adapter before rendering");
this.adapter.executeInGLContext((A) => {
t.shaderProgram.use(), t.shaderProgram.updateUniforms(this.adapter), this.draw({
gl: A,
renderData: t
}), t.shaderProgram.disable();
});
}
draw({
gl: t,
renderData: A
}) {
A.bindTextures(), A.enableAllVertexBuffers(), A.hasIndexBuffer ? (A.enableIndexBuffer(), t.drawElements(t.TRIANGLES, A.elementsCount, t.UNSIGNED_SHORT, 0), A.disableIndexBuffer()) : t.drawArrays(t.POINTS, 0, A.elementsCount), A.disableAllVertexBuffers(), A.disableTextures();
}
}
var h, m, L, p, N, X, W, z, b, M;
class dA {
constructor(t, A, e) {
k(this, h, null);
k(this, m, null);
k(this, L, null);
k(this, p, /* @__PURE__ */ new Map());
k(this, N);
k(this, X, () => {
u(this, m, this.glContext.createShader(this.glContext.VERTEX_SHADER)), u(this, L, this.glContext.createShader(this.glContext.FRAGMENT_SHADER));
});
k(this, W, () => {
if (!a(this, m))
throw new Error("Vertex shader not found");
if (!a(this, L))
throw new Error("Fragment shader not found");
if (this.glContext.shaderSource(a(this, m), this.vertexShaderSource), this.glContext.shaderSource(a(this, L), this.fragmentShaderSource), this.glContext.compileShader(a(this, m)), !this.glContext.getShaderParameter(a(this, m), this.glContext.COMPILE_STATUS)) {
console.error(
"ERROR compiling vertex shader!",
this.glContext.getShaderInfoLog(a(this, m))
);
return;
}
if (this.glContext.compileShader(a(this, L)), !this.glContext.getShaderParameter(a(this, L), this.glContext.COMPILE_STATUS)) {
console.error(
"ERROR compiling fragment shader!",
this.glContext.getShaderInfoLog(a(this, L))
);
return;
}
});
k(this, z, () => {
if (!a(this, m))
throw new Error("Vertex shader not found");
if (!a(this, L))
throw new Error("Fragment shader not found");
if (u(this, h, this.glContext.createProgram()), !a(this, h))
throw new Error("Error creating gl program");
if (this.glContext.attachShader(a(this, h), a(this, m)), this.glContext.attachShader(a(this, h), a(this, L)), this.glContext.linkProgram(a(this, h)), !this.glContext.getProgramParameter(a(this, h), this.glContext.LINK_STATUS)) {
console.error("ERROR linking program!", this.glContext.getProgramInfoLog(a(this, h)));
return;
}
if (this.glContext.validateProgram(a(this, h)), !this.glContext.getProgramParameter(a(this, h), this.glContext.VALIDATE_STATUS)) {
console.error("ERROR validating program!", this.glContext.getProgramInfoLog(a(this, h)));
return;
}
});
k(this, b, () => {
if (!a(this, h))
throw new Error("Program not found");
const t = this.glContext.getProgramParameter(
a(this, h),
this.glContext.ACTIVE_UNIFORMS
);
for (let A = 0; A < t; A++) {
const e = this.glContext.getActiveUniform(a(this, h), A);
if (!e) continue;
const i = this.glContext.getUniformLocation(
a(this, h),
e.name
);
if (i) {
const s = e.name.replace(/\[.*?\]/, "");
a(this, p).set(s, i);
}
}
});
k(this, M, (t) => {
if (!a(this, h)) throw new Error("Shader program not defined");
const A = a(this, p).get(t);
if (A) return A;
const e = this.glContext.getUniformLocation(a(this, h), t);
if (e === -1 || e === null) throw new Error(`Uniform '${t}' not found or optimized out`);
return a(this, p).set(t, e), e;
});
g(this, "setMat4", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniformMatrix4fv(e, !1, A);
});
g(this, "setMat3", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniformMatrix3fv(e, !1, A);
});
g(this, "setMat2", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniformMatrix2fv(e, !1, A);
});
g(this, "setInt", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform1i(e, A);
});
g(this, "setFloat", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform1f(e, A);
});
g(this, "setVec2", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform2fv(e, A);
});
g(this, "setVec3", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform3fv(e, A);
});
g(this, "setVec4", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform4fv(e, A);
});
g(this, "setIntArray", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform1iv(e, A);
});
g(this, "setFloatArray", (t, A) => {
const e = a(this, M).call(this, t);
this.glContext.uniform1fv(e, A);
});
this.vertexShaderSource = t, this.fragmentShaderSource = A, this.glContext = e, a(this, X).call(this), a(this, W).call(this), a(this, z).call(this), this.use(), a(this, b).call(this);
}
setUniformsManager(t) {
u(this, N, t);
}
updateUniforms(t) {
var A;
(A = a(this, N)) == null || A.updateUniforms({
adapter: t,
shader: this
});
}
get program() {
return a(this, h);
}
use() {
this.glContext.useProgram(a(this, h));
}
disable() {
this.glContext.useProgram(null);
}
cleanup() {
a(this, h) && (this.glContext.deleteProgram(a(this, h)), u(this, h, null)), a(this, p).clear();
}
}
h = new WeakMap(), m = new WeakMap(), L = new WeakMap(), p = new WeakMap(), N = new WeakMap(), X = new WeakMap(), W = new WeakMap(), z = new WeakMap(), b = new WeakMap(), M = new WeakMap();
class O {
}
class V {
}
class DA extends V {
constructor(t = [0, 0, 0], A = 20, e = 10, i = 10, s = [1, 0, 0]) {
super(), this.origin = t, this.minParticleSize = A, this.maxParticleSize = e, this.maxParticleSizeStep = i, this.color = s;
}
}
class kA extends O {
constructor() {
super(...arguments);
g(this, "settings", new DA());
}
shellEffect(A, e, i, s, o, n) {
let c = 1, C = 0, B = 0;
switch (s) {
case 1:
c = Math.random() * 30;
break;
case 2:
o.updateParticle(n, {
x: A.x + Math.cos(Math.PI * 2 * i) * Math.random() * 3,
z: A.z + Math.sin(Math.PI * 2 * i) * Math.random() * 3
});
break;
case 3:
o.updateParticle(n, { size: Math.random() > 0.5 ? 150 : 10 }), c = Math.random() * 10, C = 2 - Math.random() * 4, B = 2 - Math.random() * 4;
break;
}
for (let Q = 0; Q < c; Q++)
o.add({
x: A.x,
y: A.y,
z: A.z,
mass: 2e-3,
gravity: -0.2,
size: 20 + Math.random() * 40,
vx: C,
vz: B,
r: 1,
g: 0,
b: 0,
life: Math.random() * 3,
decay: 50
});
}
crackleEffect(A, e, i, s, o, n) {
let c = 0, C = 0, B = 0;
switch (s) {
case 1:
break;
case 2:
break;
case 3:
c = o[0] * 2, C = o[1] * 2, B = o[2];
break;
}
for (let Q = 0; Q < 10 + Math.random() * 150; Q++) {
const P = Math.random() * 80, I = -0.2, v = 1 - Math.random() * 2, D = 1 - Math.random() * 2, S = 1 - Math.random() * 2, U = 0.1 + Math.random() * 2;
Math.random() > 0.5 && s === 2 && (c = o[0], C = o[1], B = o[2]), n.add({
x: A.x,
y: A.y,
z: A.z,
size: P,
mass: 0.02,
gravity: I,
r: c,
g: C,
b: B,
vy: v,
vx: D,
vz: S,
life: U,
decay: Math.random() * 50
});
}
}
explodeEffect(A, e, i, s, o) {
for (let n = 0; n < 100 + Math.random() * 200; n++) {
const c = Math.random() * 80, C = -0.5, B = 1 - Math.random() * 2, Q = 1 - Math.random() * 2, P = 1 - Math.random() * 2, I = 0.1 + Math.random();
o.add({
x: A.x,
y: A.y,
z: A.z,
size: c,
mass: 0.5,
gravity: C,
vy: B,
vx: Q,
vz: P,
life: I,
decay: Math.random() * 50
});
}
}
flairEffect(A, e, i, s, o, n, c, C) {
let B = 1, Q = 0, P = 0;
switch (s) {
case 1:
c.updateParticle(C, { size: Math.random() > 0.5 ? 250 : 10 });
break;
case 2:
A.vy < 0 && c.updateParticle(C, {
x: A.x + Math.cos(Math.PI * 2 * i) * Math.random() * 3,
z: A.z + Math.sin(Math.PI * 2 * i) * Math.random() * 3
});
break;
case 3:
c.updateParticle(C, { size: Math.random() > 0.5 ? 150 : 10 }), Math.random() > 0.5 && c.updateParticle(C, {
r: o[0],
g: o[1],
b: o[2]
});
break;
}
n > 250 && A.life < 1 && Math.random() < 0.05 && (this.crackleEffect(A, e, i, s, o, c), c.reset(C)), c.add({
x: A.x,
y: A.y,
z: A.z,
mass: 2e-3,
gravity: -0.2,
size: 20 + Math.random() * 40,
r: B,
g: Q,
b: P,
life: Math.random() * 3,
decay: 50
});
}
launch(A) {
const e = this.settings.origin, i = this.settings.color, s = this.settings.minParticleSize + Math.random() * Math.min(350, this.settings.maxParticleSize);
this.settings.maxParticleSize += this.settings.maxParticleSizeStep;
const o = Math.random() * 4 | 0, n = A.add({
x: e[0],
y: e[1],
z: e[2],
size: s,
mass: 0.5,
vz: 0,
vx: 0,
vy: 10 + Math.min(s / 30, 7),
r: i[0],
g: i[1],
b: i[2],
life: 20,
decay: 10 + Math.random() * 20,
isActionTriggered: (c) => c.vy <= -Math.random() * 20,
action: (c, C, B) => {
this.explodeEffect(c, C, B, o, A);
const Q = -0.1 - Math.random() * 2, P = 1 + Math.random() * 6, I = 2 + Math.random() * 2, v = 2 / s, D = Math.PI * (3 - Math.sqrt(5));
for (let S = 0; S < s; S++) {
let U, w, d;
switch (o) {
case 1:
w = Math.abs(S * v - 1 + v / 2);
const G = Math.sqrt(1 - Math.pow(w, 2)), y = (S + 1) % s * D;
U = Math.cos(y) * G, d = Math.sin(y) * G, U *= I, w *= I, d *= I;
break;
case 2:
w = 1 + Math.random() * 2, U = Math.sin(S * Math.PI * 2 * I) * (2 - Math.random() * 4), d = Math.sin(S * Math.PI * 2 * I) * (2 - Math.random() * 4);
break;
default:
w = S * v - 1 + v / 2;
const H = Math.sqrt(1 - Math.pow(w, 2)), Z = (S + 1) % s * D;
U = Math.cos(Z) * H, d = Math.sin(Z) * H, U *= I, w *= I, d *= I;
break;
}
const x = A.add({
x: c.x,
y: c.y,
z: c.z,
size: s,
mass: 1e-3,
gravity: Q,
vy: w,
vz: d,
vx: U,
r: i[0],
g: i[1],
b: i[2],
life: 0.5 + Math.random() * P,
decay: Math.random() * 100
});
A.updateParticle(x, {
persistentEffect: (G, y, H) => {
this.flairEffect(G, y, H, o, i, s, A, x);
}
});
}
}
});
A.updateParticle(n, {
persistentEffect: (c, C, B) => {
this.shellEffect(c, C, B, o, A, n);
}
});
}
}
const R = () => Math.random() < 0.5 ? -1 : 1;
class mA extends V {
constructor(t = [0, 0, 0], A = 10, e = 10, i = f.fromValues(1, 1, 1)) {
super(), this.origin = t, this.maxParticleSize = A, this.maxParticleVelocity = e, this.color = i;
}
}
const T = {
x: {
min: 5,
max: 20
},
y: {
min: 5,
max: 20
},
z: {
min: 5,
max: 20
}
};
class LA extends O {
constructor() {
super(...arguments);
g(this, "settings", new mA());
}
launch(A) {
const e = this.settings.origin;
for (let i = 0; i < 100; i++) {
const s = A.add({
persistentEffect: function(o, n, c) {
o.vz += Math.sin(c * Math.random()) * 0.02, o.vx += Math.sin(c * Math.random()) * 0.02;
},
x: e[0] + T.x.min + R() * Math.random() * (T.x.max - T.x.min),
y: e[1] + T.y.min + R() * Math.random() * (T.y.max - T.y.min),
z: e[2] + T.z.min + R() * Math.random() * (T.z.max - T.z.min),
mass: 2e-3,
gravity: Math.random(),
size: 20 + Math.random() * 100,
r: this.settings.color[0],
g: this.settings.color[1],
b: this.settings.color[2],
life: Math.random() * 5,
decay: 20 + Math.random() * 20
});
A.updateParticle(s, {
persistentEffect: (o, n, c) => {
}
});
}
}
}
class GA extends V {
constructor(t = [0, 0, 0], A = 10, e = 10, i = [1, 0, 0]) {
super(), this.origin = t, this.maxParticleSize = A, this.maxParticleVelocity = e, this.color = i;
}
}
const l = {
size: {
min: 20,
max: 120
},
life: {
min: 0,
max: 5
},
decay: {
min: 20,
max: 60
},
color: [0.2, 0.2, 0.2],
mass: 2e-3,
x: {
min: 5,
max: 30
},
y: {
min: 5,
max: 30
},
z: {
min: 10,
max: 30
}
};
class TA extends O {
constructor() {
super(...arguments);
g(this, "settings", new GA());
}
launch(A) {
for (let e = 0; e < 100; e++)
A.add({
persistentEffect: (i, s, o) => {
i.vz += Math.sin(o * Math.random()) * 0.07, i.vx += Math.sin(o * Math.random()) * 0.07;
},
x: this.settings.origin[0] + l.x.min + R() * Math.random() * (l.x.max - l.x.min),
y: this.settings.origin[1] + l.y.min + R() * Math.random() * (l.y.max - l.y.min),
z: this.settings.origin[2] + l.z.min + R() * Math.random() * (l.z.max - l.z.min),
mass: l.mass,
gravity: Math.random(),
size: l.size.min + Math.random() * (l.size.max - l.size.min),
r: l.color[0],
g: l.color[1],
b: l.color[2],
life: l.life.min + Math.random() * (l.life.max - l.life.min),
decay: l.decay.min + Math.random() * (l.decay.max - l.decay.min)
});
}
}
const rA = (r) => r.min + Math.random() * (r.max - r.min);
class xA extends V {
constructor(t = [0, 0, 0], A = 10, e = 10, i = [1, 0, 0]) {
super(), this.origin = t, this.maxParticleSize = A, this.maxParticleVelocity = e, this.color = i;
}
}
const pA = {
decay: {
min: 20,
max: 60
}
}, yA = () => rA(pA.decay);
class uA extends O {
constructor() {
super(...arguments);
g(this, "settings", new xA());
g(this, "maxSize", 10);
}
flairEffect(A, e, i, s, o, n, c) {
Math.random() > 0.5 && (A.size = A.size * 0.5), Math.random() > 0.25 && (A.size = A.size * 0.5), o < 5 && A.life < 1 && Math.random() < 0.5 && n.reset(c), n.add({
x: A.x,
y: A.y,
z: A.z,
vy: A.vy * 0.5,
vx: A.vx * 0.5,
vz: A.vz * 0.5,
mass: A.mass * 0.5,
gravity: A.gravity * 0.5,
size: A.size * 0.5,
r: this.settings.color[0],
g: this.settings.color[1],
b: this.settings.color[2],
life: Math.random(),
decay: 1
});
}
launch(A) {
const e = Math.random() * 4 | 0, i = 20 + Math.random() * Math.min(5, this.maxSize);
this.maxSize += 10;
for (let o = 0; o < 300 * (1 + Math.random()); o++) {
const n = gA.randomPointOnCircle(2), c = rA({
min: 2.5,
max: 3.5
}), C = 0.25 * i * (1 + Math.random()), B = A.add({
x: this.settings.origin[0],
y: this.settings.origin[1],
z: this.settings.origin[2],
size: i,
mass: 0.2,
gravity: -0.9,
vx: n[0],
vy: c,
vz: n[1],
r: this.settings.color[0],
g: this.settings.color[1],
b: this.settings.color[2],
life: Math.random(),
decay: 1
});
A.updateParticle(B, {
persistentEffect: (Q, P, I) => {
this.flairEffect(Q, P, I, e, C * 0.5, A, B);
}
});
}
const s = A.add({
x: this.settings.origin[0],
y: this.settings.origin[1],
z: this.settings.origin[2],
size: i,
mass: 1,
vz: 0,
vx: 0,
vy: 10 + Math.min(i * 0.1, 7),
r: this.settings.color[0],
g: this.settings.color[1],
b: this.settings.color[2],
life: 10,
decay: yA()
});
A.updateParticle(s, {
persistentEffect: (o, n, c) => {
const C = -0.1 - Math.random() * 2, B = 2 + Math.random() * 2, Q = 2 / i, P = Math.PI * (3 - Math.sqrt(5)), I = 1 + Math.random() * 2;
for (let v = 0; v < i; v++) {
let D, S, U;
switch (e) {
case 1:
S = Math.abs(v * Q - 1 + Q / 2);
const w = Math.sqrt(1 - Math.pow(S, 2)), d = (v + 1) % i * P;
D = Math.cos(d) * w, U = Math.sin(d) * w, D *= B, S *= B, U *= B;
break;
case 2:
S = 1 + Math.random() * 2, D = Math.sin(v * Math.PI * 2 * B) * (2 - Math.random() * 4), U = Math.sin(v * Math.PI * 2 * B) * (2 - Math.random() * 4);
break;
default:
S = v * Q - 1 + Q / 2;
const x = Math.sqrt(1 - Math.pow(S, 2)), G = (v + 1) % i * P;
D = Math.cos(G) * x, U = Math.sin(G) * x, D *= B, S *= B, U *= B;
break;
}
if (Math.random() < 0.4) {
const w = 0.5 * i * (1 + Math.random()), d = A.add({
x: o.x,
y: o.y,
z: o.z,
size: w,
mass: 1e-3,
gravity: C,
vy: S,
vz: U * 0.5,
vx: D * 0.5,
r: this.settings.color[0],
g: this.settings.color[1],
b: this.settings.color[2],
life: 0.1 + Math.random() * I * 0.5,
decay: Math.random() * 100
});
A.updateParticle(d, {
persistentEffect: (x, G, y) => {
this.flairEffect(x, G, y, e, w * 0.5, A, d);
}
});
}
}
}
});
}
}
const JA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAACPWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8ZXhpZjpVc2VyQ29tbWVudD4KICAgICAgICAgICAgPHJkZjpBbHQ+CiAgICAgICAgICAgICAgIDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+Q3JlYXRlZCB3aXRoIEdJTVA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QWx0PgogICAgICAgICA8L2V4aWY6VXNlckNvbW1lbnQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZvVQyAAAPd0lEQVR4Ae2aS28cSXLHIzPr0U+SelACbcIrDGQMQJ8M7WVPq6uBvcpfZ6jPww/gq+y7MCcLsC0MfJChHVEi2exHvfLhX1SPpBkNJJFNzlyWBRarujorM+Mf/4iMiGyRm+MGgRsEbhC4QeAGgRsEbhC4QeAGgRsEbhD4G0TA/J4yp5SMGIZM6QvD9k1oSksjX2r4hT4u/pW9eNOrtTw8PNSxjBweKuicz5w8f571V+6f6/0znsmh6YH6cL3auF97+zdlwFoQpnB0ZOXJN1ZevrEv+fgwGxoZ3nZvz+ZrBdwRuaszTV167adxr5lH/Sire1EODgJ3/Wcoce2MQAO/zZF6jR8B8K55+c8TN34tbm/7D3bn5NTInYGd/3icDXYKOzHOLCMn08BC0h7CnmdljL6JO7tvvLyaBdkvvMgPEekjHV4rCL8JA1JSuv8Zje87GRxbGdlcKpMvC5OPTWbrLmZigzNd4ups1/meCXmeRclDlKoLKTc+trGLpfhJOWqllk5Oh14Z8fTp0/Tdd9+l62DEtQOwpj22/LJyMv37TPLKLU7DYHIrL5tVHBiedMHkRWGtBAAw0dVNwvZFMhdj5nLfRe+5dgkIaNENXN5IF9uTpW9vjzMvewDx7E2Ux4/DVUG4VgB6zT9D8w8kk0mez7tB6VrJnW1GpihHxvuxsbYIKZbOWBdsykxILsTYM8BZG5MzAYvvnHEtMjeZsU3qpEri6pBMFbLQNouuvVt2HeNgGv8ejTlc+4wNrPnaAOg1r1783j0ru1KIrwaS4vA8xkEW4gSNj0XsJEoaOGtKiJ6zzKkPYt2LJqBL9QI9CAm6m9RCi1VnpHLJLuB7VZi0XDVNPdraqqR918ms6uThECe5OQjX4gTXmn+21vwYoUIzRNhR69J0aOMoWrMVxUyMxCkebMj9wBrJkR3S49f4oBSw1iQAUi+HU7BNlLDiuuI6AOBVF/ESmV1Vi5X1dlpPt1Xl+5wHfK0u4fKrxJUZ8MHhyT379r9Oy3KrK6eyPZZSxr72O8GkKUJuM7lximnKbIdoeYCGAd/2tq9iqPaVxz0QBgeYUgsQlUXzBEVzvl9iKDOXwiLGfBZTWLahW67ys2Zv7y8Nr2IKlwfgSgzoaS+61O274xev8mHhBhOZDttQb4U6m+LnbhkTtm0yt+D5OAKGSWaAYCXaZ+y4BgDJ0X6/xKkQQOHF2Ja7IW0bAsIBzBih9tzYrLDRG+PE5tHEYTNJL1/+W/j++wX+QDRmuNRxJQD6kZ7tGvl25opJlrssDlppRya3Y9v6Kfa77STbxsp3EBgTsBM0WUDyAkcHEYyF7z3/ETRhCfjHiK+TDibgJ62LKRZ8dsCTJ4t3TGBlTeDV6Mq8zZdZmE7b7smTbyBNujQLrmQCDGjlxYvsdFANS7cauXy4FUK7hTXeya3ZRtBdTHMHQW4j3wTtT+A4tr9mQO8EEUjdn0Eg2vsYYgsLatq3PGwiXLeC948Rc0gz2s2wlXfJ2FOb0tvg06x1YbZ0Rb2390MjT18kc3jxVWFjAHr6a/x+v2Utd6Pa+omL+a3g/HYKadcke8s6dxdb32HCtxFujCAThBsAwoiBS1SZYxr9EggPMATTeB9aFElgqMFhqqLAd7GVxFTDhHPAPOeFd4x/Bl2OWVFOfdOeNqFZ3frm7yoR4gNWBTGHNP961LiRCfTCC/H9nV13Ug/zQdmVmbVDb8KYAG+C0FPj7Bbjb+PAtow1U3zcFNpuEf5oLDDhLIl8CjUEsUyjX/9TRyDYiPcLCX7uuzDHf9TYP4qnnWAe6iyT6TAXfGKqvRAvwJg8lv7166rb27vnj44O0hMm2WeeX/EIGwGw7hPbJ6HJumVmEQSrLNEmzioOFQwoO8ZWR2i87LUu+AXMgsh3iuCYAsKXRSZFjmBqFZm6AZxY58U3I6nqIU8ypD1HVkwDgRB2DUIc87nD6Mc2dath7go/KrK9NOzZ9OTJC9pejNybA/B8auQPc9RiMuOZQIoDPoxQ6Ai7HQPGCKNmRoklz4xUcExiW5ybIvSIK8KXrAIDhNez4GTe4qNkVSFTAFpUxnTeWO9ZFYA2JpRtaRRa3meVMMPgI2CH0s2bAlfr5H/vWHnwHf3o+XUQesRoefnj0VxnKxOLu3OEtM4QpLgcrQxU64xNpGdUrTlsVBaM8N8jAmOon2WwgLEV/598Yg8C8ZMArGzzcDKW4WBL8mwC60eAWNBn/wID5oRMhUt8ax3hdM74hZNl634c/jegPruwXBduqML+4lAGuIGt2sgEEN5kOSwtcemqygLNZ2hMn2nIWxjnBmh+IGWZS47mLTUBGdFUhSYs+HjwvETQ6YD+x4g4BThdPmESaCE0woO6hgGmYJGgb5+3rs4WmXfuDF+rc7vgsSkARh4NzTmImza4jqQmJJ+baDMYgOCsBWQveG5wYHnHgyEEeWDuxOEqPmhbhVf6/+rQNswNIPJsALswL6dUcThYogE9uWcsViA9XYmNce0Ff/6r7j7/YHMf8LIwW0NnakQjk4F2CJgF+iO8tThoXLXG+EwS8VnqICsAINSAh6p5JcrXhsdJWkyG00QAThibOn+NmHvhNe8IWR9PkEjjJuzdO63c/XZtnp8X++M3mzKAHv6n76UxLQIxBYxcNQASrHrcU91R6bWREgAG0C7jVAYoAF8TXt9Ujapm6RY4VfP0iPAAigHSM65U2zBe6e14Ys3JmY5x8eMKAIhmKL8gcAgazjMZ5vjTAf8tSxu66V28Pr+I4O9f16vGM4j78+ND9z9/uL4n5LzU8YWuvtzPy5++TmWRcOoJp46QqnGVNa6VrtlZIkFJkSIHFYD+y8tkbET+LH70S9BH3xqBGTxNAlDtV+MGiiiZc3zO4pJGsoP3ucSxMQAP5R9lOiUwI0ZhHoTkOAJrPE8QmKoO2R1kILExnqm3LO+krFRxqG1dbH6a3FVBfNcK+QErCrEA/QIANqZXDwgETZpFA1KygNTFt7z1/HdYBWDyKyJzSjarvnap0+iAQkNUkhiuOjkiFj4z0YgQoRbfAsISzRHQffVYoMnKS9M0lAgbPhAE0Z+yiGhY++4BQfgOZjSkCkoUeSfy6Kt9f2xwWYP8+OaD/SRnizgInjA1R7O+c3nR9NmclRbL7SA7pS2qPsTs1odzU7cDGVW4sxk2PWVsXep+Yd/IGfjuHPAWnazqpTTdHN+ygPq1Akt6rBz3ONqWqglgI7syRIzfjlmY7IyjfHtCk4sdGwLwVOTFQTop/iEWUxdybzz5gHK7wwxbzJVSgPUUNIiDyNHFttHGufO+kIpq8ZAqsO2IfoashcRM/eqgc1Zm1DCkaqSuV9K25whHLmAWqmQaAoDWCkzLMtsCQm2Tq0zR1RYinDVtXMCQ/aPjJE8uBsAvvevF3ul9EeGm+/HHthx2U1Ias0WJd5sCzS4TvI3nv4fGdlgLbwEKqa9hgaIUlrlt7m8RExC1uxHJ0IB7lKBhMTgFH6QlGWq7FXY/x62chhDO6UMpo+WxOcxaMYFTgD4Dsr/iEN+QeB2XpWVRGi/kGBQPDjCXiznbDRmgSB2n+9VuOPHWZ6Vvcfvk7mnFpCh5pRXUpPDpiJOSRgFEa3jFqHVAwsMWhrgwwnyH0rJpsl4bAYDVwgcoHVZQXZ36HNqvYFIDqA3MamACGZKhf1nhZypCgjo5HKVnvyCwi3Twp0vtFWwEgKKr1JZ3z8Pt+203N3kDG6nwlgvnbIaoA5M0RCVJQmJ8tGbzvKC+S5rAvpeNFEa8p3ROfP++PI7JYO9Q267QdI3TQ9sGx2moDKuXkyX0n7OqnNN07pNZEHqtgnO1ZL6Vv25jPutBdKCLHChns0NBOPrhhyj722E6TN2QMnUmUSe6IvxfkAUwSaOx0pKgkEqN2rBRTdaEb+rUZkplhD/BLN7iPN9iPm9h0gmCn/P9EnBq2vQnbSiRmyXAL/EsS1KDeZbcMpquHtdd+7o5ZtvsPxWASx0b+YD3IzAZ3n9GSEqGd2LzVSwmIwlT9jVvo9ctCH2HBluYxC3iggkCjEmM+oyOLK4PZdFmH8vSpl/fqISu13gNcgCMxIq8H81bxylnlMzOYcI7KHUWAcsv/WIxmi3uvyIJePSIcvHFbP+9DBuZwPuX19fHzOclEcAqjCK2SAGT0GxhfaQqplliHx/2BS+cJKsVtQHSZqIZzeYAgSd9uEuuRGFUAyh8RQ8CPqAhASIGSIuA1nn/nGxgRtEchoRFaNqqM10znwf/H7DxX//4R0a73HElABRtNkYY9M9B5rB8Z6thP1CmbAW1LPx4Z00IiY8MaSK1PZYu0hh2eSiTrfcEKHure9RsGaB6LLT2pVEe6z31QEy65sGcAvkC0pyxb04ZKjvDXy4JgKqqXLQPH/zFP3x4Odt/D9OVTOB9Jx93hx5kcrxab40lGbU2TEPXjaArO0OYhBZIqRjhClkhNHmHAescvs8d6I+soTesDjT6nSFcaE0CTHE0Lpx1M8qEy6L0i3mT1fXpvN492CcI+57A6cml9wR0/ldiwHsAdHeWaSd+4iLymF91HBPj+AqXTnROZMN2FqX7VJvcrdArZXEKqJgABGLfNOr+GGbAf5WdSgLCd2KJ8jAnxlAzWLDeL4mrFwOHY1x0dT2sullRdbvyCl/BXsAlbf/D3N/fXMd1vUnK9vhjmPC2yecnr0tbUP2TwYAi+NB3VImdoYQVKaMTAPH7gKBlJOLl9fiWjMezQ5x1hAtdR4k8M7GpW6nyMlXsmFa+atudctrKni55KvzmO8M65rWYwM/B6wms2+SP2SZ/NXPH502/bZYN8sIFXxpXag2xoLCbmxJsVHh8d98HL7MrkigwegJDn3zDb0jKLjTzNmRlu5WPG5n/n5eH/wLlj3hFNX/YBxc/n8Nl7jeOAz43SE9Ffrnx9OmRl/0/tbsH02aVD5t2Ma8HMV+W0c2LXGbRxRlRzxmJ9Gkw3Unen+6EsvpJkeWnvl3NWFPmA5xdG6fVFltfcr9rj9aboAitNn814VWGa2fAp8D0jNBdpBf/5F5tzdw+eyiSsV2QkRRhD2dnZx9e2dnm5wOJZA9HcfymS7u3pvEVO2X759D9p1+LbWrrHwb55ObaGfBJ/xBcA5Mn8enRkd+HEbKHg5sVnPNGzs5qto0/nP2z23d4fr/dxcFpW31H36Xfjbz8p/P59PNvzoBPBzzk53P8wovHT/u/T7/vN3TW//Srjb37r/r9zIPfHYBeqj6EZuhPR/8Qx61vrpvun8Hg5vENAjcI3CBwg8ANAn+rCPw/MQ8vhEXqLmYAAAAASUVORK5CYII=", RA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABEUlEQVR4AYyQA0x3ARTF78fsMc52bjbzvGb2nxHGMBvZtm3bbsg1NWd3Oi/j6W6/ncvzIG+B9L8W0QnO/fSGHsj7c0v10dnJ0ho4oU5KsCpAg1SzdlPZ+U9OFVUz2MS8AMdkUcB6l3h92wlBvYAapGZgjxopwIqAS2WsHVV2EjEloMZrfYbn6z/wVp33yCQOBeiWcb0faflWW5MItMkAjgS4IDRh3c9+JLHSMwsjB+gQYJuckztFX2v2OT8k0Xom/0g4WqUbB6/HVKV+7nMuZgMdMox9gaKGy3ROVenFYligqNFxONoE1JhvfW8U/oKiesfJaBHgaTfhgdSBJr+bGOf7Ql0QhUXODkQTY0gzAz0BAIZEz3uin06+AAAAAElFTkSuQmCC", jA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC+UlEQVR4AWLYuKaA4aKlfv3DnJT/d1Ni/h9KcY3ftLaob8eWiuu7d9b8AGFA19QAK1kWBV+wNoJlsLZt28Hadms8823btm3b1mt8N7/dTu09dz1JKqmUHi/j06SRRxnKUoe6fGDhrZex9vwTiPviRTzz9B146eX7kJV/FGptBkde0XG8+NK9ePaZO5D49ctYfeFJUIcPjN53q4v+yYfQ6fcxpLJ3MKfLxcZ+P3z8j8PiMHL4B50ijXsSlunw/wTUoa6guec29MvexuBwKHrFWhyJncHROBGidpGV9QTiTBeZPsMzlKUOdYXJB25EV5sPdKtlOJU0CZvNyeGSNMXKizAznGL8b50yurVydLIOdYX2Y+9pZycSsL/bC48UDd564y0Od8YtDg54pP5f39/pgWYqAe3H3tUKIwWHjVu90bAtNbMBNT758BN8/MHHPGhziAQa+FdPVsM234CtwXgMFB/TC9pshcOcLoO1IRIu4Z38Ni0WOzKl/liS/8yRxThp/NECW2CtDIK58CQ0pafswlrSL05z8OcwR34LZVk8jkaN4Uj0AFQvvYCdF9/BzgtvQ/XqSzjOtENhwxATvcDzUd9hKf+oVVjKkK4dxP8Ec6YClt4YWHUV2DRVY8r7R2iuv4XA+aa2HJaZbFgqPGBO+BkHmXIo848sC72ZkozVOm/s9UTCeO3lMD15B4zxCqg7IzDSF8UQzbkxVgbT47fBeM1l2GsPwUqTPzpypMlCXa7krvEmH4dBTIbh0Vuw4+WKjW8+h/aOG6C58mICcdLI4xnjdBLGmn0dtbnSO/mvXJUnjx4fDMVCjQd07Apb8t9gGemDfW+DQJw07i3UemJiMAxV+fLof85CWd7vZ9YWH24Y7Q+CusMXi9++CO3NV0J/wVkcxElTd/pidCAItSWHG6nz7wAfkZxZmSuL7G71dI4PhUCcjIRajIF6JoZz0npavZyVebJYlj2Hd/4d+BfluZLbWCi0ufqk2NXkYWPYY3ySjYcy7/bT838AJXrAbNyQa+QAAAAASUVORK5CYII=", FA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABPElEQVR4AWKgGvA88Z8tHFDrWKhKAUVR9P6J8z36A9I2aSsNdgeN3UoZhB2Er7uLmu7unllvNpOv+8KGwzlrbe4wBw+P8+7aAlMvbYS/uCkrmrXTTYzYJfKBAfadn2F+IAyuDCSKUKhAtarUZ+10EyO25lha8sVZbHMJqFTZ8IkRK0cl5sQEti8BGEvCUAIcOYiVIF+h9fQD7XQTI1aOXHNqGgYS8CkIr3wwnmrnX0xZuhMjVo5cY/5gPzYPD93w2ANdDUHAM289mrXTTYzYowsg15ifWMxvbKYfzDQ89dXhD/46rGjW7rmvzhixv2uyXL1WSR+YQbjrgcuupbnvqd/ELJX1lpdMwi33kmi3jrxKyQ03PPUrmjcjLyvZPwvfIvVo3pS8pOQPtndueO+B2rx5eXnJtuQlJcpevkUJ+gRZqjyc2QAAAABJRU5ErkJggg==", NA = "data:image/png;base64,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