textmode.synth.js 1.1.1 → 1.2.0-beta.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.
Files changed (41) hide show
  1. package/dist/textmode.synth.esm.js +613 -329
  2. package/dist/textmode.synth.umd.js +202 -47
  3. package/dist/types/api/index.d.ts +1 -1
  4. package/dist/types/api/index.d.ts.map +1 -1
  5. package/dist/types/api/sources.d.ts +57 -23
  6. package/dist/types/api/sources.d.ts.map +1 -1
  7. package/dist/types/augmentations/textmode.d.ts +2 -2
  8. package/dist/types/augmentations/textmode.d.ts.map +1 -1
  9. package/dist/types/compiler/GLSLGenerator.d.ts +3 -1
  10. package/dist/types/compiler/GLSLGenerator.d.ts.map +1 -1
  11. package/dist/types/compiler/SynthCompiler.d.ts.map +1 -1
  12. package/dist/types/compiler/TextmodeSourceManager.d.ts +57 -0
  13. package/dist/types/compiler/TextmodeSourceManager.d.ts.map +1 -0
  14. package/dist/types/compiler/TransformCodeGenerator.d.ts +17 -6
  15. package/dist/types/compiler/TransformCodeGenerator.d.ts.map +1 -1
  16. package/dist/types/compiler/types.d.ts +4 -0
  17. package/dist/types/compiler/types.d.ts.map +1 -1
  18. package/dist/types/core/ISynthSource.d.ts +122 -0
  19. package/dist/types/core/ISynthSource.d.ts.map +1 -1
  20. package/dist/types/core/SynthSource.d.ts +15 -1
  21. package/dist/types/core/SynthSource.d.ts.map +1 -1
  22. package/dist/types/core/types.d.ts +33 -3
  23. package/dist/types/core/types.d.ts.map +1 -1
  24. package/dist/types/extensions/textmodelayer.d.ts.map +1 -1
  25. package/dist/types/index.d.ts +1 -1
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/dist/types/lifecycle/synthRender.d.ts.map +1 -1
  28. package/dist/types/transforms/categories/combine.d.ts +8 -0
  29. package/dist/types/transforms/categories/combine.d.ts.map +1 -1
  30. package/dist/types/transforms/categories/coordinates.d.ts +8 -0
  31. package/dist/types/transforms/categories/coordinates.d.ts.map +1 -1
  32. package/dist/types/transforms/categories/index.d.ts +3 -3
  33. package/dist/types/transforms/categories/index.d.ts.map +1 -1
  34. package/dist/types/transforms/categories/sources.d.ts +3 -0
  35. package/dist/types/transforms/categories/sources.d.ts.map +1 -1
  36. package/dist/types/utils/collectExternalLayerRefs.d.ts.map +1 -1
  37. package/dist/types/utils/collectTextmodeSourceRefs.d.ts +8 -0
  38. package/dist/types/utils/collectTextmodeSourceRefs.d.ts.map +1 -0
  39. package/dist/types/utils/index.d.ts +1 -0
  40. package/dist/types/utils/index.d.ts.map +1 -1
  41. package/package.json +3 -3
