@rosalana/sandbox 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -1,9 +1,9 @@
1
- var D = Object.defineProperty;
2
- var N = (u, e, n) => e in u ? D(u, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : u[e] = n;
3
- var a = (u, e, n) => N(u, typeof e != "symbol" ? e + "" : e, n);
4
- class x {
5
- constructor(e, n, t, i) {
6
- this.target = e, this.type = n, this.listener = t, this.options = i, this.target.addEventListener(
1
+ var B = Object.defineProperty;
2
+ var N = (u, e, t) => e in u ? B(u, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[e] = t;
3
+ var a = (u, e, t) => N(u, typeof e != "symbol" ? e + "" : e, t);
4
+ class y {
5
+ constructor(e, t, n, i) {
6
+ this.target = e, this.type = t, this.listener = n, this.options = i, this.target.addEventListener(
7
7
  this.type,
8
8
  this.listener,
9
9
  this.options
@@ -16,23 +16,23 @@ class x {
16
16
  this.options
17
17
  );
18
18
  }
19
- static on(e, n, t, i) {
20
- return e.addEventListener(n, t, i), () => e.removeEventListener(n, t, i);
19
+ static on(e, t, n, i) {
20
+ return e.addEventListener(t, n, i), () => e.removeEventListener(t, n, i);
21
21
  }
22
22
  }
23
23
  class h extends Error {
24
- constructor(n, t) {
25
- super(n);
24
+ constructor(t, n) {
25
+ super(t);
26
26
  a(this, "name", "SandboxError");
27
- this.code = t;
27
+ this.code = n;
28
28
  }
29
29
  }
30
- class z extends h {
30
+ class G extends h {
31
31
  constructor() {
32
32
  super("WebGL is not supported in this browser.", "CONTEXT_ERROR");
33
33
  }
34
34
  }
35
- class de extends h {
35
+ class pe extends h {
36
36
  constructor() {
37
37
  super(
38
38
  "Failed to create WebGL context. The GPU may be unavailable.",
@@ -40,35 +40,35 @@ class de extends h {
40
40
  );
41
41
  }
42
42
  }
43
- class G extends h {
44
- constructor(e, n) {
43
+ class W extends h {
44
+ constructor(e, t) {
45
45
  super(
46
- `Vertex and fragment shader WebGL versions do not match (${e} vs ${n})`,
46
+ `Vertex and fragment shader WebGL versions do not match (${e} vs ${t})`,
47
47
  "VALIDATION_ERROR"
48
- ), this.vertexVersion = e, this.fragmentVersion = n;
48
+ ), this.vertexVersion = e, this.fragmentVersion = t;
49
49
  }
50
50
  }
51
51
  class _ extends h {
52
- constructor(n, t, i) {
52
+ constructor(t, n, i) {
53
53
  const r = _.parseErrorLines(i), s = r.length > 0 ? ` at line(s): ${r.join(", ")}` : "";
54
54
  super(
55
- `${n} shader compilation failed${s}
55
+ `${t} shader compilation failed${s}
56
56
 
57
57
  ${i}`,
58
58
  "SHADER_ERROR"
59
59
  );
60
60
  a(this, "lines");
61
- this.shaderType = n, this.source = t, this.infoLog = i, this.lines = r;
61
+ this.shaderType = t, this.source = n, this.infoLog = i, this.lines = r;
62
62
  }
63
- static parseErrorLines(n) {
64
- const t = [
63
+ static parseErrorLines(t) {
64
+ const n = [
65
65
  /ERROR:\s*\d*:(\d+)/g,
66
66
  /(\d+):(\d+)\(\d+\):/g,
67
67
  /^(\d+):/gm
68
68
  ], i = /* @__PURE__ */ new Set();
69
- for (const r of t) {
69
+ for (const r of n) {
70
70
  let s;
71
- for (; (s = r.exec(n)) !== null; ) {
71
+ for (; (s = r.exec(t)) !== null; ) {
72
72
  const o = parseInt(s[1], 10);
73
73
  o > 0 && i.add(o);
74
74
  }
@@ -76,33 +76,33 @@ ${i}`,
76
76
  return [...i].sort((r, s) => r - s);
77
77
  }
78
78
  }
79
- class C extends h {
80
- constructor(e, n, t, i) {
79
+ class T extends h {
80
+ constructor(e, t, n, i) {
81
81
  super(
82
- `The shader ${e} "${n}" has type "${i}" but expected "${t}"`,
82
+ `The shader ${e} "${t}" has type "${i}" but expected "${n}"`,
83
83
  "SHADER_ERROR"
84
- ), this.requirement = e, this.name = n, this.expectedType = t, this.actualType = i;
84
+ ), this.requirement = e, this.name = t, this.expectedType = n, this.actualType = i;
85
85
  }
86
86
  }
87
- class W extends h {
87
+ class z extends h {
88
88
  constructor() {
89
89
  super("Shader source does not contain any function.", "SHADER_ERROR");
90
90
  }
91
91
  }
92
- class q extends h {
93
- constructor(e, n) {
92
+ class H extends h {
93
+ constructor(e, t) {
94
94
  super(
95
- `Syntax error in shader import statement at line ${e}: ${n}`,
95
+ `Syntax error in shader import statement at line ${e}: ${t}`,
96
96
  "SHADER_ERROR"
97
- ), this.line = e, this.details = n;
97
+ ), this.line = e, this.details = t;
98
98
  }
99
99
  }
100
- class H extends h {
101
- constructor(e, n) {
100
+ class q extends h {
101
+ constructor(e, t) {
102
102
  super(
103
- `Duplicate import name "${e}" found at line ${n}. Each import must have a unique name.`,
103
+ `Duplicate import name "${e}" found at line ${t}. Each import must have a unique name.`,
104
104
  "SHADER_ERROR"
105
- ), this.name = e, this.line = n;
105
+ ), this.name = e, this.line = t;
106
106
  }
107
107
  }
108
108
  class j extends h {
@@ -113,15 +113,15 @@ class j extends h {
113
113
  ), this.moduleName = e;
114
114
  }
115
115
  }
116
- class Y extends h {
117
- constructor(e, n) {
116
+ class X extends h {
117
+ constructor(e, t) {
118
118
  super(
119
- `Method '${n}' not found in shader module '${e}'. Check if the method is defined in the module source code or if the name is correct.`,
119
+ `Method '${t}' not found in shader module '${e}'. Check if the method is defined in the module source code or if the name is correct.`,
120
120
  "MODULE_ERROR"
121
- ), this.moduleName = e, this.methodName = n;
121
+ ), this.moduleName = e, this.methodName = t;
122
122
  }
123
123
  }
124
- class K extends h {
124
+ class Y extends h {
125
125
  constructor(e) {
126
126
  super(
127
127
  `Importing 'main' function from module '${e}' is forbidden.`,
@@ -129,7 +129,7 @@ class K extends h {
129
129
  ), this.moduleName = e;
130
130
  }
131
131
  }
132
- class X extends h {
132
+ class K extends h {
133
133
  constructor(e) {
134
134
  super(
135
135
  `Name 'default' is reserved and cannot be used as a function name in module '${e}'.`,
@@ -154,27 +154,27 @@ class J extends h {
154
154
  }
155
155
  }
156
156
  class Z extends h {
157
- constructor(e, n, t) {
157
+ constructor(e, t, n) {
158
158
  super(
159
- `Uniform '${t}' mentioned for function '${n}' of module '${e}' was not found among the module's declared uniforms. Check if the uniform is declared in the module source code or if the name is correct.`,
159
+ `Uniform '${n}' mentioned for function '${t}' of module '${e}' was not found among the module's declared uniforms. Check if the uniform is declared in the module source code or if the name is correct.`,
160
160
  "MODULE_ERROR"
161
- ), this.moduleName = e, this.functionName = n, this.uniformName = t;
161
+ ), this.moduleName = e, this.functionName = t, this.uniformName = n;
162
162
  }
163
163
  }
164
164
  class ee extends h {
165
- constructor(e, n) {
165
+ constructor(e, t) {
166
166
  super(
167
- `Uniform '${n}' mentioned for function '${e}' was not imported from any module. Check if the function is imported from the correct module and if the uniform is declared in that module's source code with the correct name.`,
167
+ `Uniform '${t}' mentioned for function '${e}' was not imported from any module. Check if the function is imported from the correct module and if the uniform is declared in that module's source code with the correct name.`,
168
168
  "MODULE_ERROR"
169
- ), this.functionName = e, this.uniformName = n;
169
+ ), this.functionName = e, this.uniformName = t;
170
170
  }
171
171
  }
172
- class ne extends h {
173
- constructor(e, n) {
172
+ class te extends h {
173
+ constructor(e, t) {
174
174
  super(
175
- `Mention '${e}' called in function '${n}' could not be replaced with the corresponding uniform reference. There might be an issue with the compilation process because the referenced uniform was not found among the shader requirements. Try use a different name for uniforms you want to mention in functions or check if the uniform is properly declared and mentioned in the module source code.`,
175
+ `Mention '${e}' called in function '${t}' could not be replaced with the corresponding uniform reference. There might be an issue with the compilation process because the referenced uniform was not found among the shader requirements. Try use a different name for uniforms you want to mention in functions or check if the uniform is properly declared and mentioned in the module source code.`,
176
176
  "MODULE_ERROR"
177
- ), this.mentionName = e, this.calledInFunction = n;
177
+ ), this.mentionName = e, this.calledInFunction = t;
178
178
  }
179
179
  }
180
180
  class R extends h {
@@ -184,14 +184,34 @@ class R extends h {
184
184
  ${e}`, "PROGRAM_ERROR"), this.infoLog = e;
185
185
  }
186
186
  }
187
- class te extends h {
187
+ class ve extends h {
188
+ constructor(t) {
189
+ super(
190
+ `Failed to create WebGL texture for "${t}".`,
191
+ "TEXTURE_ERROR"
192
+ );
193
+ a(this, "name", "SandboxTextureCreationError");
194
+ this.textureName = t;
195
+ }
196
+ }
197
+ class ge extends h {
198
+ constructor(t, n) {
199
+ super(
200
+ `Cannot bind texture "${t}": all ${n} texture units are in use.`,
201
+ "TEXTURE_ERROR"
202
+ );
203
+ a(this, "name", "SandboxTextureUnitLimitError");
204
+ this.textureName = t, this.maxUnits = n;
205
+ }
206
+ }
207
+ class ne extends h {
188
208
  constructor(e) {
189
209
  super(`Error in onLoad callback: ${e}`, "UNKNOWN_ERROR");
190
210
  }
191
211
  }
192
212
  class ie extends h {
193
- constructor(e, n) {
194
- super(`Error in onBefore/onAfter hook callback with ID ${e}: ${n}`, "UNKNOWN_ERROR");
213
+ constructor(e, t) {
214
+ super(`Error in onBefore/onAfter hook callback with ID ${e}: ${t}`, "UNKNOWN_ERROR");
195
215
  }
196
216
  }
197
217
  class re {
@@ -219,8 +239,8 @@ class re {
219
239
  start(e) {
220
240
  if (this.running) return this;
221
241
  this.callback = e, this.running = !0;
222
- const n = performance.now();
223
- return this.frame === 0 ? this.startTime = n : this.startTime = n - this.time * 1e3, this.lastTime = n, this.rafId = requestAnimationFrame(this.loop), this;
242
+ const t = performance.now();
243
+ return this.frame === 0 ? this.startTime = t : this.startTime = t - this.time * 1e3, this.lastTime = t, this.rafId = requestAnimationFrame(this.loop), this;
224
244
  }
225
245
  /**
226
246
  * Stop the animation loop.
@@ -278,15 +298,15 @@ class re {
278
298
  loop(e) {
279
299
  if (!this.running) return;
280
300
  if (this.maxFps > 0) {
281
- const t = 1e3 / this.maxFps;
282
- if (e - this.lastTime < t) {
301
+ const n = 1e3 / this.maxFps;
302
+ if (e - this.lastTime < n) {
283
303
  this.rafId = requestAnimationFrame(this.loop);
284
304
  return;
285
305
  }
286
306
  }
287
307
  this.delta = (e - this.lastTime) / 1e3, this.lastTime = e;
288
- const n = this.delta > 0 ? 1 / this.delta : 0;
289
- this.fps = this.fps * 0.95 + n * 0.05, this.time = (e - this.startTime) / 1e3, this.frame++, this.callback && this.callback(this.getState()), this.rafId = requestAnimationFrame(this.loop);
308
+ const t = this.delta > 0 ? 1 / this.delta : 0;
309
+ this.fps = this.fps * 0.95 + t * 0.05, this.time = (e - this.startTime) / 1e3, this.frame++, this.callback && this.callback(this.getState()), this.rafId = requestAnimationFrame(this.loop);
290
310
  }
291
311
  }
292
312
  class A {
@@ -308,7 +328,7 @@ class A {
308
328
  * This is the most common use case for shader effects.
309
329
  */
310
330
  static fullscreenQuad(e) {
311
- const n = new A(e), t = new Float32Array([
331
+ const t = new A(e), n = new Float32Array([
312
332
  // position texcoord
313
333
  -1,
314
334
  -1,
@@ -340,33 +360,33 @@ class A {
340
360
  3
341
361
  // second triangle
342
362
  ]);
343
- return n.setup(t, i), n;
363
+ return t.setup(n, i), t;
344
364
  }
345
365
  /**
346
366
  * Setup geometry from vertex and index data.
347
367
  */
348
- setup(e, n) {
349
- const t = this.gl;
350
- return this.createVAO(), this.bindVAO(), this.vbo = t.createBuffer(), t.bindBuffer(t.ARRAY_BUFFER, this.vbo), t.bufferData(t.ARRAY_BUFFER, e, t.STATIC_DRAW), this.vertexCount = e.length / 4, n && (this.ibo = t.createBuffer(), t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.ibo), t.bufferData(t.ELEMENT_ARRAY_BUFFER, n, t.STATIC_DRAW), this.indexCount = n.length, this.useIndices = !0), this.unbindVAO(), this;
368
+ setup(e, t) {
369
+ const n = this.gl;
370
+ return this.createVAO(), this.bindVAO(), this.vbo = n.createBuffer(), n.bindBuffer(n.ARRAY_BUFFER, this.vbo), n.bufferData(n.ARRAY_BUFFER, e, n.STATIC_DRAW), this.vertexCount = e.length / 4, t && (this.ibo = n.createBuffer(), n.bindBuffer(n.ELEMENT_ARRAY_BUFFER, this.ibo), n.bufferData(n.ELEMENT_ARRAY_BUFFER, t, n.STATIC_DRAW), this.indexCount = t.length, this.useIndices = !0), this.unbindVAO(), this;
351
371
  }
352
372
  /**
353
373
  * Link vertex attributes to shader program.
354
374
  * Call this after compiling shaders.
355
375
  */
356
376
  linkAttributes(e) {
357
- const n = this.gl;
358
- this.bindVAO(), n.bindBuffer(n.ARRAY_BUFFER, this.vbo);
359
- const t = 4 * Float32Array.BYTES_PER_ELEMENT, i = this.getPositionLocation(e);
360
- i >= 0 && (n.enableVertexAttribArray(i), n.vertexAttribPointer(i, 2, n.FLOAT, !1, t, 0));
377
+ const t = this.gl;
378
+ this.bindVAO(), t.bindBuffer(t.ARRAY_BUFFER, this.vbo);
379
+ const n = 4 * Float32Array.BYTES_PER_ELEMENT, i = this.getPositionLocation(e);
380
+ i >= 0 && (t.enableVertexAttribArray(i), t.vertexAttribPointer(i, 2, t.FLOAT, !1, n, 0));
361
381
  const r = this.getTexcoordLocation(e);
362
- return r >= 0 && (n.enableVertexAttribArray(r), n.vertexAttribPointer(
382
+ return r >= 0 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(
363
383
  r,
364
384
  2,
365
- n.FLOAT,
385
+ t.FLOAT,
366
386
  !1,
367
- t,
387
+ n,
368
388
  2 * Float32Array.BYTES_PER_ELEMENT
369
- )), this.useIndices && n.bindBuffer(n.ELEMENT_ARRAY_BUFFER, this.ibo), this.unbindVAO(), this;
389
+ )), this.useIndices && t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.ibo), this.unbindVAO(), this;
370
390
  }
371
391
  /**
372
392
  * Bind geometry for rendering.
@@ -399,16 +419,16 @@ class A {
399
419
  * Tries common naming conventions.
400
420
  */
401
421
  getPositionLocation(e) {
402
- let n = e.getAttribLocation("a_position");
403
- return n >= 0 || (n = e.getAttribLocation("aPosition"), n >= 0) || (n = e.getAttribLocation("position"), n >= 0) ? n : -1;
422
+ let t = e.getAttribLocation("a_position");
423
+ return t >= 0 || (t = e.getAttribLocation("aPosition"), t >= 0) || (t = e.getAttribLocation("position"), t >= 0) ? t : -1;
404
424
  }
405
425
  /**
406
426
  * Get texcoord attribute location.
407
427
  * Tries common naming conventions.
408
428
  */
409
429
  getTexcoordLocation(e) {
410
- let n = e.getAttribLocation("a_texcoord");
411
- return n >= 0 || (n = e.getAttribLocation("aTexCoord"), n >= 0) || (n = e.getAttribLocation("texcoord"), n >= 0) || (n = e.getAttribLocation("a_uv"), n >= 0) ? n : -1;
430
+ let t = e.getAttribLocation("a_texcoord");
431
+ return t >= 0 || (t = e.getAttribLocation("aTexCoord"), t >= 0) || (t = e.getAttribLocation("texcoord"), t >= 0) || (t = e.getAttribLocation("a_uv"), t >= 0) ? t : -1;
412
432
  }
413
433
  // ============================================================================
414
434
  // VAO helpers (handle WebGL1 vs WebGL2 differences)
@@ -439,8 +459,8 @@ class se {
439
459
  * @throws ShaderCompilationError if compilation fails
440
460
  * @throws ProgramLinkError if linking fails
441
461
  */
442
- compile(e, n) {
443
- return this.destroy(), this.vertexShader = this.compileShader("vertex", e), this.fragmentShader = this.compileShader("fragment", n), this.linkProgram(), this;
462
+ compile(e, t) {
463
+ return this.destroy(), this.vertexShader = this.compileShader("vertex", e), this.fragmentShader = this.compileShader("fragment", t), this.linkProgram(), this;
444
464
  }
445
465
  /**
446
466
  * Bind this program for rendering.
@@ -477,17 +497,17 @@ class se {
477
497
  * Compile a single shader.
478
498
  * @throws ShaderCompilationError if compilation fails
479
499
  */
480
- compileShader(e, n) {
481
- const t = this.gl, i = e === "vertex" ? t.VERTEX_SHADER : t.FRAGMENT_SHADER, r = t.createShader(i);
500
+ compileShader(e, t) {
501
+ const n = this.gl, i = e === "vertex" ? n.VERTEX_SHADER : n.FRAGMENT_SHADER, r = n.createShader(i);
482
502
  if (!r)
483
503
  throw new _(
484
504
  e,
485
- n,
505
+ t,
486
506
  "Failed to create shader object"
487
507
  );
488
- if (t.shaderSource(r, n), t.compileShader(r), !t.getShaderParameter(r, t.COMPILE_STATUS)) {
489
- const o = t.getShaderInfoLog(r) || "Unknown error";
490
- throw t.deleteShader(r), new _(e, n, o);
508
+ if (n.shaderSource(r, t), n.compileShader(r), !n.getShaderParameter(r, n.COMPILE_STATUS)) {
509
+ const o = n.getShaderInfoLog(r) || "Unknown error";
510
+ throw n.deleteShader(r), new _(e, t, o);
491
511
  }
492
512
  return r;
493
513
  }
@@ -499,18 +519,18 @@ class se {
499
519
  const e = this.gl;
500
520
  if (!this.vertexShader || !this.fragmentShader)
501
521
  throw new R("Shaders not compiled");
502
- const n = e.createProgram();
503
- if (!n)
522
+ const t = e.createProgram();
523
+ if (!t)
504
524
  throw new R("Failed to create program object");
505
- if (e.attachShader(n, this.vertexShader), e.attachShader(n, this.fragmentShader), e.linkProgram(n), !e.getProgramParameter(n, e.LINK_STATUS)) {
506
- const i = e.getProgramInfoLog(n) || "Unknown error";
507
- throw e.deleteProgram(n), new R(i);
525
+ if (e.attachShader(t, this.vertexShader), e.attachShader(t, this.fragmentShader), e.linkProgram(t), !e.getProgramParameter(t, e.LINK_STATUS)) {
526
+ const i = e.getProgramInfoLog(t) || "Unknown error";
527
+ throw e.deleteProgram(t), new R(i);
508
528
  }
509
- this.program = n;
529
+ this.program = t;
510
530
  }
511
531
  }
512
- class k {
513
- constructor(e, n) {
532
+ class M {
533
+ constructor(e, t) {
514
534
  a(this, "name");
515
535
  a(this, "method");
516
536
  a(this, "isArray");
@@ -518,9 +538,9 @@ class k {
518
538
  a(this, "location", null);
519
539
  a(this, "locationResolved", !1);
520
540
  a(this, "value");
521
- this.name = e, this.value = n;
522
- const t = k.inferMethodInfo(n);
523
- this.method = t.method, this.isArray = t.isArray, this.isMatrix = t.isMatrix;
541
+ this.name = e, this.value = t;
542
+ const n = M.inferMethodInfo(t);
543
+ this.method = n.method, this.isArray = n.isArray, this.isMatrix = n.isMatrix;
524
544
  }
525
545
  /**
526
546
  * Infer WebGL method and metadata from value type.
@@ -532,9 +552,9 @@ class k {
532
552
  return { method: "uniform1f", isArray: !1, isMatrix: !1 };
533
553
  if (!Array.isArray(e))
534
554
  return { method: "uniform1f", isArray: !1, isMatrix: !1 };
535
- const n = e.length, t = e[0];
536
- if (Array.isArray(t))
537
- switch (t.length) {
555
+ const t = e.length, n = e[0];
556
+ if (Array.isArray(n))
557
+ switch (n.length) {
538
558
  case 2:
539
559
  return { method: "uniform2fv", isArray: !0, isMatrix: !1 };
540
560
  case 3:
@@ -544,7 +564,7 @@ class k {
544
564
  default:
545
565
  return { method: "uniform1fv", isArray: !0, isMatrix: !1 };
546
566
  }
547
- switch (n) {
567
+ switch (t) {
548
568
  case 2:
549
569
  return { method: "uniform2fv", isArray: !1, isMatrix: !1 };
550
570
  case 3:
@@ -563,8 +583,8 @@ class k {
563
583
  * Resolve and cache uniform location from program.
564
584
  * Returns null if uniform doesn't exist (optimized out by compiler, etc.)
565
585
  */
566
- resolveLocation(e, n) {
567
- return this.locationResolved || (this.location = e.getUniformLocation(n, this.name), this.locationResolved = !0), this.location;
586
+ resolveLocation(e, t) {
587
+ return this.locationResolved || (this.location = e.getUniformLocation(t, this.name), this.locationResolved = !0), this.location;
568
588
  }
569
589
  /**
570
590
  * Invalidate cached location (call when program changes).
@@ -589,9 +609,9 @@ class k {
589
609
  * @param gl - WebGL context
590
610
  * @param program - Current WebGL program (for location resolution)
591
611
  */
592
- upload(e, n) {
593
- const t = this.resolveLocation(e, n);
594
- if (t === null)
612
+ upload(e, t) {
613
+ const n = this.resolveLocation(e, t);
614
+ if (n === null)
595
615
  return;
596
616
  const i = this.value;
597
617
  let r;
@@ -599,31 +619,31 @@ class k {
599
619
  i.flat()
600
620
  ) : r = new Float32Array(i), this.method) {
601
621
  case "uniform1f":
602
- e.uniform1f(t, r);
622
+ e.uniform1f(n, r);
603
623
  break;
604
624
  case "uniform1i":
605
- e.uniform1i(t, r);
625
+ e.uniform1i(n, r);
606
626
  break;
607
627
  case "uniform1fv":
608
- e.uniform1fv(t, r);
628
+ e.uniform1fv(n, r);
609
629
  break;
610
630
  case "uniform2fv":
611
- e.uniform2fv(t, r);
631
+ e.uniform2fv(n, r);
612
632
  break;
613
633
  case "uniform3fv":
614
- e.uniform3fv(t, r);
634
+ e.uniform3fv(n, r);
615
635
  break;
616
636
  case "uniform4fv":
617
- e.uniform4fv(t, r);
637
+ e.uniform4fv(n, r);
618
638
  break;
619
639
  case "uniformMatrix2fv":
620
- e.uniformMatrix2fv(t, !1, r);
640
+ e.uniformMatrix2fv(n, !1, r);
621
641
  break;
622
642
  case "uniformMatrix3fv":
623
- e.uniformMatrix3fv(t, !1, r);
643
+ e.uniformMatrix3fv(n, !1, r);
624
644
  break;
625
645
  case "uniformMatrix4fv":
626
- e.uniformMatrix4fv(t, !1, r);
646
+ e.uniformMatrix4fv(n, !1, r);
627
647
  break;
628
648
  }
629
649
  }
@@ -638,11 +658,11 @@ class w {
638
658
  */
639
659
  parse() {
640
660
  if (this.parsed) return this.parsed;
641
- const e = this.detectVersion(), n = this.detectImports(), t = this.detectUniforms(), i = this.detectFunctions(t);
661
+ const e = this.detectVersion(), t = this.detectImports(), n = this.detectUniforms(), i = this.detectFunctions(n);
642
662
  return this.parsed = {
643
663
  version: e,
644
- imports: n,
645
- uniforms: t,
664
+ imports: t,
665
+ uniforms: n,
646
666
  functions: i
647
667
  };
648
668
  }
@@ -668,32 +688,32 @@ class w {
668
688
  return /^\s*#version\s+300\s+es/m.test(this.source) ? 2 : 1;
669
689
  }
670
690
  detectImports() {
671
- const e = /^[ \t]*#import\s+(\w+)(?:\s+as\s+(\w+))?\s+from\s+["'](.+)["']/gm, n = /^[ \t]*[^\w\s]?import\b/gm, t = [], i = /* @__PURE__ */ new Set();
691
+ const e = /^[ \t]*#import\s+(\w+)(?:\s+as\s+(\w+))?\s+from\s+["'](.+)["']/gm, t = /^[ \t]*[^\w\s]?import\b/gm, n = [], i = /* @__PURE__ */ new Set();
672
692
  let r, s = 1, o = 0;
673
693
  for (; (r = e.exec(this.source)) !== null; ) {
674
694
  s += (this.source.substring(o, r.index).match(/\n/g) || []).length, o = r.index, i.add(s);
675
- const f = r[1], c = r[2] || r[1], m = r[3];
676
- if (t.some((p) => p.alias === c))
677
- throw new H(c, s);
678
- t.push({ name: f, alias: c, module: m, line: s });
695
+ const f = r[1], c = r[2] || r[1], d = r[3];
696
+ if (n.some((m) => m.alias === c))
697
+ throw new q(c, s);
698
+ n.push({ name: f, alias: c, module: d, line: s });
679
699
  }
680
700
  let l;
681
- for (; (l = n.exec(this.source)) !== null; ) {
701
+ for (; (l = t.exec(this.source)) !== null; ) {
682
702
  const f = (this.source.substring(0, l.index).match(/\n/g) || []).length + 1;
683
703
  if (i.has(f)) continue;
684
704
  const c = this.source.split(`
685
705
  `)[f - 1].trim();
686
- throw new q(
706
+ throw new H(
687
707
  f,
688
708
  this.diagnoseImport(c)
689
709
  );
690
710
  }
691
- return t;
711
+ return n;
692
712
  }
693
713
  diagnoseImport(e) {
694
- const n = e.match(/^([^\w\s])import\b/);
695
- if (n && n[1] !== "#")
696
- return `Invalid prefix '${n[1]}'. Expected: #import <function> from '<module>'`;
714
+ const t = e.match(/^([^\w\s])import\b/);
715
+ if (t && t[1] !== "#")
716
+ return `Invalid prefix '${t[1]}'. Expected: #import <function> from '<module>'`;
697
717
  if (/^import\b/.test(e))
698
718
  return "Missing '#' prefix. Expected: #import <function> from '<module>'";
699
719
  if (/^#import\s+from\b/.test(e))
@@ -703,64 +723,64 @@ class w {
703
723
  if (/^#import\s+\w+\s+as\s*$/.test(e) || /^#import\s+\w+\s+as\s+from\b/.test(e))
704
724
  return `Missing alias name after 'as'. Expected: #import ${e.split(/\s+/)[1]} as <alias> from '<module>'`;
705
725
  if (/^#import\s+\w+\s+as\s+\w+\s*$/.test(e)) {
706
- const t = e.split(/\s+/);
707
- return `Missing 'from' clause. Expected: #import ${t[1]} as ${t[3]} from '<module>'`;
726
+ const n = e.split(/\s+/);
727
+ return `Missing 'from' clause. Expected: #import ${n[1]} as ${n[3]} from '<module>'`;
708
728
  }
709
729
  if (/^#import\s+\w+(?:\s+as\s+\w+)?\s+from\s+\w+/.test(e)) {
710
- const t = e.match(/from\s+(\S+)/);
711
- return `Module name must be quoted. Expected: from '${t == null ? void 0 : t[1]}'`;
730
+ const n = e.match(/from\s+(\S+)/);
731
+ return `Module name must be quoted. Expected: from '${n == null ? void 0 : n[1]}'`;
712
732
  }
713
733
  return "Invalid syntax. Expected: #import <function> from '<module>'";
714
734
  }
715
735
  detectUniforms() {
716
- const e = /^[ \t]*uniform\s+(?:(?:highp|mediump|lowp)\s+)?(\w+)\s+(\w+)(?:\[(\d+)\])?\s*;/gm, n = [];
717
- let t, i = 1, r = 0;
718
- for (; (t = e.exec(this.source)) !== null; ) {
719
- i += (this.source.substring(r, t.index).match(/\n/g) || []).length, r = t.index;
720
- const s = t[1], o = t[2], l = t[3] ? parseInt(t[3], 10) : void 0;
721
- n.push({ name: o, type: s, line: i, arrayNum: l });
736
+ const e = /^[ \t]*uniform\s+(?:(?:highp|mediump|lowp)\s+)?(\w+)\s+(\w+)(?:\[(\d+)\])?\s*;/gm, t = [];
737
+ let n, i = 1, r = 0;
738
+ for (; (n = e.exec(this.source)) !== null; ) {
739
+ i += (this.source.substring(r, n.index).match(/\n/g) || []).length, r = n.index;
740
+ const s = n[1], o = n[2], l = n[3] ? parseInt(n[3], 10) : void 0;
741
+ t.push({ name: o, type: s, line: i, arrayNum: l });
722
742
  }
723
- return n;
743
+ return t;
724
744
  }
725
745
  detectFunctions(e) {
726
- const n = [], t = "void|float|int|uint|bool|vec[234]|ivec[234]|uvec[234]|bvec[234]|mat[234](?:x[234])?|sampler2D|samplerCube|sampler3D|sampler2DArray", i = new RegExp(
727
- `^[ \\t]*(${t})\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*\\{`,
746
+ const t = [], n = "void|float|int|uint|bool|vec[234]|ivec[234]|uvec[234]|bvec[234]|mat[234](?:x[234])?|sampler2D|samplerCube|sampler3D|sampler2DArray", i = new RegExp(
747
+ `^[ \\t]*(${n})\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*\\{`,
728
748
  "gm"
729
749
  );
730
750
  let r;
731
751
  for (; (r = i.exec(this.source)) !== null; ) {
732
- const s = r[1], o = r[2], l = r[3].trim(), f = r.index, c = (this.source.substring(0, f).match(/\n/g) || []).length + 1, m = this.source.indexOf("{", f), p = this.findClosingBrace(this.source, m);
733
- if (p === -1) continue;
734
- const g = this.source.slice(m, p + 1), T = this.parseParams(l), I = this.findFunctionCalls(g), P = this.findUniformCalls(g, e), B = this.findMentionCalls(g);
735
- n.push({
752
+ const s = r[1], o = r[2], l = r[3].trim(), f = r.index, c = (this.source.substring(0, f).match(/\n/g) || []).length + 1, d = this.source.indexOf("{", f), m = this.findClosingBrace(this.source, d);
753
+ if (m === -1) continue;
754
+ const v = this.source.slice(d, m + 1), I = this.parseParams(l), P = this.findFunctionCalls(v), $ = this.findUniformCalls(v, e), D = this.findMentionCalls(v);
755
+ t.push({
736
756
  name: o,
737
757
  type: s,
738
- params: T,
739
- body: g,
740
- dependencies: [...I, ...P, ...B],
758
+ params: I,
759
+ body: v,
760
+ dependencies: [...P, ...$, ...D],
741
761
  line: c
742
762
  });
743
763
  }
744
- return n;
764
+ return t;
745
765
  }
746
766
  parseParams(e) {
747
767
  if (!e.trim()) return [];
748
- const n = [], t = e.split(",");
749
- for (const i of t) {
768
+ const t = [], n = e.split(",");
769
+ for (const i of n) {
750
770
  const r = i.trim();
751
771
  if (!r) continue;
752
772
  const o = r.replace(/\b(in|out|inout|const|highp|mediump|lowp)\b\s*/g, "").trim().match(/^(\w+)\s+(\w+)(?:\[\d*\])?$/);
753
- o && n.push({
773
+ o && t.push({
754
774
  type: o[1],
755
775
  name: o[2]
756
776
  });
757
777
  }
758
- return n;
778
+ return t;
759
779
  }
760
- findClosingBrace(e, n) {
761
- let t = 0, i = !1, r = !1, s = !1, o = !1;
762
- for (let l = n; l < e.length; l++) {
763
- const f = e[l], c = e[l + 1], m = e[l - 1];
780
+ findClosingBrace(e, t) {
781
+ let n = 0, i = !1, r = !1, s = !1, o = !1;
782
+ for (let l = t; l < e.length; l++) {
783
+ const f = e[l], c = e[l + 1], d = e[l - 1];
764
784
  if (!r && !o && f === "/" && c === "/") {
765
785
  s = !0;
766
786
  continue;
@@ -779,14 +799,14 @@ class w {
779
799
  continue;
780
800
  }
781
801
  if (!(s || o)) {
782
- if (f === '"' && m !== "\\") {
802
+ if (f === '"' && d !== "\\") {
783
803
  r = !r;
784
804
  continue;
785
805
  }
786
806
  if (!r) {
787
807
  if (f === "{")
788
- t++, i = !0;
789
- else if (f === "}" && (t--, i && t === 0))
808
+ n++, i = !0;
809
+ else if (f === "}" && (n--, i && n === 0))
790
810
  return l;
791
811
  }
792
812
  }
@@ -794,7 +814,7 @@ class w {
794
814
  return -1;
795
815
  }
796
816
  findFunctionCalls(e) {
797
- const n = [], t = /* @__PURE__ */ new Set([
817
+ const t = [], n = /* @__PURE__ */ new Set([
798
818
  "if",
799
819
  "else",
800
820
  "for",
@@ -810,43 +830,43 @@ class w {
810
830
  let r;
811
831
  for (; (r = i.exec(e)) !== null; ) {
812
832
  const s = r[1];
813
- t.has(s) || n.push({
833
+ n.has(s) || t.push({
814
834
  name: s,
815
835
  type: "function",
816
836
  index: r.index
817
837
  });
818
838
  }
819
- return n;
839
+ return t;
820
840
  }
821
- findUniformCalls(e, n) {
822
- const t = [];
823
- for (const i of n) {
841
+ findUniformCalls(e, t) {
842
+ const n = [];
843
+ for (const i of t) {
824
844
  const r = new RegExp(`\\b${i.name}\\b`, "g");
825
845
  let s;
826
846
  for (; (s = r.exec(e)) !== null; )
827
- t.push({
847
+ n.push({
828
848
  name: i.name,
829
849
  type: "uniform",
830
850
  index: s.index
831
851
  });
832
852
  }
833
- return t;
853
+ return n;
834
854
  }
835
855
  findMentionCalls(e) {
836
- const n = [], t = /@(\w+)\.([a-zA-Z_]\w*)/g;
856
+ const t = [], n = /@(\w+)\.([a-zA-Z_]\w*)/g;
837
857
  let i;
838
- for (; (i = t.exec(e)) !== null; ) {
858
+ for (; (i = n.exec(e)) !== null; ) {
839
859
  const r = i[1], s = i[2];
840
- n.push({
860
+ t.push({
841
861
  name: `${r}.${s}`,
842
862
  type: "mention",
843
863
  index: i.index
844
864
  });
845
865
  }
846
- return n;
866
+ return t;
847
867
  }
848
868
  }
849
- class F {
869
+ class C {
850
870
  constructor(e) {
851
871
  /** Flag to track if the shader has been compiled */
852
872
  a(this, "isCompiled", !1);
@@ -883,45 +903,45 @@ class F {
883
903
  /**
884
904
  * Compile the shader source, resolving all imports
885
905
  */
886
- compile() {
887
- return this.isCompiled ? this.compiled.source : (this.original.parse().imports.length > 0 && this.processImports(), this.compiled.setSource(this.build()), this.isCompiled = !0, this.compiled.source);
906
+ compile(e) {
907
+ return this.isCompiled ? this.compiled.source : (this.original.parse().imports.length > 0 && this.processImports(e), this.compiled.setSource(this.build()), this.isCompiled = !0, this.compiled.source);
888
908
  }
889
909
  /**
890
910
  * Process all #import directives
891
911
  */
892
- processImports() {
893
- const e = this.original.parse(), n = e.functions.flatMap((t) => t.dependencies.filter((i) => i.type === "mention").map((i) => ({
894
- name: i.name.split(".")[0],
895
- uniform: i.name.split(".")[1]
912
+ processImports(e) {
913
+ const t = this.original.parse(), n = t.functions.flatMap((i) => i.dependencies.filter((r) => r.type === "mention").map((r) => ({
914
+ name: r.name.split(".")[0],
915
+ uniform: r.name.split(".")[1]
896
916
  })));
897
- for (const t of e.imports) {
898
- const i = b.resolve(t.module), r = i.extract(t.name);
899
- let s = n.filter(
900
- (l) => l.name === r.function.name
917
+ for (const i of t.imports) {
918
+ const r = b.resolve(i.module), s = r.extract(i.name);
919
+ let o = n.filter(
920
+ (f) => f.name === s.function.name
901
921
  );
902
- if (s.length > 0) {
903
- const l = i.getDefinition().uniforms;
904
- if (s = s.filter((f) => {
905
- const c = l.find(
906
- (m) => m.name === `u_${f.uniform}` || m.name === f.uniform
922
+ if (o.length > 0) {
923
+ const f = r.getDefinition().uniforms;
924
+ if (o = o.filter((c) => {
925
+ const d = f.find(
926
+ (m) => m.name === `u_${c.uniform}` || m.name === c.uniform
907
927
  );
908
- if (c) {
909
- r.dependencies.uniforms.some(
910
- (p) => p.name === c.name
911
- ) || r.dependencies.uniforms.push(c);
912
- const m = n.indexOf(f);
928
+ if (d) {
929
+ s.dependencies.uniforms.some(
930
+ (v) => v.name === d.name
931
+ ) || s.dependencies.uniforms.push(d);
932
+ const m = n.indexOf(c);
913
933
  return m > -1 && n.splice(m, 1), !1;
914
934
  }
915
935
  return !0;
916
- }), s.length > 0)
936
+ }), o.length > 0)
917
937
  throw new Z(
918
- t.module,
919
- r.function.name,
920
- s[0].uniform
938
+ i.module,
939
+ s.function.name,
940
+ o[0].uniform
921
941
  );
922
942
  }
923
- const o = i.copy();
924
- this.processExtraction(r, t.alias, o.options), y.merge(t.module, o);
943
+ const l = r.copy();
944
+ this.processExtraction(s, i.alias, l.options), e == null || e.merge(i.module, l);
925
945
  }
926
946
  if (n.length > 0)
927
947
  throw new ee(
@@ -932,17 +952,17 @@ class F {
932
952
  /**
933
953
  * Process an extraction: rewrite names and collect as requirements
934
954
  */
935
- processExtraction(e, n, t = {}) {
936
- const i = e.function, r = Math.random().toString(36).substring(2, 8), s = `${n}_${r}`;
955
+ processExtraction(e, t, n = {}) {
956
+ const i = e.function, r = Math.random().toString(36).substring(2, 8), s = `${t}_${r}`;
937
957
  for (let l = e.dependencies.functions.length - 1; l >= 0; l--) {
938
- const f = e.dependencies.functions[l], c = this.rewriteFunction(f, n, {
958
+ const f = e.dependencies.functions[l], c = this.rewriteFunction(f, t, {
939
959
  uniforms: e.dependencies.uniforms,
940
960
  functions: e.dependencies.functions,
941
961
  unique: s
942
962
  });
943
963
  this.requirements.functions.set(c.name, c);
944
964
  }
945
- const o = this.rewriteFunction(i, n, {
965
+ const o = this.rewriteFunction(i, t, {
946
966
  uniforms: e.dependencies.uniforms,
947
967
  functions: e.dependencies.functions,
948
968
  rename: !0,
@@ -955,21 +975,21 @@ class F {
955
975
  ...l,
956
976
  name: `${s}_${l.name}${l.arrayNum ? `[${l.arrayNum}]` : ""}`
957
977
  };
958
- if (t[i.name]) {
959
- const c = Object.entries(t[i.name]).find(
960
- ([m, p]) => p.uniform === l.name
978
+ if (n[i.name]) {
979
+ const c = Object.entries(n[i.name]).find(
980
+ ([d, m]) => m.uniform === l.name
961
981
  );
962
982
  c && (c[1].uniform = `${s}_${l.name}`);
963
983
  }
964
984
  this.requirements.uniforms.set(f.name, f);
965
985
  }
966
- t[i.name] && n !== i.name && (t[n] = t[i.name], delete t[i.name]);
986
+ n[i.name] && t !== i.name && (n[t] = n[i.name], delete n[i.name]);
967
987
  }
968
988
  /**
969
989
  * Rewrite a function: namespace all uniform and helper function references
970
990
  */
971
- rewriteFunction(e, n, t = { rename: !1, uniforms: [], functions: [], unique: "" }) {
972
- const i = new Set(t.uniforms.map((c) => c.name)), r = new Set(t.functions.map((c) => c.name)), s = [], o = t.unique ? t.unique : n;
991
+ rewriteFunction(e, t, n = { rename: !1, uniforms: [], functions: [], unique: "" }) {
992
+ const i = new Set(n.uniforms.map((c) => c.name)), r = new Set(n.functions.map((c) => c.name)), s = [], o = n.unique ? n.unique : t;
973
993
  for (const c of e.dependencies)
974
994
  if (c.index !== void 0)
975
995
  if (c.type === "uniform" && i.has(c.name)) {
@@ -984,7 +1004,7 @@ class F {
984
1004
  oldText: c.name,
985
1005
  newText: `${o}_${c.name}`
986
1006
  });
987
- const l = this.applyRewrites(e.body, s), f = t.rename ? n : `${o}_${e.name}`;
1007
+ const l = this.applyRewrites(e.body, s), f = n.rename ? t : `${o}_${e.name}`;
988
1008
  return {
989
1009
  ...e,
990
1010
  name: f,
@@ -994,10 +1014,10 @@ class F {
994
1014
  /**
995
1015
  * Apply rewrite operations to a string, processing from end to start
996
1016
  */
997
- applyRewrites(e, n) {
998
- const t = [...n].sort((r, s) => s.index - r.index);
1017
+ applyRewrites(e, t) {
1018
+ const n = [...t].sort((r, s) => s.index - r.index);
999
1019
  let i = e;
1000
- for (const r of t)
1020
+ for (const r of n)
1001
1021
  i = i.slice(0, r.index) + r.newText + i.slice(r.index + r.oldText.length);
1002
1022
  return i;
1003
1023
  }
@@ -1006,46 +1026,46 @@ class F {
1006
1026
  */
1007
1027
  build() {
1008
1028
  const e = this.original.parse();
1009
- let n = this.original.source;
1010
- n = this.removeImportLines(n, e);
1011
- const t = this.findInsertionPointForUniforms(n), i = this.generateUniformsCode();
1012
- i && (n = n.slice(0, t) + i + `
1013
- ` + n.slice(t));
1014
- const r = this.findInsertionPointForFunctions(n), s = this.generateFunctionCode();
1015
- return s && (n = n.slice(0, r) + s + n.slice(r)), n = n.replace(/\n{3,}/g, `
1016
-
1017
- `), n = this.replaceMentions(n, e), n;
1018
- }
1019
- replaceMentions(e, n) {
1020
- let t = e;
1021
- const i = n.functions.filter(
1029
+ let t = this.original.source;
1030
+ t = this.removeImportLines(t, e);
1031
+ const n = this.findInsertionPointForUniforms(t), i = this.generateUniformsCode();
1032
+ i && (t = t.slice(0, n) + i + `
1033
+ ` + t.slice(n));
1034
+ const r = this.findInsertionPointForFunctions(t), s = this.generateFunctionCode();
1035
+ return s && (t = t.slice(0, r) + s + t.slice(r)), t = t.replace(/\n{3,}/g, `
1036
+
1037
+ `), t = this.replaceMentions(t, e), t;
1038
+ }
1039
+ replaceMentions(e, t) {
1040
+ let n = e;
1041
+ const i = t.functions.filter(
1022
1042
  (r) => r.dependencies.some((s) => s.type === "mention")
1023
1043
  );
1024
1044
  for (const r of i) {
1025
1045
  const s = r.dependencies.filter((o) => o.type === "mention");
1026
1046
  for (const o of s) {
1027
- const l = o.name.split("."), f = new RegExp(`\\b${l[0]}_(\\w+)_${l[1]}\\b`, "g"), c = this.requirements.uniforms.keys().find((p) => {
1028
- var g;
1029
- return ((g = p.match(f)) == null ? void 0 : g[0]) === p;
1047
+ const l = o.name.split("."), f = new RegExp(`\\b${l[0]}_(\\w+)_${l[1]}\\b`, "g"), c = this.requirements.uniforms.keys().find((m) => {
1048
+ var v;
1049
+ return ((v = m.match(f)) == null ? void 0 : v[0]) === m;
1030
1050
  });
1031
1051
  if (!c)
1032
- throw new ne(
1052
+ throw new te(
1033
1053
  o.name,
1034
1054
  r.name
1035
1055
  );
1036
- const m = new RegExp(`@\\b${o.name}\\b`, "g");
1037
- t = t.replace(m, c);
1056
+ const d = new RegExp(`@\\b${o.name}\\b`, "g");
1057
+ n = n.replace(d, c);
1038
1058
  }
1039
1059
  }
1040
- return t;
1060
+ return n;
1041
1061
  }
1042
1062
  /**
1043
1063
  * Remove #import lines from shader source
1044
1064
  */
1045
- removeImportLines(e, n) {
1046
- const t = e.split(`
1047
- `), i = new Set(n.imports.map((r) => r.line));
1048
- return t.filter((r, s) => {
1065
+ removeImportLines(e, t) {
1066
+ const n = e.split(`
1067
+ `), i = new Set(t.imports.map((r) => r.line));
1068
+ return n.filter((r, s) => {
1049
1069
  const o = i.has(s + 1);
1050
1070
  if (!o && r.trim() === "" && s > 0) {
1051
1071
  const l = s - 1;
@@ -1060,13 +1080,13 @@ class F {
1060
1080
  * Find insertion point for uniforms (after existing uniforms)
1061
1081
  */
1062
1082
  findInsertionPointForUniforms(e) {
1063
- const n = new w(e).parse(), t = n.uniforms.find(
1064
- (o) => o.line === Math.max(...n.uniforms.map((l) => l.line ?? 0))
1083
+ const t = new w(e).parse(), n = t.uniforms.find(
1084
+ (o) => o.line === Math.max(...t.uniforms.map((l) => l.line ?? 0))
1065
1085
  ), i = e.split(`
1066
1086
  `);
1067
1087
  let r = 0;
1068
- if (t && t.line)
1069
- r = t.line;
1088
+ if (n && n.line)
1089
+ r = n.line;
1070
1090
  else
1071
1091
  for (let o = 0; o < i.length; o++) {
1072
1092
  const l = i[o].trim();
@@ -1090,15 +1110,15 @@ class F {
1090
1110
  return s;
1091
1111
  }
1092
1112
  findInsertionPointForFunctions(e) {
1093
- const n = new w(e).parse(), t = n.functions.find(
1094
- (o) => o.line === Math.min(...n.functions.map((l) => l.line ?? 1 / 0))
1113
+ const t = new w(e).parse(), n = t.functions.find(
1114
+ (o) => o.line === Math.min(...t.functions.map((l) => l.line ?? 1 / 0))
1095
1115
  ), i = e.split(`
1096
1116
  `);
1097
1117
  let r = 0;
1098
- if (t && t.line)
1099
- r = t.line - 2;
1118
+ if (n && n.line)
1119
+ r = n.line - 2;
1100
1120
  else
1101
- throw new W();
1121
+ throw new z();
1102
1122
  let s = 0;
1103
1123
  for (let o = 0; o < r; o++)
1104
1124
  s += i[o].length + 1;
@@ -1110,8 +1130,8 @@ class F {
1110
1130
  generateUniformsCode() {
1111
1131
  const e = [];
1112
1132
  if (this.requirements.uniforms.size > 0)
1113
- for (const n of this.checkUniformsPresence())
1114
- e.push(`uniform ${n.type} ${n.name};`);
1133
+ for (const t of this.checkUniformsPresence())
1134
+ e.push(`uniform ${t.type} ${t.name};`);
1115
1135
  return e.length === 0 ? "" : e.join(`
1116
1136
  `) + `
1117
1137
  `;
@@ -1122,10 +1142,10 @@ class F {
1122
1142
  generateFunctionCode() {
1123
1143
  const e = [];
1124
1144
  if (this.requirements.functions.size > 0)
1125
- for (const n of this.checkFunctionsPresence()) {
1126
- const t = n.params.map((i) => `${i.type} ${i.name}`).join(", ");
1145
+ for (const t of this.checkFunctionsPresence()) {
1146
+ const n = t.params.map((i) => `${i.type} ${i.name}`).join(", ");
1127
1147
  e.push(`
1128
- ${n.type} ${n.name}(${t}) ${n.body}`);
1148
+ ${t.type} ${t.name}(${n}) ${t.body}`);
1129
1149
  }
1130
1150
  return e.length === 0 ? "" : e.join(`
1131
1151
  `) + `
@@ -1135,91 +1155,91 @@ ${n.type} ${n.name}(${t}) ${n.body}`);
1135
1155
  * Check which required uniforms are missing from the original shader
1136
1156
  */
1137
1157
  checkUniformsPresence() {
1138
- const e = this.original.parse(), n = [], t = this.requirements.uniforms;
1139
- for (const [i, r] of t) {
1158
+ const e = this.original.parse(), t = [], n = this.requirements.uniforms;
1159
+ for (const [i, r] of n) {
1140
1160
  const s = e.uniforms.find((o) => o.name === i);
1141
1161
  if (!s) {
1142
- n.push(r);
1162
+ t.push(r);
1143
1163
  continue;
1144
1164
  }
1145
1165
  if (s.type !== r.type)
1146
- throw new C(
1166
+ throw new T(
1147
1167
  "uniform",
1148
1168
  i,
1149
1169
  r.type,
1150
1170
  s.type
1151
1171
  );
1152
1172
  }
1153
- return n;
1173
+ return t;
1154
1174
  }
1155
1175
  /**
1156
1176
  * Check which required functions are missing from the original shader
1157
1177
  */
1158
1178
  checkFunctionsPresence() {
1159
- const e = this.original.parse(), n = [], t = this.requirements.functions;
1160
- for (const [i, r] of t) {
1179
+ const e = this.original.parse(), t = [], n = this.requirements.functions;
1180
+ for (const [i, r] of n) {
1161
1181
  const s = e.functions.find((o) => o.name === i);
1162
1182
  if (!s) {
1163
- n.push(r);
1183
+ t.push(r);
1164
1184
  continue;
1165
1185
  }
1166
1186
  if (s.type !== r.type)
1167
- throw new C(
1187
+ throw new T(
1168
1188
  "function",
1169
1189
  i,
1170
1190
  r.type,
1171
1191
  s.type
1172
1192
  );
1173
1193
  }
1174
- return n;
1194
+ return t;
1175
1195
  }
1176
1196
  }
1177
- class v extends F {
1178
- constructor(n, t, i = {}) {
1179
- super(t);
1197
+ class g extends C {
1198
+ constructor(t, n, i = {}) {
1199
+ super(n);
1180
1200
  a(this, "name");
1181
1201
  a(this, "options", {});
1182
- this.name = n, this.options = this.resolveOptions(i);
1202
+ this.name = t, this.options = this.resolveOptions(i);
1183
1203
  }
1184
- resolveOptions(n) {
1185
- if (!(n != null && n.default)) return n || {};
1186
- const t = this.original.parse(), i = n.default;
1187
- for (const r of t.functions)
1204
+ resolveOptions(t) {
1205
+ if (!(t != null && t.default)) return t || {};
1206
+ const n = this.original.parse(), i = t.default;
1207
+ for (const r of n.functions)
1188
1208
  if (!(r.name === "main" || r.name === "default"))
1189
- if (n[r.name]) {
1190
- const s = n[r.name];
1209
+ if (t[r.name]) {
1210
+ const s = t[r.name];
1191
1211
  for (const o in i)
1192
1212
  o in s || (s[o] = i[o]);
1193
1213
  } else
1194
- n[r.name] = { ...i };
1195
- return delete n.default, n || {};
1214
+ t[r.name] = { ...i };
1215
+ return delete t.default, t || {};
1196
1216
  }
1197
1217
  /**
1198
1218
  * Define a module with given name and source, and register it
1199
1219
  */
1200
- static define(n) {
1201
- const { name: t, source: i, options: r } = n;
1202
- if (t === "sandbox" || t.startsWith("sandbox/"))
1203
- throw new Q(t);
1204
- const s = new v(t, i, r);
1205
- if (b.has(t))
1206
- throw new J(t);
1207
- return b.register(t, s), s;
1220
+ static define(t) {
1221
+ const { name: n, source: i, options: r } = t;
1222
+ if (n === "sandbox" || n.startsWith("sandbox/"))
1223
+ throw new Q(n);
1224
+ const s = new g(n, i, r);
1225
+ if (b.has(n))
1226
+ throw new J(n);
1227
+ return b.register(n, s), s;
1208
1228
  }
1209
1229
  /**
1210
1230
  * Resolve a module by name from the registry, throwing an error if not found
1211
1231
  */
1212
- static resolve(n) {
1213
- return b.resolve(n);
1232
+ static resolve(t) {
1233
+ return b.resolve(t);
1214
1234
  }
1215
1235
  /**
1216
1236
  * Create a copy of the module. To unplug references to the original object.
1217
1237
  * Used when copying module to the runtime registry to allow independent runtime changes to options without affecting the original module definition.
1218
1238
  */
1219
- copy(n = "original") {
1220
- return new v(
1239
+ copy(t = "original") {
1240
+ return new g(
1221
1241
  this.name,
1222
- this[n].source,
1242
+ this[t].source,
1223
1243
  JSON.parse(JSON.stringify(this.options))
1224
1244
  );
1225
1245
  }
@@ -1227,14 +1247,14 @@ class v extends F {
1227
1247
  * Merge options from another module into this one, without affecting the original module definition.
1228
1248
  * Used when merging imported modules into the runtime registry.
1229
1249
  */
1230
- merge(n) {
1250
+ merge(t) {
1231
1251
  this.options = this.options || {};
1232
- const t = this.getDefinition().uniforms.map((i) => i.name);
1233
- for (const [i, r] of Object.entries(n.options ?? {}))
1252
+ const n = this.getDefinition().uniforms.map((i) => i.name);
1253
+ for (const [i, r] of Object.entries(t.options ?? {}))
1234
1254
  if (!this.options[i]) this.options[i] = r;
1235
1255
  else
1236
1256
  for (const [s, o] of Object.entries(r))
1237
- t.includes(o.uniform) || (this.options[i][s] = o);
1257
+ n.includes(o.uniform) || (this.options[i][s] = o);
1238
1258
  }
1239
1259
  /**
1240
1260
  * Get the module definition
@@ -1242,34 +1262,34 @@ class v extends F {
1242
1262
  getDefinition() {
1243
1263
  return this.compile(), {
1244
1264
  name: this.name,
1245
- methods: this.compiled.parse().functions.map((n) => n.name).filter((n) => n !== "main" && n !== "default"),
1246
- uniforms: this.compiled.parse().uniforms.map((n) => ({ name: n.name, type: n.type })),
1265
+ methods: this.compiled.parse().functions.map((t) => t.name).filter((t) => t !== "main" && t !== "default"),
1266
+ uniforms: this.compiled.parse().uniforms.map((t) => ({ name: t.name, type: t.type })),
1247
1267
  options: this.options
1248
1268
  };
1249
1269
  }
1250
1270
  /**
1251
1271
  * Extract a method with all its dependencies
1252
1272
  */
1253
- extract(n) {
1254
- if (this.compile(), n === "main")
1273
+ extract(t) {
1274
+ if (this.compile(), t === "main")
1275
+ throw new Y(this.name);
1276
+ if (t === "default")
1255
1277
  throw new K(this.name);
1256
- if (n === "default")
1257
- throw new X(this.name);
1258
- const t = this.compiled.parse(), i = t.functions.find((o) => o.name === n);
1278
+ const n = this.compiled.parse(), i = n.functions.find((o) => o.name === t);
1259
1279
  if (!i)
1260
- throw new Y(this.name, n);
1280
+ throw new X(this.name, t);
1261
1281
  const r = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
1262
1282
  return this.collectDependencies({
1263
1283
  current: i,
1264
1284
  scope: {
1265
- functions: t.functions,
1266
- uniforms: t.uniforms
1285
+ functions: n.functions,
1286
+ uniforms: n.uniforms
1267
1287
  },
1268
1288
  collected: {
1269
1289
  functions: r,
1270
1290
  uniforms: s
1271
1291
  },
1272
- visited: /* @__PURE__ */ new Set([n])
1292
+ visited: /* @__PURE__ */ new Set([t])
1273
1293
  }), {
1274
1294
  function: i,
1275
1295
  dependencies: {
@@ -1281,36 +1301,36 @@ class v extends F {
1281
1301
  /**
1282
1302
  * Recursively collect all function and uniform dependencies
1283
1303
  */
1284
- collectDependencies(n) {
1285
- for (const t of n.current.dependencies)
1286
- if (t.type === "function") {
1287
- if (n.visited.has(t.name)) continue;
1288
- const i = n.scope.functions.find((r) => r.name === t.name);
1289
- i && (n.visited.add(t.name), n.collected.functions.set(t.name, i), this.collectDependencies({
1304
+ collectDependencies(t) {
1305
+ for (const n of t.current.dependencies)
1306
+ if (n.type === "function") {
1307
+ if (t.visited.has(n.name)) continue;
1308
+ const i = t.scope.functions.find((r) => r.name === n.name);
1309
+ i && (t.visited.add(n.name), t.collected.functions.set(n.name, i), this.collectDependencies({
1290
1310
  current: i,
1291
1311
  scope: {
1292
- functions: n.scope.functions,
1293
- uniforms: n.scope.uniforms
1312
+ functions: t.scope.functions,
1313
+ uniforms: t.scope.uniforms
1294
1314
  },
1295
1315
  collected: {
1296
- functions: n.collected.functions,
1297
- uniforms: n.collected.uniforms
1316
+ functions: t.collected.functions,
1317
+ uniforms: t.collected.uniforms
1298
1318
  },
1299
- visited: n.visited
1319
+ visited: t.visited
1300
1320
  }));
1301
- } else if (t.type === "uniform") {
1302
- const i = n.scope.uniforms.find(
1303
- (r) => r.name === t.name
1321
+ } else if (n.type === "uniform") {
1322
+ const i = t.scope.uniforms.find(
1323
+ (r) => r.name === n.name
1304
1324
  );
1305
- i && !n.collected.uniforms.has(t.name) && n.collected.uniforms.set(t.name, i);
1325
+ i && !t.collected.uniforms.has(n.name) && t.collected.uniforms.set(n.name, i);
1306
1326
  }
1307
1327
  }
1308
1328
  }
1309
- class V {
1329
+ class F {
1310
1330
  constructor(e = []) {
1311
1331
  a(this, "modules", /* @__PURE__ */ new Map());
1312
- e.forEach((n) => {
1313
- this.register(n.name, n);
1332
+ e.forEach((t) => {
1333
+ this.register(t.name, t);
1314
1334
  });
1315
1335
  }
1316
1336
  /**
@@ -1335,14 +1355,14 @@ class V {
1335
1355
  */
1336
1356
  defaults() {
1337
1357
  const e = {};
1338
- return this.modules.forEach((n) => {
1339
- const t = n.getDefinition();
1340
- if (t.options)
1341
- for (const i in t.options) {
1342
- const r = t.options[i];
1358
+ return this.modules.forEach((t) => {
1359
+ const n = t.getDefinition();
1360
+ if (n.options)
1361
+ for (const i in n.options) {
1362
+ const r = n.options[i];
1343
1363
  for (const s in r) {
1344
1364
  const o = r[s];
1345
- o.default !== void 0 && !t.uniforms.map((l) => l.name).includes(o.uniform) && (e[o.uniform] = o.default);
1365
+ o.default !== void 0 && !n.uniforms.map((l) => l.name).includes(o.uniform) && (e[o.uniform] = o.default);
1346
1366
  }
1347
1367
  }
1348
1368
  }), e;
@@ -1351,33 +1371,33 @@ class V {
1351
1371
  * Resolve the options from the module definitions for a given function name.
1352
1372
  */
1353
1373
  resolveOptions(e) {
1354
- for (const n of this.modules.values())
1355
- if (n.options && n.options[e])
1356
- return n.options[e];
1374
+ for (const t of this.modules.values())
1375
+ if (t.options && t.options[e])
1376
+ return t.options[e];
1357
1377
  return null;
1358
1378
  }
1359
1379
  /**
1360
1380
  * Register a new module in the registry.
1361
1381
  */
1362
- register(e, n) {
1363
- this.modules.set(e, n);
1382
+ register(e, t) {
1383
+ this.modules.set(e, t);
1364
1384
  }
1365
1385
  /**
1366
1386
  * Merge a module into the registry. If a module with the same name already exists, options will be merged together.
1367
1387
  */
1368
- merge(e, n) {
1369
- if (!this.modules.has(e)) return this.register(e, n);
1370
- const t = this.modules.get(e);
1371
- t.merge(n), this.modules.set(e, t);
1388
+ merge(e, t) {
1389
+ if (!this.modules.has(e)) return this.register(e, t);
1390
+ const n = this.modules.get(e);
1391
+ n.merge(t), this.modules.set(e, n);
1372
1392
  }
1373
1393
  /**
1374
1394
  * Resolve a module by name. Throws an error if the module is not found.
1375
1395
  */
1376
1396
  resolve(e) {
1377
- const n = this.modules.get(e);
1378
- if (!n)
1397
+ const t = this.modules.get(e);
1398
+ if (!t)
1379
1399
  throw new j(e);
1380
- return n;
1400
+ return t;
1381
1401
  }
1382
1402
  /**
1383
1403
  * Check if a module exists in the registry by name.
@@ -1401,8 +1421,8 @@ class V {
1401
1421
  * Load multiple modules into the registry at once.
1402
1422
  */
1403
1423
  load(e) {
1404
- e.forEach((n) => {
1405
- this.register(n.name, n);
1424
+ e.forEach((t) => {
1425
+ this.register(t.name, t);
1406
1426
  });
1407
1427
  }
1408
1428
  /**
@@ -2224,11 +2244,11 @@ vec3 arcade(vec3 color, vec2 uv, float intensity) {
2224
2244
  }
2225
2245
 
2226
2246
  void main() {}
2227
- `, b = new V([
2228
- new v("sandbox", oe),
2229
- new v("sandbox/colors", ae),
2230
- new v("sandbox/time", le),
2231
- new v("sandbox/effects", ce, {
2247
+ `, b = new F([
2248
+ new g("sandbox", oe),
2249
+ new g("sandbox/colors", ae),
2250
+ new g("sandbox/time", le),
2251
+ new g("sandbox/effects", ce, {
2232
2252
  default: {
2233
2253
  intensity: { uniform: "u_intensity", default: 1 }
2234
2254
  },
@@ -2278,7 +2298,7 @@ void main() {}
2278
2298
  intensity: { uniform: "u_intensity", default: 1 }
2279
2299
  }
2280
2300
  }),
2281
- new v("sandbox/filters", ue, {
2301
+ new g("sandbox/filters", ue, {
2282
2302
  default: {
2283
2303
  intensity: { uniform: "u_intensity", default: 1 }
2284
2304
  },
@@ -2307,7 +2327,7 @@ void main() {}
2307
2327
  intensity: { uniform: "u_intensity", default: 0.5 }
2308
2328
  }
2309
2329
  })
2310
- ]), y = new V(), E = /* @__PURE__ */ new Map([
2330
+ ]), E = /* @__PURE__ */ new Map([
2311
2331
  ["u_resolution", "vec2"],
2312
2332
  ["u_time", "float"],
2313
2333
  ["u_delta", "float"],
@@ -2327,32 +2347,32 @@ class fe {
2327
2347
  */
2328
2348
  attachProgram(e) {
2329
2349
  this.program = e;
2330
- for (const n of this.uniforms.values())
2331
- n.invalidateLocation();
2350
+ for (const t of this.uniforms.values())
2351
+ t.invalidateLocation();
2332
2352
  return this;
2333
2353
  }
2334
2354
  /**
2335
2355
  * Set a uniform value.
2336
2356
  * Creates the uniform if it doesn't exist, updates if it does.
2337
2357
  */
2338
- set(e, n) {
2339
- const t = this.uniforms.get(e);
2340
- return t ? t.setValue(n) : this.uniforms.set(e, new k(e, n)), this;
2358
+ set(e, t) {
2359
+ const n = this.uniforms.get(e);
2360
+ return n ? n.setValue(t) : this.uniforms.set(e, new M(e, t)), this;
2341
2361
  }
2342
2362
  /**
2343
2363
  * Set multiple uniforms at once.
2344
2364
  */
2345
2365
  setMany(e) {
2346
- for (const [n, t] of Object.entries(e))
2347
- this.set(n, t);
2366
+ for (const [t, n] of Object.entries(e))
2367
+ this.set(t, n);
2348
2368
  return this;
2349
2369
  }
2350
2370
  /**
2351
2371
  * Get current uniform value.
2352
2372
  */
2353
2373
  get(e) {
2354
- var n;
2355
- return (n = this.uniforms.get(e)) == null ? void 0 : n.getValue();
2374
+ var t;
2375
+ return (t = this.uniforms.get(e)) == null ? void 0 : t.getValue();
2356
2376
  }
2357
2377
  /**
2358
2378
  * Check if uniform exists.
@@ -2381,8 +2401,8 @@ class fe {
2381
2401
  * Upload only built-in uniforms (u_resolution, u_time, u_delta, u_mouse, u_frame).
2382
2402
  * Call this every frame with current values.
2383
2403
  */
2384
- uploadBuiltIns(e, n, t) {
2385
- if (this.set("u_resolution", n), this.set("u_time", e.time), this.set("u_delta", e.delta), this.set("u_mouse", t), this.set("u_frame", e.frame), !this.program)
2404
+ uploadBuiltIns(e, t, n) {
2405
+ if (this.set("u_resolution", t), this.set("u_time", e.time), this.set("u_delta", e.delta), this.set("u_mouse", n), this.set("u_frame", e.frame), !this.program)
2386
2406
  return this;
2387
2407
  for (const i of E.keys()) {
2388
2408
  const r = this.uniforms.get(i);
@@ -2415,7 +2435,207 @@ class fe {
2415
2435
  return this.uniforms.size;
2416
2436
  }
2417
2437
  }
2418
- class O {
2438
+ class x {
2439
+ constructor(e, t, n, i) {
2440
+ a(this, "name");
2441
+ a(this, "gl");
2442
+ a(this, "texture", null);
2443
+ a(this, "location", null);
2444
+ a(this, "locationResolved", !1);
2445
+ a(this, "source");
2446
+ a(this, "options");
2447
+ a(this, "dynamicOverride");
2448
+ a(this, "needsUpload", !0);
2449
+ a(this, "needsReupload", !1);
2450
+ this.gl = e, this.name = t, this.source = n, this.dynamicOverride = i == null ? void 0 : i.dynamic, this.options = x.resolveOptions(n, i), this.needsReupload = this.options.dynamic;
2451
+ }
2452
+ /**
2453
+ * Update the texture source.
2454
+ * Marks texture for re-upload on next bind.
2455
+ * Respects the original `dynamic` option if explicitly set, otherwise re-infers from source type.
2456
+ */
2457
+ setSource(e) {
2458
+ this.source = e, this.needsUpload = !0, this.needsReupload = this.dynamicOverride ?? x.isDynamicSource(e);
2459
+ }
2460
+ /**
2461
+ * Resolve and cache uniform location from program.
2462
+ * Returns null if the sampler uniform doesn't exist in the shader.
2463
+ */
2464
+ resolveLocation(e, t) {
2465
+ return this.locationResolved || (this.location = e.getUniformLocation(t, this.name), this.locationResolved = !0), this.location;
2466
+ }
2467
+ /**
2468
+ * Invalidate cached location (call when program changes).
2469
+ */
2470
+ invalidateLocation() {
2471
+ this.location = null, this.locationResolved = !1;
2472
+ }
2473
+ /**
2474
+ * Bind texture to a texture unit and set the sampler uniform.
2475
+ * @param program - Current WebGL program (for location resolution)
2476
+ * @param unit - Texture unit index (0, 1, 2, ...)
2477
+ */
2478
+ upload(e, t) {
2479
+ const n = this.gl, i = this.resolveLocation(n, e);
2480
+ if (i !== null) {
2481
+ if (!this.texture) {
2482
+ if (this.texture = n.createTexture(), !this.texture) return;
2483
+ this.needsUpload = !0;
2484
+ }
2485
+ n.activeTexture(n.TEXTURE0 + t), n.bindTexture(n.TEXTURE_2D, this.texture), (this.needsUpload || this.needsReupload) && (this.uploadPixels(), this.needsUpload = !1), n.uniform1i(i, t);
2486
+ }
2487
+ }
2488
+ /**
2489
+ * Cleanup WebGL texture resource.
2490
+ */
2491
+ destroy() {
2492
+ this.texture && (this.gl.deleteTexture(this.texture), this.texture = null), this.location = null, this.locationResolved = !1;
2493
+ }
2494
+ /**
2495
+ * Upload pixel data from source and apply texture parameters.
2496
+ */
2497
+ uploadPixels() {
2498
+ const e = this.gl;
2499
+ e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL, this.options.flipY), e.texImage2D(
2500
+ e.TEXTURE_2D,
2501
+ 0,
2502
+ e.RGBA,
2503
+ e.RGBA,
2504
+ e.UNSIGNED_BYTE,
2505
+ this.source
2506
+ ), this.applyParameters();
2507
+ }
2508
+ /**
2509
+ * Apply texture wrap and filter parameters.
2510
+ */
2511
+ applyParameters() {
2512
+ const e = this.gl;
2513
+ e.texParameteri(
2514
+ e.TEXTURE_2D,
2515
+ e.TEXTURE_WRAP_S,
2516
+ x.resolveWrap(e, this.options.wrapS)
2517
+ ), e.texParameteri(
2518
+ e.TEXTURE_2D,
2519
+ e.TEXTURE_WRAP_T,
2520
+ x.resolveWrap(e, this.options.wrapT)
2521
+ ), e.texParameteri(
2522
+ e.TEXTURE_2D,
2523
+ e.TEXTURE_MIN_FILTER,
2524
+ this.options.minFilter === "nearest" ? e.NEAREST : e.LINEAR
2525
+ ), e.texParameteri(
2526
+ e.TEXTURE_2D,
2527
+ e.TEXTURE_MAG_FILTER,
2528
+ this.options.magFilter === "nearest" ? e.NEAREST : e.LINEAR
2529
+ );
2530
+ }
2531
+ /**
2532
+ * Resolve wrap mode string to WebGL constant.
2533
+ */
2534
+ static resolveWrap(e, t) {
2535
+ switch (t) {
2536
+ case "repeat":
2537
+ return e.REPEAT;
2538
+ case "mirror":
2539
+ return e.MIRRORED_REPEAT;
2540
+ case "clamp":
2541
+ default:
2542
+ return e.CLAMP_TO_EDGE;
2543
+ }
2544
+ }
2545
+ /**
2546
+ * Resolve texture options with defaults.
2547
+ */
2548
+ static resolveOptions(e, t) {
2549
+ const n = (t == null ? void 0 : t.wrap) ?? "clamp";
2550
+ return {
2551
+ wrap: n,
2552
+ wrapS: (t == null ? void 0 : t.wrapS) ?? n,
2553
+ wrapT: (t == null ? void 0 : t.wrapT) ?? n,
2554
+ minFilter: (t == null ? void 0 : t.minFilter) ?? "linear",
2555
+ magFilter: (t == null ? void 0 : t.magFilter) ?? "linear",
2556
+ flipY: (t == null ? void 0 : t.flipY) ?? !0,
2557
+ dynamic: (t == null ? void 0 : t.dynamic) ?? x.isDynamicSource(e)
2558
+ };
2559
+ }
2560
+ /**
2561
+ * Check if a source is dynamic (needs re-upload every frame).
2562
+ */
2563
+ static isDynamicSource(e) {
2564
+ return e instanceof HTMLVideoElement;
2565
+ }
2566
+ }
2567
+ class he {
2568
+ constructor(e) {
2569
+ a(this, "gl");
2570
+ a(this, "program", null);
2571
+ a(this, "textures", /* @__PURE__ */ new Map());
2572
+ this.gl = e;
2573
+ }
2574
+ /**
2575
+ * Attach to a WebGL program.
2576
+ * Invalidates all cached locations since they're program-specific.
2577
+ */
2578
+ attachProgram(e) {
2579
+ this.program = e;
2580
+ for (const t of this.textures.values())
2581
+ t.invalidateLocation();
2582
+ return this;
2583
+ }
2584
+ /**
2585
+ * Set a texture.
2586
+ * Creates the texture entry if it doesn't exist, updates source if it does.
2587
+ */
2588
+ set(e, t, n) {
2589
+ const i = this.textures.get(e);
2590
+ return i ? i.setSource(t) : this.textures.set(e, new x(this.gl, e, t, n)), this;
2591
+ }
2592
+ /**
2593
+ * Get a texture by name.
2594
+ */
2595
+ get(e) {
2596
+ return this.textures.get(e);
2597
+ }
2598
+ /**
2599
+ * Check if a texture exists.
2600
+ */
2601
+ has(e) {
2602
+ return this.textures.has(e);
2603
+ }
2604
+ /**
2605
+ * Remove a texture and free its GPU resources.
2606
+ */
2607
+ delete(e) {
2608
+ const t = this.textures.get(e);
2609
+ return t ? (t.destroy(), this.textures.delete(e)) : !1;
2610
+ }
2611
+ /**
2612
+ * Upload all textures to their respective texture units.
2613
+ * Units are assigned sequentially (0, 1, 2, ...).
2614
+ */
2615
+ uploadAll() {
2616
+ if (!this.program)
2617
+ return this;
2618
+ let e = 0;
2619
+ for (const t of this.textures.values())
2620
+ t.upload(this.program, e), e++;
2621
+ return this;
2622
+ }
2623
+ /**
2624
+ * Get texture count.
2625
+ */
2626
+ get size() {
2627
+ return this.textures.size;
2628
+ }
2629
+ /**
2630
+ * Cleanup all textures.
2631
+ */
2632
+ destroy() {
2633
+ for (const e of this.textures.values())
2634
+ e.destroy();
2635
+ this.textures.clear(), this.program = null;
2636
+ }
2637
+ }
2638
+ class U {
2419
2639
  constructor() {
2420
2640
  a(this, "hooks", /* @__PURE__ */ new Map());
2421
2641
  }
@@ -2424,8 +2644,8 @@ class O {
2424
2644
  }
2425
2645
  /** Add a new hook, returns a removal function */
2426
2646
  add(e) {
2427
- const n = this.id();
2428
- return this.hooks.set(n, e), () => this.remove(n);
2647
+ const t = this.id();
2648
+ return this.hooks.set(t, e), () => this.remove(t);
2429
2649
  }
2430
2650
  /** Remove a hook by its ID */
2431
2651
  remove(e) {
@@ -2433,12 +2653,12 @@ class O {
2433
2653
  }
2434
2654
  /** Run all hooks with the given state */
2435
2655
  run(e) {
2436
- for (const [n, t] of this.hooks)
2656
+ for (const [t, n] of this.hooks)
2437
2657
  try {
2438
- t(e) === !1 && this.remove(n);
2658
+ n(e) === !1 && this.remove(t);
2439
2659
  } catch (i) {
2440
2660
  throw new ie(
2441
- n,
2661
+ t,
2442
2662
  i instanceof Error ? i.message : String(i)
2443
2663
  );
2444
2664
  }
@@ -2447,29 +2667,31 @@ class O {
2447
2667
  this.hooks.clear();
2448
2668
  }
2449
2669
  }
2450
- class M {
2451
- constructor(e, n) {
2670
+ class k {
2671
+ constructor(e, t) {
2452
2672
  a(this, "canvas");
2453
2673
  a(this, "gl");
2454
2674
  a(this, "options");
2455
- a(this, "onBeforeHooks", new O());
2456
- a(this, "onAfterHooks", new O());
2675
+ a(this, "onBeforeHooks", new U());
2676
+ a(this, "onAfterHooks", new U());
2457
2677
  a(this, "_program");
2458
2678
  a(this, "_geometry");
2459
2679
  a(this, "_uniforms");
2680
+ a(this, "_textures");
2460
2681
  a(this, "_clock");
2461
2682
  a(this, "_resolution", [1, 1]);
2462
2683
  a(this, "_mouse", [0, 0]);
2463
2684
  a(this, "_version", 1);
2685
+ a(this, "_runtimeModules", new F());
2464
2686
  a(this, "playing", !1);
2465
- this.canvas = e, this.options = n, this.gl = this.initContext(), this.enableExtensions(), this._program = new se(this.gl), this._geometry = A.fullscreenQuad(this.gl), this._uniforms = new fe(this.gl), this._clock = new re(), this.options.fps && this._clock.setMaxFps(this.options.fps), this.options.onBeforeRender && this.onBeforeHooks.add(this.options.onBeforeRender), this.options.onAfterRender && this.onAfterHooks.add(this.options.onAfterRender), this.onRender = this.onRender.bind(this);
2687
+ this.canvas = e, this.options = t, this.gl = this.initContext(), this.enableExtensions(), this._program = new se(this.gl), this._geometry = A.fullscreenQuad(this.gl), this._uniforms = new fe(this.gl), this._textures = new he(this.gl), this._clock = new re(), this.options.fps && this._clock.setMaxFps(this.options.fps), this.options.onBeforeRender && this.onBeforeHooks.add(this.options.onBeforeRender), this.options.onAfterRender && this.onAfterHooks.add(this.options.onAfterRender), this.onRender = this.onRender.bind(this);
2466
2688
  }
2467
2689
  /**
2468
2690
  * Factory method to create and setup WebGL instance.
2469
2691
  */
2470
- static setup(e, n) {
2471
- const t = new M(e, n);
2472
- return n.vertex && n.fragment && t.shader(n.vertex, n.fragment), n.uniforms && t._uniforms.setMany(n.uniforms), y.isEmpty() || t._uniforms.setMany(y.defaults()), t;
2692
+ static setup(e, t) {
2693
+ const n = new k(e, t);
2694
+ return t.vertex && t.fragment && n.shader(t.vertex, t.fragment), t.uniforms && n._uniforms.setMany(t.uniforms), t.textures && n.texturesFromSchema(t.textures), n._runtimeModules.isEmpty() || n._uniforms.setMany(n._runtimeModules.defaults()), n;
2473
2695
  }
2474
2696
  /**
2475
2697
  * Initialize WebGL context.
@@ -2483,13 +2705,13 @@ class M {
2483
2705
  alpha: !0,
2484
2706
  depth: !1,
2485
2707
  stencil: !1
2486
- }, n = this.canvas.getContext("webgl2", e);
2487
- if (n)
2488
- return this._version = 2, n;
2489
- const t = this.canvas.getContext("webgl", e);
2708
+ }, t = this.canvas.getContext("webgl2", e);
2490
2709
  if (t)
2491
- return this._version = 1, t;
2492
- const i = new z();
2710
+ return this._version = 2, t;
2711
+ const n = this.canvas.getContext("webgl", e);
2712
+ if (n)
2713
+ return this._version = 1, n;
2714
+ const i = new G();
2493
2715
  throw this.options.onError(i), i;
2494
2716
  }
2495
2717
  /**
@@ -2501,8 +2723,8 @@ class M {
2501
2723
  /**
2502
2724
  * Set viewport dimensions.
2503
2725
  */
2504
- viewport(e, n, t, i) {
2505
- return this.canvas.width = t, this.canvas.height = i, this.gl.viewport(e, n, t, i), this._resolution = [t, i], this;
2726
+ viewport(e, t, n, i) {
2727
+ return this.canvas.width = n, this.canvas.height = i, this.gl.viewport(e, t, n, i), this._resolution = [n, i], this;
2506
2728
  }
2507
2729
  /**
2508
2730
  * Set the clock time
@@ -2513,14 +2735,14 @@ class M {
2513
2735
  /**
2514
2736
  * Update mouse position.
2515
2737
  */
2516
- mouse(e, n) {
2517
- return this._mouse = [e, n], this;
2738
+ mouse(e, t) {
2739
+ return this._mouse = [e, t], this;
2518
2740
  }
2519
2741
  /**
2520
2742
  * Set a uniform value.
2521
2743
  */
2522
- uniform(e, n) {
2523
- return this._uniforms.set(e, n), this;
2744
+ uniform(e, t) {
2745
+ return this._uniforms.set(e, t), this;
2524
2746
  }
2525
2747
  /**
2526
2748
  * Set multiple uniforms.
@@ -2534,29 +2756,54 @@ class M {
2534
2756
  getUniform(e) {
2535
2757
  return this._uniforms.get(e);
2536
2758
  }
2759
+ /**
2760
+ * Set a texture.
2761
+ */
2762
+ texture(e, t, n) {
2763
+ return this._textures.set(e, t, n), this;
2764
+ }
2765
+ /**
2766
+ * Set multiple textures from a schema.
2767
+ */
2768
+ texturesFromSchema(e) {
2769
+ for (const [t, n] of Object.entries(e))
2770
+ if (n instanceof HTMLImageElement || n instanceof HTMLCanvasElement || n instanceof HTMLVideoElement || n instanceof ImageBitmap || n instanceof ImageData || n instanceof OffscreenCanvas)
2771
+ this._textures.set(t, n);
2772
+ else {
2773
+ const { source: i, ...r } = n;
2774
+ this._textures.set(t, i, r);
2775
+ }
2776
+ return this;
2777
+ }
2778
+ /**
2779
+ * Remove a texture.
2780
+ */
2781
+ removeTexture(e) {
2782
+ return this._textures.delete(e), this;
2783
+ }
2537
2784
  /**
2538
2785
  * Compile and link shaders.
2539
2786
  * Errors are handled via onError callback, never thrown.
2540
2787
  */
2541
- shader(e, n) {
2788
+ shader(e, t) {
2542
2789
  try {
2543
- if (y.clear(), e.version() !== n.version())
2544
- throw new G(
2790
+ if (this._runtimeModules.clear(), e.version() !== t.version())
2791
+ throw new W(
2545
2792
  e.version(),
2546
- n.version()
2793
+ t.version()
2547
2794
  );
2548
- this._program.compile(e.source(), n.compile()), this._version = n.version(), this._geometry.linkAttributes(this._program);
2549
- const t = this._program.getProgram();
2550
- t && this._uniforms.attachProgram(t);
2795
+ this._program.compile(e.source(), t.compile(this._runtimeModules)), this._version = t.version(), this._geometry.linkAttributes(this._program);
2796
+ const n = this._program.getProgram();
2797
+ n && (this._uniforms.attachProgram(n), this._textures.attachProgram(n));
2551
2798
  try {
2552
2799
  this.options.onLoad();
2553
2800
  } catch (i) {
2554
- throw new te(
2801
+ throw new ne(
2555
2802
  i instanceof Error ? i.message : String(i)
2556
2803
  );
2557
2804
  }
2558
- } catch (t) {
2559
- t instanceof h && this.options.onError(t);
2805
+ } catch (n) {
2806
+ n instanceof h && this.options.onError(n);
2560
2807
  }
2561
2808
  return this;
2562
2809
  }
@@ -2574,14 +2821,14 @@ class M {
2574
2821
  const e = this._clock.getState();
2575
2822
  try {
2576
2823
  this.onBeforeHooks.run(e);
2577
- } catch (n) {
2578
- n instanceof h && this.options.onError(n);
2824
+ } catch (t) {
2825
+ t instanceof h && this.options.onError(t);
2579
2826
  }
2580
2827
  this.playing = !1, this._clock.stop();
2581
2828
  try {
2582
2829
  this.onAfterHooks.run(e);
2583
- } catch (n) {
2584
- n instanceof h && this.options.onError(n);
2830
+ } catch (t) {
2831
+ t instanceof h && this.options.onError(t);
2585
2832
  }
2586
2833
  return this;
2587
2834
  }
@@ -2597,6 +2844,12 @@ class M {
2597
2844
  getContext() {
2598
2845
  return this.gl;
2599
2846
  }
2847
+ /**
2848
+ * Get registered runtime modules.
2849
+ */
2850
+ getUsingModules() {
2851
+ return this._runtimeModules;
2852
+ }
2600
2853
  /**
2601
2854
  * Get detected WebGL version.
2602
2855
  */
@@ -2613,30 +2866,30 @@ class M {
2613
2866
  * Cleanup all resources.
2614
2867
  */
2615
2868
  destroy() {
2616
- this.pause(), this._clock.destroy(), this._geometry.destroy(), this._program.destroy(), this._uniforms.destroy(), this.onAfterHooks.destroy(), this.onBeforeHooks.destroy(), y.clear();
2869
+ this.pause(), this._clock.destroy(), this._geometry.destroy(), this._program.destroy(), this._uniforms.destroy(), this._textures.destroy(), this.onAfterHooks.destroy(), this.onBeforeHooks.destroy(), this._runtimeModules.clear();
2617
2870
  }
2618
2871
  /**
2619
2872
  * Internal render callback.
2620
2873
  */
2621
2874
  onRender(e) {
2622
- const n = this.gl;
2875
+ const t = this.gl;
2623
2876
  try {
2624
2877
  this.onBeforeHooks.run(e);
2625
- } catch (t) {
2626
- t instanceof h && this.options.onError(t);
2878
+ } catch (n) {
2879
+ n instanceof h && this.options.onError(n);
2627
2880
  }
2628
- n.clearColor(0, 0, 0, 0), n.clear(n.COLOR_BUFFER_BIT), this._program.use(), this._uniforms.uploadBuiltIns(e, this._resolution, this._mouse), this._uniforms.uploadAll(), this._geometry.bind(), this._geometry.draw();
2881
+ t.clearColor(0, 0, 0, 0), t.clear(t.COLOR_BUFFER_BIT), this._program.use(), this._uniforms.uploadBuiltIns(e, this._resolution, this._mouse), this._uniforms.uploadAll(), this._textures.uploadAll(), this._geometry.bind(), this._geometry.draw();
2629
2882
  try {
2630
2883
  this.onAfterHooks.run(e);
2631
- } catch (t) {
2632
- t instanceof h && this.options.onError(t);
2884
+ } catch (n) {
2885
+ n instanceof h && this.options.onError(n);
2633
2886
  }
2634
2887
  }
2635
2888
  }
2636
- class d extends F {
2889
+ class p extends C {
2637
2890
  constructor(e) {
2638
- super(e), E.forEach((n, t) => {
2639
- this.requirements.uniforms.set(t, { name: t, type: n, line: 0 });
2891
+ super(e), E.forEach((t, n) => {
2892
+ this.requirements.uniforms.set(n, { name: n, type: t, line: 0 });
2640
2893
  });
2641
2894
  }
2642
2895
  }
@@ -2667,7 +2920,7 @@ void main() {
2667
2920
  vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time));
2668
2921
  gl_FragColor = vec4(color, 1.0);
2669
2922
  }
2670
- `, U = `#version 300 es
2923
+ `, O = `#version 300 es
2671
2924
 
2672
2925
  in vec2 a_position;
2673
2926
  in vec2 a_texcoord;
@@ -2677,7 +2930,7 @@ out vec2 v_texcoord;
2677
2930
  void main() {
2678
2931
  v_texcoord = a_texcoord;
2679
2932
  gl_Position = vec4(a_position, 0.0, 1.0);
2680
- }`, he = `#version 300 es
2933
+ }`, me = `#version 300 es
2681
2934
  precision highp float;
2682
2935
 
2683
2936
  uniform vec2 u_resolution;
@@ -2692,8 +2945,8 @@ void main() {
2692
2945
  vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time));
2693
2946
  fragColor = vec4(color, 1.0);
2694
2947
  }`;
2695
- class $ {
2696
- constructor(e, n) {
2948
+ class V {
2949
+ constructor(e, t) {
2697
2950
  /** Active event listeners */
2698
2951
  a(this, "listeners", []);
2699
2952
  /** HTML canvas element */
@@ -2704,9 +2957,9 @@ class $ {
2704
2957
  a(this, "engine");
2705
2958
  /** User sets custom vertex shader */
2706
2959
  a(this, "usingCustomVertex", !1);
2707
- if (this.canvasEl = e, this.options = this.resolveOptions(n), this.engine = M.setup(this.canvasEl, this.options), this.setupListeners(), this.setViewport(), this.options.modules)
2708
- for (const [t, i] of Object.entries(this.options.modules))
2709
- this.module(t, i);
2960
+ if (this.canvasEl = e, this.options = this.resolveOptions(t), this.engine = k.setup(this.canvasEl, this.options), this.setupListeners(), this.setViewport(), this.options.modules)
2961
+ for (const [n, i] of Object.entries(this.options.modules))
2962
+ this.module(n, i);
2710
2963
  this.options.autoplay && this.play();
2711
2964
  }
2712
2965
  /**
@@ -2727,8 +2980,8 @@ class $ {
2727
2980
  * autoplay: true,
2728
2981
  * });
2729
2982
  */
2730
- static create(e, n) {
2731
- return new $(e, n);
2983
+ static create(e, t) {
2984
+ return new V(e, t);
2732
2985
  }
2733
2986
  /**
2734
2987
  * Define a shader module that can be imported in shader source with `#import <function> from "module_name"`.
@@ -2740,8 +2993,8 @@ class $ {
2740
2993
  * // myFunc();
2741
2994
  * // }
2742
2995
  */
2743
- static defineModule(e, n, t = {}) {
2744
- v.define({ name: e, source: n, options: t });
2996
+ static defineModule(e, t, n = {}) {
2997
+ g.define({ name: e, source: t, options: n });
2745
2998
  }
2746
2999
  /**
2747
3000
  * Get the list of available shader modules that can be used with `#import` in shader source.
@@ -2754,12 +3007,12 @@ class $ {
2754
3007
  * This is useful for debugging shader code or precompiling shaders for production use.
2755
3008
  */
2756
3009
  static compile(e) {
2757
- return new d(e).compile();
3010
+ return new p(e).compile();
2758
3011
  }
2759
3012
  resolveOptions(e) {
2760
- const n = {
2761
- vertex: new d(S),
2762
- fragment: new d(L),
3013
+ const t = {
3014
+ vertex: new p(S),
3015
+ fragment: new p(L),
2763
3016
  autoplay: !0,
2764
3017
  pauseWhenHidden: !0,
2765
3018
  dpr: "auto",
@@ -2779,45 +3032,46 @@ You can handle errors programmatically by providing an onError callback to suppr
2779
3032
  onBeforeRender: null,
2780
3033
  onAfterRender: null,
2781
3034
  uniforms: {},
2782
- modules: {}
3035
+ modules: {},
3036
+ textures: {}
2783
3037
  };
2784
3038
  if (e != null && e.vertex && (this.usingCustomVertex = !0), e != null && e.vertex && !(e != null && e.fragment)) {
2785
- n.vertex = new d(e.vertex);
2786
- const s = n.vertex.version();
2787
- n.fragment = new d(s === 2 ? he : L);
3039
+ t.vertex = new p(e.vertex);
3040
+ const s = t.vertex.version();
3041
+ t.fragment = new p(s === 2 ? me : L);
2788
3042
  }
2789
3043
  if (e != null && e.fragment && !(e != null && e.vertex)) {
2790
- n.fragment = new d(e.fragment);
2791
- const s = n.fragment.version();
2792
- n.vertex = new d(s === 2 ? U : S);
3044
+ t.fragment = new p(e.fragment);
3045
+ const s = t.fragment.version();
3046
+ t.vertex = new p(s === 2 ? O : S);
2793
3047
  }
2794
- e != null && e.vertex && (e != null && e.fragment) && (n.vertex = new d(e.vertex), n.fragment = new d(e.fragment));
2795
- const { vertex: t, fragment: i, ...r } = e || {};
2796
- return { ...n, ...r };
3048
+ e != null && e.vertex && (e != null && e.fragment) && (t.vertex = new p(e.vertex), t.fragment = new p(e.fragment));
3049
+ const { vertex: n, fragment: i, ...r } = e || {};
3050
+ return { ...t, ...r };
2797
3051
  }
2798
3052
  setupListeners() {
2799
3053
  this.listeners.push(
2800
3054
  // Window resize
2801
- x.on(window, "resize", () => {
3055
+ y.on(window, "resize", () => {
2802
3056
  this.setViewport();
2803
3057
  }),
2804
3058
  // Canvas resize
2805
- x.on(this.canvasEl, "resize", () => {
3059
+ y.on(this.canvasEl, "resize", () => {
2806
3060
  this.setViewport();
2807
3061
  }),
2808
3062
  // Visibility check on scroll
2809
3063
  (() => {
2810
3064
  let e = !1;
2811
- return x.on(document, "scroll", (n) => {
3065
+ return y.on(document, "scroll", (t) => {
2812
3066
  this.options.pauseWhenHidden && (this.isInViewport() ? e && !this.isPlaying() && (this.play(), e = !1) : this.isPlaying() && (this.pause(), e = !0));
2813
3067
  });
2814
3068
  })(),
2815
3069
  // Mouse tracking
2816
- x.on(document, "mousemove", (e) => {
3070
+ y.on(document, "mousemove", (e) => {
2817
3071
  this.setMouse(e.clientX || e.pageX, e.clientY || e.pageY);
2818
3072
  }),
2819
3073
  // Touch tracking
2820
- x.on(document, "touchmove", (e) => {
3074
+ y.on(document, "touchmove", (e) => {
2821
3075
  e.touches.length > 0 && this.setMouse(e.touches[0].clientX, e.touches[0].clientY);
2822
3076
  })
2823
3077
  );
@@ -2826,21 +3080,21 @@ You can handle errors programmatically by providing an onError callback to suppr
2826
3080
  this.listeners.forEach((e) => e()), this.listeners = [];
2827
3081
  }
2828
3082
  setViewport() {
2829
- const e = this.options.dpr === "auto" ? Math.min(2, window.devicePixelRatio || 1) : this.options.dpr, n = this.canvasEl.clientWidth || this.canvasEl.width || 1, t = this.canvasEl.clientHeight || this.canvasEl.height || 1;
3083
+ const e = this.options.dpr === "auto" ? Math.min(2, window.devicePixelRatio || 1) : this.options.dpr, t = this.canvasEl.clientWidth || this.canvasEl.width || 1, n = this.canvasEl.clientHeight || this.canvasEl.height || 1;
2830
3084
  this.engine.viewport(
2831
3085
  0,
2832
3086
  0,
2833
- Math.max(1, Math.floor(n * e)),
2834
- Math.max(1, Math.floor(t * e))
3087
+ Math.max(1, Math.floor(t * e)),
3088
+ Math.max(1, Math.floor(n * e))
2835
3089
  );
2836
3090
  }
2837
3091
  isInViewport() {
2838
3092
  const e = this.canvasEl.getBoundingClientRect();
2839
3093
  return e.bottom >= 0 && e.right >= 0 && e.top <= (window.innerHeight || document.documentElement.clientHeight) && e.left <= (window.innerWidth || document.documentElement.clientWidth);
2840
3094
  }
2841
- setMouse(e, n) {
2842
- const t = this.canvasEl.getBoundingClientRect();
2843
- e >= t.left && e <= t.right && n >= t.top && n <= t.bottom && this.engine.mouse(e - t.left, n - t.top);
3095
+ setMouse(e, t) {
3096
+ const n = this.canvasEl.getBoundingClientRect();
3097
+ e >= n.left && e <= n.right && t >= n.top && t <= n.bottom && this.engine.mouse(e - n.left, t - n.top);
2844
3098
  }
2845
3099
  /**
2846
3100
  * Set a single uniform value with type checking.
@@ -2849,8 +3103,8 @@ You can handle errors programmatically by providing an onError callback to suppr
2849
3103
  * sandbox.setUniform<number>("u_time", 1.5);
2850
3104
  * sandbox.setUniform<Vec3[]>("u_colors", [[1, 0, 0], [0, 1, 0]]);
2851
3105
  */
2852
- setUniform(e, n) {
2853
- return this.engine.uniform(e, n), this;
3106
+ setUniform(e, t) {
3107
+ return this.engine.uniform(e, t), this;
2854
3108
  }
2855
3109
  /**
2856
3110
  * Set multiple uniforms at once with type checking.
@@ -2875,13 +3129,41 @@ You can handle errors programmatically by providing an onError callback to suppr
2875
3129
  getUniform(e) {
2876
3130
  return this.engine.getUniform(e);
2877
3131
  }
3132
+ /**
3133
+ * Set a texture for a sampler2D uniform.
3134
+ * @example
3135
+ * sandbox.setTexture("u_texture", imageElement);
3136
+ * sandbox.setTexture("u_texture", imageElement, { wrap: "repeat" });
3137
+ */
3138
+ setTexture(e, t, n) {
3139
+ return this.engine.texture(e, t, n), this;
3140
+ }
3141
+ /**
3142
+ * Set multiple textures at once.
3143
+ * @example
3144
+ * sandbox.setTextures({
3145
+ * u_texture: imageElement,
3146
+ * u_detail: { source: detailImg, wrap: "repeat" },
3147
+ * });
3148
+ */
3149
+ setTextures(e) {
3150
+ return this.engine.texturesFromSchema(e), this;
3151
+ }
3152
+ /**
3153
+ * Remove a texture and free its GPU resources.
3154
+ * @example
3155
+ * sandbox.removeTexture("u_texture");
3156
+ */
3157
+ removeTexture(e) {
3158
+ return this.engine.removeTexture(e), this;
3159
+ }
2878
3160
  /**
2879
3161
  * Update shaders.
2880
3162
  * @example
2881
3163
  * sandbox.setShader(vertexSource, fragmentSource);
2882
3164
  */
2883
- setShader(e, n) {
2884
- return this.options.vertex = new d(e), this.options.fragment = new d(n), this.usingCustomVertex = !0, this.engine.shader(this.options.vertex, this.options.fragment), this;
3165
+ setShader(e, t) {
3166
+ return this.options.vertex = new p(e), this.options.fragment = new p(t), this.usingCustomVertex = !0, this.engine.shader(this.options.vertex, this.options.fragment), this;
2885
3167
  }
2886
3168
  /**
2887
3169
  * Update only fragment shader (uses default vertex).
@@ -2889,9 +3171,9 @@ You can handle errors programmatically by providing an onError callback to suppr
2889
3171
  * sandbox.setFragment(fragmentSource);
2890
3172
  */
2891
3173
  setFragment(e) {
2892
- const n = new d(e), t = n.version(), i = this.options.vertex.version();
2893
- return this.options.fragment = n, t !== i && (this.usingCustomVertex || (this.options.vertex = new d(
2894
- t === 2 ? U : S
3174
+ const t = new p(e), n = t.version(), i = this.options.vertex.version();
3175
+ return this.options.fragment = t, n !== i && (this.usingCustomVertex || (this.options.vertex = new p(
3176
+ n === 2 ? O : S
2895
3177
  ))), this.engine.shader(this.options.vertex, this.options.fragment), this;
2896
3178
  }
2897
3179
  /**
@@ -2919,29 +3201,29 @@ You can handle errors programmatically by providing an onError callback to suppr
2919
3201
  /**
2920
3202
  * Add a runtime render hook.
2921
3203
  */
2922
- hook(e, n = "before") {
2923
- return n === "before" ? this.engine.onBeforeHooks.add(e) : this.engine.onAfterHooks.add(e);
3204
+ hook(e, t = "before") {
3205
+ return t === "before" ? this.engine.onBeforeHooks.add(e) : this.engine.onAfterHooks.add(e);
2924
3206
  }
2925
3207
  /**
2926
3208
  * Runtime configure the module behavior
2927
3209
  * @example
2928
3210
  * sandbox.module("my_module", { intensity: 0.5 });
2929
3211
  */
2930
- module(e, n) {
2931
- const t = y.resolveOptions(e);
2932
- if (!t)
3212
+ module(e, t) {
3213
+ const i = this.engine.getUsingModules().resolveOptions(e);
3214
+ if (!i)
2933
3215
  return console.warn(
2934
3216
  `Sandbox: Counld not find options for '${e}' function. Make sure you used the correct imported name and the module is currently in use by the shader.`
2935
3217
  ), this;
2936
- for (const [i, r] of Object.entries(n)) {
2937
- const s = t[i];
2938
- if (!s) {
3218
+ for (const [r, s] of Object.entries(t)) {
3219
+ const o = i[r];
3220
+ if (!o) {
2939
3221
  console.warn(
2940
- `Sandbox: Option '${i}' not found for function '${e}'. Make sure to check available options with Sandbox.availableModules() and provide the correct option name.`
3222
+ `Sandbox: Option '${r}' not found for function '${e}'. Make sure to check available options with Sandbox.availableModules() and provide the correct option name.`
2941
3223
  );
2942
3224
  continue;
2943
3225
  }
2944
- this.setUniform(s.uniform, r);
3226
+ this.setUniform(o.uniform, s);
2945
3227
  }
2946
3228
  return this;
2947
3229
  }
@@ -2967,8 +3249,8 @@ You can handle errors programmatically by providing an onError callback to suppr
2967
3249
  * Pause animation loop at specific time (in seconds).
2968
3250
  */
2969
3251
  pauseAt(e) {
2970
- const n = this.hook((t) => {
2971
- t.time >= e && (n(), this.pause());
3252
+ const t = this.hook((n) => {
3253
+ n.time >= e && (t(), this.pause());
2972
3254
  }, "after");
2973
3255
  return this;
2974
3256
  }
@@ -3018,6 +3300,57 @@ You can handle errors programmatically by providing an onError callback to suppr
3018
3300
  get canvas() {
3019
3301
  return this.canvasEl;
3020
3302
  }
3303
+ /**
3304
+ * Export current frame as a data URL string.
3305
+ * Requires `preserveDrawingBuffer: true` if called while playing.
3306
+ * @example
3307
+ * const url = sandbox.renderAt(1.5).exportAsURL("image/png");
3308
+ */
3309
+ exportAsURL(e = "image/png", t) {
3310
+ return this.canvas.toDataURL(e, t);
3311
+ }
3312
+ /**
3313
+ * Export current frame as a Blob.
3314
+ * Requires `preserveDrawingBuffer: true` if called while playing.
3315
+ * @example
3316
+ * const blob = await sandbox.renderAt(1.5).exportAsBlob("image/png");
3317
+ */
3318
+ exportAsBlob(e = "image/png", t) {
3319
+ return new Promise((n, i) => {
3320
+ this.canvas.toBlob(
3321
+ (r) => {
3322
+ r ? n(r) : i(new Error("Failed to create blob from canvas."));
3323
+ },
3324
+ e,
3325
+ t
3326
+ );
3327
+ });
3328
+ }
3329
+ /**
3330
+ * Export current frame as an HTMLImageElement.
3331
+ * Requires `preserveDrawingBuffer: true` if called while playing.
3332
+ * @example
3333
+ * const img = sandbox.renderAt(1.5).exportAsImage("image/png");
3334
+ * img.onload = () => document.body.appendChild(img);
3335
+ */
3336
+ exportAsImage(e = "image/png", t) {
3337
+ const n = new Image();
3338
+ return n.src = this.exportAsURL(e, t), n;
3339
+ }
3340
+ /**
3341
+ * Capture the canvas as a MediaStream for video calls or recording.
3342
+ * @example
3343
+ * // WebRTC video call
3344
+ * const stream = sandbox.stream(30);
3345
+ * peerConnection.addTrack(stream.getVideoTracks()[0], stream);
3346
+ *
3347
+ * @example
3348
+ * // Record to video file
3349
+ * const recorder = new MediaRecorder(sandbox.stream(30));
3350
+ */
3351
+ stream(e) {
3352
+ return this.canvasEl.captureStream(e);
3353
+ }
3021
3354
  /**
3022
3355
  * Destroy sandbox and release all resources.
3023
3356
  * @example
@@ -3030,26 +3363,28 @@ You can handle errors programmatically by providing an onError callback to suppr
3030
3363
  }
3031
3364
  }
3032
3365
  export {
3033
- $ as Sandbox,
3034
- X as SandboxAttemptedToImportDefaultFunctionError,
3035
- K as SandboxAttemptedToImportMainFunctionError,
3036
- de as SandboxContextCreationError,
3366
+ V as Sandbox,
3367
+ K as SandboxAttemptedToImportDefaultFunctionError,
3368
+ Y as SandboxAttemptedToImportMainFunctionError,
3369
+ pe as SandboxContextCreationError,
3037
3370
  h as SandboxError,
3038
3371
  Q as SandboxForbiddenModuleNameError,
3039
3372
  _ as SandboxGLSLShaderCompilationError,
3040
- ne as SandboxMentionCouldNotBeReplacedError,
3373
+ te as SandboxMentionCouldNotBeReplacedError,
3041
3374
  ee as SandboxMentionFunctionNotFoundError,
3042
3375
  Z as SandboxMentionUniformNotFoundError,
3043
- Y as SandboxModuleMethodNotFoundError,
3376
+ X as SandboxModuleMethodNotFoundError,
3044
3377
  j as SandboxModuleNotFoundError,
3045
3378
  ie as SandboxOnHookCallbackError,
3046
- te as SandboxOnLoadCallbackError,
3379
+ ne as SandboxOnLoadCallbackError,
3047
3380
  J as SandboxOverwriteModuleError,
3048
3381
  R as SandboxProgramError,
3049
- H as SandboxShaderDuplicateImportNameError,
3050
- q as SandboxShaderImportSyntaxError,
3051
- C as SandboxShaderRequirementMismatchError,
3052
- G as SandboxShaderVersionMismatchError,
3053
- W as SandboxShaderWithoutFunctionError,
3054
- z as SandboxWebGLNotSupportedError
3382
+ q as SandboxShaderDuplicateImportNameError,
3383
+ H as SandboxShaderImportSyntaxError,
3384
+ T as SandboxShaderRequirementMismatchError,
3385
+ W as SandboxShaderVersionMismatchError,
3386
+ z as SandboxShaderWithoutFunctionError,
3387
+ ve as SandboxTextureCreationError,
3388
+ ge as SandboxTextureUnitLimitError,
3389
+ G as SandboxWebGLNotSupportedError
3055
3390
  };