UNPKG

mondlich

Version:
1,216 lines 379 kB
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,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", 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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