@@ -1,12 +1,12 @@
1
- const re = { src: { returnType: "vec4", args: [{ type: "vec2", name: "_st" }] }, coord: { returnType: "vec2", args: [{ type: "vec2", name: "_st" }] }, color: { returnType: "vec4", args: [{ type: "vec4", name: "_c0" }] }, combine: { returnType: "vec4", args: [{ type: "vec4", name: "_c0" }, { type: "vec4", name: "_c1" }] }, combineCoord: { returnType: "vec2", args: [{ type: "vec2", name: "_st" }, { type: "vec4", name: "_c0" }] } };
2
- function oe(t) {
3
- const e = re[t.type], n = [...e.args, ...t.inputs.map((o) => ({ type: o.type, name: o.name }))].map((o) => `${o.type} ${o.name}`).join(", "), r = `
1
+ const ae = { src: { returnType: "vec4", args: [{ type: "vec2", name: "_st" }] }, coord: { returnType: "vec2", args: [{ type: "vec2", name: "_st" }] }, color: { returnType: "vec4", args: [{ type: "vec4", name: "_c0" }] }, combine: { returnType: "vec4", args: [{ type: "vec4", name: "_c0" }, { type: "vec4", name: "_c1" }] }, combineCoord: { returnType: "vec2", args: [{ type: "vec2", name: "_st" }, { type: "vec4", name: "_c0" }] } };
2
+ function se(t) {
3
+ const e = ae[t.type], n = [...e.args, ...t.inputs.map((o) => ({ type: o.type, name: o.name }))].map((o) => `${o.type} ${o.name}`).join(", "), r = `
4
4
  ${e.returnType} ${t.name}(${n}) {
5
5
  ${t.glsl}
6
6
  }`;
7
7
  return { ...t, glslFunction: r };
8
8
  }
9
- class ae {
9
+ class ce {
10
10
  _transforms = /* @__PURE__ */ new Map();
11
11
  _processedCache = /* @__PURE__ */ new Map();
12
12
  register(e) {
@@ -22,7 +22,7 @@ class ae {
22
22
  let n = this._processedCache.get(e);
23
23
  if (!n) {
24
24
  const r = this._transforms.get(e);
25
- r && (n = oe(r), this._processedCache.set(e, n));
25
+ r && (n = se(r), this._processedCache.set(e, n));
26
26
  }
27
27
  return n;
28
28
  }
@@ -51,31 +51,31 @@ class ae {
51
51
  return this._transforms.size;
52
52
  }
53
53
  }
54
- const P = new ae(), Y = /* @__PURE__ */ new Set(["src"]);
55
- class se {
54
+ const L = new ce(), G = /* @__PURE__ */ new Set(["src"]);
55
+ class le {
56
56
  _generatedFunctions = {};
57
57
  _synthSourceClass = null;
58
58
  setSynthSourceClass(e) {
59
59
  this._synthSourceClass = e;
60
60
  }
61
61
  injectMethods(e) {
62
- const n = P.getAll();
62
+ const n = L.getAll();
63
63
  for (const r of n) this._injectMethod(e, r);
64
64
  }
65
65
  _injectMethod(e, n) {
66
- const r = this._synthSourceClass, { name: o, inputs: a, type: u } = n, s = e;
67
- if (u === "combine" || u === "combineCoord") s[o] = function(c, ...i) {
68
- let l = c;
69
- if (r && !(c instanceof r)) {
70
- const p = new r(), f = typeof c == "number" ? [c, c, c, null] : [c, null, null, null];
71
- p.addTransform("solid", f), l = p;
66
+ const r = this._synthSourceClass, { name: o, inputs: a, type: u } = n, l = e;
67
+ if (u === "combine" || u === "combineCoord") l[o] = function(m, ...i) {
68
+ let s = m;
69
+ if (r && !(m instanceof r)) {
70
+ const c = new r(), f = typeof m == "number" ? [m, m, m, null] : [m, null, null, null];
71
+ c.addTransform("solid", f), s = c;
72
72
  }
73
- return this.addCombineTransform(o, l, k(a, i));
73
+ return this.addCombineTransform(o, s, U(a, i));
74
74
  };
75
75
  else {
76
- const c = this;
77
- s[o] = function(...i) {
78
- return i = c._expandColorArgs(o, i), this.addTransform(o, k(a, i));
76
+ const m = this;
77
+ l[o] = function(...i) {
78
+ return i = m._expandColorArgs(o, i), this.addTransform(o, U(a, i));
79
79
  };
80
80
  }
81
81
  }
@@ -88,12 +88,12 @@ class se {
88
88
  }
89
89
  generateStandaloneFunctions() {
90
90
  if (!this._synthSourceClass) throw new Error("[TransformFactory] SynthSource class not set. Call setSynthSourceClass first.");
91
- const e = {}, n = P.getAll(), r = this._synthSourceClass;
92
- for (const o of n) if (Y.has(o.type)) {
91
+ const e = {}, n = L.getAll(), r = this._synthSourceClass;
92
+ for (const o of n) if (G.has(o.type)) {
93
93
  const { name: a, inputs: u } = o;
94
- e[a] = (...s) => {
95
- const c = new r();
96
- return s = this._expandColorArgs(a, s), c.addTransform(a, k(u, s));
94
+ e[a] = (...l) => {
95
+ const m = new r();
96
+ return l = this._expandColorArgs(a, l), m.addTransform(a, U(u, l));
97
97
  };
98
98
  }
99
99
  return this._generatedFunctions = e, e;
@@ -102,27 +102,47 @@ class se {
102
102
  return this._generatedFunctions;
103
103
  }
104
104
  addTransform(e, n) {
105
- if (P.register(e), n && this._injectMethod(n, e), Y.has(e.type) && this._synthSourceClass) {
105
+ if (L.register(e), n && this._injectMethod(n, e), G.has(e.type) && this._synthSourceClass) {
106
106
  const r = this._synthSourceClass, { name: o, inputs: a } = e;
107
107
  this._generatedFunctions[o] = (...u) => {
108
- const s = new r();
109
- return u = this._expandColorArgs(o, u), s.addTransform(o, k(a, u));
108
+ const l = new r();
109
+ return u = this._expandColorArgs(o, u), l.addTransform(o, U(a, u));
110
110
  };
111
111
  }
112
112
  }
113
113
  }
114
- function k(t, e) {
114
+ function U(t, e) {
115
115
  return t.map((n, r) => e[r] ?? n.default);
116
116
  }
117
- const z = new se(), S = { charColor: "prevCharColorBuffer", char: "prevCharBuffer", cellColor: "prevCellColorBuffer" }, $ = { charColor: "_charColor", char: "_char", cellColor: "_cellColor" }, ce = { name: "osc", type: "src", inputs: [{ name: "frequency", type: "float", default: 60 }, { name: "sync", type: "float", default: 0.1 }, { name: "offset", type: "float", default: 0 }], glsl: `
117
+ const B = new le(), $ = { charColor: "prevCharColorBuffer", char: "prevCharBuffer", cellColor: "prevCellColorBuffer" }, R = { charColor: "_charColor", char: "_char", cellColor: "_cellColor" }, ie = { name: "osc", type: "src", inputs: [{ name: "frequency", type: "float", default: 60 }, { name: "sync", type: "float", default: 0.1 }, { name: "offset", type: "float", default: 0 }], glsl: `
118
118
  vec2 st = _st;
119
119
  float r = sin((st.x - offset/frequency + time*sync) * frequency) * 0.5 + 0.5;
120
120
  float g = sin((st.x + time*sync) * frequency) * 0.5 + 0.5;
121
121
  float b = sin((st.x + offset/frequency + time*sync) * frequency) * 0.5 + 0.5;
122
122
  return vec4(r, g, b, 1.0);
123
- `, description: "Generate oscillating color pattern" }, ie = { name: "noise", type: "src", inputs: [{ name: "scale", type: "float", default: 10 }, { name: "offset", type: "float", default: 0.1 }], glsl: `
123
+ `, description: "Generate oscillating color pattern" }, ue = { name: "noise", type: "src", inputs: [{ name: "scale", type: "float", default: 10 }, { name: "offset", type: "float", default: 0.1 }], glsl: `
124
124
  return vec4(vec3(_noise(vec3(_st * scale, offset * time))), 1.0);
125
- `, description: "Generate noise pattern" }, le = { name: "voronoi", type: "src", inputs: [{ name: "scale", type: "float", default: 5 }, { name: "speed", type: "float", default: 0.3 }, { name: "blending", type: "float", default: 0.3 }], glsl: `
125
+ `, description: "Generate noise pattern" }, fe = { name: "plasma", type: "src", inputs: [{ name: "scale", type: "float", default: 10 }, { name: "speed", type: "float", default: 0.5 }, { name: "phase", type: "float", default: 0 }, { name: "contrast", type: "float", default: 1 }], glsl: `
126
+ float t = time * speed + phase;
127
+ float v = 0.0;
128
+ v += sin((_st.x * scale) + t);
129
+ v += sin((_st.y * scale * 1.1) + t * 1.2);
130
+ v += sin(((_st.x + _st.y) * scale * 0.7) + t * 0.8);
131
+ v = v / 3.0;
132
+ v = v * 0.5 + 0.5;
133
+ v = clamp((v - 0.5) * contrast + 0.5, 0.0, 1.0);
134
+ return vec4(vec3(v), 1.0);
135
+ `, description: "Generate plasma-like sine field" }, me = { name: "moire", type: "src", inputs: [{ name: "freqA", type: "float", default: 20 }, { name: "freqB", type: "float", default: 21 }, { name: "angleA", type: "float", default: 0 }, { name: "angleB", type: "float", default: 1.5708 }, { name: "speed", type: "float", default: 0.1 }, { name: "phase", type: "float", default: 0 }], glsl: `
136
+ float t = time * speed + phase;
137
+ vec2 p = _st - vec2(0.5);
138
+ vec2 dirA = vec2(cos(angleA), sin(angleA));
139
+ vec2 dirB = vec2(cos(angleB), sin(angleB));
140
+ float a = sin(dot(p, dirA) * freqA + t);
141
+ float b = sin(dot(p, dirB) * freqB - t * 0.7);
142
+ float v = a * b;
143
+ v = v * 0.5 + 0.5;
144
+ return vec4(vec3(v), 1.0);
145
+ `, description: "Generate moire interference patterns" }, pe = { name: "voronoi", type: "src", inputs: [{ name: "scale", type: "float", default: 5 }, { name: "speed", type: "float", default: 0.3 }, { name: "blending", type: "float", default: 0.3 }], glsl: `
126
146
  vec3 color = vec3(0.0);
127
147
  vec2 st = _st * scale;
128
148
  vec2 i_st = floor(st);
@@ -146,20 +166,23 @@ const z = new se(), S = { charColor: "prevCharColorBuffer", char: "prevCharBuffe
146
166
  color += dot(m_point, vec2(0.3, 0.6));
147
167
  color *= 1.0 - blending * m_dist;
148
168
  return vec4(color, 1.0);
149
- `, description: "Generate voronoi pattern" }, ue = { name: "gradient", type: "src", inputs: [{ name: "speed", type: "float", default: 0 }], glsl: `
169
+ `, description: "Generate voronoi pattern" }, de = { name: "gradient", type: "src", inputs: [{ name: "speed", type: "float", default: 0 }], glsl: `
150
170
  return vec4(_st, sin(time * speed), 1.0);
151
- `, description: "Generate gradient pattern" }, fe = { name: "shape", type: "src", inputs: [{ name: "sides", type: "float", default: 3 }, { name: "radius", type: "float", default: 0.3 }, { name: "smoothing", type: "float", default: 0.01 }], glsl: `
171
+ `, description: "Generate gradient pattern" }, he = { name: "shape", type: "src", inputs: [{ name: "sides", type: "float", default: 3 }, { name: "radius", type: "float", default: 0.3 }, { name: "smoothing", type: "float", default: 0.01 }], glsl: `
152
172
  vec2 st = _st * 2.0 - 1.0;
153
173
  float a = atan(st.x, st.y) + 3.1416;
154
174
  float r = (2.0 * 3.1416) / sides;
155
175
  float d = cos(floor(0.5 + a/r) * r - a) * length(st);
156
176
  return vec4(vec3(1.0 - smoothstep(radius, radius + smoothing + 0.0000001, d)), 1.0);
157
- `, description: "Generate polygon shape" }, pe = { name: "solid", type: "src", inputs: [{ name: "r", type: "float", default: 0 }, { name: "g", type: "float", default: 0 }, { name: "b", type: "float", default: 0 }, { name: "a", type: "float", default: 1 }], glsl: `
177
+ `, description: "Generate polygon shape" }, ge = { name: "solid", type: "src", inputs: [{ name: "r", type: "float", default: 0 }, { name: "g", type: "float", default: 0 }, { name: "b", type: "float", default: 0 }, { name: "a", type: "float", default: 1 }], glsl: `
158
178
  return vec4(r, g, b, a);
159
- `, description: "Generate solid color" }, me = { name: "src", type: "src", inputs: [], glsl: `
160
- return texture(${S.charColor}, fract(_st));
161
- `, description: "Sample the previous frame for feedback effects. Context-aware: automatically samples the appropriate texture based on where it is used (char, charColor, or cellColor context)." }, he = [ce, ie, le, ue, fe, pe, me];
162
- function q(t) {
179
+ `, description: "Generate solid color" }, ye = { name: "src", type: "src", inputs: [], glsl: `
180
+ return texture(${$.charColor}, fract(_st));
181
+ `, description: "Sample the previous frame for feedback effects. Context-aware: automatically samples the appropriate texture based on where it is used (char, charColor, or cellColor context)." }, _e = { name: "srcTexture", type: "src", inputs: [], glsl: `
182
+ // Placeholder - actual texture sampling is handled dynamically per TextmodeSource
183
+ return texture(u_textmodeSource0, fract(_st));
184
+ `, description: "Sample from a TextmodeSource (image/video). Context-aware: the actual sampler uniform is determined at compile time based on the source reference." }, ve = [ie, ue, fe, me, pe, de, he, ge, ye, _e];
185
+ function Q(t) {
163
186
  const e = t === "x" ? "scrollX" : "scrollY";
164
187
  return { name: e, type: "coord", inputs: [{ name: e, type: "float", default: 0.5 }, { name: "speed", type: "float", default: 0 }], glsl: `
165
188
  vec2 st = _st;
@@ -167,38 +190,38 @@ function q(t) {
167
190
  return fract(st);
168
191
  `, description: `Scroll ${t.toUpperCase()} coordinate` };
169
192
  }
170
- function H(t) {
193
+ function W(t) {
171
194
  return { name: t === "x" ? "repeatX" : "repeatY", type: "coord", inputs: [{ name: "reps", type: "float", default: 3 }, { name: "offset", type: "float", default: 0 }], glsl: `
172
195
  vec2 st = _st * vec2(${t === "x" ? "reps, 1.0" : "1.0, reps"});
173
196
  st.${t === "x" ? "y" : "x"} += step(1.0, mod(st.${t}, 2.0)) * offset;
174
197
  return fract(st);
175
198
  `, description: "Repeat pattern " + (t === "x" ? "horizontally" : "vertically") };
176
199
  }
177
- const de = { name: "rotate", type: "coord", inputs: [{ name: "angle", type: "float", default: 10 }, { name: "speed", type: "float", default: 0 }], glsl: `
200
+ const xe = { name: "rotate", type: "coord", inputs: [{ name: "angle", type: "float", default: 10 }, { name: "speed", type: "float", default: 0 }], glsl: `
178
201
  vec2 xy = _st - vec2(0.5);
179
202
  float ang = angle + speed * time;
180
203
  xy = mat2(cos(ang), -sin(ang), sin(ang), cos(ang)) * xy;
181
204
  xy += 0.5;
182
205
  return xy;
183
- `, description: "Rotate coordinates" }, ye = { name: "scale", type: "coord", inputs: [{ name: "amount", type: "float", default: 1.5 }, { name: "xMult", type: "float", default: 1 }, { name: "yMult", type: "float", default: 1 }, { name: "offsetX", type: "float", default: 0.5 }, { name: "offsetY", type: "float", default: 0.5 }], glsl: `
206
+ `, description: "Rotate coordinates" }, Ce = { name: "scale", type: "coord", inputs: [{ name: "amount", type: "float", default: 1.5 }, { name: "xMult", type: "float", default: 1 }, { name: "yMult", type: "float", default: 1 }, { name: "offsetX", type: "float", default: 0.5 }, { name: "offsetY", type: "float", default: 0.5 }], glsl: `
184
207
  vec2 xy = _st - vec2(offsetX, offsetY);
185
208
  xy *= (1.0 / vec2(amount * xMult, amount * yMult));
186
209
  xy += vec2(offsetX, offsetY);
187
210
  return xy;
188
- `, description: "Scale coordinates" }, ge = { name: "scroll", type: "coord", inputs: [{ name: "scrollX", type: "float", default: 0.5 }, { name: "scrollY", type: "float", default: 0.5 }, { name: "speedX", type: "float", default: 0 }, { name: "speedY", type: "float", default: 0 }], glsl: `
211
+ `, description: "Scale coordinates" }, be = { name: "scroll", type: "coord", inputs: [{ name: "scrollX", type: "float", default: 0.5 }, { name: "scrollY", type: "float", default: 0.5 }, { name: "speedX", type: "float", default: 0 }, { name: "speedY", type: "float", default: 0 }], glsl: `
189
212
  vec2 st = _st;
190
213
  st.x += scrollX + time * speedX;
191
214
  st.y += scrollY + time * speedY;
192
215
  return fract(st);
193
- `, description: "Scroll coordinates" }, _e = q("x"), ve = q("y"), Ce = { name: "pixelate", type: "coord", inputs: [{ name: "pixelX", type: "float", default: 20 }, { name: "pixelY", type: "float", default: 20 }], glsl: `
216
+ `, description: "Scroll coordinates" }, Se = Q("x"), we = Q("y"), $e = { name: "pixelate", type: "coord", inputs: [{ name: "pixelX", type: "float", default: 20 }, { name: "pixelY", type: "float", default: 20 }], glsl: `
194
217
  vec2 xy = vec2(pixelX, pixelY);
195
218
  return (floor(_st * xy) + 0.5) / xy;
196
- `, description: "Pixelate coordinates" }, xe = { name: "repeat", type: "coord", inputs: [{ name: "repeatX", type: "float", default: 3 }, { name: "repeatY", type: "float", default: 3 }, { name: "offsetX", type: "float", default: 0 }, { name: "offsetY", type: "float", default: 0 }], glsl: `
219
+ `, description: "Pixelate coordinates" }, Me = { name: "repeat", type: "coord", inputs: [{ name: "repeatX", type: "float", default: 3 }, { name: "repeatY", type: "float", default: 3 }, { name: "offsetX", type: "float", default: 0 }, { name: "offsetY", type: "float", default: 0 }], glsl: `
197
220
  vec2 st = _st * vec2(repeatX, repeatY);
198
221
  st.x += step(1.0, mod(st.y, 2.0)) * offsetX;
199
222
  st.y += step(1.0, mod(st.x, 2.0)) * offsetY;
200
223
  return fract(st);
201
- `, description: "Repeat pattern" }, be = H("x"), Se = H("y"), we = { name: "kaleid", type: "coord", inputs: [{ name: "nSides", type: "float", default: 4 }], glsl: `
224
+ `, description: "Repeat pattern" }, Te = W("x"), Fe = W("y"), Re = { name: "kaleid", type: "coord", inputs: [{ name: "nSides", type: "float", default: 4 }], glsl: `
202
225
  vec2 st = _st;
203
226
  st -= 0.5;
204
227
  float r = length(st);
@@ -207,81 +230,184 @@ const de = { name: "rotate", type: "coord", inputs: [{ name: "angle", type: "flo
207
230
  a = mod(a, pi / nSides);
208
231
  a = abs(a - pi / nSides / 2.0);
209
232
  return r * vec2(cos(a), sin(a));
210
- `, description: "Kaleidoscope effect" }, Me = [de, ye, ge, _e, ve, Ce, xe, be, Se, we], $e = [{ name: "scale", type: "float", default: 1 }, { name: "offset", type: "float", default: 0 }];
211
- function V(t) {
212
- return { name: t, type: "color", inputs: $e, glsl: `
233
+ `, description: "Kaleidoscope effect" }, Ae = { name: "polar", type: "coord", inputs: [{ name: "angle", type: "float", default: 0 }, { name: "radius", type: "float", default: 1 }], glsl: `
234
+ vec2 st = _st - vec2(0.5);
235
+ float r = length(st) * radius;
236
+ float a = atan(st.y, st.x) + angle;
237
+ a = a / (2.0 * 3.1416);
238
+ return vec2(fract(a), r);
239
+ `, description: "Convert to polar coordinates" }, Pe = { name: "twirl", type: "coord", inputs: [{ name: "amount", type: "float", default: 2 }, { name: "radius", type: "float", default: 0.5 }, { name: "centerX", type: "float", default: 0.5 }, { name: "centerY", type: "float", default: 0.5 }], glsl: `
240
+ vec2 center = vec2(centerX, centerY);
241
+ vec2 p = _st - center;
242
+ float r = length(p);
243
+ float safeRadius = max(radius, 0.00001);
244
+ float t = clamp((safeRadius - r) / safeRadius, 0.0, 1.0);
245
+ float angle = amount * t * t;
246
+ float s = sin(angle);
247
+ float c = cos(angle);
248
+ p = vec2(c * p.x - s * p.y, s * p.x + c * p.y);
249
+ return p + center;
250
+ `, description: "Twirl distortion with radial falloff" }, ke = { name: "swirl", type: "coord", inputs: [{ name: "amount", type: "float", default: 4 }, { name: "centerX", type: "float", default: 0.5 }, { name: "centerY", type: "float", default: 0.5 }], glsl: `
251
+ vec2 center = vec2(centerX, centerY);
252
+ vec2 p = _st - center;
253
+ float r = length(p);
254
+ float angle = amount * r;
255
+ float s = sin(angle);
256
+ float c = cos(angle);
257
+ p = vec2(c * p.x - s * p.y, s * p.x + c * p.y);
258
+ return p + center;
259
+ `, description: "Swirl distortion around a center" }, Ie = { name: "mirror", type: "coord", inputs: [{ name: "mirrorX", type: "float", default: 1 }, { name: "mirrorY", type: "float", default: 1 }], glsl: `
260
+ vec2 m = abs(fract(_st * 2.0) - 1.0);
261
+ vec2 mixAmt = clamp(vec2(mirrorX, mirrorY), 0.0, 1.0);
262
+ return mix(_st, m, mixAmt);
263
+ `, description: "Mirror coordinates across X and/or Y axes" }, Le = { name: "shear", type: "coord", inputs: [{ name: "x", type: "float", default: 0 }, { name: "y", type: "float", default: 0 }, { name: "centerX", type: "float", default: 0.5 }, { name: "centerY", type: "float", default: 0.5 }], glsl: `
264
+ vec2 center = vec2(centerX, centerY);
265
+ vec2 p = _st - center;
266
+ p = vec2(p.x + y * p.y, p.y + x * p.x);
267
+ return p + center;
268
+ `, description: "Shear coordinates along X and Y" }, Ue = { name: "barrel", type: "coord", inputs: [{ name: "amount", type: "float", default: 0.5 }, { name: "centerX", type: "float", default: 0.5 }, { name: "centerY", type: "float", default: 0.5 }], glsl: `
269
+ vec2 center = vec2(centerX, centerY);
270
+ vec2 p = _st - center;
271
+ float r2 = dot(p, p);
272
+ p *= 1.0 + amount * r2;
273
+ return p + center;
274
+ `, description: "Barrel distortion (bulge outward)" }, De = { name: "pinch", type: "coord", inputs: [{ name: "amount", type: "float", default: 0.5 }, { name: "centerX", type: "float", default: 0.5 }, { name: "centerY", type: "float", default: 0.5 }], glsl: `
275
+ vec2 center = vec2(centerX, centerY);
276
+ vec2 p = _st - center;
277
+ float r2 = dot(p, p);
278
+ p *= 1.0 / (1.0 + amount * r2);
279
+ return p + center;
280
+ `, description: "Pinch distortion (pull inward)" }, Ne = { name: "fisheye", type: "coord", inputs: [{ name: "amount", type: "float", default: 1 }, { name: "centerX", type: "float", default: 0.5 }, { name: "centerY", type: "float", default: 0.5 }], glsl: `
281
+ vec2 center = vec2(centerX, centerY);
282
+ vec2 p = _st - center;
283
+ float r = length(p);
284
+ if (r > 0.0) {
285
+ float k = max(amount, 0.00001);
286
+ float r2 = atan(r * k) / atan(k);
287
+ p = p / r * r2;
288
+ }
289
+ return p + center;
290
+ `, description: "Fisheye lens distortion" }, Oe = [xe, Ce, be, Se, we, $e, Me, Te, Fe, Re, Ae, Pe, ke, Ie, Le, Ue, De, Ne], ze = [{ name: "scale", type: "float", default: 1 }, { name: "offset", type: "float", default: 0 }];
291
+ function X(t) {
292
+ return { name: t, type: "color", inputs: ze, glsl: `
213
293
  return vec4(_c0.${t} * scale + offset);
214
294
  `, description: `Extract ${t === "r" ? "red" : t === "g" ? "green" : "blue"} channel` };
215
295
  }
216
- const Te = { name: "brightness", type: "color", inputs: [{ name: "amount", type: "float", default: 0.4 }], glsl: `
296
+ const Ye = { name: "brightness", type: "color", inputs: [{ name: "amount", type: "float", default: 0.4 }], glsl: `
217
297
  return vec4(_c0.rgb + vec3(amount), _c0.a);
218
- `, description: "Adjust brightness" }, Fe = { name: "contrast", type: "color", inputs: [{ name: "amount", type: "float", default: 1.6 }], glsl: `
298
+ `, description: "Adjust brightness" }, Be = { name: "contrast", type: "color", inputs: [{ name: "amount", type: "float", default: 1.6 }], glsl: `
219
299
  vec4 c = (_c0 - vec4(0.5)) * vec4(amount) + vec4(0.5);
220
300
  return vec4(c.rgb, _c0.a);
221
- `, description: "Adjust contrast" }, Pe = { name: "invert", type: "color", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
301
+ `, description: "Adjust contrast" }, Ee = { name: "invert", type: "color", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
222
302
  return vec4((1.0 - _c0.rgb) * amount + _c0.rgb * (1.0 - amount), _c0.a);
223
- `, description: "Invert colors" }, ke = { name: "saturate", type: "color", inputs: [{ name: "amount", type: "float", default: 2 }], glsl: `
303
+ `, description: "Invert colors" }, Ve = { name: "saturate", type: "color", inputs: [{ name: "amount", type: "float", default: 2 }], glsl: `
224
304
  vec3 intensity = vec3(_luminance(_c0.rgb));
225
305
  return vec4(mix(intensity, _c0.rgb, amount), _c0.a);
226
- `, description: "Adjust saturation" }, Ie = { name: "hue", type: "color", inputs: [{ name: "hue", type: "float", default: 0.4 }], glsl: `
306
+ `, description: "Adjust saturation" }, Xe = { name: "hue", type: "color", inputs: [{ name: "hue", type: "float", default: 0.4 }], glsl: `
227
307
  vec3 c = _rgbToHsv(_c0.rgb);
228
308
  c.r += hue;
229
309
  return vec4(_hsvToRgb(c), _c0.a);
230
- `, description: "Shift hue" }, Le = { name: "colorama", type: "color", inputs: [{ name: "amount", type: "float", default: 5e-3 }], glsl: `
310
+ `, description: "Shift hue" }, je = { name: "colorama", type: "color", inputs: [{ name: "amount", type: "float", default: 5e-3 }], glsl: `
231
311
  vec3 c = _rgbToHsv(_c0.rgb);
232
312
  c += vec3(amount);
233
313
  c = _hsvToRgb(c);
234
314
  c = fract(c);
235
315
  return vec4(c, _c0.a);
236
- `, description: "Color cycle effect" }, Ae = { name: "posterize", type: "color", inputs: [{ name: "bins", type: "float", default: 3 }, { name: "gamma", type: "float", default: 0.6 }], glsl: `
316
+ `, description: "Color cycle effect" }, qe = { name: "posterize", type: "color", inputs: [{ name: "bins", type: "float", default: 3 }, { name: "gamma", type: "float", default: 0.6 }], glsl: `
237
317
  vec4 c2 = pow(_c0, vec4(gamma));
238
318
  c2 *= vec4(bins);
239
319
  c2 = floor(c2);
240
320
  c2 /= vec4(bins);
241
321
  c2 = pow(c2, vec4(1.0 / gamma));
242
322
  return vec4(c2.xyz, _c0.a);
243
- `, description: "Posterize colors" }, Re = { name: "luma", type: "color", inputs: [{ name: "threshold", type: "float", default: 0.5 }, { name: "tolerance", type: "float", default: 0.1 }], glsl: `
323
+ `, description: "Posterize colors" }, Ge = { name: "luma", type: "color", inputs: [{ name: "threshold", type: "float", default: 0.5 }, { name: "tolerance", type: "float", default: 0.1 }], glsl: `
244
324
  float a = _smoothThreshold(_luminance(_c0.rgb), threshold, tolerance);
245
325
  return vec4(_c0.rgb * a, a);
246
- `, description: "Luma key" }, Ue = { name: "thresh", type: "color", inputs: [{ name: "threshold", type: "float", default: 0.5 }, { name: "tolerance", type: "float", default: 0.04 }], glsl: `
326
+ `, description: "Luma key" }, He = { name: "thresh", type: "color", inputs: [{ name: "threshold", type: "float", default: 0.5 }, { name: "tolerance", type: "float", default: 0.04 }], glsl: `
247
327
  return vec4(vec3(_smoothThreshold(_luminance(_c0.rgb), threshold, tolerance)), _c0.a);
248
- `, description: "Threshold" }, ze = { name: "color", type: "color", inputs: [{ name: "r", type: "float", default: 1 }, { name: "g", type: "float", default: 1 }, { name: "b", type: "float", default: 1 }, { name: "a", type: "float", default: 1 }], glsl: `
328
+ `, description: "Threshold" }, Ke = { name: "color", type: "color", inputs: [{ name: "r", type: "float", default: 1 }, { name: "g", type: "float", default: 1 }, { name: "b", type: "float", default: 1 }, { name: "a", type: "float", default: 1 }], glsl: `
249
329
  vec4 c = vec4(r, g, b, a);
250
330
  vec4 pos = step(0.0, c);
251
331
  return vec4(mix((1.0 - _c0.rgb) * abs(c.rgb), c.rgb * _c0.rgb, pos.rgb), c.a * _c0.a);
252
- `, description: "Multiply by color" }, De = V("r"), Oe = V("g"), Ne = V("b"), Ve = { name: "shift", type: "color", inputs: [{ name: "r", type: "float", default: 0.5 }, { name: "g", type: "float", default: 0 }, { name: "b", type: "float", default: 0 }, { name: "a", type: "float", default: 0 }], glsl: `
332
+ `, description: "Multiply by color" }, Qe = X("r"), We = X("g"), Je = X("b"), Ze = { name: "shift", type: "color", inputs: [{ name: "r", type: "float", default: 0.5 }, { name: "g", type: "float", default: 0 }, { name: "b", type: "float", default: 0 }, { name: "a", type: "float", default: 0 }], glsl: `
253
333
  vec4 c2 = vec4(_c0);
254
334
  c2.r += fract(r);
255
335
  c2.g += fract(g);
256
336
  c2.b += fract(b);
257
337
  c2.a += fract(a);
258
338
  return vec4(c2.rgba);
259
- `, description: "Shift color channels by adding offset values" }, Ee = { name: "gamma", type: "color", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
339
+ `, description: "Shift color channels by adding offset values" }, et = { name: "gamma", type: "color", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
260
340
  return vec4(pow(max(vec3(0.0), _c0.rgb), vec3(1.0 / amount)), _c0.a);
261
- `, description: "Apply gamma correction" }, Be = { name: "levels", type: "color", inputs: [{ name: "inMin", type: "float", default: 0 }, { name: "inMax", type: "float", default: 1 }, { name: "outMin", type: "float", default: 0 }, { name: "outMax", type: "float", default: 1 }, { name: "gamma", type: "float", default: 1 }], glsl: `
341
+ `, description: "Apply gamma correction" }, tt = { name: "levels", type: "color", inputs: [{ name: "inMin", type: "float", default: 0 }, { name: "inMax", type: "float", default: 1 }, { name: "outMin", type: "float", default: 0 }, { name: "outMax", type: "float", default: 1 }, { name: "gamma", type: "float", default: 1 }], glsl: `
262
342
  vec3 v = clamp((_c0.rgb - vec3(inMin)) / (vec3(inMax - inMin) + 0.0000001), 0.0, 1.0);
263
343
  v = pow(v, vec3(1.0 / gamma));
264
344
  v = mix(vec3(outMin), vec3(outMax), v);
265
345
  return vec4(v, _c0.a);
266
- `, description: "Adjust input/output levels and gamma" }, je = { name: "clamp", type: "color", inputs: [{ name: "min", type: "float", default: 0 }, { name: "max", type: "float", default: 1 }], glsl: `
346
+ `, description: "Adjust input/output levels and gamma" }, nt = { name: "clamp", type: "color", inputs: [{ name: "min", type: "float", default: 0 }, { name: "max", type: "float", default: 1 }], glsl: `
267
347
  return vec4(clamp(_c0.rgb, vec3(min), vec3(max)), _c0.a);
268
- `, description: "Clamp color values to a range" }, Ye = [Te, Fe, Pe, ke, Ie, Le, Ae, Re, Ue, ze, De, Oe, Ne, Ve, Ee, Be, je], Xe = { name: "add", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
348
+ `, description: "Clamp color values to a range" }, rt = [Ye, Be, Ee, Ve, Xe, je, qe, Ge, He, Ke, Qe, We, Je, Ze, et, tt, nt], ot = { name: "add", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
269
349
  return (_c0 + _c1) * amount + _c0 * (1.0 - amount);
270
- `, description: "Add another source" }, Ge = { name: "sub", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
350
+ `, description: "Add another source" }, at = { name: "sub", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
271
351
  return (_c0 - _c1) * amount + _c0 * (1.0 - amount);
272
- `, description: "Subtract another source" }, qe = { name: "mult", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
352
+ `, description: "Subtract another source" }, st = { name: "mult", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
273
353
  return _c0 * (1.0 - amount) + (_c0 * _c1) * amount;
274
- `, description: "Multiply with another source" }, He = { name: "blend", type: "combine", inputs: [{ name: "amount", type: "float", default: 0.5 }], glsl: `
354
+ `, description: "Multiply with another source" }, ct = { name: "blend", type: "combine", inputs: [{ name: "amount", type: "float", default: 0.5 }], glsl: `
275
355
  return _c0 * (1.0 - amount) + _c1 * amount;
276
- `, description: "Blend with another source" }, Ke = { name: "diff", type: "combine", inputs: [], glsl: `
356
+ `, description: "Blend with another source" }, lt = { name: "diff", type: "combine", inputs: [], glsl: `
277
357
  return vec4(abs(_c0.rgb - _c1.rgb), max(_c0.a, _c1.a));
278
- `, description: "Difference with another source" }, Qe = { name: "layer", type: "combine", inputs: [], glsl: `
358
+ `, description: "Difference with another source" }, it = { name: "layer", type: "combine", inputs: [], glsl: `
279
359
  return vec4(mix(_c0.rgb, _c1.rgb, _c1.a), clamp(_c0.a + _c1.a, 0.0, 1.0));
280
- `, description: "Layer another source on top" }, We = { name: "mask", type: "combine", inputs: [], glsl: `
360
+ `, description: "Layer another source on top" }, ut = { name: "mask", type: "combine", inputs: [], glsl: `
281
361
  float a = _luminance(_c1.rgb);
282
362
  return vec4(_c0.rgb * a, a * _c0.a);
283
- `, description: "Mask with another source" }, Je = [Xe, Ge, qe, He, Ke, Qe, We];
284
- function K(t) {
363
+ `, description: "Mask with another source" }, ft = { name: "screen", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
364
+ vec3 result = 1.0 - (1.0 - _c0.rgb) * (1.0 - _c1.rgb);
365
+ vec3 outRgb = mix(_c0.rgb, result, amount);
366
+ float outA = mix(_c0.a, _c1.a, amount);
367
+ return vec4(outRgb, outA);
368
+ `, description: "Screen blend with another source" }, mt = { name: "overlay", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
369
+ vec3 mult = 2.0 * _c0.rgb * _c1.rgb;
370
+ vec3 screen = 1.0 - 2.0 * (1.0 - _c0.rgb) * (1.0 - _c1.rgb);
371
+ vec3 result = mix(mult, screen, step(0.5, _c0.rgb));
372
+ vec3 outRgb = mix(_c0.rgb, result, amount);
373
+ float outA = mix(_c0.a, _c1.a, amount);
374
+ return vec4(outRgb, outA);
375
+ `, description: "Overlay blend with another source" }, pt = { name: "softlight", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
376
+ vec3 result = (1.0 - 2.0 * _c1.rgb) * _c0.rgb * _c0.rgb + 2.0 * _c1.rgb * _c0.rgb;
377
+ vec3 outRgb = mix(_c0.rgb, result, amount);
378
+ float outA = mix(_c0.a, _c1.a, amount);
379
+ return vec4(outRgb, outA);
380
+ `, description: "Soft light blend with another source" }, dt = { name: "hardlight", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
381
+ vec3 mult = 2.0 * _c0.rgb * _c1.rgb;
382
+ vec3 screen = 1.0 - 2.0 * (1.0 - _c0.rgb) * (1.0 - _c1.rgb);
383
+ vec3 result = mix(mult, screen, step(0.5, _c1.rgb));
384
+ vec3 outRgb = mix(_c0.rgb, result, amount);
385
+ float outA = mix(_c0.a, _c1.a, amount);
386
+ return vec4(outRgb, outA);
387
+ `, description: "Hard light blend with another source" }, ht = { name: "dodge", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
388
+ vec3 result = _c0.rgb / max(vec3(0.00001), 1.0 - _c1.rgb);
389
+ result = clamp(result, 0.0, 1.0);
390
+ vec3 outRgb = mix(_c0.rgb, result, amount);
391
+ float outA = mix(_c0.a, _c1.a, amount);
392
+ return vec4(outRgb, outA);
393
+ `, description: "Color dodge blend with another source" }, gt = { name: "burn", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
394
+ vec3 result = 1.0 - (1.0 - _c0.rgb) / max(vec3(0.00001), _c1.rgb);
395
+ result = clamp(result, 0.0, 1.0);
396
+ vec3 outRgb = mix(_c0.rgb, result, amount);
397
+ float outA = mix(_c0.a, _c1.a, amount);
398
+ return vec4(outRgb, outA);
399
+ `, description: "Color burn blend with another source" }, yt = { name: "lighten", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
400
+ vec3 result = max(_c0.rgb, _c1.rgb);
401
+ vec3 outRgb = mix(_c0.rgb, result, amount);
402
+ float outA = mix(_c0.a, _c1.a, amount);
403
+ return vec4(outRgb, outA);
404
+ `, description: "Lighten blend with another source" }, _t = { name: "darken", type: "combine", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
405
+ vec3 result = min(_c0.rgb, _c1.rgb);
406
+ vec3 outRgb = mix(_c0.rgb, result, amount);
407
+ float outA = mix(_c0.a, _c1.a, amount);
408
+ return vec4(outRgb, outA);
409
+ `, description: "Darken blend with another source" }, vt = [ot, at, st, ct, lt, it, ut, ft, mt, pt, dt, ht, gt, yt, _t];
410
+ function J(t) {
285
411
  const e = t === "x" ? "scrollX" : "scrollY";
286
412
  return { name: t === "x" ? "modulateScrollX" : "modulateScrollY", type: "combineCoord", inputs: [{ name: e, type: "float", default: 0.5 }, { name: "speed", type: "float", default: 0 }], glsl: `
287
413
  vec2 st = _st;
@@ -289,30 +415,30 @@ function K(t) {
289
415
  return fract(st);
290
416
  `, description: `Modulate ${t.toUpperCase()} scroll with another source` };
291
417
  }
292
- function Q(t) {
418
+ function Z(t) {
293
419
  return { name: t === "x" ? "modulateRepeatX" : "modulateRepeatY", type: "combineCoord", inputs: [{ name: "reps", type: "float", default: 3 }, { name: "offset", type: "float", default: 0.5 }], glsl: `
294
420
  vec2 st = _st * vec2(${t === "x" ? "reps, 1.0" : "1.0, reps"});
295
421
  st.${t === "x" ? "y" : "x"} += step(1.0, mod(st.${t}, 2.0)) + _c0.r * offset;
296
422
  return fract(st);
297
423
  `, description: `Modulate ${t.toUpperCase()} repeat with another source` };
298
424
  }
299
- const Ze = { name: "modulate", type: "combineCoord", inputs: [{ name: "amount", type: "float", default: 0.1 }], glsl: `
425
+ const xt = { name: "modulate", type: "combineCoord", inputs: [{ name: "amount", type: "float", default: 0.1 }], glsl: `
300
426
  return _st + _c0.xy * amount;
301
- `, description: "Modulate coordinates with another source" }, et = { name: "modulateScale", type: "combineCoord", inputs: [{ name: "multiple", type: "float", default: 1 }, { name: "offset", type: "float", default: 1 }], glsl: `
427
+ `, description: "Modulate coordinates with another source" }, Ct = { name: "modulateScale", type: "combineCoord", inputs: [{ name: "multiple", type: "float", default: 1 }, { name: "offset", type: "float", default: 1 }], glsl: `
302
428
  vec2 xy = _st - vec2(0.5);
303
429
  xy *= (1.0 / vec2(offset + multiple * _c0.r, offset + multiple * _c0.g));
304
430
  xy += vec2(0.5);
305
431
  return xy;
306
- `, description: "Modulate scale with another source" }, tt = { name: "modulateRotate", type: "combineCoord", inputs: [{ name: "multiple", type: "float", default: 1 }, { name: "offset", type: "float", default: 0 }], glsl: `
432
+ `, description: "Modulate scale with another source" }, bt = { name: "modulateRotate", type: "combineCoord", inputs: [{ name: "multiple", type: "float", default: 1 }, { name: "offset", type: "float", default: 0 }], glsl: `
307
433
  vec2 xy = _st - vec2(0.5);
308
434
  float angle = offset + _c0.x * multiple;
309
435
  xy = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * xy;
310
436
  xy += 0.5;
311
437
  return xy;
312
- `, description: "Modulate rotation with another source" }, nt = { name: "modulatePixelate", type: "combineCoord", inputs: [{ name: "multiple", type: "float", default: 10 }, { name: "offset", type: "float", default: 3 }], glsl: `
438
+ `, description: "Modulate rotation with another source" }, St = { name: "modulatePixelate", type: "combineCoord", inputs: [{ name: "multiple", type: "float", default: 10 }, { name: "offset", type: "float", default: 3 }], glsl: `
313
439
  vec2 xy = vec2(offset + _c0.x * multiple, offset + _c0.y * multiple);
314
440
  return (floor(_st * xy) + 0.5) / xy;
315
- `, description: "Modulate pixelation with another source" }, rt = { name: "modulateKaleid", type: "combineCoord", inputs: [{ name: "nSides", type: "float", default: 4 }], glsl: `
441
+ `, description: "Modulate pixelation with another source" }, wt = { name: "modulateKaleid", type: "combineCoord", inputs: [{ name: "nSides", type: "float", default: 4 }], glsl: `
316
442
  vec2 st = _st - 0.5;
317
443
  float r = length(st);
318
444
  float a = atan(st.y, st.x);
@@ -320,24 +446,24 @@ const Ze = { name: "modulate", type: "combineCoord", inputs: [{ name: "amount",
320
446
  a = mod(a, pi / nSides);
321
447
  a = abs(a - pi / nSides / 2.0);
322
448
  return (_c0.r + r) * vec2(cos(a), sin(a));
323
- `, description: "Modulate kaleidoscope with another source" }, ot = K("x"), at = K("y"), st = { name: "modulateRepeat", type: "combineCoord", inputs: [{ name: "repeatX", type: "float", default: 3 }, { name: "repeatY", type: "float", default: 3 }, { name: "offsetX", type: "float", default: 0.5 }, { name: "offsetY", type: "float", default: 0.5 }], glsl: `
449
+ `, description: "Modulate kaleidoscope with another source" }, $t = J("x"), Mt = J("y"), Tt = { name: "modulateRepeat", type: "combineCoord", inputs: [{ name: "repeatX", type: "float", default: 3 }, { name: "repeatY", type: "float", default: 3 }, { name: "offsetX", type: "float", default: 0.5 }, { name: "offsetY", type: "float", default: 0.5 }], glsl: `
324
450
  vec2 st = _st * vec2(repeatX, repeatY);
325
451
  st.x += step(1.0, mod(st.y, 2.0)) + _c0.r * offsetX;
326
452
  st.y += step(1.0, mod(st.x, 2.0)) + _c0.g * offsetY;
327
453
  return fract(st);
328
- `, description: "Modulate repeat pattern with another source" }, ct = Q("x"), it = Q("y"), lt = { name: "modulateHue", type: "combineCoord", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
454
+ `, description: "Modulate repeat pattern with another source" }, Ft = Z("x"), Rt = Z("y"), At = { name: "modulateHue", type: "combineCoord", inputs: [{ name: "amount", type: "float", default: 1 }], glsl: `
329
455
  return _st + (vec2(_c0.g - _c0.r, _c0.b - _c0.g) * amount * 1.0 / resolution);
330
- `, description: "Modulate coordinates based on hue differences" }, ut = [Ze, et, tt, nt, rt, ot, at, st, ct, it, lt], ft = [...he, ...Me, ...Ye, ...Je, ...ut];
331
- class F {
456
+ `, description: "Modulate coordinates based on hue differences" }, Pt = [xt, Ct, bt, St, wt, $t, Mt, Tt, Ft, Rt, At], kt = [...ve, ...Oe, ...rt, ...vt, ...Pt];
457
+ class k {
332
458
  _transforms;
333
459
  constructor(e) {
334
460
  this._transforms = e;
335
461
  }
336
462
  static empty() {
337
- return new F([]);
463
+ return new k([]);
338
464
  }
339
465
  static from(e) {
340
- return new F([...e]);
466
+ return new k([...e]);
341
467
  }
342
468
  get transforms() {
343
469
  return this._transforms;
@@ -352,7 +478,7 @@ class F {
352
478
  return this._transforms.length === 0;
353
479
  }
354
480
  append(e) {
355
- return new F([...this._transforms, e]);
481
+ return new k([...this._transforms, e]);
356
482
  }
357
483
  get(e) {
358
484
  return this._transforms[e];
@@ -361,7 +487,7 @@ class F {
361
487
  return this._transforms[Symbol.iterator]();
362
488
  }
363
489
  }
364
- class y {
490
+ class _ {
365
491
  _chain;
366
492
  _charMapping;
367
493
  _nestedSources;
@@ -369,8 +495,9 @@ class y {
369
495
  _charColorSource;
370
496
  _cellColorSource;
371
497
  _charSource;
498
+ _textmodeSourceRefs;
372
499
  constructor(e) {
373
- this._chain = e?.chain ?? F.empty(), this._charMapping = e?.charMapping, this._charColorSource = e?.charColorSource, this._cellColorSource = e?.cellColorSource, this._charSource = e?.charSource, this._nestedSources = e?.nestedSources ?? /* @__PURE__ */ new Map(), this._externalLayerRefs = e?.externalLayerRefs ?? /* @__PURE__ */ new Map();
500
+ this._chain = e?.chain ?? k.empty(), this._charMapping = e?.charMapping, this._charColorSource = e?.charColorSource, this._cellColorSource = e?.cellColorSource, this._charSource = e?.charSource, this._nestedSources = e?.nestedSources ?? /* @__PURE__ */ new Map(), this._externalLayerRefs = e?.externalLayerRefs ?? /* @__PURE__ */ new Map(), this._textmodeSourceRefs = e?.textmodeSourceRefs ?? /* @__PURE__ */ new Map();
374
501
  }
375
502
  addTransform(e, n) {
376
503
  const r = { name: e, userArgs: n };
@@ -384,14 +511,19 @@ class y {
384
511
  const n = this._chain.length;
385
512
  return this._externalLayerRefs.set(n, e), this.addTransform("src", []);
386
513
  }
514
+ addTextmodeSourceRef(e) {
515
+ const n = this._chain.length;
516
+ return this._textmodeSourceRefs.set(n, e), this.addTransform("srcTexture", []);
517
+ }
387
518
  charMap(e) {
519
+ if (e.length === 0) return this._charMapping = void 0, this;
388
520
  const n = Array.from(e), r = [];
389
521
  for (const o of n) r.push(o.codePointAt(0) ?? 32);
390
522
  return this._charMapping = { chars: e, indices: r }, this;
391
523
  }
392
524
  _ensureSource(e, n, r, o) {
393
- if (e instanceof y) return e;
394
- const a = new y(), u = typeof e == "number" && n === void 0 && r === void 0 && o === void 0 ? [e, e, e, null] : [e, n, r, o].map((s) => s === void 0 ? null : s);
525
+ if (e instanceof _) return e;
526
+ const a = new _(), u = typeof e == "number" && n === void 0 && r === void 0 && o === void 0 ? [e, e, e, null] : [e, n, r, o].map((l) => l === void 0 ? null : l);
395
527
  return a.addTransform("solid", u), a;
396
528
  }
397
529
  charColor(e, n, r, o) {
@@ -409,10 +541,12 @@ class y {
409
541
  }
410
542
  clone() {
411
543
  const e = /* @__PURE__ */ new Map();
412
- for (const [r, o] of this._nestedSources) e.set(r, o.clone());
544
+ for (const [o, a] of this._nestedSources) e.set(o, a.clone());
413
545
  const n = /* @__PURE__ */ new Map();
414
- for (const [r, o] of this._externalLayerRefs) n.set(r, { ...o });
415
- return new y({ chain: F.from(this._chain.transforms), charMapping: this._charMapping, charColorSource: this._charColorSource?.clone(), cellColorSource: this._cellColorSource?.clone(), charSource: this._charSource?.clone(), nestedSources: e, externalLayerRefs: n });
546
+ for (const [o, a] of this._externalLayerRefs) n.set(o, { ...a });
547
+ const r = /* @__PURE__ */ new Map();
548
+ for (const [o, a] of this._textmodeSourceRefs) r.set(o, { ...a });
549
+ return new _({ chain: k.from(this._chain.transforms), charMapping: this._charMapping, charColorSource: this._charColorSource?.clone(), cellColorSource: this._cellColorSource?.clone(), charSource: this._charSource?.clone(), nestedSources: e, externalLayerRefs: n, textmodeSourceRefs: r });
416
550
  }
417
551
  get transforms() {
418
552
  return this._chain.transforms;
@@ -435,53 +569,56 @@ class y {
435
569
  get externalLayerRefs() {
436
570
  return this._externalLayerRefs;
437
571
  }
572
+ get textmodeSourceRefs() {
573
+ return this._textmodeSourceRefs;
574
+ }
438
575
  }
439
- const D = { linear: (t) => t, easeInQuad: (t) => t * t, easeOutQuad: (t) => t * (2 - t), easeInOutQuad: (t) => t < 0.5 ? 2 * t * t : (4 - 2 * t) * t - 1, easeInCubic: (t) => t * t * t, easeOutCubic: (t) => --t * t * t + 1, easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1, easeInQuart: (t) => t * t * t * t, easeOutQuart: (t) => 1 - --t * t * t * t, easeInOutQuart: (t) => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t, easeInQuint: (t) => t * t * t * t * t, easeOutQuint: (t) => 1 + --t * t * t * t * t, easeInOutQuint: (t) => t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t, sin: (t) => (1 + Math.sin(Math.PI * t - Math.PI / 2)) / 2 };
440
- function X(t, e) {
576
+ const E = { linear: (t) => t, easeInQuad: (t) => t * t, easeOutQuad: (t) => t * (2 - t), easeInOutQuad: (t) => t < 0.5 ? 2 * t * t : (4 - 2 * t) * t - 1, easeInCubic: (t) => t * t * t, easeOutCubic: (t) => --t * t * t + 1, easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1, easeInQuart: (t) => t * t * t * t, easeOutQuart: (t) => 1 - --t * t * t * t, easeInOutQuart: (t) => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t, easeInQuint: (t) => t * t * t * t * t, easeOutQuint: (t) => 1 + --t * t * t * t * t, easeInOutQuint: (t) => t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t, sin: (t) => (1 + Math.sin(Math.PI * t - Math.PI / 2)) / 2 };
577
+ function H(t, e) {
441
578
  return (t % e + e) % e;
442
579
  }
443
- function pt(t, e, n, r, o) {
580
+ function It(t, e, n, r, o) {
444
581
  return e === n ? (r + o) / 2 : (t - e) * (o - r) / (n - e) + r;
445
582
  }
446
- function mt() {
583
+ function Lt() {
447
584
  "fast" in Array.prototype || (Object.defineProperty(Array.prototype, "fast", { value: function(t = 1) {
448
585
  return this._speed = t, this;
449
586
  }, writable: !0, configurable: !0, enumerable: !1 }), Object.defineProperty(Array.prototype, "smooth", { value: function(t = 1) {
450
587
  return this._smooth = t, this;
451
588
  }, writable: !0, configurable: !0, enumerable: !1 }), Object.defineProperty(Array.prototype, "ease", { value: function(t = "linear") {
452
- return typeof t == "function" ? (this._smooth = 1, this._ease = t) : D[t] && (this._smooth = 1, this._ease = D[t]), this;
589
+ return typeof t == "function" ? (this._smooth = 1, this._ease = t) : E[t] && (this._smooth = 1, this._ease = E[t]), this;
453
590
  }, writable: !0, configurable: !0, enumerable: !1 }), Object.defineProperty(Array.prototype, "offset", { value: function(t = 0.5) {
454
591
  return this._offset = t % 1, this;
455
592
  }, writable: !0, configurable: !0, enumerable: !1 }), Object.defineProperty(Array.prototype, "fit", { value: function(t = 0, e = 1) {
456
- const n = Math.min(...this), r = Math.max(...this), o = this.map((a) => pt(a, n, r, t, e));
593
+ const n = Math.min(...this), r = Math.max(...this), o = this.map((a) => It(a, n, r, t, e));
457
594
  return o._speed = this._speed, o._smooth = this._smooth, o._ease = this._ease, o._offset = this._offset, o;
458
595
  }, writable: !0, configurable: !0, enumerable: !1 }));
459
596
  }
460
- function ht(t, e) {
597
+ function Ut(t, e) {
461
598
  const n = t._speed ?? 1, r = t._smooth ?? 0;
462
599
  let o = e.time * n * (e.bpm / 60) + (t._offset ?? 0);
463
600
  if (r !== 0) {
464
- const a = t._ease ?? D.linear, u = o - r / 2, s = Math.floor(u), c = X(s, t.length), i = (c + 1) % t.length, l = t[c], p = t[i];
465
- return a(Math.min((u - s) / r, 1)) * (p - l) + l;
601
+ const a = t._ease ?? E.linear, u = o - r / 2, l = Math.floor(u), m = H(l, t.length), i = (m + 1) % t.length, s = t[m], c = t[i];
602
+ return a(Math.min((u - l) / r, 1)) * (c - s) + s;
466
603
  }
467
- return t[Math.floor(X(o, t.length))];
604
+ return t[Math.floor(H(o, t.length))];
468
605
  }
469
- function dt(t) {
606
+ function Dt(t) {
470
607
  return Array.isArray(t) && t.length > 0 && typeof t[0] == "number";
471
608
  }
472
- mt(), P.registerMany(ft), z.setSynthSourceClass(y), z.injectMethods(y.prototype);
473
- const w = z.generateStandaloneFunctions(), _ = "textmode.synth.js";
474
- function O(t) {
609
+ Lt(), L.registerMany(kt), B.setSynthSourceClass(_), B.injectMethods(_.prototype);
610
+ const S = B.generateStandaloneFunctions(), C = "textmode.synth.js";
611
+ function V(t) {
475
612
  return t === "char" || t === "cellColor" ? t : "charColor";
476
613
  }
477
- function W(t, e) {
478
- const n = O(e);
614
+ function ee(t, e) {
615
+ const n = V(e);
479
616
  n === "char" ? t.usesChar = !0 : n === "cellColor" ? t.usesCellColor = !0 : t.usesCharColor = !0;
480
617
  }
481
- class yt {
618
+ class Nt {
482
619
  _usage = { usesChar: !1, usesCharColor: !1, usesCellColor: !1 };
483
620
  trackUsage(e) {
484
- W(this._usage, e);
621
+ ee(this._usage, e);
485
622
  }
486
623
  reset() {
487
624
  this._usage.usesChar = !1, this._usage.usesCharColor = !1, this._usage.usesCellColor = !1;
@@ -502,7 +639,7 @@ class yt {
502
639
  return this._usage.usesCellColor;
503
640
  }
504
641
  }
505
- class gt {
642
+ class Ot {
506
643
  _externalLayers = /* @__PURE__ */ new Map();
507
644
  _counter = 0;
508
645
  _layerIdToPrefix = /* @__PURE__ */ new Map();
@@ -513,7 +650,7 @@ class gt {
513
650
  trackUsage(e, n) {
514
651
  const r = this.getPrefix(e.layerId);
515
652
  let o = this._externalLayers.get(e.layerId);
516
- o || (o = { layerId: e.layerId, uniformPrefix: r, usesChar: !1, usesCharColor: !1, usesCellColor: !1 }, this._externalLayers.set(e.layerId, o)), W(o, n);
653
+ o || (o = { layerId: e.layerId, uniformPrefix: r, usesChar: !1, usesCharColor: !1, usesCellColor: !1 }, this._externalLayers.set(e.layerId, o)), ee(o, n);
517
654
  }
518
655
  hasLayer(e) {
519
656
  return this._externalLayers.has(e);
@@ -534,74 +671,134 @@ class gt {
534
671
  this._externalLayers.clear(), this._counter = 0, this._layerIdToPrefix.clear();
535
672
  }
536
673
  }
537
- class _t {
538
- getContextAwareGlslFunction(e, n, r, o, a) {
539
- return n !== "src" ? e.glslFunction : o && a ? this._generateExternalSrcFunction(o, r, a) : this._generateSelfFeedbackSrcFunction(r);
674
+ class zt {
675
+ _sources = /* @__PURE__ */ new Map();
676
+ _counter = 0;
677
+ reset() {
678
+ this._sources.clear(), this._counter = 0;
679
+ }
680
+ trackUsage(e, n) {
681
+ let r = this._sources.get(e.sourceId);
682
+ switch (r || (r = { sourceId: e.sourceId, uniformName: "u_tms" + this._counter++, usesChar: !1, usesCharColor: !1, usesCellColor: !1, sourceRef: e }, this._sources.set(e.sourceId, r)), n) {
683
+ case "char":
684
+ r.usesChar = !0;
685
+ break;
686
+ case "charColor":
687
+ case "main":
688
+ r.usesCharColor = !0;
689
+ break;
690
+ case "cellColor":
691
+ r.usesCellColor = !0;
692
+ }
693
+ }
694
+ getSources() {
695
+ return this._sources;
696
+ }
697
+ getUniformName(e) {
698
+ return this._sources.get(e)?.uniformName ?? "u_tms0";
699
+ }
700
+ hasAnySources() {
701
+ return this._sources.size > 0;
702
+ }
703
+ }
704
+ class Yt {
705
+ getContextAwareGlslFunction(e, n, r, o, a, u, l) {
706
+ return n === "srcTexture" && a && l ? this._generateTextmodeSourceFunction(a, r, l) : n !== "src" ? e.glslFunction : o && u ? this._generateExternalSrcFunction(o, r, u) : this._generateSelfFeedbackSrcFunction(r);
540
707
  }
541
- getFunctionName(e, n, r, o) {
542
- return e.name !== "src" ? e.name : r && o ? `src_ext_${o(r.layerId)}_${n}` : `src_${n}`;
708
+ getFunctionName(e, n, r, o, a, u) {
709
+ return e.name === "srcTexture" && o && u ? `srcTexture_${u(o.sourceId)}_${n}` : e.name !== "src" ? e.name : r && a ? `src_ext_${a(r.layerId)}_${n}` : `src_${n}`;
543
710
  }
544
- generateTransformCode(e, n, r, o, a, u, s, c, i, l, p, f, g) {
545
- const v = this.getFunctionName(n, l, f, g), C = (...m) => [...m, ...i].join(", ");
546
- let h = a, d = u, b = s, x = c;
711
+ generateTransformCode(e, n, r, o, a, u, l, m, i, s, c, f, p, b, w) {
712
+ const d = this.getFunctionName(n, s, f, p, b, w), g = (...h) => [...h, ...i].join(", ");
713
+ let v = a, M = u, x = l, I = m;
547
714
  switch (n.type) {
548
715
  case "src": {
549
- const m = `c${r}`;
550
- e.push(` vec4 ${m} = ${v}(${C(o)});`), h = m;
716
+ const h = `c${r}`;
717
+ e.push(` vec4 ${h} = ${d}(${g(o)});`), v = h;
551
718
  break;
552
719
  }
553
720
  case "coord": {
554
- const m = `st${r}`;
555
- e.push(` vec2 ${m} = ${v}(${C(o)});`), e.push(` ${o} = ${m};`);
721
+ const h = `st${r}`;
722
+ e.push(` vec2 ${h} = ${d}(${g(o)});`), e.push(` ${o} = ${h};`);
556
723
  break;
557
724
  }
558
725
  case "color": {
559
- const m = `c${r}`;
560
- e.push(` vec4 ${m} = ${v}(${C(a)});`), h = m;
726
+ const h = `c${r}`;
727
+ e.push(` vec4 ${h} = ${d}(${g(a)});`), v = h;
561
728
  break;
562
729
  }
563
730
  case "combine": {
564
- const m = `c${r}`;
565
- e.push(` vec4 ${m} = ${v}(${C(a, p ?? "vec4(0.0)")});`), h = m;
731
+ const h = `c${r}`;
732
+ e.push(` vec4 ${h} = ${d}(${g(a, c ?? "vec4(0.0)")});`), v = h;
566
733
  break;
567
734
  }
568
735
  case "combineCoord": {
569
- const m = `st${r}`;
570
- e.push(` vec2 ${m} = ${v}(${C(o, p ?? "vec4(0.0)")});`), e.push(` ${o} = ${m};`);
736
+ const h = `st${r}`;
737
+ e.push(` vec2 ${h} = ${d}(${g(o, c ?? "vec4(0.0)")});`), e.push(` ${o} = ${h};`);
571
738
  break;
572
739
  }
573
740
  }
574
- return { colorVar: h, charVar: d, flagsVar: b, rotationVar: x };
741
+ return { colorVar: v, charVar: M, flagsVar: x, rotationVar: I };
575
742
  }
576
743
  _generateExternalSrcFunction(e, n, r) {
577
- const o = r(e.layerId), a = O(n);
744
+ const o = r(e.layerId), a = V(n);
578
745
  return `
579
746
  vec4 ${`src_ext_${o}_${n}`}(vec2 _st) {
580
- return texture(${`${o}${$[a]}`}, fract(_st));
747
+ return texture(${`${o}${R[a]}`}, fract(_st));
581
748
  }
582
749
  `;
583
750
  }
584
751
  _generateSelfFeedbackSrcFunction(e) {
585
- const n = O(e);
752
+ const n = V(e);
586
753
  return `
587
754
  vec4 ${`src_${e}`}(vec2 _st) {
588
- return texture(${S[n]}, fract(_st));
755
+ return texture(${$[n]}, fract(_st));
756
+ }
757
+ `;
758
+ }
759
+ _generateTextmodeSourceFunction(e, n, r) {
760
+ const o = r(e.sourceId);
761
+ return `
762
+ vec4 ${`srcTexture_${o}_${n}`}(vec2 _st) {
763
+ // Flip Y axis to match image orientation (top-left origin)
764
+ vec2 st = vec2(_st.x, 1.0 - _st.y);
765
+
766
+ // Source dimensions
767
+ vec2 dim = ${o}_dim;
768
+
769
+ // Scale coordinates based on source dimensions vs grid resolution
770
+ // Higher scale value = smaller texture relative to screen
771
+ vec2 scale = u_resolution / dim;
772
+
773
+ // Calculate offset to center the texture
774
+ // offset = (scale - 1.0) * 0.5
775
+ vec2 offset = (scale - 1.0) * 0.5;
776
+
777
+ // Apply scaling and offset
778
+ vec2 uv = st * scale - offset;
779
+
780
+ // Bounds check - return black/transparent if outside texture area
781
+ if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
782
+ return vec4(0.0);
783
+ }
784
+
785
+ return texture(${o}, uv);
589
786
  }
590
787
  `;
591
788
  }
592
789
  }
593
- let J = null;
594
- function Dt(t) {
595
- J = t;
790
+ let te = null;
791
+ function cn(t) {
792
+ te = t;
596
793
  }
597
- function G(t, e, n) {
598
- const r = n ?? J;
794
+ function K(t, e, n) {
795
+ const r = n ?? te;
599
796
  if (r) try {
600
797
  r(t, e);
601
798
  } catch {
602
799
  }
603
800
  }
604
- function Z(t) {
801
+ function ne(t) {
605
802
  if (t === void 0) return "undefined";
606
803
  if (t === null) return "null";
607
804
  if (typeof t == "number") {
@@ -610,37 +807,37 @@ function Z(t) {
610
807
  }
611
808
  if (Array.isArray(t)) {
612
809
  const e = t.findIndex((n) => typeof n != "number" || !Number.isFinite(n));
613
- if (e >= 0) return `array with invalid element at index ${e}: ${Z(t[e])}`;
810
+ if (e >= 0) return `array with invalid element at index ${e}: ${ne(t[e])}`;
614
811
  }
615
812
  return String(t);
616
813
  }
617
- function vt(t) {
814
+ function Bt(t) {
618
815
  return t != null && (typeof t == "number" ? Number.isFinite(t) : !!Array.isArray(t) && t.length > 0 && t.every((e) => typeof e == "number" && Number.isFinite(e)));
619
816
  }
620
- function Ct(t, e, n) {
817
+ function Et(t, e, n) {
621
818
  return (r) => {
622
819
  let o;
623
820
  try {
624
821
  o = t(r);
625
822
  } catch (a) {
626
- return G(a, e, r.onError), n;
823
+ return K(a, e, r.onError), n;
627
824
  }
628
- return vt(o) ? o : (G(new Error(`[textmode.synth.js] Invalid dynamic parameter value for "${e}": ${Z(o)}`), e, r.onError), n);
825
+ return Bt(o) ? o : (K(new Error(`[textmode.synth.js] Invalid dynamic parameter value for "${e}": ${ne(o)}`), e, r.onError), n);
629
826
  };
630
827
  }
631
- class xt {
828
+ class Vt {
632
829
  _uniforms = /* @__PURE__ */ new Map();
633
830
  _dynamicUpdaters = /* @__PURE__ */ new Map();
634
831
  processArgument(e, n, r) {
635
- return dt(e) ? this._createDynamicUniform(n, r, (o) => ht(e, o)) : typeof e == "function" ? this._createDynamicUniform(n, r, e) : typeof e == "number" ? { glslValue: R(e) } : this.processDefault(n);
832
+ return Dt(e) ? this._createDynamicUniform(n, r, (o) => Ut(e, o)) : typeof e == "function" ? this._createDynamicUniform(n, r, e) : typeof e == "number" ? { glslValue: z(e) } : this.processDefault(n);
636
833
  }
637
834
  _createDynamicUniform(e, n, r) {
638
- const o = `${n}_${e.name}`, a = { name: o, type: e.type, value: e.default ?? 0, isDynamic: !0 }, u = Ct(r, o, a.value);
835
+ const o = `${n}_${e.name}`, a = { name: o, type: e.type, value: e.default ?? 0, isDynamic: !0 }, u = Et(r, o, a.value);
639
836
  return this._uniforms.set(o, a), this._dynamicUpdaters.set(o, u), { glslValue: o, uniform: a, updater: u };
640
837
  }
641
838
  processDefault(e) {
642
839
  const n = e.default;
643
- return typeof n == "number" ? { glslValue: R(n) } : Array.isArray(n) ? { glslValue: `vec${n.length}(${n.map(R).join(", ")})` } : { glslValue: "0.0" };
840
+ return typeof n == "number" ? { glslValue: z(n) } : Array.isArray(n) ? { glslValue: `vec${n.length}(${n.map(z).join(", ")})` } : { glslValue: "0.0" };
644
841
  }
645
842
  getUniforms() {
646
843
  return new Map(this._uniforms);
@@ -652,10 +849,10 @@ class xt {
652
849
  this._uniforms.clear(), this._dynamicUpdaters.clear();
653
850
  }
654
851
  }
655
- function R(t) {
852
+ function z(t) {
656
853
  return Number.isInteger(t) ? t.toString() + ".0" : t.toString();
657
854
  }
658
- const bt = `
855
+ const Xt = `
659
856
  // Utility functions
660
857
  float _luminance(vec3 rgb) {
661
858
  const vec3 W = vec3(0.2125, 0.7154, 0.0721);
@@ -764,21 +961,25 @@ int _unpackChar(vec4 c) {
764
961
  return int(c.r * 255.0 + c.g * 255.0 * 256.0);
765
962
  }
766
963
  `;
767
- function St(t) {
768
- const { uniforms: e, glslFunctions: n, mainCode: r, charOutputCode: o, primaryColorVar: a, cellColorVar: u, charMapping: s, usesFeedback: c, usesCharFeedback: i, usesCellColorFeedback: l, usesCharSource: p, externalLayers: f } = t, g = Array.from(e.values()).map((m) => `uniform ${m.type} ${m.name};`).join(`
964
+ function jt(t) {
965
+ const { uniforms: e, glslFunctions: n, mainCode: r, charOutputCode: o, primaryColorVar: a, cellColorVar: u, charMapping: l, usesFeedback: m, usesCharFeedback: i, usesCellColorFeedback: s, usesCharSource: c, externalLayers: f, textmodeSources: p } = t, b = Array.from(e.values()).map((y) => `uniform ${y.type} ${y.name};`).join(`
769
966
  `);
770
- let v = "", C = "";
771
- s && (v = `uniform int u_charMap[${s.indices.length}];
772
- uniform int u_charMapSize;`, C = `
967
+ let w = "", d = "";
968
+ l && (w = `uniform int u_charMap[${l.indices.length}];
969
+ uniform int u_charMapSize;`, d = `
773
970
  // Apply character mapping
774
971
  int rawCharIdx = _unpackChar(charOutput);
775
972
  int mappedCharIdx = u_charMap[int(mod(float(rawCharIdx), float(u_charMapSize)))];
776
973
  charOutput = _packChar(mappedCharIdx);`);
777
- const h = [];
778
- c && h.push(`uniform sampler2D ${S.charColor};`), i && h.push(`uniform sampler2D ${S.char};`), l && h.push(`uniform sampler2D ${S.cellColor};`);
779
- const d = h.join(`
780
- `), b = p ? "uniform float u_charSourceCount;" : "", x = [];
781
- if (f) for (const [, m] of f) m.usesChar && x.push(`uniform sampler2D ${m.uniformPrefix}${$.char};`), m.usesCharColor && x.push(`uniform sampler2D ${m.uniformPrefix}${$.charColor};`), m.usesCellColor && x.push(`uniform sampler2D ${m.uniformPrefix}${$.cellColor};`);
974
+ const g = [];
975
+ m && g.push(`uniform sampler2D ${$.charColor};`), i && g.push(`uniform sampler2D ${$.char};`), s && g.push(`uniform sampler2D ${$.cellColor};`);
976
+ const v = g.join(`
977
+ `), M = c ? "uniform float u_charSourceCount;" : "", x = [];
978
+ if (f) for (const [, y] of f) y.usesChar && x.push(`uniform sampler2D ${y.uniformPrefix}${R.char};`), y.usesCharColor && x.push(`uniform sampler2D ${y.uniformPrefix}${R.charColor};`), y.usesCellColor && x.push(`uniform sampler2D ${y.uniformPrefix}${R.cellColor};`);
979
+ const I = x.length > 0 ? `// External layer samplers
980
+ ${x.join(`
981
+ `)}` : "", h = [];
982
+ if (p) for (const [, y] of p) h.push(`uniform sampler2D ${y.uniformName};`), h.push(`uniform vec2 ${y.uniformName}_dim;`);
782
983
  return `#version 300 es
783
984
  precision highp float;
784
985
 
@@ -792,18 +993,19 @@ layout(location = 2) out vec4 o_secondaryColor;
792
993
 
793
994
  // Standard uniforms
794
995
  uniform float time;
795
- uniform vec2 resolution;
796
- ${d}
797
- ${x.length > 0 ? `// External layer samplers
798
- ${x.join(`
799
- `)}` : ""}
996
+ uniform vec2 u_resolution;
800
997
  ${v}
801
- ${b}
998
+ ${I}
999
+ ${h.length > 0 ? `// TextmodeSource samplers (images/videos)
1000
+ ${h.join(`
1001
+ `)}` : ""}
1002
+ ${w}
1003
+ ${M}
802
1004
 
803
1005
  // Dynamic uniforms
804
- ${g}
1006
+ ${b}
805
1007
 
806
- ${bt}
1008
+ ${Xt}
807
1009
 
808
1010
  // Transform functions
809
1011
  ${Array.from(n).join(`
@@ -815,7 +1017,7 @@ ${r.join(`
815
1017
  `)}
816
1018
 
817
1019
  ${o}
818
- ${C}
1020
+ ${d}
819
1021
 
820
1022
  // Output to MRT
821
1023
  o_character = charOutput;
@@ -824,7 +1026,7 @@ ${C}
824
1026
  }
825
1027
  `;
826
1028
  }
827
- function wt(t, e, n) {
1029
+ function qt(t, e, n) {
828
1030
  return t ? `
829
1031
  // Character output from generator
830
1032
  vec4 charOutput = ${e};` : `
@@ -834,13 +1036,14 @@ function wt(t, e, n) {
834
1036
  vec4 charOutput = _packChar(charIdx);`;
835
1037
  }
836
1038
  function N(t) {
837
- return new Mt().compile(t);
838
- }
839
- class Mt {
840
- _uniformManager = new xt();
841
- _feedbackTracker = new yt();
842
- _externalLayerManager = new gt();
843
- _codeGenerator = new _t();
1039
+ return new Gt().compile(t);
1040
+ }
1041
+ class Gt {
1042
+ _uniformManager = new Vt();
1043
+ _feedbackTracker = new Nt();
1044
+ _externalLayerManager = new Ot();
1045
+ _textmodeSourceManager = new zt();
1046
+ _codeGenerator = new Yt();
844
1047
  _glslFunctions = /* @__PURE__ */ new Set();
845
1048
  _mainCode = [];
846
1049
  _varCounter = 0;
@@ -855,42 +1058,42 @@ class Mt {
855
1058
  e.charColorSource && (o = this._compileChain(e.charColorSource, "charColor", "vec4(1.0, 1.0, 1.0, 1.0)", "v_uv", "charColor").colorVar);
856
1059
  let a = "vec4(0.0, 0.0, 0.0, 0.0)";
857
1060
  e.cellColorSource && (a = this._compileChain(e.cellColorSource, "cellColor", "vec4(0.0, 0.0, 0.0, 0.0)", "v_uv", "cellColor").colorVar);
858
- const u = wt(!!r, r ?? "vec4(0.0)", n.colorVar), s = this._feedbackTracker.getUsage();
859
- return { fragmentSource: St({ uniforms: this._uniformManager.getUniforms(), glslFunctions: this._glslFunctions, mainCode: this._mainCode, charOutputCode: u, primaryColorVar: o, cellColorVar: a, charMapping: e.charMapping, usesFeedback: s.usesCharColorFeedback, usesCharFeedback: s.usesCharFeedback, usesCellColorFeedback: s.usesCellColorFeedback, usesCharSource: this._usesCharSource, externalLayers: this._externalLayerManager.getExternalLayers() }), uniforms: this._uniformManager.getUniforms(), dynamicUpdaters: this._uniformManager.getDynamicUpdaters(), charMapping: e.charMapping, usesCharColorFeedback: s.usesCharColorFeedback, usesCharFeedback: s.usesCharFeedback, usesCellColorFeedback: s.usesCellColorFeedback, usesCharSource: this._usesCharSource, externalLayers: this._externalLayerManager.getExternalLayers() };
1061
+ const u = qt(!!r, r ?? "vec4(0.0)", n.colorVar), l = this._feedbackTracker.getUsage();
1062
+ return { fragmentSource: jt({ uniforms: this._uniformManager.getUniforms(), glslFunctions: this._glslFunctions, mainCode: this._mainCode, charOutputCode: u, primaryColorVar: o, cellColorVar: a, charMapping: e.charMapping, usesFeedback: l.usesCharColorFeedback, usesCharFeedback: l.usesCharFeedback, usesCellColorFeedback: l.usesCellColorFeedback, usesCharSource: this._usesCharSource, externalLayers: this._externalLayerManager.getExternalLayers(), textmodeSources: this._textmodeSourceManager.getSources() }), uniforms: this._uniformManager.getUniforms(), dynamicUpdaters: this._uniformManager.getDynamicUpdaters(), charMapping: e.charMapping, usesCharColorFeedback: l.usesCharColorFeedback, usesCharFeedback: l.usesCharFeedback, usesCellColorFeedback: l.usesCellColorFeedback, usesCharSource: this._usesCharSource, externalLayers: this._externalLayerManager.getExternalLayers(), textmodeSources: this._textmodeSourceManager.getSources() };
860
1063
  }
861
1064
  _reset() {
862
- this._varCounter = 0, this._uniformManager.clear(), this._feedbackTracker.reset(), this._externalLayerManager.reset(), this._glslFunctions.clear(), this._mainCode.length = 0, this._currentTarget = "main", this._usesCharSource = !1;
1065
+ this._varCounter = 0, this._uniformManager.clear(), this._feedbackTracker.reset(), this._externalLayerManager.reset(), this._textmodeSourceManager.reset(), this._glslFunctions.clear(), this._mainCode.length = 0, this._currentTarget = "main", this._usesCharSource = !1;
863
1066
  }
864
1067
  _compileCharSource(e) {
865
1068
  this._usesCharSource = !0;
866
1069
  const n = this._compileChain(e.charSource, "charSrc", "vec4(1.0, 1.0, 1.0, 1.0)", "v_uv", "char"), r = "charFromSource_" + this._varCounter++;
867
- return this._mainCode.push(" // Convert charSource color to character index"), this._mainCode.push(` float charLum_${r} = _luminance(${n.colorVar}.rgb);`), this._mainCode.push(` int charIdx_${r} = int(charLum_${r} * u_charSourceCount);`), this._mainCode.push(` vec4 ${r} = _packChar(charIdx_${r});`), r;
1070
+ return this._mainCode.push(" // Convert charSource color to character index"), this._mainCode.push(` float charLum_${r} = clamp(_luminance(${n.colorVar}.rgb), 0.0, 1.0);`), this._mainCode.push(` float charCount_${r} = max(u_charSourceCount, 1.0);`), this._mainCode.push(` int charIdx_${r} = int(min(charLum_${r} * charCount_${r}, charCount_${r} - 1.0));`), this._mainCode.push(` vec4 ${r} = _packChar(charIdx_${r});`), r;
868
1071
  }
869
1072
  _compileChain(e, n, r, o = "v_uv", a = "main") {
870
1073
  const u = this._currentTarget;
871
1074
  this._currentTarget = a;
872
- const s = `${n}_st`;
873
- let c, i, l, p = `${n}_c`;
874
- this._mainCode.push(` vec2 ${s} = ${o};`), this._mainCode.push(` vec4 ${p} = ${r};`);
875
- const f = e.transforms, g = f.map((h) => this._getProcessedTransform(h.name)), v = this._identifyCoordTransforms(g), C = (h) => {
876
- const d = f[h], b = g[h];
877
- if (!b) return void console.warn(`[SynthCompiler] Unknown transform: ${d.name}`);
878
- const x = e.externalLayerRefs.get(h);
879
- d.name === "src" && this._trackSrcUsage(x);
880
- const m = this._codeGenerator.getContextAwareGlslFunction(b, d.name, this._currentTarget, x, (A) => this._externalLayerManager.getPrefix(A));
881
- this._glslFunctions.add(m);
882
- const ne = this._processArguments(d.userArgs, b.inputs, `${n}_${h}_${d.name}`), B = e.nestedSources.get(h);
883
- let j;
884
- B && (b.type === "combine" || b.type === "combineCoord") && (j = this._compileChain(B, `${n}_nested_${h}`, r, s, a).colorVar);
885
- const M = this._codeGenerator.generateTransformCode(this._mainCode, b, this._varCounter++, s, p, c, i, l, ne, this._currentTarget, j, x, (A) => this._externalLayerManager.getPrefix(A));
886
- p = M.colorVar, M.charVar && (c = M.charVar), M.flagsVar && (i = M.flagsVar), M.rotationVar && (l = M.rotationVar);
1075
+ const l = `${n}_st`;
1076
+ let m, i, s, c = `${n}_c`;
1077
+ this._mainCode.push(` vec2 ${l} = ${o};`), this._mainCode.push(` vec4 ${c} = ${r};`);
1078
+ const f = e.transforms, p = f.map((d) => this._getProcessedTransform(d.name)), b = this._identifyCoordTransforms(p), w = (d) => {
1079
+ const g = f[d], v = p[d];
1080
+ if (!v) return void console.warn(`[SynthCompiler] Unknown transform: ${g.name}`);
1081
+ const M = e.externalLayerRefs.get(d), x = e.textmodeSourceRefs.get(d);
1082
+ g.name === "src" ? this._trackSrcUsage(M) : g.name === "srcTexture" && x && this._textmodeSourceManager.trackUsage(x, this._currentTarget);
1083
+ const I = this._codeGenerator.getContextAwareGlslFunction(v, g.name, this._currentTarget, M, x, (F) => this._externalLayerManager.getPrefix(F), (F) => this._textmodeSourceManager.getUniformName(F));
1084
+ this._glslFunctions.add(I);
1085
+ const h = this._processArguments(g.userArgs, v.inputs, `${n}_${d}_${g.name}`), y = e.nestedSources.get(d);
1086
+ let q;
1087
+ y && (v.type === "combine" || v.type === "combineCoord") && (q = this._compileChain(y, `${n}_nested_${d}`, r, l, a).colorVar);
1088
+ const T = this._codeGenerator.generateTransformCode(this._mainCode, v, this._varCounter++, l, c, m, i, s, h, this._currentTarget, q, M, x, (F) => this._externalLayerManager.getPrefix(F), (F) => this._textmodeSourceManager.getUniformName(F));
1089
+ c = T.colorVar, T.charVar && (m = T.charVar), T.flagsVar && (i = T.flagsVar), T.rotationVar && (s = T.rotationVar);
887
1090
  };
888
- for (let h = v.length - 1; h >= 0; h--) C(v[h]);
889
- for (let h = 0; h < f.length; h++) {
890
- const d = g[h];
891
- (!d || d.type !== "coord" && d.type !== "combineCoord") && C(h);
1091
+ for (let d = b.length - 1; d >= 0; d--) w(b[d]);
1092
+ for (let d = 0; d < f.length; d++) {
1093
+ const g = p[d];
1094
+ (!g || g.type !== "coord" && g.type !== "combineCoord") && w(d);
892
1095
  }
893
- return this._currentTarget = u, { coordVar: s, colorVar: p, charVar: c, flagsVar: i, rotationVar: l };
1096
+ return this._currentTarget = u, { coordVar: l, colorVar: c, charVar: m, flagsVar: i, rotationVar: s };
894
1097
  }
895
1098
  _identifyCoordTransforms(e) {
896
1099
  const n = [];
@@ -904,38 +1107,38 @@ class Mt {
904
1107
  e ? this._externalLayerManager.trackUsage(e, this._currentTarget) : this._feedbackTracker.trackUsage(this._currentTarget);
905
1108
  }
906
1109
  _getProcessedTransform(e) {
907
- return P.getProcessed(e);
1110
+ return L.getProcessed(e);
908
1111
  }
909
1112
  _processArguments(e, n, r) {
910
1113
  const o = [];
911
1114
  for (let a = 0; a < n.length; a++) {
912
- const u = n[a], s = e[a] ?? u.default, c = this._uniformManager.processArgument(s, u, r);
913
- o.push(c.glslValue);
1115
+ const u = n[a], l = e[a] ?? u.default, m = this._uniformManager.processArgument(l, u, r);
1116
+ o.push(m.glslValue);
914
1117
  }
915
1118
  return o;
916
1119
  }
917
1120
  }
918
- class L {
1121
+ class O {
919
1122
  static _fontIndexCache = /* @__PURE__ */ new WeakMap();
920
1123
  _resolvedIndices;
921
1124
  _lastFont;
922
1125
  _lastChars = "";
923
1126
  resolve(e, n) {
924
1127
  if (this._resolvedIndices && this._lastFont === n && this._lastChars === e) return this._resolvedIndices;
925
- let r = L._fontIndexCache.get(n);
1128
+ let r = O._fontIndexCache.get(n);
926
1129
  if (!r) {
927
1130
  r = /* @__PURE__ */ new Map();
928
1131
  const i = n.characters;
929
- for (let l = 0; l < i.length; l++) r.set(i[l], l);
930
- L._fontIndexCache.set(n, r);
1132
+ for (let s = 0; s < i.length; s++) r.set(i[s], s);
1133
+ O._fontIndexCache.set(n, r);
931
1134
  }
932
- const o = Array.from(e), a = new Int32Array(o.length), u = n.characterMap, s = u.get(" "), c = s && r.has(s) ? r.get(s) : 0;
1135
+ const o = Array.from(e), a = new Int32Array(o.length), u = n.characterMap, l = u.get(" "), m = l && r.has(l) ? r.get(l) : 0;
933
1136
  for (let i = 0; i < o.length; i++) {
934
- const l = o[i], p = u.get(l);
935
- if (p) {
936
- const f = r.get(p);
937
- a[i] = f !== void 0 ? f : c;
938
- } else a[i] = c;
1137
+ const s = o[i], c = u.get(s);
1138
+ if (c) {
1139
+ const f = r.get(c);
1140
+ a[i] = f !== void 0 ? f : m;
1141
+ } else a[i] = m;
939
1142
  }
940
1143
  return this._resolvedIndices = a, this._lastFont = n, this._lastChars = e, a;
941
1144
  }
@@ -943,62 +1146,91 @@ class L {
943
1146
  this._resolvedIndices = void 0, this._lastFont = void 0, this._lastChars = "";
944
1147
  }
945
1148
  }
946
- function ee(t = {}) {
947
- return { source: t.source ?? new y(), compiled: t.compiled, shader: t.shader, characterResolver: t.characterResolver ?? new L(), needsCompile: t.needsCompile ?? !1, isCompiling: t.isCompiling ?? !1, pingPongBuffers: t.pingPongBuffers, pingPongDimensions: t.pingPongDimensions, pingPongIndex: t.pingPongIndex ?? 0, externalLayerMap: t.externalLayerMap, bpm: t.bpm, dynamicValues: t.dynamicValues ?? /* @__PURE__ */ new Map(), synthContext: t.synthContext ?? { time: 0, frameCount: 0, width: 0, height: 0, cols: 0, rows: 0, bpm: 0 }, isDisposed: !1 };
1149
+ function re(t = {}) {
1150
+ return { source: t.source ?? new _(), sourceFactory: t.sourceFactory, compiled: t.compiled, shader: t.shader, characterResolver: t.characterResolver ?? new O(), needsCompile: t.needsCompile ?? !1, isCompiling: t.isCompiling ?? !1, pingPongBuffers: t.pingPongBuffers, pingPongDimensions: t.pingPongDimensions, pingPongIndex: t.pingPongIndex ?? 0, externalLayerMap: t.externalLayerMap, bpm: t.bpm, dynamicValues: t.dynamicValues ?? /* @__PURE__ */ new Map(), synthContext: t.synthContext ?? { time: 0, frameCount: 0, width: 0, height: 0, cols: 0, rows: 0, bpm: 0 }, isDisposed: !1 };
948
1151
  }
949
- function $t(t) {
1152
+ function Ht(t) {
950
1153
  t.extendLayer("synth", function(e) {
951
1154
  const n = this.grid !== void 0 && this.drawFramebuffer !== void 0;
952
- let r = this.getPluginState(_);
953
- r ? (r.source = e, r.needsCompile = !0, r.characterResolver.invalidate(), n && (r.compiled = N(e))) : r = ee({ source: e, compiled: n ? N(e) : void 0, needsCompile: !0 }), this.setPluginState(_, r);
1155
+ let r, o;
1156
+ typeof e == "function" ? (o = e, r = new _()) : r = e;
1157
+ let a = this.getPluginState(C);
1158
+ a ? (a.source = r, a.sourceFactory = o, a.needsCompile = !0, a.characterResolver.invalidate(), n && !o && (a.compiled = N(r))) : a = re({ source: r, sourceFactory: o, compiled: n && !o ? N(r) : void 0, needsCompile: !0 }), this.setPluginState(C, a);
954
1159
  });
955
1160
  }
956
- function Tt(t) {
1161
+ function Kt(t) {
957
1162
  t.extendLayer("clearSynth", function() {
958
- const e = this.getPluginState(_);
959
- e && (e.shader?.dispose && e.shader.dispose(), e.pingPongBuffers && (e.pingPongBuffers[0].dispose?.(), e.pingPongBuffers[1].dispose?.()), this.setPluginState(_, void 0));
1163
+ const e = this.getPluginState(C);
1164
+ e && (e.shader?.dispose && e.shader.dispose(), e.pingPongBuffers && (e.pingPongBuffers[0].dispose?.(), e.pingPongBuffers[1].dispose?.()), this.setPluginState(C, void 0));
960
1165
  });
961
1166
  }
962
- function Ft(t) {
1167
+ function Qt(t) {
963
1168
  t.extendLayer("bpm", function(e) {
964
- let n = this.getPluginState(_);
965
- n ? n.bpm = e : n = ee({ bpm: e }), this.setPluginState(_, n);
1169
+ let n = this.getPluginState(C);
1170
+ n ? n.bpm = e : n = re({ bpm: e }), this.setPluginState(C, n);
966
1171
  });
967
1172
  }
968
- let te = 60;
969
- function Pt(t) {
970
- te = t;
1173
+ let oe = 60;
1174
+ function Wt(t) {
1175
+ oe = t;
971
1176
  }
972
- function kt() {
973
- return te;
1177
+ function Jt() {
1178
+ return oe;
974
1179
  }
975
- function It(t) {
1180
+ function Zt(t) {
976
1181
  t.bpm = function(e) {
977
- return Pt(e), e;
1182
+ return Wt(e), e;
978
1183
  };
979
1184
  }
980
- function T(t) {
1185
+ function A(t) {
1186
+ const e = /* @__PURE__ */ new Map();
1187
+ for (const [, n] of t.externalLayerRefs) {
1188
+ const r = typeof n.layer == "function" ? n.layer() : n.layer;
1189
+ r && e.set(n.layerId, r);
1190
+ }
1191
+ for (const [, n] of t.nestedSources) {
1192
+ const r = A(n);
1193
+ for (const [o, a] of r) e.set(o, a);
1194
+ }
1195
+ if (t.charSource) {
1196
+ const n = A(t.charSource);
1197
+ for (const [r, o] of n) e.set(r, o);
1198
+ }
1199
+ if (t.charColorSource) {
1200
+ const n = A(t.charColorSource);
1201
+ for (const [r, o] of n) e.set(r, o);
1202
+ }
1203
+ if (t.cellColorSource) {
1204
+ const n = A(t.cellColorSource);
1205
+ for (const [r, o] of n) e.set(r, o);
1206
+ }
1207
+ return e;
1208
+ }
1209
+ function P(t) {
981
1210
  const e = /* @__PURE__ */ new Map();
982
- for (const [, n] of t.externalLayerRefs) e.set(n.layerId, n.layer);
1211
+ for (const [, n] of t.textmodeSourceRefs) {
1212
+ const r = typeof n.source == "function" ? n.source() : n.source;
1213
+ r && e.set(n.sourceId, r);
1214
+ }
983
1215
  for (const [, n] of t.nestedSources) {
984
- const r = T(n);
1216
+ const r = P(n);
985
1217
  for (const [o, a] of r) e.set(o, a);
986
1218
  }
987
1219
  if (t.charSource) {
988
- const n = T(t.charSource);
1220
+ const n = P(t.charSource);
989
1221
  for (const [r, o] of n) e.set(r, o);
990
1222
  }
991
1223
  if (t.charColorSource) {
992
- const n = T(t.charColorSource);
1224
+ const n = P(t.charColorSource);
993
1225
  for (const [r, o] of n) e.set(r, o);
994
1226
  }
995
1227
  if (t.cellColorSource) {
996
- const n = T(t.cellColorSource);
1228
+ const n = P(t.cellColorSource);
997
1229
  for (const [r, o] of n) e.set(r, o);
998
1230
  }
999
1231
  return e;
1000
1232
  }
1001
- const Lt = `#version 300 es
1233
+ const en = `#version 300 es
1002
1234
  precision highp float;
1003
1235
 
1004
1236
  in vec2 v_uv;
@@ -1017,7 +1249,7 @@ void main() {
1017
1249
  o_secondaryColor = texture(u_cellColorTex, v_uv);
1018
1250
  }
1019
1251
  `;
1020
- class At {
1252
+ class tn {
1021
1253
  _shader = null;
1022
1254
  _isCompiling = !1;
1023
1255
  _isDisposed = !1;
@@ -1025,7 +1257,7 @@ class At {
1025
1257
  if (!(this._shader || this._isCompiling || this._isDisposed)) {
1026
1258
  this._isCompiling = !0;
1027
1259
  try {
1028
- this._shader = await e.createFilterShader(Lt);
1260
+ this._shader = await e.createFilterShader(en);
1029
1261
  } catch (n) {
1030
1262
  console.warn("[textmode.synth.js] Failed to compile copy shader:", n);
1031
1263
  } finally {
@@ -1046,141 +1278,193 @@ class At {
1046
1278
  this._isDisposed = !1;
1047
1279
  }
1048
1280
  }
1049
- const I = new At();
1050
- async function Rt(t, e) {
1051
- const n = t.getPluginState(_);
1281
+ const D = new tn();
1282
+ async function nn(t, e) {
1283
+ const n = t.getPluginState(C);
1052
1284
  if (!n) return;
1053
1285
  const r = t.grid, o = t.drawFramebuffer;
1054
1286
  if (!r || !o) return;
1055
1287
  let a = !1;
1056
- if (n.compiled || (n.compiled = N(n.source), n.externalLayerMap = T(n.source), a = !0, n.needsCompile = !0), n.needsCompile && n.compiled && !n.isCompiling) {
1288
+ if (n.sourceFactory && n.needsCompile || !n.compiled) {
1289
+ let c = n.source, f = !1;
1290
+ if (n.sourceFactory) try {
1291
+ const p = n.sourceFactory(), b = N(p);
1292
+ n.compiled && b.fragmentSource === n.compiled.fragmentSource || (n.source = p, c = p, n.compiled = b, a = !1, f = !0);
1293
+ } catch (p) {
1294
+ console.warn("[textmode.synth.js] Failed to evaluate synth factory:", p);
1295
+ }
1296
+ (f || !n.compiled || n.needsCompile) && (n.compiled || (n.compiled = N(c)), n.externalLayerMap = A(c), n.textmodeSourceMap = P(c), a = !0, n.needsCompile = !0);
1297
+ }
1298
+ if (n.needsCompile && n.compiled && !n.isCompiling) {
1057
1299
  n.isCompiling = !0;
1058
- const p = n.compiled;
1059
- a || (n.externalLayerMap = T(n.source));
1300
+ const c = n.compiled;
1301
+ a || (n.externalLayerMap = A(n.source), n.textmodeSourceMap = P(n.source));
1060
1302
  try {
1061
- const f = await e.createFilterShader(p.fragmentSource);
1303
+ const f = await e.createFilterShader(c.fragmentSource);
1062
1304
  if (n.isDisposed) return void (f.dispose && f.dispose());
1063
- n.shader?.dispose && n.shader.dispose(), n.shader = f, n.compiled === p && (n.needsCompile = !1);
1305
+ n.shader?.dispose && n.shader.dispose(), n.shader = f, n.compiled === c && (n.needsCompile = !1);
1064
1306
  } finally {
1065
1307
  n.isCompiling = !1;
1066
1308
  }
1067
1309
  }
1068
1310
  if (!n.shader || !n.compiled || n.isDisposed) return;
1069
- const u = n.compiled.usesCharColorFeedback, s = n.compiled.usesCharFeedback, c = n.compiled.usesCellColorFeedback, i = u || s || c;
1311
+ const u = n.compiled.usesCharColorFeedback, l = n.compiled.usesCharFeedback, m = n.compiled.usesCellColorFeedback, i = u || l || m;
1070
1312
  if (n.pingPongBuffers) {
1071
- const p = n.pingPongDimensions, f = !p || p.cols !== r.cols || p.rows !== r.rows;
1313
+ const c = n.pingPongDimensions, f = !c || c.cols !== r.cols || c.rows !== r.rows;
1072
1314
  i && !f || (n.pingPongBuffers[0].dispose(), n.pingPongBuffers[1].dispose(), n.pingPongBuffers = void 0, n.pingPongDimensions = void 0);
1073
1315
  }
1074
1316
  i && !n.pingPongBuffers && (n.pingPongBuffers = [e.createFramebuffer({ width: r.cols, height: r.rows, attachments: 3 }), e.createFramebuffer({ width: r.cols, height: r.rows, attachments: 3 })], n.pingPongDimensions = { cols: r.cols, rows: r.rows }, n.pingPongIndex = 0), n.synthContext || (n.synthContext = { time: 0, frameCount: 0, width: 0, height: 0, cols: 0, rows: 0, bpm: 0 });
1075
- const l = n.synthContext;
1076
- l.time = e.secs, l.frameCount = e.frameCount, l.width = r.width, l.height = r.height, l.cols = r.cols, l.rows = r.rows, l.bpm = n.bpm ?? kt(), l.onError = n.onDynamicError, n.dynamicValues.clear();
1077
- for (const [p, f] of n.compiled.dynamicUpdaters) {
1078
- const g = f(l);
1079
- n.dynamicValues.set(p, g);
1317
+ const s = n.synthContext;
1318
+ s.time = e.secs, s.frameCount = e.frameCount, s.width = r.width, s.height = r.height, s.cols = r.cols, s.rows = r.rows, s.bpm = n.bpm ?? Jt(), s.onError = n.onDynamicError, n.dynamicValues.clear();
1319
+ for (const [c, f] of n.compiled.dynamicUpdaters) {
1320
+ const p = f(s);
1321
+ n.dynamicValues.set(c, p);
1080
1322
  }
1081
1323
  if (i && n.pingPongBuffers) {
1082
- const p = n.pingPongBuffers[n.pingPongIndex], f = n.pingPongBuffers[1 - n.pingPongIndex];
1083
- f.begin(), e.clear(), e.shader(n.shader), U(t, e, n, l, p), e.rect(r.cols, r.rows), f.end(), o.begin(), e.clear();
1084
- const g = I.getShader();
1085
- g ? (e.shader(g), e.setUniform("u_charTex", f.textures[0]), e.setUniform("u_charColorTex", f.textures[1]), e.setUniform("u_cellColorTex", f.textures[2])) : (e.shader(n.shader), U(t, e, n, l, p)), e.rect(r.cols, r.rows), o.end(), n.pingPongIndex = 1 - n.pingPongIndex;
1086
- } else o.begin(), e.clear(), e.shader(n.shader), U(t, e, n, l, null), e.rect(r.cols, r.rows), o.end();
1087
- }
1088
- function U(t, e, n, r, o) {
1089
- e.setUniform("time", r.time), e.setUniform("resolution", [r.cols, r.rows]);
1090
- for (const [c, i] of n.dynamicValues) e.setUniform(c, i);
1324
+ const c = n.pingPongBuffers[n.pingPongIndex], f = n.pingPongBuffers[1 - n.pingPongIndex];
1325
+ f.begin(), e.clear(), e.shader(n.shader), Y(t, e, n, s, c), e.rect(r.cols, r.rows), f.end(), o.begin(), e.clear();
1326
+ const p = D.getShader();
1327
+ p ? (e.shader(p), e.setUniform("u_charTex", f.textures[0]), e.setUniform("u_charColorTex", f.textures[1]), e.setUniform("u_cellColorTex", f.textures[2])) : (e.shader(n.shader), Y(t, e, n, s, c)), e.rect(r.cols, r.rows), o.end(), n.pingPongIndex = 1 - n.pingPongIndex;
1328
+ } else o.begin(), e.clear(), e.shader(n.shader), Y(t, e, n, s, null), e.rect(r.cols, r.rows), o.end();
1329
+ e.resetShader();
1330
+ }
1331
+ function Y(t, e, n, r, o) {
1332
+ e.setUniform("time", r.time), e.setUniform("u_resolution", [r.cols, r.rows]);
1333
+ for (const [i, s] of n.dynamicValues) e.setUniform(i, s);
1091
1334
  const a = n.compiled, u = n.staticUniformsAppliedTo !== n.shader;
1092
1335
  if (u) {
1093
- for (const [c, i] of a.uniforms) i.isDynamic || typeof i.value == "function" || e.setUniform(c, i.value);
1336
+ for (const [i, s] of a.uniforms) s.isDynamic || typeof s.value == "function" || e.setUniform(i, s.value);
1094
1337
  n.staticUniformsAppliedTo = n.shader;
1095
1338
  }
1096
1339
  if (a.charMapping) {
1097
- const c = n.characterResolver.resolve(a.charMapping.chars, t.font);
1098
- (u || c !== n.lastCharMapIndices) && (e.setUniform("u_charMap", c), e.setUniform("u_charMapSize", c.length), n.lastCharMapIndices = c);
1340
+ const i = n.characterResolver.resolve(a.charMapping.chars, t.font);
1341
+ (u || i !== n.lastCharMapIndices) && (e.setUniform("u_charMap", i), e.setUniform("u_charMapSize", i.length), n.lastCharMapIndices = i);
1099
1342
  }
1100
1343
  if (a.usesCharSource) {
1101
- const c = a.charMapping ? a.charMapping.chars.length : t.font.characters.length;
1102
- e.setUniform("u_charSourceCount", c);
1103
- }
1104
- o && (a.usesCharColorFeedback && e.setUniform(S.charColor, o.textures[1]), a.usesCharFeedback && e.setUniform(S.char, o.textures[0]), a.usesCellColorFeedback && e.setUniform(S.cellColor, o.textures[2]));
1105
- const s = a.externalLayers;
1106
- if (s && s.size > 0 && n.externalLayerMap) for (const [c, i] of s) {
1107
- const l = n.externalLayerMap.get(c);
1108
- if (!l) {
1109
- console.warn(`[textmode.synth.js] External layer not found: ${c}`);
1344
+ const i = a.charMapping ? a.charMapping.chars.length : t.font.characters.length;
1345
+ e.setUniform("u_charSourceCount", i);
1346
+ }
1347
+ o && (a.usesCharColorFeedback && e.setUniform($.charColor, o.textures[1]), a.usesCharFeedback && e.setUniform($.char, o.textures[0]), a.usesCellColorFeedback && e.setUniform($.cellColor, o.textures[2]));
1348
+ const l = a.externalLayers;
1349
+ if (l && l.size > 0 && n.externalLayerMap) for (const [i, s] of l) {
1350
+ const c = n.externalLayerMap.get(i);
1351
+ if (!c) {
1352
+ console.warn(`[textmode.synth.js] External layer not found: ${i}`);
1353
+ continue;
1354
+ }
1355
+ const f = c.getPluginState(C);
1356
+ let p;
1357
+ f?.pingPongBuffers ? p = f.pingPongBuffers[f.pingPongIndex].textures : c.drawFramebuffer && (p = c.drawFramebuffer.textures), p && (s.usesChar && e.setUniform(`${s.uniformPrefix}${R.char}`, p[0]), s.usesCharColor && e.setUniform(`${s.uniformPrefix}${R.charColor}`, p[1]), s.usesCellColor && e.setUniform(`${s.uniformPrefix}${R.cellColor}`, p[2]));
1358
+ }
1359
+ const m = a.textmodeSources;
1360
+ if (m && m.size > 0 && n.textmodeSourceMap) for (const [i, s] of m) {
1361
+ const c = n.textmodeSourceMap.get(i);
1362
+ if (!c) {
1363
+ console.warn(`[textmode.synth.js] TextmodeSource not found: ${i}`);
1110
1364
  continue;
1111
1365
  }
1112
- const p = l.getPluginState(_);
1113
- let f;
1114
- p?.pingPongBuffers ? f = p.pingPongBuffers[p.pingPongIndex].textures : l.drawFramebuffer && (f = l.drawFramebuffer.textures), f && (i.usesChar && e.setUniform(`${i.uniformPrefix}${$.char}`, f[0]), i.usesCharColor && e.setUniform(`${i.uniformPrefix}${$.charColor}`, f[1]), i.usesCellColor && e.setUniform(`${i.uniformPrefix}${$.cellColor}`, f[2]));
1366
+ c.update && c.update();
1367
+ const f = c.width ?? 1, p = c.height ?? 1, b = f > 0 ? f : 1, w = p > 0 ? p : 1;
1368
+ e.setUniform(`${s.uniformName}_dim`, [b, w]), c.texture ? e.setUniform(s.uniformName, c.texture) : console.warn(`[textmode.synth.js] TextmodeSource texture not loaded: ${i}`);
1115
1369
  }
1116
1370
  }
1117
- function Ut(t) {
1118
- const e = t.getPluginState(_);
1371
+ function rn(t) {
1372
+ const e = t.getPluginState(C);
1119
1373
  e && (e.isDisposed = !0, e.shader?.dispose && e.shader.dispose(), e.pingPongBuffers && (e.pingPongBuffers[0].dispose?.(), e.pingPongBuffers[1].dispose?.()));
1120
1374
  }
1121
- const Ot = { name: _, version: "1.0.0", install(t, e) {
1122
- I.reset(), It(t), $t(e), Ft(e), Tt(e), e.registerPreSetupHook(async () => {
1123
- await I.initialize(t);
1124
- }), e.registerLayerPreRenderHook((n) => Rt(n, t)), e.registerLayerDisposedHook(Ut);
1375
+ const ln = { name: C, version: "1.0.0", install(t, e) {
1376
+ D.reset(), Zt(t), Ht(e), Qt(e), Kt(e), e.registerPreSetupHook(async () => {
1377
+ await D.initialize(t);
1378
+ }), e.registerLayerPreRenderHook((n) => nn(n, t)), e.registerLayerDisposedHook(rn);
1125
1379
  }, uninstall(t, e) {
1126
1380
  const n = [e.layerManager.base, ...e.layerManager.all];
1127
1381
  for (const r of n) {
1128
- const o = r.getPluginState(_);
1129
- o && (o.isDisposed = !0, o.shader?.dispose && o.shader.dispose(), o.pingPongBuffers && (o.pingPongBuffers[0].dispose?.(), o.pingPongBuffers[1].dispose?.()), r.setPluginState(_, void 0));
1382
+ const o = r.getPluginState(C);
1383
+ o && (o.isDisposed = !0, o.shader?.dispose && o.shader.dispose(), o.pingPongBuffers && (o.pingPongBuffers[0].dispose?.(), o.pingPongBuffers[1].dispose?.()), r.setPluginState(C, void 0));
1130
1384
  }
1131
- delete t.bpm, e.removeLayerExtension("synth"), e.removeLayerExtension("bpm"), e.removeLayerExtension("clearSynth"), I.dispose();
1385
+ delete t.bpm, e.removeLayerExtension("synth"), e.removeLayerExtension("bpm"), e.removeLayerExtension("clearSynth"), D.dispose();
1132
1386
  } };
1133
- function Nt(t, e, n, r) {
1134
- return new y({ cellColorSource: E(t, e, n, r) });
1387
+ function un(t, e, n, r) {
1388
+ return new _({ cellColorSource: j(t, e, n, r) });
1135
1389
  }
1136
- const Vt = (t) => new y({ charSource: t });
1137
- function Et(t, e, n, r) {
1138
- return new y({ charColorSource: E(t, e, n, r) });
1390
+ const fn = (t) => new _({ charSource: t });
1391
+ function mn(t, e, n, r) {
1392
+ return new _({ charColorSource: j(t, e, n, r) });
1139
1393
  }
1140
- function Bt(t) {
1141
- return w.gradient(t ?? null);
1394
+ function pn(t) {
1395
+ return S.gradient(t ?? null);
1396
+ }
1397
+ function dn(t, e) {
1398
+ return S.noise(t ?? null, e ?? null);
1142
1399
  }
1143
- function jt(t, e) {
1144
- return w.noise(t ?? null, e ?? null);
1400
+ function hn(t, e, n, r) {
1401
+ return S.plasma(t ?? null, e ?? null, n ?? null, r ?? null);
1145
1402
  }
1146
- function Yt(t, e, n) {
1147
- return w.osc(t ?? null, e ?? null, n ?? null);
1403
+ function gn(t, e, n, r, o, a) {
1404
+ return S.moire(t ?? null, e ?? null, n ?? null, r ?? null, o ?? null, a ?? null);
1148
1405
  }
1149
- function Xt(t, e, n, r) {
1150
- const o = E(t, e, n, r);
1151
- return new y({ charColorSource: o, cellColorSource: o });
1406
+ function yn(t, e, n) {
1407
+ return S.osc(t ?? null, e ?? null, n ?? null);
1152
1408
  }
1153
- function Gt(t, e, n) {
1154
- return w.shape(t ?? null, e ?? null, n ?? null);
1409
+ function _n(t, e, n, r) {
1410
+ const o = j(t, e, n, r);
1411
+ return new _({ charColorSource: o, cellColorSource: o });
1155
1412
  }
1156
- function zt(t, e, n, r) {
1157
- return t !== void 0 && e === void 0 && n === void 0 && r === void 0 && typeof t == "number" ? w.solid(t) : w.solid(t ?? null, e ?? null, n ?? null, r ?? null);
1413
+ function vn(t, e, n) {
1414
+ return S.shape(t ?? null, e ?? null, n ?? null);
1158
1415
  }
1159
- const qt = (t) => {
1160
- const e = w.src;
1416
+ function on(t, e, n, r) {
1417
+ return t !== void 0 && e === void 0 && n === void 0 && r === void 0 && typeof t == "number" ? S.solid(t) : S.solid(t ?? null, e ?? null, n ?? null, r ?? null);
1418
+ }
1419
+ const xn = (t) => {
1420
+ const e = S.src;
1161
1421
  if (!t) return e();
1162
- const n = new y(), r = t.id ?? `layer_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1163
- return n.addExternalLayerRef({ layerId: r, layer: t }), n;
1422
+ const n = new _();
1423
+ if (typeof t == "function") {
1424
+ const r = t();
1425
+ if (r && sn(r)) {
1426
+ const o = r.id ?? `layer_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1427
+ n.addExternalLayerRef({ layerId: o, layer: t });
1428
+ } else {
1429
+ const o = `tms_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1430
+ n.addTextmodeSourceRef({ sourceId: o, source: t });
1431
+ }
1432
+ } else if (an(t)) {
1433
+ const r = `tms_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1434
+ n.addTextmodeSourceRef({ sourceId: r, source: t });
1435
+ } else {
1436
+ const r = t, o = r.id ?? `layer_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1437
+ n.addExternalLayerRef({ layerId: o, layer: r });
1438
+ }
1439
+ return n;
1164
1440
  };
1165
- function Ht(t, e, n) {
1166
- return w.voronoi(t ?? null, e ?? null, n ?? null);
1441
+ function an(t) {
1442
+ return t !== null && typeof t == "object" && "texture" in t && "originalWidth" in t && "originalHeight" in t;
1443
+ }
1444
+ function sn(t) {
1445
+ return t !== null && typeof t == "object" && "grid" in t && "drawFramebuffer" in t;
1446
+ }
1447
+ function Cn(t, e, n) {
1448
+ return S.voronoi(t ?? null, e ?? null, n ?? null);
1167
1449
  }
1168
- function E(t, e, n, r) {
1169
- return t instanceof y ? t : zt(t, e, n, r);
1450
+ function j(t, e, n, r) {
1451
+ return t instanceof _ ? t : on(t, e, n, r);
1170
1452
  }
1171
1453
  export {
1172
- Ot as SynthPlugin,
1173
- y as SynthSource,
1174
- Nt as cellColor,
1175
- Vt as char,
1176
- Et as charColor,
1177
- Bt as gradient,
1178
- jt as noise,
1179
- Yt as osc,
1180
- Xt as paint,
1181
- Dt as setGlobalErrorCallback,
1182
- Gt as shape,
1183
- zt as solid,
1184
- qt as src,
1185
- Ht as voronoi
1454
+ ln as SynthPlugin,
1455
+ _ as SynthSource,
1456
+ un as cellColor,
1457
+ fn as char,
1458
+ mn as charColor,
1459
+ pn as gradient,
1460
+ gn as moire,
1461
+ dn as noise,
1462
+ yn as osc,
1463
+ _n as paint,
1464
+ hn as plasma,
1465
+ cn as setGlobalErrorCallback,
1466
+ vn as shape,
1467
+ on as solid,
1468
+ xn as src,
1469
+ Cn as voronoi
1186
1470
  };