@tensordoc/prism 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/backends/milkdrop.d.ts +28 -0
- package/dist/backends/shadertoy.d.ts +22 -0
- package/dist/image-feed.d.ts +32 -0
- package/dist/image-overlay.d.ts +84 -0
- package/dist/index.d.ts +9 -0
- package/dist/player.d.ts +150 -0
- package/dist/prism.cjs +37 -0
- package/dist/prism.cjs.map +1 -0
- package/dist/prism.mjs +1271 -0
- package/dist/prism.mjs.map +1 -0
- package/dist/registry.d.ts +18 -0
- package/dist/runtime.d.ts +25 -0
- package/dist/synth.d.ts +47 -0
- package/dist/types.d.ts +28 -0
- package/package.json +58 -0
- package/src/backends/milkdrop.ts +190 -0
- package/src/backends/shadertoy.ts +290 -0
- package/src/image-feed.ts +185 -0
- package/src/image-overlay.ts +302 -0
- package/src/index.ts +27 -0
- package/src/peer-types.d.ts +18 -0
- package/src/player.ts +395 -0
- package/src/registry.generated.json +2022 -0
- package/src/registry.ts +70 -0
- package/src/runtime.ts +100 -0
- package/src/synth.ts +251 -0
- package/src/types.ts +98 -0
package/dist/prism.mjs
ADDED
|
@@ -0,0 +1,1271 @@
|
|
|
1
|
+
var H = Object.defineProperty;
|
|
2
|
+
var z = (t, e, s) => e in t ? H(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
|
|
3
|
+
var i = (t, e, s) => z(t, typeof e != "symbol" ? e + "" : e, s);
|
|
4
|
+
import K from "butterchurn";
|
|
5
|
+
import Y from "butterchurn-presets";
|
|
6
|
+
import * as J from "milkdrop-preset-converter";
|
|
7
|
+
const Z = J;
|
|
8
|
+
function W(t) {
|
|
9
|
+
const e = t;
|
|
10
|
+
return e && typeof e == "object" && "default" in e ? e.default : t;
|
|
11
|
+
}
|
|
12
|
+
const $ = W(K), Q = W(Y);
|
|
13
|
+
function ee(t, e, s, o, r = {}) {
|
|
14
|
+
const l = (k, x) => {
|
|
15
|
+
e.width = k, e.height = x;
|
|
16
|
+
};
|
|
17
|
+
l(window.innerWidth, window.innerHeight);
|
|
18
|
+
const a = $.createVisualizer(t, e, {
|
|
19
|
+
width: e.width,
|
|
20
|
+
height: e.height,
|
|
21
|
+
pixelRatio: 1,
|
|
22
|
+
textureRatio: 1
|
|
23
|
+
});
|
|
24
|
+
a.connectAudio(s);
|
|
25
|
+
const c = Q.getPresets(), u = Object.keys(c);
|
|
26
|
+
let n;
|
|
27
|
+
const h = r.initialPresetName, v = h ? N(u, h) : null;
|
|
28
|
+
v ? n = v : n = u[Math.floor(Math.random() * u.length)], a.loadPreset(c[n], 0);
|
|
29
|
+
const m = () => {
|
|
30
|
+
const k = window.innerWidth, x = window.innerHeight;
|
|
31
|
+
l(k, x), a.setRendererSize(k, x);
|
|
32
|
+
};
|
|
33
|
+
window.addEventListener("resize", m, { passive: !0 });
|
|
34
|
+
let f = !0, w = !0;
|
|
35
|
+
const y = () => {
|
|
36
|
+
f && (a.render(), w && (w = !1, window.setTimeout(() => o == null ? void 0 : o(), 0)), requestAnimationFrame(y));
|
|
37
|
+
};
|
|
38
|
+
requestAnimationFrame(y);
|
|
39
|
+
const R = () => {
|
|
40
|
+
if (u.length < 2) return n;
|
|
41
|
+
let k = n;
|
|
42
|
+
for (; k === n; ) k = u[Math.floor(Math.random() * u.length)];
|
|
43
|
+
return k;
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
get presetName() {
|
|
47
|
+
return P(n);
|
|
48
|
+
},
|
|
49
|
+
get currentPresetId() {
|
|
50
|
+
return n;
|
|
51
|
+
},
|
|
52
|
+
connectAudio: (k) => a.connectAudio(k),
|
|
53
|
+
loadRandom: (k = 2.5) => {
|
|
54
|
+
const x = R();
|
|
55
|
+
return a.loadPreset(c[x], k), n = x, P(x);
|
|
56
|
+
},
|
|
57
|
+
loadByName: (k, x = 2.5) => {
|
|
58
|
+
const b = N(u, k);
|
|
59
|
+
return b ? (a.loadPreset(c[b], x), n = b, P(b)) : null;
|
|
60
|
+
},
|
|
61
|
+
loadFromUrl: async (k, x = 2.5) => {
|
|
62
|
+
var A;
|
|
63
|
+
const b = await fetch(k);
|
|
64
|
+
if (!b.ok)
|
|
65
|
+
throw new Error(`fetch ${k} → ${b.status} ${b.statusText}`);
|
|
66
|
+
const C = await b.text(), M = await Z.convertPreset(C);
|
|
67
|
+
a.loadPreset(M, x);
|
|
68
|
+
const G = ((A = k.split("/").pop()) == null ? void 0 : A.replace(/\.milk$/, "")) ?? k;
|
|
69
|
+
return n = G, P(G);
|
|
70
|
+
},
|
|
71
|
+
destroy: () => {
|
|
72
|
+
f = !1, window.removeEventListener("resize", m);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function N(t, e) {
|
|
77
|
+
if (t.includes(e)) return e;
|
|
78
|
+
const s = e.toLowerCase(), o = t.find((a) => a.toLowerCase() === s);
|
|
79
|
+
if (o) return o;
|
|
80
|
+
const r = (a) => a.toLowerCase().replace(/[^a-z0-9]/g, ""), l = r(e);
|
|
81
|
+
return t.find((a) => r(a) === l) ?? null;
|
|
82
|
+
}
|
|
83
|
+
function P(t) {
|
|
84
|
+
return t.replace(/^[\W\d]+/, "").replace(/[_]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
const re = `#version 300 es
|
|
87
|
+
precision highp float;
|
|
88
|
+
out vec2 v_uv;
|
|
89
|
+
void main() {
|
|
90
|
+
// Fullscreen triangle (no buffer needed; gl_VertexID drives positions).
|
|
91
|
+
vec2 p = vec2((gl_VertexID & 1) * 4 - 1, (gl_VertexID & 2) * 2 - 1);
|
|
92
|
+
v_uv = p * 0.5 + 0.5;
|
|
93
|
+
gl_Position = vec4(p, 0.0, 1.0);
|
|
94
|
+
}
|
|
95
|
+
`, se = `#version 300 es
|
|
96
|
+
precision highp float;
|
|
97
|
+
precision highp int;
|
|
98
|
+
|
|
99
|
+
uniform float iTime;
|
|
100
|
+
uniform float iTimeDelta;
|
|
101
|
+
uniform int iFrame;
|
|
102
|
+
uniform vec3 iResolution;
|
|
103
|
+
uniform vec4 iMouse;
|
|
104
|
+
uniform sampler2D iChannel0; // audio FFT (256x1, R8)
|
|
105
|
+
uniform sampler2D iChannel1; // image input (default_image or bound source)
|
|
106
|
+
in vec2 v_uv;
|
|
107
|
+
out vec4 outColor;
|
|
108
|
+
|
|
109
|
+
`, oe = `
|
|
110
|
+
|
|
111
|
+
void main() {
|
|
112
|
+
vec4 c;
|
|
113
|
+
mainImage(c, gl_FragCoord.xy);
|
|
114
|
+
outColor = vec4(c.rgb, 1.0);
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
function ie(t, e, s) {
|
|
118
|
+
const o = e.getContext("webgl2", {
|
|
119
|
+
alpha: !1,
|
|
120
|
+
antialias: !1,
|
|
121
|
+
preserveDrawingBuffer: !1,
|
|
122
|
+
powerPreference: "high-performance"
|
|
123
|
+
});
|
|
124
|
+
if (!o) throw new Error("WebGL2 not available");
|
|
125
|
+
const r = o, l = (d, p) => {
|
|
126
|
+
e.width = d, e.height = p, r.viewport(0, 0, d, p);
|
|
127
|
+
};
|
|
128
|
+
l(window.innerWidth, window.innerHeight);
|
|
129
|
+
let a = s;
|
|
130
|
+
const c = t.createAnalyser();
|
|
131
|
+
c.fftSize = 512, a.connect(c);
|
|
132
|
+
const u = new Uint8Array(256), n = r.createTexture();
|
|
133
|
+
r.bindTexture(r.TEXTURE_2D, n), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, r.LINEAR), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MAG_FILTER, r.LINEAR), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_S, r.CLAMP_TO_EDGE), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_T, r.CLAMP_TO_EDGE), r.texImage2D(r.TEXTURE_2D, 0, r.R8, 256, 1, 0, r.RED, r.UNSIGNED_BYTE, null);
|
|
134
|
+
const h = r.createTexture();
|
|
135
|
+
r.bindTexture(r.TEXTURE_2D, h), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, r.LINEAR), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MAG_FILTER, r.LINEAR), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_S, r.REPEAT), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_T, r.REPEAT), r.texImage2D(
|
|
136
|
+
r.TEXTURE_2D,
|
|
137
|
+
0,
|
|
138
|
+
r.RGBA,
|
|
139
|
+
1,
|
|
140
|
+
1,
|
|
141
|
+
0,
|
|
142
|
+
r.RGBA,
|
|
143
|
+
r.UNSIGNED_BYTE,
|
|
144
|
+
new Uint8Array([32, 32, 38, 255])
|
|
145
|
+
);
|
|
146
|
+
const v = r.createVertexArray();
|
|
147
|
+
let m = null, f = null, w = "—", y = null;
|
|
148
|
+
const R = performance.now();
|
|
149
|
+
let k = R, x = 0, b = 0, C = 0, M = !1, G = !0;
|
|
150
|
+
function A(d, p) {
|
|
151
|
+
const g = r.createShader(d);
|
|
152
|
+
if (r.shaderSource(g, p), r.compileShader(g), !r.getShaderParameter(g, r.COMPILE_STATUS)) {
|
|
153
|
+
const _ = r.getShaderInfoLog(g) ?? "(no log)";
|
|
154
|
+
throw r.deleteShader(g), new Error(`GLSL compile error:
|
|
155
|
+
${_}
|
|
156
|
+
--- source ---
|
|
157
|
+
${X(p)}`);
|
|
158
|
+
}
|
|
159
|
+
return g;
|
|
160
|
+
}
|
|
161
|
+
function X(d) {
|
|
162
|
+
return d.split(`
|
|
163
|
+
`).map((p, g) => `${String(g + 1).padStart(3)}: ${p}`).join(`
|
|
164
|
+
`);
|
|
165
|
+
}
|
|
166
|
+
function j(d) {
|
|
167
|
+
const p = A(r.VERTEX_SHADER, re), g = A(r.FRAGMENT_SHADER, se + d + oe), _ = r.createProgram();
|
|
168
|
+
if (r.attachShader(_, p), r.attachShader(_, g), r.linkProgram(_), !r.getProgramParameter(_, r.LINK_STATUS)) {
|
|
169
|
+
const S = r.getProgramInfoLog(_) ?? "(no log)";
|
|
170
|
+
throw r.deleteShader(p), r.deleteShader(g), r.deleteProgram(_), new Error(`Shader link error: ${S}`);
|
|
171
|
+
}
|
|
172
|
+
return r.deleteShader(p), r.deleteShader(g), _;
|
|
173
|
+
}
|
|
174
|
+
function F() {
|
|
175
|
+
if (!G) return;
|
|
176
|
+
const d = performance.now(), p = (d - R) * 1e-3, g = (d - k) * 1e-3;
|
|
177
|
+
if (k = d, x++, c.getByteFrequencyData(u), r.bindTexture(r.TEXTURE_2D, n), r.texImage2D(r.TEXTURE_2D, 0, r.R8, 256, 1, 0, r.RED, r.UNSIGNED_BYTE, u), y && (y instanceof HTMLCanvasElement ? y.width > 0 && y.height > 0 : y.readyState >= 2)) {
|
|
178
|
+
r.bindTexture(r.TEXTURE_2D, h), r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL, !0);
|
|
179
|
+
try {
|
|
180
|
+
r.texImage2D(r.TEXTURE_2D, 0, r.RGBA, r.RGBA, r.UNSIGNED_BYTE, y);
|
|
181
|
+
} catch {
|
|
182
|
+
}
|
|
183
|
+
r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL, !1);
|
|
184
|
+
}
|
|
185
|
+
if (m) {
|
|
186
|
+
r.useProgram(m);
|
|
187
|
+
const _ = (S) => r.getUniformLocation(m, S);
|
|
188
|
+
r.uniform1f(_("iTime"), p), r.uniform1f(_("iTimeDelta"), g), r.uniform1i(_("iFrame"), x), r.uniform3f(_("iResolution"), e.width, e.height, 1), r.uniform4f(_("iMouse"), b, e.height - C, M ? 1 : 0, 0), r.activeTexture(r.TEXTURE0), r.bindTexture(r.TEXTURE_2D, n), r.uniform1i(_("iChannel0"), 0), r.activeTexture(r.TEXTURE1), r.bindTexture(r.TEXTURE_2D, h), r.uniform1i(_("iChannel1"), 1), r.bindVertexArray(v), r.drawArrays(r.TRIANGLES, 0, 3);
|
|
189
|
+
} else
|
|
190
|
+
r.clearColor(0, 0, 0, 1), r.clear(r.COLOR_BUFFER_BIT);
|
|
191
|
+
requestAnimationFrame(F);
|
|
192
|
+
}
|
|
193
|
+
requestAnimationFrame(F);
|
|
194
|
+
const I = () => l(window.innerWidth, window.innerHeight), B = (d) => {
|
|
195
|
+
b = d.clientX, C = d.clientY;
|
|
196
|
+
}, L = () => {
|
|
197
|
+
M = !0;
|
|
198
|
+
}, U = () => {
|
|
199
|
+
M = !1;
|
|
200
|
+
};
|
|
201
|
+
return window.addEventListener("resize", I, { passive: !0 }), window.addEventListener("pointermove", B, { passive: !0 }), window.addEventListener("pointerdown", L, { passive: !0 }), window.addEventListener("pointerup", U, { passive: !0 }), {
|
|
202
|
+
get presetName() {
|
|
203
|
+
return w;
|
|
204
|
+
},
|
|
205
|
+
get currentUrl() {
|
|
206
|
+
return f;
|
|
207
|
+
},
|
|
208
|
+
connectAudio: (d) => {
|
|
209
|
+
a.disconnect(), a = d, a.connect(c);
|
|
210
|
+
},
|
|
211
|
+
loadFromUrl: async (d) => {
|
|
212
|
+
var S;
|
|
213
|
+
const p = await fetch(d);
|
|
214
|
+
if (!p.ok) throw new Error(`fetch ${d} → ${p.status}`);
|
|
215
|
+
const g = await p.text(), _ = j(g);
|
|
216
|
+
return m && r.deleteProgram(m), m = _, f = d, w = ((S = d.split("/").pop()) == null ? void 0 : S.replace(/\.glsl$/, "")) ?? d, w;
|
|
217
|
+
},
|
|
218
|
+
setLiveSource: (d) => {
|
|
219
|
+
y = d;
|
|
220
|
+
},
|
|
221
|
+
bindImage: async (d) => {
|
|
222
|
+
if (!d) {
|
|
223
|
+
r.bindTexture(r.TEXTURE_2D, h), r.texImage2D(
|
|
224
|
+
r.TEXTURE_2D,
|
|
225
|
+
0,
|
|
226
|
+
r.RGBA,
|
|
227
|
+
1,
|
|
228
|
+
1,
|
|
229
|
+
0,
|
|
230
|
+
r.RGBA,
|
|
231
|
+
r.UNSIGNED_BYTE,
|
|
232
|
+
new Uint8Array([32, 32, 38, 255])
|
|
233
|
+
);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const p = new Image();
|
|
237
|
+
p.crossOrigin = "anonymous", await new Promise((_, S) => {
|
|
238
|
+
p.onload = () => _(), p.onerror = () => S(new Error(`image load failed: ${d}`)), p.src = d;
|
|
239
|
+
}), r.bindTexture(r.TEXTURE_2D, h), r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL, !0), r.texImage2D(r.TEXTURE_2D, 0, r.RGBA, r.RGBA, r.UNSIGNED_BYTE, p), r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL, !1), (p.naturalWidth & p.naturalWidth - 1) === 0 && (p.naturalHeight & p.naturalHeight - 1) === 0 ? (r.generateMipmap(r.TEXTURE_2D), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, r.LINEAR_MIPMAP_LINEAR)) : r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, r.LINEAR);
|
|
240
|
+
},
|
|
241
|
+
destroy: () => {
|
|
242
|
+
G = !1, window.removeEventListener("resize", I), window.removeEventListener("pointermove", B), window.removeEventListener("pointerdown", L), window.removeEventListener("pointerup", U), m && r.deleteProgram(m), r.deleteTexture(n), r.deleteTexture(h), r.deleteVertexArray(v);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const te = 6, le = 1, T = 1280, E = 720;
|
|
247
|
+
class ae {
|
|
248
|
+
constructor(e, s = {}) {
|
|
249
|
+
/** The output canvas — bind this to the shader via setLiveSource. */
|
|
250
|
+
i(this, "canvas");
|
|
251
|
+
i(this, "ctx");
|
|
252
|
+
i(this, "urls");
|
|
253
|
+
i(this, "holdMs");
|
|
254
|
+
i(this, "images");
|
|
255
|
+
i(this, "currentIndex", 0);
|
|
256
|
+
i(this, "nextIndex", 1);
|
|
257
|
+
/** Wall-clock time the current crossfade started, or null if we're
|
|
258
|
+
* in the steady-hold portion of the cycle. */
|
|
259
|
+
i(this, "crossfadeStartMs", null);
|
|
260
|
+
i(this, "holdTimer", null);
|
|
261
|
+
i(this, "rafHandle", null);
|
|
262
|
+
i(this, "destroyed", !1);
|
|
263
|
+
if (e.length === 0)
|
|
264
|
+
throw new Error("HeadlessSlideshow: urls list cannot be empty");
|
|
265
|
+
this.urls = e, this.holdMs = Math.max(0.5, s.holdSeconds ?? te) * 1e3, this.canvas = document.createElement("canvas"), this.canvas.width = T, this.canvas.height = E;
|
|
266
|
+
const o = this.canvas.getContext("2d");
|
|
267
|
+
if (!o) throw new Error("HeadlessSlideshow: 2D canvas context unavailable");
|
|
268
|
+
this.ctx = o, this.images = e.map(() => null), this.preload();
|
|
269
|
+
}
|
|
270
|
+
destroy() {
|
|
271
|
+
this.destroyed = !0, this.holdTimer != null && clearTimeout(this.holdTimer), this.rafHandle != null && cancelAnimationFrame(this.rafHandle);
|
|
272
|
+
}
|
|
273
|
+
async preload() {
|
|
274
|
+
const e = this.urls.map(
|
|
275
|
+
(s, o) => ue(s).then(
|
|
276
|
+
(r) => {
|
|
277
|
+
this.destroyed || (this.images[o] = r, o === 0 && this.start());
|
|
278
|
+
},
|
|
279
|
+
(r) => {
|
|
280
|
+
console.warn(`[/prism] image-feed: ${s} → ${r.message}`);
|
|
281
|
+
}
|
|
282
|
+
)
|
|
283
|
+
);
|
|
284
|
+
await Promise.allSettled(e);
|
|
285
|
+
}
|
|
286
|
+
start() {
|
|
287
|
+
this.destroyed || (this.drawFrame(), this.scheduleNext());
|
|
288
|
+
}
|
|
289
|
+
scheduleNext() {
|
|
290
|
+
this.destroyed || (this.holdTimer = window.setTimeout(() => this.advance(), this.holdMs));
|
|
291
|
+
}
|
|
292
|
+
advance() {
|
|
293
|
+
if (this.destroyed) return;
|
|
294
|
+
let e = (this.currentIndex + 1) % this.urls.length;
|
|
295
|
+
for (let s = 0; s < this.urls.length && !this.images[e]; s++)
|
|
296
|
+
e = (e + 1) % this.urls.length;
|
|
297
|
+
if (e === this.currentIndex) {
|
|
298
|
+
this.scheduleNext();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
this.nextIndex = e, this.crossfadeStartMs = performance.now(), this.rafHandle = requestAnimationFrame(() => this.tickCrossfade());
|
|
302
|
+
}
|
|
303
|
+
tickCrossfade() {
|
|
304
|
+
if (this.destroyed || this.crossfadeStartMs == null) return;
|
|
305
|
+
const e = (performance.now() - this.crossfadeStartMs) / 1e3 / le;
|
|
306
|
+
if (e >= 1) {
|
|
307
|
+
this.currentIndex = this.nextIndex, this.crossfadeStartMs = null, this.drawFrame(), this.scheduleNext();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
this.drawCrossfade(e), this.rafHandle = requestAnimationFrame(() => this.tickCrossfade());
|
|
311
|
+
}
|
|
312
|
+
/** Draw the current image fully opaque. */
|
|
313
|
+
drawFrame() {
|
|
314
|
+
const e = this.images[this.currentIndex];
|
|
315
|
+
e && (this.ctx.fillStyle = "#000", this.ctx.fillRect(0, 0, T, E), D(this.ctx, e, T, E));
|
|
316
|
+
}
|
|
317
|
+
/** Draw the current image, then the next one at alpha=t on top. */
|
|
318
|
+
drawCrossfade(e) {
|
|
319
|
+
const s = this.images[this.currentIndex], o = this.images[this.nextIndex];
|
|
320
|
+
this.ctx.fillStyle = "#000", this.ctx.fillRect(0, 0, T, E), s && D(this.ctx, s, T, E), o && (this.ctx.save(), this.ctx.globalAlpha = e, D(this.ctx, o, T, E), this.ctx.restore());
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function ue(t) {
|
|
324
|
+
return new Promise((e, s) => {
|
|
325
|
+
const o = new Image();
|
|
326
|
+
o.crossOrigin = "anonymous", o.onload = () => e(o), o.onerror = () => s(new Error(`image load failed: ${t}`)), o.src = t;
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function D(t, e, s, o) {
|
|
330
|
+
const r = e.naturalWidth / e.naturalHeight, l = s / o;
|
|
331
|
+
let a = 0, c = 0, u = e.naturalWidth, n = e.naturalHeight;
|
|
332
|
+
r > l ? (u = e.naturalHeight * l, a = (e.naturalWidth - u) / 2) : (n = e.naturalWidth / l, c = (e.naturalHeight - n) / 2), t.drawImage(e, a, c, u, n, 0, 0, s, o);
|
|
333
|
+
}
|
|
334
|
+
const ne = { name: "shifter - spincycle c", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-spincycle-c.milk" }, ce = { name: "phat + Eo.S. - TesellatingFractal_Mix3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-eo-s-tesellatingfractal-mix3.milk" }, me = { name: "phat + Eo.S. - TesellatingFractal_Mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-eo-s-tesellatingfractal-mix.milk" }, de = { name: "phat + Eo.S. - 2ct2V5", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-eo-s-2ct2v5.milk" }, pe = { name: "nil - Vortex of Vortices", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/nil-vortex-of-vortices.milk" }, ke = { name: "mstress - Scattered gravity (Smoked mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mstress-scattered-gravity-smoked-mix.milk" }, _e = { name: "mstress - Cleaning a path - Painterly Crossfire", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mstress-cleaning-a-path-painterly-crossfire.milk" }, he = { name: "fiShbRaiN - the adventures of prismo jenkins", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fishbrain-the-adventures-of-prismo-jenkins.milk" }, ye = { name: "amandio c - new life", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/amandio-c-new-life.milk" }, ge = { name: "Vovan + Geiss - Bass With Flover (Feedback Mix) 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/vovan-geiss-bass-with-flover-feedback-mix-3.milk" }, fe = { name: "Vovan + Geiss - Bass With Flover (Feedback Mix) 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/vovan-geiss-bass-with-flover-feedback-mix-2.milk" }, xe = { name: "Unchained - elite vectronics", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-elite-vectronics.milk" }, ve = { name: "Telek - Slow Thing (Spiderman Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/telek-slow-thing-spiderman-mix.milk" }, be = { name: "Rovastar + Zylot - Narell's Fever", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-zylot-narell-s-fever.milk" }, we = { name: "Rovastar + Unchained - Ambrosia Mystic (Dark Heart Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-unchained-ambrosia-mystic-dark-heart-mix-2.milk" }, Se = { name: "Rovastar + Telek - Altars of Madness (Rolling Oceans Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-telek-altars-of-madness-rolling-oceans-mix.milk" }, Te = { name: "Rovastar & Unchained - Unified Drag 2 (Ghostly Vision Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-unchained-unified-drag-2-ghostly-vision-mix.milk" }, Ee = { name: "Rovastar & Rocke - Sugar Spun Sister", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-rocke-sugar-spun-sister.milk" }, Re = { name: "Reenen - phoenix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/reenen-phoenix.milk" }, Me = { name: "Phat + Eo.S. - Data_swimmer", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-eo-s-data-swimmer.milk" }, Ge = { name: "Krash - War Machine (Shifting Complexity Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/krash-war-machine-shifting-complexity-mix.milk" }, Ae = { name: "Illusion & Boz - Hot Air Balloon", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/illusion-boz-hot-air-balloon.milk" }, Ce = { name: "Geiss - Tokamak Plus Painterly", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-tokamak-plus-painterly.milk" }, Pe = { name: "Geiss - Tokamak Plus 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-tokamak-plus-3.milk" }, De = { name: "Geiss - Swirlie 4", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-swirlie-4.milk" }, Fe = { name: "Geiss - Sound And The Fury", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-sound-and-the-fury.milk" }, Ie = { name: "Geiss - Mega Swirl 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-mega-swirl-2.milk" }, Be = { name: "Geiss - Cycloid 1 - painterly", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cycloid-1-painterly.milk" }, Le = { name: "Geiss - Cycloid 1 - painterly vortex", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cycloid-1-painterly-vortex.milk" }, Ue = { name: "Geiss - Cycloid 1 - painterly vortex 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cycloid-1-painterly-vortex-3.milk" }, Ne = { name: "Geiss - Cauldron - painterly 3 (saturation remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cauldron-painterly-3-saturation-remix.milk" }, Ve = { name: "Image Metaball", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/image-metaball.glsl", default_image: "/api/image-proxy?url=https%3A%2F%2Fimages-assets.nasa.gov%2Fimage%2FPIA15985%2FPIA15985~medium.jpg" }, We = { name: "Eo.S. - nematodes E daemon", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-nematodes-e-daemon.milk" }, Oe = { name: "Eo.S. + Phat - chasers 11 sentinel C_poltergeist_mix response daemon (geiss flicker fix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-chasers-11-sentinel-c-poltergeist-mix-response-daemon-geiss-flicker.milk" }, qe = { name: "Eo.S. + Phat - chasers 11 sentinel C", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-chasers-11-sentinel-c.milk" }, Xe = { name: "Che - Terracarbon Stream", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/che-terracarbon-stream.milk" }, je = { name: "Aderrasi - The Lurker (Twin Mix) - Bitcore Tweak", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-the-lurker-twin-mix-bitcore-tweak.milk" }, He = { name: "Aderrasi - Ghast (Quarter Past Ghast Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-ghast-quarter-past-ghast-mix.milk" }, ze = { name: "Aderrasi - Contortion (Wide Twist Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-contortion-wide-twist-mix.milk" }, Ke = { name: "Aderrasi - Airhandler (Last Breath - Eden)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-airhandler-last-breath-eden.milk" }, Ye = { name: "Aderrasi - Airhandler (Last Breath - Calm)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-airhandler-last-breath-calm.milk" }, Je = { name: "Cosmic Flow", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/cosmic-flow.glsl" }, Ze = { name: "Image Pool", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/image-pool.glsl", default_image: "/api/image-proxy?url=https%3A%2F%2Fimages-assets.nasa.gov%2Fimage%2FPIA17563%2FPIA17563~medium.jpg" }, $e = { name: "shifter - glassworms flare", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-glassworms-flare.milk" }, Qe = { name: "shifter - escape the worm - Eo.S. + Phat 5362", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-escape-the-worm-eo-s-phat-5362.milk" }, er = { name: "shifter + geiss - neon pulse (glow mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-geiss-neon-pulse-glow-mix.milk" }, rr = { name: "martin - volcano", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-volcano.milk" }, sr = { name: "martin - violet flash", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-violet-flash.milk" }, or = { name: "martin - soma in pink (Ati Fix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-soma-in-pink-ati-fix.milk" }, ir = { name: "martin - push cx", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-push-cx.milk" }, tr = { name: "martin - push ax", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-push-ax.milk" }, lr = { name: "martin - move this body", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-move-this-body.milk" }, ar = { name: "martin - infinity", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-infinity.milk" }, ur = { name: "martin - bring up the big guns", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-bring-up-the-big-guns.milk" }, nr = { name: "martin - another kind of groove", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-another-kind-of-groove.milk" }, cr = { name: "martin - another kind of groove (Ati Fix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-another-kind-of-groove-ati-fix.milk" }, mr = { name: "martin - angel flight", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-angel-flight.milk" }, dr = { name: "martin - Geiss - Psychotic Roulette", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-geiss-psychotic-roulette.milk" }, pr = { name: "martin + stahlregen - martin in da mash 12a", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-stahlregen-martin-in-da-mash-12a.milk" }, kr = { name: "martin + stahlregen - martin in da mash 12", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-stahlregen-martin-in-da-mash-12.milk" }, _r = { name: "idiot - Spectrum", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/idiot-spectrum.milk" }, hr = { name: "geiss - liquid beats (jelly v4.5)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-liquid-beats-jelly-v4-5.milk" }, yr = { name: "flexi, fishbrain + stahlregen - witchcraft [jelly5.5]", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-fishbrain-stahlregen-witchcraft-jelly5-5.milk" }, gr = { name: "flexi - what is the matrix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-what-is-the-matrix.milk" }, fr = { name: "flexi - lorenz attractor", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-lorenz-attractor.milk" }, xr = { name: "flexi - hyperspaceflight (bn cn Jelly 4)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-hyperspaceflight-bn-cn-jelly-4.milk" }, vr = { name: "flexi - bouncing balls [neon mix]", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-bouncing-balls-neon-mix.milk" }, br = { name: "flexi - alien web bouncer", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-alien-web-bouncer.milk" }, wr = { name: "flexi + stahlregen - jewelry tiles", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-stahlregen-jewelry-tiles.milk" }, Sr = { name: "flexi + nitorami - beat explorer (cn bc jelly 4)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-nitorami-beat-explorer-cn-bc-jelly-4.milk" }, Tr = { name: "flexi + fishbrain - neon mindblob grafitti", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-fishbrain-neon-mindblob-grafitti.milk" }, Er = { name: "fiShbRaiN + geiss - witchcraft (Stahl's Mirror Crossfire Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fishbrain-geiss-witchcraft-stahl-s-mirror-crossfire-mix.milk" }, Rr = { name: "fiShbRaiN + geiss - witchcraft (Grow Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fishbrain-geiss-witchcraft-grow-mix.milk" }, Mr = { name: "beta106i - It's the Sun (Brotherhood of Tears) - mash0000 - vascular chemical allergy", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/beta106i-it-s-the-sun-brotherhood-of-tears-mash0000-vascular-chemical-allergy.milk" }, Gr = { name: "amandio c - salty beats - spiral", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/amandio-c-salty-beats-spiral.milk" }, Ar = { name: "amandio c - odd star", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/amandio-c-odd-star.milk" }, Cr = { name: "geiss_experimental__LSB Bass Cubes", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-experimental-lsb-bass-cubes.milk" }, Pr = { name: "geiss_experimental__Aderrasi - Kevlar Ore Deposit - geiss core stripe mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-experimental-aderrasi-kevlar-ore-deposit-geiss-core-stripe-mix.milk" }, Dr = { name: "Geiss - Cosmic Dust 2 - Game of Life - zoom mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-game-of-life-zoom-mix.milk" }, Fr = { name: "Vovan + Geiss - Bass With Flover (Feedback Mix ORIG)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/vovan-geiss-bass-with-flover-feedback-mix-orig.milk" }, Ir = { name: "Mig_Oscilloscope022", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-oscilloscope022.milk" }, Br = { name: "Mig_Oscilloscope022 b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-oscilloscope022-b.milk" }, Lr = { name: "Mig_304 - geiss remix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-304-geiss-remix.milk" }, Ur = { name: "Mig_304 - geiss remix 3b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-304-geiss-remix-3b.milk" }, Nr = { name: "Mig_304 - geiss remix 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-304-geiss-remix-3.milk" }, Vr = { name: "Mig_304 - geiss remix 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-304-geiss-remix-2.milk" }, Wr = { name: "Mig_197b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-197b.milk" }, Or = { name: "Mig_120", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-120.milk" }, qr = { name: "Mig_091b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-091b.milk" }, Xr = { name: "Mig_091", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-091.milk" }, jr = { name: "Mig_085", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-085-2.milk" }, Hr = { name: "Mig_082_version2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-082-version2.milk" }, zr = { name: "Mig_068", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-068.milk" }, Kr = { name: "Mig_036_version3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-036-version3.milk" }, Yr = { name: "Mig_032_version3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-032-version3.milk" }, Jr = { name: "Martin - wire dance (geiss warp shader mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-wire-dance-geiss-warp-shader-mix.milk" }, Zr = { name: "Geiss - Confetti (Kaleidoscope Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-confetti-kaleidoscope-mix.milk" }, $r = { name: "Eo.S. - glowsticks v2 02 - Geiss HPF", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-02-geiss-hpf.milk" }, Qr = { name: "Eo.S. + Zylot - skylight (Stained Glass Majesty mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-zylot-skylight-stained-glass-majesty-mix-2.milk" }, es = { name: "Unchained - Perverted Dialect", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-perverted-dialect.milk" }, rs = { name: "Unchained - Free to Feel (Valium Remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-free-to-feel-valium-remix.milk" }, ss = { name: "Unchained & Rovastar - Rainbow Obscura", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-rovastar-rainbow-obscura.milk" }, os = { name: "Unchained & Rovastar - Luckless", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-rovastar-luckless.milk" }, is = { name: "Telek - Directive Swagger (Spectral Inferno) with radial blur", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/telek-directive-swagger-spectral-inferno-with-radial-blur.milk" }, ts = { name: "Stahlregen - Spiral Beats (Fluctuating Flowers)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/stahlregen-spiral-beats-fluctuating-flowers.milk" }, ls = { name: "Stahlregen + Unchained - Psychedelic Flower Kung Fu (Corrupt)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/stahlregen-unchained-psychedelic-flower-kung-fu-corrupt.milk" }, as = { name: "Stahlregen & Geiss + TobiasWolfBoi - Space Gelatin (Color Xplosion)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/stahlregen-geiss-tobiaswolfboi-space-gelatin-color-xplosion.milk" }, us = { name: "Stahlregen & Geiss + TobiasWolfBoi - Space Gelatin (Color Xplosion 2)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/stahlregen-geiss-tobiaswolfboi-space-gelatin-color-xplosion-2.milk" }, ns = { name: "Rovastar - Snapshot Of Space", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-snapshot-of-space.milk" }, cs = { name: "Rovastar - LabFunk", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-labfunk.milk" }, ms = { name: "Rovastar - Hyperspace", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-hyperspace.milk" }, ds = { name: "Rovastar - Demon Sunflower (Double Resistance Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-demon-sunflower-double-resistance-mix.milk" }, ps = { name: "Rovastar + Rocke - Sugar Spun Sister - Painterly", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-rocke-sugar-spun-sister-painterly.milk" }, ks = { name: "Rovastar + Loadus - FractalDrop (Active Sparks Mix) Steady", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-loadus-fractaldrop-active-sparks-mix-steady.milk" }, _s = { name: "Rovastar + Loadus + Geiss - Tone-mapped FractalDrop", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-loadus-geiss-tone-mapped-fractaldrop.milk" }, hs = { name: "Rovastar + Loadus + Geiss - Tone-mapped FractalDrop 7c", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-loadus-geiss-tone-mapped-fractaldrop-7c.milk" }, ys = { name: "Rovastar + Loadus + Geiss - FractalDrop (Triple Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-loadus-geiss-fractaldrop-triple-mix.milk" }, gs = { name: "Rovastar + Geiss - Bipolar 2 (Vectrip Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-geiss-bipolar-2-vectrip-mix.milk" }, fs = { name: "Rovastar + Che - Asylum Animations", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-che-asylum-animations.milk" }, xs = { name: "Phat+fiShbRaiN+Eo.S_Mandala_Chasers_remix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-fishbrain-eo-s-mandala-chasers-remix.milk" }, vs = { name: "ORB - Solar Radiation", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-solar-radiation.milk" }, bs = { name: "ORB - Saturns Rings", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-saturns-rings.milk" }, ws = { name: "ORB - Quicksand", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-quicksand.milk" }, Ss = { name: "ORB - Pastel Primer", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-pastel-primer.milk" }, Ts = { name: "ORB - Liquid Fire", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-liquid-fire.milk" }, Es = { name: "ORB - Inferno", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-inferno.milk" }, Rs = { name: "ORB - Crysal Storm", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-crysal-storm.milk" }, Ms = { name: "Mstress - Acoustic Nerve Impulses", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mstress-acoustic-nerve-impulses.milk" }, Gs = { name: "Martin - journey into space", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-journey-into-space.milk" }, As = { name: "Martin - charisma", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-charisma.milk" }, Cs = { name: "Krash - Vinyl Disk", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/krash-vinyl-disk.milk" }, Ps = { name: "Krash + Rovastar - Rainbow Orb", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/krash-rovastar-rainbow-orb.milk" }, Ds = { name: "Idiot - What Is", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/idiot-what-is.milk" }, Fs = { name: "Goody - Vertigo - revisited", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/goody-vertigo-revisited.milk" }, Is = { name: "Goody - Unstable Sonic Reactor - Final", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/goody-unstable-sonic-reactor-final.milk" }, Bs = { name: "Goody - Need - Gloam", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/goody-need-gloam.milk" }, Ls = { name: "Goody - Need - Desire remix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/goody-need-desire-remix.milk" }, Us = { name: "Geiss - Vortex 2 Painterly", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-vortex-2-painterly.milk" }, Ns = { name: "Geiss - Tokamak Plus 4", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-tokamak-plus-4.milk" }, Vs = { name: "Geiss - Swirlie 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-swirlie-2.milk" }, Ws = { name: "Geiss - Smoke Rings", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-smoke-rings.milk" }, Os = { name: "Geiss - Skin Dots Multi-layer 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-skin-dots-multi-layer-3.milk" }, qs = { name: "Geiss - Skin Dots 9", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-skin-dots-9.milk" }, Xs = { name: "Geiss - Skin Dots 11b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-skin-dots-11b.milk" }, js = { name: "Geiss - Rose 5 Crossfire Beats", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-5-crossfire-beats.milk" }, Hs = { name: "Geiss - Rose 5 Crossfire Beats - mash0000 - ill gotten slobber catcher", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-5-crossfire-beats-mash0000-ill-gotten-slobber-catcher.milk" }, zs = { name: "Geiss - Rose 5 Crossfire Beats (composite remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-5-crossfire-beats-composite-remix.milk" }, Ks = { name: "Geiss - Rose 4 (composite remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-4-composite-remix.milk" }, Ys = { name: "Geiss - Rose 4 (bccn Jelly V4)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-4-bccn-jelly-v4.milk" }, Js = { name: "Geiss - Rose 4 (LSB mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-4-lsb-mix.milk" }, Zs = { name: "Geiss - Rose 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-3.milk" }, $s = { name: "Geiss - Reaction Diffusion (Shifting Sphere Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-reaction-diffusion-shifting-sphere-mix.milk" }, Qs = { name: "Geiss - Reaction Diffusion (Relief Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-reaction-diffusion-relief-mix.milk" }, eo = { name: "Geiss - Reaction Diffusion (Puddle Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-reaction-diffusion-puddle-mix.milk" }, ro = { name: "Geiss - Plasma 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-plasma-2.milk" }, so = { name: "Geiss - Pistons", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-pistons.milk" }, oo = { name: "Geiss - Neutron - radial blur 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-neutron-radial-blur-2.milk" }, io = { name: "Geiss - Motion Blur 2 (Stahl's Neon Jelly 2 RMX)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-motion-blur-2-stahl-s-neon-jelly-2-rmx.milk" }, to = { name: "Geiss - Motion Blur 2 (Reverse Jelly V3)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-motion-blur-2-reverse-jelly-v3.milk" }, lo = { name: "Geiss - Motion Blur 2 (Relief Mix 2)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-motion-blur-2-relief-mix-2.milk" }, ao = { name: "Geiss - Mosaic Octopus 7", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-mosaic-octopus-7.milk" }, uo = { name: "Geiss - MicroCheckers 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-microcheckers-3.milk" }, no = { name: "Geiss - Mega Swirl 3 (color tweak)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-mega-swirl-3-color-tweak.milk" }, co = { name: "Geiss - Mash-Up 1", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-mash-up-1.milk" }, mo = { name: "Geiss - Liquid Beats 2 (Reverse Jelly V3)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-liquid-beats-2-reverse-jelly-v3.milk" }, po = { name: "Geiss - Iris", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-iris.milk" }, ko = { name: "Geiss - Iris Storm", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-iris-storm.milk" }, _o = { name: "Geiss - Hyperion (LSB mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-hyperion-lsb-mix.milk" }, ho = { name: "Geiss - Hurricane", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-hurricane.milk" }, yo = { name: "Geiss - Game of Life", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-game-of-life.milk" }, go = { name: "Geiss - Game of Life 3", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-game-of-life-3.milk" }, fo = { name: "Geiss - Eye of Jupiter", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-eye-of-jupiter.milk" }, xo = { name: "Geiss - Downward Spiral - color invert mirror x", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-downward-spiral-color-invert-mirror-x.milk" }, vo = { name: "Geiss - Digitunnel", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-digitunnel.milk" }, bo = { name: "Geiss - Diffuser (Red Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-diffuser-red-mix.milk" }, wo = { name: "Geiss - Desert Rose 4", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-desert-rose-4.milk" }, So = { name: "Geiss - Dancing Spirits (Bright)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-dancing-spirits-bright.milk" }, To = { name: "Geiss - Cosmic Dust 2 - quasistatic noise dual pane window", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-quasistatic-noise-dual-pane-window.milk" }, Eo = { name: "Geiss - Cosmic Dust 2 - quasistatic noise desat trails", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-quasistatic-noise-desat-trails.milk" }, Ro = { name: "Geiss - Cosmic Dust 2 - quasistatic noise desat trails 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-quasistatic-noise-desat-trails-2.milk" }, Mo = { name: "Geiss - Cosmic Dust 2 - Trails 7", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-trails-7.milk" }, Go = { name: "Geiss - Cosmic Dust 2 - Tiny Reaction Diffusion Mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-tiny-reaction-diffusion-mix.milk" }, Ao = { name: "Geiss - Constant Velocity - angular blur", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-constant-velocity-angular-blur.milk" }, Co = { name: "Geiss - Color Pox (Measles Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-color-pox-measles-mix.milk" }, Po = { name: "Geiss - Color Pox (Acid Impression Mix) (color saturation remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-color-pox-acid-impression-mix-color-saturation-remix.milk" }, Do = { name: "Geiss - Cepia Dither", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cepia-dither.milk" }, Fo = { name: "Geiss - Cauldron - painterly 5 (saturation remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cauldron-painterly-5-saturation-remix.milk" }, Io = { name: "Geiss - Cauldron - painterly 4 (saturation remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cauldron-painterly-4-saturation-remix.milk" }, Bo = { name: "Geiss - Casino", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-casino.milk" }, Lo = { name: "Geiss - All-Spark Sinews", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-all-spark-sinews.milk" }, Uo = { name: "Geiss - All-Spark Polar", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-all-spark-polar.milk" }, No = { name: "Geiss - 3 layers (Tunnel Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-3-layers-tunnel-mix.milk" }, Vo = { name: "Geiss - 3 layers (Planar Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-3-layers-planar-mix.milk" }, Wo = { name: "Geiss + Rovastar - Julia Fractal (Vectrip Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rovastar-julia-fractal-vectrip-mix.milk" }, Oo = { name: "Geiss - Cauldron - Tendrils (saturation remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cauldron-tendrils-saturation-remix.milk" }, qo = { name: "Geiss - Eggs", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-eggs.milk" }, Xo = { name: "Tunnel of Images", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/tunnel-of-images.glsl", default_image: "/api/image-proxy?url=https%3A%2F%2Fimages-assets.nasa.gov%2Fimage%2FPIA13994%2FPIA13994~medium.jpg" }, jo = { name: "Image Mosaic", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/image-mosaic.glsl", default_image: "/api/image-proxy?url=https%3A%2F%2Fimages-assets.nasa.gov%2Fimage%2FPIA22351%2FPIA22351~medium.jpg" }, Ho = { name: "Raymarch Sphere", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/raymarch-sphere.glsl" }, zo = { name: "Audio Spectrum", source_type: "shadertoy", source_loader: "url", source_url: "/presets/shadertoy/audio-spectrum.glsl" }, Ko = { name: "Flexi - using jedi forces", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-using-jedi-forces.milk" }, Yo = { name: "Flexi - layered + Boz - Buckwild", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-layered-boz-buckwild.milk" }, Jo = { name: "Esotic & Rozzor - Pixie Party Light ((No Wave Invasion) Mandala Chill Red Yellow Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/esotic-rozzor-pixie-party-light-no-wave-invasion-mandala-chill-red-yellow-mix.milk" }, Zo = { name: "Eo.S.+Phat - spectrum bubble new colors_v2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-spectrum-bubble-new-colors-v2.milk" }, $o = { name: "Eo.S. and Zylot - skylight (Stained Glass Majesty mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-and-zylot-skylight-stained-glass-majesty-mix.milk" }, Qo = { name: "Eo.S. - skylight a1 [music warp switch]", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-skylight-a1-music-warp-switch.milk" }, ei = { name: "Eo.S. - sarc c_Phats Zoom Mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-sarc-c-phats-zoom-mix.milk" }, ri = { name: "Eo.S. - repeater 13 - definitive", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-repeater-13-definitive.milk" }, si = { name: "Aderrasi - Airhandler (Kali Mix) - Painterly", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-airhandler-kali-mix-painterly.milk" }, oi = { name: "Eo.S. - glowsticks v2 03 music shifter edit b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-03-music-shifter-edit-b.milk" }, ii = { name: "Eo.S. - glowsticks v2 03 music shifter edit b (Stahl's Reactive RMX V2i2 - feat. flexi + phat)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-03-music-shifter-edit-b-stahl-s-reactive-rmx-v2i2-feat-flexi.milk" }, ti = { name: "Eo.S. - glowsticks v2 03 music shifter edit b (Jelly V2)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-03-music-shifter-edit-b-jelly-v2.milk" }, li = { name: "Eo.S. + Phat cubetrace (cybercity madness remix) - mash0000 - evaporating crystal pharma", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-cubetrace-cybercity-madness-remix-mash0000-evaporating-crystal-pharma.milk" }, ai = { name: "Eo.S. + Phat - cubetrace - v2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-cubetrace-v2.milk" }, ui = { name: "Eo.S. + Phat - chasers 14 sentinel 616", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-chasers-14-sentinel-616.milk" }, ni = { name: "Eo.S. + Phat + Geiss - chasers 15 sentinels male and female (Dementia Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-geiss-chasers-15-sentinels-male-and-female-dementia-mix.milk" }, ci = { name: "Eo.S. + Geiss - glowsticks v2 03 music shifter edit b (Psychedelic Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-geiss-glowsticks-v2-03-music-shifter-edit-b-psychedelic-mix.milk" }, mi = { name: "Eo.S. + Geiss - glowsticks v2 02 (Relief Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-geiss-glowsticks-v2-02-relief-mix.milk" }, di = { name: "Cope-WIP - Strange Attractor 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/cope-wip-strange-attractor-2.milk" }, pi = { name: "Cope - Passage (mandala mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/cope-passage-mandala-mix.milk" }, ki = { name: "Bmelgren & Krash - Rainbow Orb Peacock (Lonely Signal Gone Mad Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/bmelgren-krash-rainbow-orb-peacock-lonely-signal-gone-mad-mix.milk" }, _i = { name: "Aderrasi - Storm of the Eye (Thunder) - mash0000 - quasi pseudo meta concentrics", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-storm-of-the-eye-thunder-mash0000-quasi-pseudo-meta-concentrics.milk" }, hi = { name: "Aderrasi - Roaming Star (Himalaya Brach Office) - mash0000 - creaming the summit", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-roaming-star-himalaya-brach-office-mash0000-creaming-the-summit.milk" }, yi = { name: "Aderrasi - Ghast Entity", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-ghast-entity.milk" }, gi = { name: "Aderrasi - Ghast (Full Circle Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-ghast-full-circle-mix.milk" }, fi = { name: "Geiss - All-Spark", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-all-spark.milk" }, xi = { name: "martin - reflections on black tiles", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-reflections-on-black-tiles.milk" }, vi = { name: "shifter - spills blender + krash beatdetect - mash0000 - here comb your hair with this planet", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-spills-blender-krash-beatdetect-mash0000-here-comb-your-hair-with-this.milk" }, bi = { name: "shifter - neon pulse (reactive)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-neon-pulse-reactive.milk" }, wi = { name: "martin - soma in pink", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-soma-in-pink.milk" }, Si = { name: "martin - infinity (2010 update)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-infinity-2010-update.milk" }, Ti = { name: "martin - infinity (2008)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-infinity-2008.milk" }, Ei = { name: "martin - gate to moria", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-gate-to-moria.milk" }, Ri = { name: "martin - disco mix 4", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-disco-mix-4.milk" }, Mi = { name: "martin + stahlregen - martin in da mash 10 (infinity mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-stahlregen-martin-in-da-mash-10-infinity-mix.milk" }, Gi = { name: "fiShbRaiN - a quiet death", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fishbrain-a-quiet-death.milk" }, Ai = { name: "fed - slowfast 1.1", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fed-slowfast-1-1.milk" }, Ci = { name: "Unchained - Unified Drag 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-unified-drag-2.milk" }, Pi = { name: "Unchained - Cranked On Failure", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-cranked-on-failure.milk" }, Di = { name: "Unchained - All You Can Eat", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/unchained-all-you-can-eat.milk" }, Fi = { name: "Rozzor & StudioMusic - Vertigyny (Geiss Shape Mod)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rozzor-studiomusic-vertigyny-geiss-shape-mod.milk" }, Ii = { name: "Rovastar - VooV's Movement (After Dark Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-voov-s-movement-after-dark-mix.milk" }, Bi = { name: "Rovastar - VooV's Movement (After Dark Mix) - Painterly", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-voov-s-movement-after-dark-mix-painterly.milk" }, Li = { name: "Rovastar - Fractopia (Upspoken Mix)_Phat_Speak_When_Spoken_2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-fractopia-upspoken-mix-phat-speak-when-spoken-2.milk" }, Ui = { name: "Rovastar + Idiot24-7 - Balk Acid", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-idiot24-7-balk-acid.milk" }, Ni = { name: "Rovastar + Fvese - Mosaic Waves", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-fvese-mosaic-waves.milk" }, Vi = { name: "Rovastar & Unchained - Demonology (Vampire Soul Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-unchained-demonology-vampire-soul-mix.milk" }, Wi = { name: "Rovastar & Unchained - Ambrosia Mystic (Dark Heart Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-unchained-ambrosia-mystic-dark-heart-mix.milk" }, Oi = { name: "Reenen & Telek - Slow Shift Matrix (bb4.5 (Dynamic Beat) Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/reenen-telek-slow-shift-matrix-bb4-5-dynamic-beat-mix.milk" }, qi = { name: "PieturP - triptrap_(ultimate-trip-mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/pieturp-triptrap-ultimate-trip-mix.milk" }, Xi = { name: "Phat + Eo.S. - rainbow bubble_mid3-f. me dood", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-eo-s-rainbow-bubble-mid3-f-me-dood.milk" }, ji = { name: "Phat + Eo.S. - Swim_waveform_mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/phat-eo-s-swim-waveform-mix.milk" }, Hi = { name: "ORB - Nova Sunrise", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-nova-sunrise.milk" }, zi = { name: "ORB - Fire and Fumes 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-fire-and-fumes-2.milk" }, Ki = { name: "ORB - Blue Emotion", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-blue-emotion.milk" }, Yi = { name: "Ishan - Anuera", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/ishan-anuera.milk" }, Ji = { name: "Idiot24-7 - Ascending to heaven 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/idiot24-7-ascending-to-heaven-2.milk" }, Zi = { name: "Geiss - Motion Blur 2 (color sat boost)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-motion-blur-2-color-sat-boost.milk" }, $i = { name: "Geiss - Electric Storm Half-Digital 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-electric-storm-half-digital-2.milk" }, Qi = { name: "Geiss - Cosmic Dust 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2.milk" }, et = { name: "Geiss + Rovastar - The Chaos Of Colours (sprouting dimentia mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rovastar-the-chaos-of-colours-sprouting-dimentia-mix.milk" }, rt = { name: "Flexi - self-lubricating", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-self-lubricating.milk" }, st = { name: "Flexi - infused with the spiral", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-infused-with-the-spiral.milk" }, ot = { name: "Flexi + Martin - cascading decay swing", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-martin-cascading-decay-swing.milk" }, it = { name: "Eo.S.+Phat Emergent factors - Bitcore Tweak", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-emergent-factors-bitcore-tweak.milk" }, tt = { name: "Eo.S.+Phat - Flare_dig_mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-flare-dig-mix.milk" }, lt = { name: "Eo.S. - pulsecube f demon - mash0000 - yakuza gut cake", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-pulsecube-f-demon-mash0000-yakuza-gut-cake.milk" }, at = { name: "Eo.S. - heater core C_Phat's_class + sparks_mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-heater-core-c-phat-s-class-sparks-mix.milk" }, ut = { name: "Eo.S. - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix07", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-05-and-proton-lights-krash-s-beat-code-phat-remix07.milk" }, nt = { name: "Eo.S. + Zylot - skylight (Stained Glass Majesty mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-zylot-skylight-stained-glass-majesty-mix.milk" }, ct = { name: "Eo.S. + Phat - Emergent factors", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-emergent-factors.milk" }, mt = { name: "Bmelgren - Pentultimate Nerual Slipstream (Tweak 2)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/bmelgren-pentultimate-nerual-slipstream-tweak-2.milk" }, dt = { name: "Aderrasi - What cannot be", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-what-cannot-be.milk" }, pt = { name: "Aderrasi - Kevlar Tunnel", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-kevlar-tunnel.milk" }, kt = { name: "Aderrasi - Kevlar Ore Deposit", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-kevlar-ore-deposit.milk" }, _t = { name: "Aderrasi - Kevlar Abyss", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-kevlar-abyss.milk" }, ht = { name: "Aderrasi - Curse of the Mirror Emu", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-curse-of-the-mirror-emu.milk" }, yt = {
|
|
335
|
+
tf1p4d: ne,
|
|
336
|
+
Wxum6n: ce,
|
|
337
|
+
dLgCse: me,
|
|
338
|
+
MVi179: de,
|
|
339
|
+
GhBm5e: pe,
|
|
340
|
+
npT2uv: ke,
|
|
341
|
+
kOzc0s: _e,
|
|
342
|
+
I9ooYK: he,
|
|
343
|
+
RDy6sq: ye,
|
|
344
|
+
Kf91oH: ge,
|
|
345
|
+
uNXJWh: fe,
|
|
346
|
+
"96nqCN": { name: "Mig_061", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-061.milk" },
|
|
347
|
+
uioEhi: xe,
|
|
348
|
+
qaHSMU: ve,
|
|
349
|
+
"5vMLPd": { name: "Telek - Sine Wave", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/telek-sine-wave.milk" },
|
|
350
|
+
"9up6f0": { name: "Rovastar - Tripmaker", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-tripmaker.milk" },
|
|
351
|
+
Az8g8u: be,
|
|
352
|
+
KeuU8h: we,
|
|
353
|
+
tCVMll: Se,
|
|
354
|
+
"0QA4xS": { name: "Rovastar + Rocke - Sugar Spun Sister", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-rocke-sugar-spun-sister-2.milk" },
|
|
355
|
+
Lrc5R0: Te,
|
|
356
|
+
d8pa1M: Ee,
|
|
357
|
+
UMZdqF: Re,
|
|
358
|
+
uX6UbW: Me,
|
|
359
|
+
xWFt5r: Ge,
|
|
360
|
+
"0EqR07": { name: "Krash + Illusion - Spiral Movement", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/krash-illusion-spiral-movement.milk" },
|
|
361
|
+
Q8GYVn: Ae,
|
|
362
|
+
"21EsIq": { name: "Idiot - When I Get Bored", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/idiot-when-i-get-bored.milk" },
|
|
363
|
+
ev6vIF: Ce,
|
|
364
|
+
rsaa2P: Pe,
|
|
365
|
+
RWvefs: De,
|
|
366
|
+
S6FOvB: Fe,
|
|
367
|
+
tjl532: Ie,
|
|
368
|
+
"60PO4U": { name: "Geiss - Inkblot", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-inkblot.milk" },
|
|
369
|
+
SeVaRS: Be,
|
|
370
|
+
jDL6Sw: Le,
|
|
371
|
+
Ajw1Df: Ue,
|
|
372
|
+
GQhtQW: Ne,
|
|
373
|
+
B1T3U8: Ve,
|
|
374
|
+
pxJwLi: We,
|
|
375
|
+
JPtzJM: Oe,
|
|
376
|
+
tWskpA: qe,
|
|
377
|
+
g5ZlWy: Xe,
|
|
378
|
+
eq9Qbc: je,
|
|
379
|
+
tIMqOl: He,
|
|
380
|
+
JsqzWG: ze,
|
|
381
|
+
eZrZ4U: Ke,
|
|
382
|
+
W8R0Yc: Ye,
|
|
383
|
+
dHmr2t: Je,
|
|
384
|
+
N6KSf3: Ze,
|
|
385
|
+
LkZ5ho: $e,
|
|
386
|
+
TXLytI: Qe,
|
|
387
|
+
gzetxX: er,
|
|
388
|
+
ALj3eW: rr,
|
|
389
|
+
cldl8y: sr,
|
|
390
|
+
sm0xFa: or,
|
|
391
|
+
hdJKtV: ir,
|
|
392
|
+
yES2AZ: tr,
|
|
393
|
+
Ko6Ekq: lr,
|
|
394
|
+
Apnvzf: ar,
|
|
395
|
+
iMXDEP: ur,
|
|
396
|
+
jviFEg: nr,
|
|
397
|
+
aavCbG: cr,
|
|
398
|
+
jPnBOy: mr,
|
|
399
|
+
Rc2xnL: dr,
|
|
400
|
+
YCR4TG: pr,
|
|
401
|
+
SKyUN4: kr,
|
|
402
|
+
fNsmHM: _r,
|
|
403
|
+
kFMyOd: hr,
|
|
404
|
+
bDifaZ: yr,
|
|
405
|
+
xr8pYG: gr,
|
|
406
|
+
Eokjpa: fr,
|
|
407
|
+
REYygJ: xr,
|
|
408
|
+
gPB8Ba: vr,
|
|
409
|
+
cfZG0z: br,
|
|
410
|
+
oIQu1w: wr,
|
|
411
|
+
sifRsK: Sr,
|
|
412
|
+
"4GwcDg": { name: "flexi + geiss - pogo-cubes on tokamak matter [mind over matter remix]2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-geiss-pogo-cubes-on-tokamak-matter-mind-over-matter-remix-2.milk" },
|
|
413
|
+
o26wbv: Tr,
|
|
414
|
+
v91g2p: Er,
|
|
415
|
+
sOX9Ne: Rr,
|
|
416
|
+
"4oZk7A": { name: "fiShbRaiN + geiss - witchcraft (Glow Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fishbrain-geiss-witchcraft-glow-mix.milk" },
|
|
417
|
+
"29G3qf": { name: "fed - slowfast 1.1 (geiss composite remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fed-slowfast-1-1-geiss-composite-remix.milk" },
|
|
418
|
+
lY8xa0: Mr,
|
|
419
|
+
"7BOBGh": { name: "beta106i - Brilliance (Space-Time Breaking) - mash0000 - it's 2009 and you haven't replaced your analog tv with digital", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/beta106i-brilliance-space-time-breaking-mash0000-it-s-2009-and-you-haven-t.milk" },
|
|
420
|
+
Y8m1Pt: Gr,
|
|
421
|
+
x5qk8x: Ar,
|
|
422
|
+
xDUeFe: Cr,
|
|
423
|
+
MHYnjw: Pr,
|
|
424
|
+
V08viA: Dr,
|
|
425
|
+
M1IT0g: Fr,
|
|
426
|
+
"8e8JOa": { name: "Vovan + Geiss - Bass With Flover (Feedback Mix 2b)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/vovan-geiss-bass-with-flover-feedback-mix-2b.milk" },
|
|
427
|
+
lYoBpw: Ir,
|
|
428
|
+
boFs3y: Br,
|
|
429
|
+
lIr7aL: Lr,
|
|
430
|
+
HxWqlq: Ur,
|
|
431
|
+
CzBdsd: Nr,
|
|
432
|
+
WjkAlB: Vr,
|
|
433
|
+
Go59jW: Wr,
|
|
434
|
+
"7OsvAQ": { name: "Mig_146", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-146.milk" },
|
|
435
|
+
zmfXPk: Or,
|
|
436
|
+
e6sfNW: qr,
|
|
437
|
+
jJMXai: Xr,
|
|
438
|
+
OZq2ir: jr,
|
|
439
|
+
AtXQ4J: Hr,
|
|
440
|
+
iXU9Y5: zr,
|
|
441
|
+
INkWj7: Kr,
|
|
442
|
+
jDcvmK: Yr,
|
|
443
|
+
"21Zqxm": { name: "Mig_010", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mig-010.milk" },
|
|
444
|
+
nrnYxI: Jr,
|
|
445
|
+
"8240cQ": { name: "Geiss - Reaction Diffusion (Relief Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-reaction-diffusion-relief-mix-2.milk" },
|
|
446
|
+
"4G2P6C": { name: "Geiss - Motion Blur 2 (Relief Mix) c", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-motion-blur-2-relief-mix-c.milk" },
|
|
447
|
+
dSobTn: Zr,
|
|
448
|
+
LBEy1N: $r,
|
|
449
|
+
hPOltW: Qr,
|
|
450
|
+
"77FD4m": { name: "Zylot - Magma Crawl", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/zylot-magma-crawl.milk" },
|
|
451
|
+
"1C5DYO": { name: "Zylot - Crossing Over (Geiss Tweak)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/zylot-crossing-over-geiss-tweak.milk" },
|
|
452
|
+
"3hbbDD": { name: "Vovan + Geiss - Bass With Flover (Feedback Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/vovan-geiss-bass-with-flover-feedback-mix.milk" },
|
|
453
|
+
jcLfPE: es,
|
|
454
|
+
pJqkeg: rs,
|
|
455
|
+
H3H6Ev: ss,
|
|
456
|
+
YDGm7t: os,
|
|
457
|
+
"8DTqcj": { name: "TobiasWolfBoi - The Pit", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/tobiaswolfboi-the-pit.milk" },
|
|
458
|
+
laytNQ: is,
|
|
459
|
+
QGCZyy: ts,
|
|
460
|
+
kfORH5: ls,
|
|
461
|
+
qmp9iC: as,
|
|
462
|
+
Qstv6S: us,
|
|
463
|
+
"912K5x": { name: "Rovastar - Tripmaker (Space Trip Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-tripmaker-space-trip-mix.milk" },
|
|
464
|
+
"13Ij96": { name: "Rovastar - Starquake (Sunquake Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-starquake-sunquake-mix.milk" },
|
|
465
|
+
jG9qgt: ns,
|
|
466
|
+
d1TVbH: cs,
|
|
467
|
+
"2WNu94": { name: "Rovastar - Inner Thoughts (Frantic Thoughts Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-inner-thoughts-frantic-thoughts-mix.milk" },
|
|
468
|
+
"6yh3Rt": { name: "Rovastar - Inner Thoughts (Distant Memories Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-inner-thoughts-distant-memories-mix.milk" },
|
|
469
|
+
R4buQw: ms,
|
|
470
|
+
XewbUX: ds,
|
|
471
|
+
zbUD7v: ps,
|
|
472
|
+
mn6kGh: ks,
|
|
473
|
+
oZB2yD: _s,
|
|
474
|
+
EudJTR: hs,
|
|
475
|
+
KyGl4e: ys,
|
|
476
|
+
"3LVtiu": { name: "Rovastar + Geiss - Snapshot Of Space (LSB mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-geiss-snapshot-of-space-lsb-mix.milk" },
|
|
477
|
+
msMe5T: gs,
|
|
478
|
+
TUDnFe: fs,
|
|
479
|
+
WFzcXl: xs,
|
|
480
|
+
CMgQij: vs,
|
|
481
|
+
Zuzg4t: bs,
|
|
482
|
+
CqzTGo: ws,
|
|
483
|
+
rlxaKq: Ss,
|
|
484
|
+
A674lj: Ts,
|
|
485
|
+
L90md1: Es,
|
|
486
|
+
XrbIZj: Rs,
|
|
487
|
+
ChEJhr: Ms,
|
|
488
|
+
"8q0c6X": { name: "Martin - wire dance", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-wire-dance.milk" },
|
|
489
|
+
cMkHlk: Gs,
|
|
490
|
+
A63DaM: As,
|
|
491
|
+
ok4OA3: Cs,
|
|
492
|
+
bgEwSc: Ps,
|
|
493
|
+
Jzp5v8: Ds,
|
|
494
|
+
d9BWoH: Fs,
|
|
495
|
+
Xvmwb5: Is,
|
|
496
|
+
WIz7uW: Bs,
|
|
497
|
+
oByLJj: Ls,
|
|
498
|
+
"5da6qp": { name: "Goody - LSD Zoomtunnel", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/goody-lsd-zoomtunnel.milk" },
|
|
499
|
+
VcUWDG: Us,
|
|
500
|
+
"6C79Ic": { name: "Geiss - Trampoline", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-trampoline.milk" },
|
|
501
|
+
g39XvK: Ns,
|
|
502
|
+
prHVsY: Vs,
|
|
503
|
+
UBZwV5: Ws,
|
|
504
|
+
BRkffY: Os,
|
|
505
|
+
v8bC4n: qs,
|
|
506
|
+
oqxj1M: Xs,
|
|
507
|
+
CHdpMB: js,
|
|
508
|
+
gO8YZM: Hs,
|
|
509
|
+
G3mP9Z: zs,
|
|
510
|
+
"1bVovV": { name: "Geiss - Rose 4 Shifted Tiles", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-rose-4-shifted-tiles.milk" },
|
|
511
|
+
eug6vI: Ks,
|
|
512
|
+
lntbPv: Ys,
|
|
513
|
+
vVX8fr: Js,
|
|
514
|
+
ot9bHP: Zs,
|
|
515
|
+
iManzA: $s,
|
|
516
|
+
sWDfCG: Qs,
|
|
517
|
+
CrLXt2: eo,
|
|
518
|
+
JIKDwH: ro,
|
|
519
|
+
EBKwMD: so,
|
|
520
|
+
duEqhk: oo,
|
|
521
|
+
W7bEj3: io,
|
|
522
|
+
NXQivi: to,
|
|
523
|
+
Hzvvbb: lo,
|
|
524
|
+
"7GqSRQ": { name: "Geiss - Mosaic Octopus", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-mosaic-octopus.milk" },
|
|
525
|
+
ubVJL4: ao,
|
|
526
|
+
UN6OBT: uo,
|
|
527
|
+
"85CTzj": { name: "Geiss - MicroCheckers 2", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-microcheckers-2.milk" },
|
|
528
|
+
Ej4WWj: no,
|
|
529
|
+
aPqQbc: co,
|
|
530
|
+
bU0fR9: mo,
|
|
531
|
+
"383gqZ": { name: "Geiss - Liquid Beats (janky ripple warp reflecto)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-liquid-beats-janky-ripple-warp-reflecto.milk" },
|
|
532
|
+
"5OYa4O": { name: "Geiss - Kaleidoscope 1", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-kaleidoscope-1.milk" },
|
|
533
|
+
bpSfLm: po,
|
|
534
|
+
zR06bi: ko,
|
|
535
|
+
pUwwK2: _o,
|
|
536
|
+
x35qdS: ho,
|
|
537
|
+
NOm3NC: yo,
|
|
538
|
+
y0QSRA: go,
|
|
539
|
+
"1a2niA": { name: "Geiss - Game of Life 2b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-game-of-life-2b.milk" },
|
|
540
|
+
"9c1K6i": { name: "Geiss - Flower", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-flower.milk" },
|
|
541
|
+
"3usf92": { name: "Geiss - Flower Blossom", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-flower-blossom.milk" },
|
|
542
|
+
Z6UbQa: fo,
|
|
543
|
+
Rwa9ja: xo,
|
|
544
|
+
Qze1QX: vo,
|
|
545
|
+
kBnBI0: bo,
|
|
546
|
+
"0pIFgC": { name: "Geiss - Diffuser (Gold Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-diffuser-gold-mix.milk" },
|
|
547
|
+
tRyAth: wo,
|
|
548
|
+
"8FhWXx": { name: "Geiss - Dancing Spirits", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-dancing-spirits.milk" },
|
|
549
|
+
JZ6Wvh: So,
|
|
550
|
+
ZmiGje: To,
|
|
551
|
+
IsUYYO: Eo,
|
|
552
|
+
bRxPDX: Ro,
|
|
553
|
+
Qy8in2: Mo,
|
|
554
|
+
TcZGam: Go,
|
|
555
|
+
"5Yo7Jr": { name: "Geiss - Cosmic Dust 2 - Game of Life mix", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-cosmic-dust-2-game-of-life-mix.milk" },
|
|
556
|
+
o9k7m7: Ao,
|
|
557
|
+
"8fSxEp": { name: "Geiss - Confetti (color saturation boosted)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-confetti-color-saturation-boosted.milk" },
|
|
558
|
+
"0LFkiK": { name: "Geiss - Color Pox (Van Gogh Mix) (color saturation remix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-color-pox-van-gogh-mix-color-saturation-remix.milk" },
|
|
559
|
+
VJQq6c: Co,
|
|
560
|
+
XmUCRN: Po,
|
|
561
|
+
Ksg664: Do,
|
|
562
|
+
j1nkP3: Fo,
|
|
563
|
+
ks2aOS: Io,
|
|
564
|
+
tarJU2: Bo,
|
|
565
|
+
Fj7fE6: Lo,
|
|
566
|
+
wxHegg: Uo,
|
|
567
|
+
"7yfapd": { name: "Geiss - 3 layers", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-3-layers.milk" },
|
|
568
|
+
iBsVaJ: No,
|
|
569
|
+
"6s6AOK": { name: "Geiss - 3 layers (Rayleigh Scattering Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-3-layers-rayleigh-scattering-mix.milk" },
|
|
570
|
+
Sgpe4q: Vo,
|
|
571
|
+
NEiYVo: Wo,
|
|
572
|
+
hcBhUY: Oo,
|
|
573
|
+
NTtk5V: qo,
|
|
574
|
+
vqgPdG: Xo,
|
|
575
|
+
OJEl9R: jo,
|
|
576
|
+
b594l9: Ho,
|
|
577
|
+
n19hhD: zo,
|
|
578
|
+
ffCuEd: Ko,
|
|
579
|
+
xD7sMo: Yo,
|
|
580
|
+
"7t90G5": { name: "Flexi - hue burst", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/flexi-hue-burst.milk" },
|
|
581
|
+
VIsedw: Jo,
|
|
582
|
+
w4P8w9: Zo,
|
|
583
|
+
eSScUv: $o,
|
|
584
|
+
q8XM4Q: Qo,
|
|
585
|
+
JmIcYJ: ei,
|
|
586
|
+
TMC3YZ: ri,
|
|
587
|
+
haCqCh: si,
|
|
588
|
+
"164MuB": { name: "Eo.S. - glowsticks v2 05 and proton lights (+Krash's beat code)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-05-and-proton-lights-krash-s-beat-code.milk" },
|
|
589
|
+
rUYLuL: oi,
|
|
590
|
+
uKnfXj: ii,
|
|
591
|
+
LXox04: ti,
|
|
592
|
+
qIKWxc: li,
|
|
593
|
+
"1JVMxZ": { name: "Eo.S. + Phat - spectrum bubble field", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-phat-spectrum-bubble-field.milk" },
|
|
594
|
+
aucRFt: ai,
|
|
595
|
+
xpVOei: ui,
|
|
596
|
+
j72Wef: ni,
|
|
597
|
+
HwoUcq: ci,
|
|
598
|
+
y3PFWY: mi,
|
|
599
|
+
vCpR86: di,
|
|
600
|
+
eYHXtB: pi,
|
|
601
|
+
"9sJSry": { name: "By Adam FX 2 shifter + geiss - neon pulse (glow mix) + Rovastar + Orb + Mstress - mash0000 - prismatic spectral haze filter", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/by-adam-fx-2-shifter-geiss-neon-pulse-glow-mix-rovastar-orb-mstress-mash0000.milk" },
|
|
602
|
+
"8yDedA": { name: "Bmelgren + Krash - Rainbow Orb Peacock (Centred Journey Mix 2)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/bmelgren-krash-rainbow-orb-peacock-centred-journey-mix-2.milk" },
|
|
603
|
+
GNrYwr: ki,
|
|
604
|
+
zH4iVV: _i,
|
|
605
|
+
JYdwqQ: hi,
|
|
606
|
+
"3HN05o": { name: "Aderrasi - Hackproof - mash0000 - stare at tv static remote viewing technique", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/aderrasi-hackproof-mash0000-stare-at-tv-static-remote-viewing-technique.milk" },
|
|
607
|
+
G9voNd: yi,
|
|
608
|
+
oyNdIT: gi,
|
|
609
|
+
RXgbpz: fi,
|
|
610
|
+
asrnYp: xi,
|
|
611
|
+
"3Tfp2i": { name: "shifter - urchin mod", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/shifter-urchin-mod.milk" },
|
|
612
|
+
nB08bI: vi,
|
|
613
|
+
c9cXzV: bi,
|
|
614
|
+
N4NU63: wi,
|
|
615
|
+
H5hh1F: Si,
|
|
616
|
+
X2yAeU: Ti,
|
|
617
|
+
nlD1AF: Ei,
|
|
618
|
+
NXMegV: Ri,
|
|
619
|
+
Oogg6s: Mi,
|
|
620
|
+
"5DnU2L": { name: "martin + flexi - bombyx mori mix2 in the beehive", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/martin-flexi-bombyx-mori-mix2-in-the-beehive.milk" },
|
|
621
|
+
"0krhfg": { name: "fiShbRaiN - the dark side of the moon", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/fishbrain-the-dark-side-of-the-moon.milk" },
|
|
622
|
+
dqLXQa: Gi,
|
|
623
|
+
qa1I9P: Ai,
|
|
624
|
+
kh3E8c: Ci,
|
|
625
|
+
S33oA8: Pi,
|
|
626
|
+
rzSBzp: Di,
|
|
627
|
+
HVjYuU: Fi,
|
|
628
|
+
Q7zyz5: Ii,
|
|
629
|
+
RvS5Pe: Bi,
|
|
630
|
+
kLtW3v: Li,
|
|
631
|
+
"4E2nFx": { name: "Rovastar - Fractopia (Upspoken Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/rovastar-fractopia-upspoken-mix.milk" },
|
|
632
|
+
gLgxTP: Ui,
|
|
633
|
+
etGSAU: Ni,
|
|
634
|
+
iBcSFe: Vi,
|
|
635
|
+
nuozxK: Wi,
|
|
636
|
+
a16Z3X: Oi,
|
|
637
|
+
MygiDZ: qi,
|
|
638
|
+
TVjhxk: Xi,
|
|
639
|
+
v0ESKE: ji,
|
|
640
|
+
"9ZbzfC": { name: "ORB - Waaa", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/orb-waaa-2.milk" },
|
|
641
|
+
na7R4N: Hi,
|
|
642
|
+
VdPJGm: zi,
|
|
643
|
+
WFaI9w: Ki,
|
|
644
|
+
"9eqQnV": { name: "Mstress & Zylot - Acid UFO", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/mstress-zylot-acid-ufo.milk" },
|
|
645
|
+
A3P2IV: Yi,
|
|
646
|
+
qwuNhy: Ji,
|
|
647
|
+
"6nFusM": { name: "Geiss - Planar Travel", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-planar-travel.milk" },
|
|
648
|
+
njxMWO: Zi,
|
|
649
|
+
"6hxTDo": { name: "Geiss - Mash-Up 4", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-mash-up-4.milk" },
|
|
650
|
+
t3xlOK: $i,
|
|
651
|
+
"75R7sz": { name: "Geiss - Electric Storm Half-Digital 2 (Fiesta Mix)", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/geiss-electric-storm-half-digital-2-fiesta-mix.milk" },
|
|
652
|
+
DMJ1SB: Qi,
|
|
653
|
+
buwqyb: et,
|
|
654
|
+
MjmlTk: rt,
|
|
655
|
+
t11nN4: st,
|
|
656
|
+
bEp10M: ot,
|
|
657
|
+
FQqWEr: it,
|
|
658
|
+
OdtDSl: tt,
|
|
659
|
+
oABstK: lt,
|
|
660
|
+
EqarxT: at,
|
|
661
|
+
x72Cbv: ut,
|
|
662
|
+
"9pPWpB": { name: "Eo.S. - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix02b", source_type: "milkdrop", source_loader: "url", source_url: "/presets/milkdrop/eo-s-glowsticks-v2-05-and-proton-lights-krash-s-beat-code-phat-remix02b.milk" },
|
|
663
|
+
I2HEKG: nt,
|
|
664
|
+
jjjX2L: ct,
|
|
665
|
+
mnQbLP: mt,
|
|
666
|
+
rZaP5M: dt,
|
|
667
|
+
xxpUNA: pt,
|
|
668
|
+
twWyLm: kt,
|
|
669
|
+
Yu9GG8: _t,
|
|
670
|
+
d3BbId: ht
|
|
671
|
+
}, O = "prism.graph/0.1";
|
|
672
|
+
function gt(t) {
|
|
673
|
+
return t.split(".")[0];
|
|
674
|
+
}
|
|
675
|
+
function ft(t, e) {
|
|
676
|
+
return Object.entries(t.nodes).filter(([, s]) => gt(s.type) === e);
|
|
677
|
+
}
|
|
678
|
+
function Gt(t, e, s = 2.5) {
|
|
679
|
+
return {
|
|
680
|
+
schema: O,
|
|
681
|
+
id: `g_${Math.random().toString(36).slice(2, 10)}`,
|
|
682
|
+
intent: e,
|
|
683
|
+
nodes: {
|
|
684
|
+
audio_in: { type: "signal.audio", params: {} },
|
|
685
|
+
main: {
|
|
686
|
+
type: "lf.milkdrop",
|
|
687
|
+
params: { preset_name: t, blend_seconds: s },
|
|
688
|
+
inputs: { audio: "audio_in.signal" }
|
|
689
|
+
},
|
|
690
|
+
out: { type: "sink.display", inputs: { frame: "main.frame" } }
|
|
691
|
+
},
|
|
692
|
+
output: "out"
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
const q = yt;
|
|
696
|
+
function xt(t) {
|
|
697
|
+
return q[t] ?? null;
|
|
698
|
+
}
|
|
699
|
+
function At() {
|
|
700
|
+
return Object.keys(q);
|
|
701
|
+
}
|
|
702
|
+
function vt(t) {
|
|
703
|
+
const e = xt(t);
|
|
704
|
+
return e ? bt(t, e) : null;
|
|
705
|
+
}
|
|
706
|
+
function bt(t, e) {
|
|
707
|
+
const s = {};
|
|
708
|
+
let o;
|
|
709
|
+
e.source_type === "shadertoy" ? (o = "lf.shadertoy", e.source_url && (s.shader_url = e.source_url), e.default_image && (s.image_url = e.default_image)) : (o = "lf.milkdrop", e.source_loader === "url" && e.source_url ? s.preset_url = e.source_url : e.source_ref && (s.preset_name = e.source_ref));
|
|
710
|
+
const r = {
|
|
711
|
+
audio: { type: "signal.audio" },
|
|
712
|
+
main: { type: o, params: s, inputs: { audio: "audio.signal" } },
|
|
713
|
+
screen: { type: "sink.display", inputs: { frame: "main.frame" } }
|
|
714
|
+
};
|
|
715
|
+
return {
|
|
716
|
+
schema: O,
|
|
717
|
+
id: `g:${t}`,
|
|
718
|
+
intent: e.name,
|
|
719
|
+
nodes: r,
|
|
720
|
+
output: "screen"
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
class wt {
|
|
724
|
+
constructor(e) {
|
|
725
|
+
i(this, "active", null);
|
|
726
|
+
this.ctx = e;
|
|
727
|
+
}
|
|
728
|
+
apply(e, s) {
|
|
729
|
+
var l, a, c, u, n, h, v;
|
|
730
|
+
const o = ft(e, "lf");
|
|
731
|
+
if (o.length === 0)
|
|
732
|
+
return { ok: !1, error: "graph has no light-field generator" };
|
|
733
|
+
const [, r] = o[0];
|
|
734
|
+
if (r.type === "lf.milkdrop") {
|
|
735
|
+
const m = (l = r.params) == null ? void 0 : l.preset_name, f = (a = r.params) == null ? void 0 : a.preset_url, w = s ?? (typeof ((c = r.params) == null ? void 0 : c.blend_seconds) == "number" ? r.params.blend_seconds : 2.5);
|
|
736
|
+
if (this.ctx.setActiveBackend("milkdrop"), typeof f == "string")
|
|
737
|
+
return this.ctx.milkdrop.loadFromUrl(f, w).catch((k) => {
|
|
738
|
+
console.warn("[runtime] milkdrop loadFromUrl failed:", k.message);
|
|
739
|
+
}), this.active = e, { ok: !0, presetName: ((u = f.split("/").pop()) == null ? void 0 : u.replace(/\.milk$/, "")) ?? f, backend: "milkdrop" };
|
|
740
|
+
if (typeof m != "string")
|
|
741
|
+
return { ok: !1, error: "lf.milkdrop missing preset_name or preset_url" };
|
|
742
|
+
const y = this.ctx.milkdrop.loadByName(m, w);
|
|
743
|
+
return y === null ? { ok: !1, error: `preset not found: ${m}` } : (this.active = e, { ok: !0, presetName: y, backend: "milkdrop" });
|
|
744
|
+
}
|
|
745
|
+
if (r.type === "lf.shadertoy") {
|
|
746
|
+
const m = (n = r.params) == null ? void 0 : n.shader_url;
|
|
747
|
+
if (typeof m != "string")
|
|
748
|
+
return { ok: !1, error: "lf.shadertoy missing shader_url" };
|
|
749
|
+
const f = (h = r.params) == null ? void 0 : h.image_url;
|
|
750
|
+
return this.ctx.setActiveBackend("shadertoy"), this.ctx.shadertoy.loadFromUrl(m).catch((y) => {
|
|
751
|
+
console.warn("[runtime] shadertoy loadFromUrl failed:", y.message);
|
|
752
|
+
}), this.ctx.shadertoy.bindImage(typeof f == "string" ? f : null).catch((y) => {
|
|
753
|
+
console.warn("[runtime] shadertoy bindImage failed:", y.message);
|
|
754
|
+
}), this.active = e, { ok: !0, presetName: ((v = m.split("/").pop()) == null ? void 0 : v.replace(/\.glsl$/, "")) ?? m, backend: "shadertoy" };
|
|
755
|
+
}
|
|
756
|
+
return { ok: !1, error: `unsupported lf type: ${r.type}` };
|
|
757
|
+
}
|
|
758
|
+
get current() {
|
|
759
|
+
return this.active;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
class St {
|
|
763
|
+
constructor(e) {
|
|
764
|
+
i(this, "ctx");
|
|
765
|
+
i(this, "output");
|
|
766
|
+
i(this, "voices", []);
|
|
767
|
+
i(this, "analyser");
|
|
768
|
+
i(this, "fft");
|
|
769
|
+
i(this, "beatTimer", null);
|
|
770
|
+
i(this, "mutationTimer", null);
|
|
771
|
+
i(this, "stopped", !1);
|
|
772
|
+
i(this, "lastCursorBeatAt", 0);
|
|
773
|
+
this.ctx = e, this.output = e.createGain(), this.output.gain.value = 0.65;
|
|
774
|
+
const s = [
|
|
775
|
+
[50, "sine", 0.55, 0.06, 18],
|
|
776
|
+
[110, "sine", 0.4, 0.09, 24],
|
|
777
|
+
[230, "triangle", 0.28, 0.12, 60],
|
|
778
|
+
[460, "sawtooth", 0.18, 0.17, 140],
|
|
779
|
+
[950, "triangle", 0.12, 0.21, 280],
|
|
780
|
+
[1900, "sine", 0.08, 0.27, 520],
|
|
781
|
+
[3900, "triangle", 0.05, 0.33, 1100]
|
|
782
|
+
];
|
|
783
|
+
for (const [o, r, l, a, c] of s) this.addVoice(o, r, l, a, c);
|
|
784
|
+
this.analyser = e.createAnalyser(), this.analyser.fftSize = 256, this.analyser.smoothingTimeConstant = 0.78, this.output.connect(this.analyser), this.fft = new Uint8Array(this.analyser.frequencyBinCount), this.scheduleBeats(), this.scheduleMutations();
|
|
785
|
+
}
|
|
786
|
+
/** The node to feed into a consumer (e.g. butterchurn.connectAudio). */
|
|
787
|
+
getOutput() {
|
|
788
|
+
return this.output;
|
|
789
|
+
}
|
|
790
|
+
/** Returns a smoothed 0..1 energy reading from our own analyser. */
|
|
791
|
+
readEnergy() {
|
|
792
|
+
if (this.stopped) return 0;
|
|
793
|
+
this.analyser.getByteFrequencyData(this.fft);
|
|
794
|
+
let e = 0;
|
|
795
|
+
for (let s = 0; s < this.fft.length; s++) e += this.fft[s];
|
|
796
|
+
return e / 255 / this.fft.length;
|
|
797
|
+
}
|
|
798
|
+
/** Returns smoothed bass/mid/treble bands (0..1 each). */
|
|
799
|
+
readBands() {
|
|
800
|
+
if (this.stopped) return { bass: 0, mid: 0, treble: 0 };
|
|
801
|
+
this.analyser.getByteFrequencyData(this.fft);
|
|
802
|
+
const e = this.fft.length, s = Math.floor(e * 0.1), o = Math.floor(e * 0.45);
|
|
803
|
+
let r = 0, l = 0, a = 0;
|
|
804
|
+
for (let c = 0; c < e; c++) {
|
|
805
|
+
const u = this.fft[c] / 255;
|
|
806
|
+
c < s ? r += u : c < o ? l += u : a += u;
|
|
807
|
+
}
|
|
808
|
+
return {
|
|
809
|
+
bass: r / Math.max(1, s),
|
|
810
|
+
mid: l / Math.max(1, o - s),
|
|
811
|
+
treble: a / Math.max(1, e - o)
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
stop() {
|
|
815
|
+
if (!this.stopped) {
|
|
816
|
+
this.stopped = !0, this.beatTimer != null && clearTimeout(this.beatTimer), this.mutationTimer != null && clearTimeout(this.mutationTimer);
|
|
817
|
+
for (const e of this.voices) {
|
|
818
|
+
try {
|
|
819
|
+
e.osc.stop(), e.lfo.stop();
|
|
820
|
+
} catch {
|
|
821
|
+
}
|
|
822
|
+
try {
|
|
823
|
+
e.osc.disconnect(), e.lfo.disconnect(), e.lfoGain.disconnect(), e.gain.disconnect();
|
|
824
|
+
} catch {
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
try {
|
|
828
|
+
this.output.disconnect();
|
|
829
|
+
} catch {
|
|
830
|
+
}
|
|
831
|
+
try {
|
|
832
|
+
this.analyser.disconnect();
|
|
833
|
+
} catch {
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
addVoice(e, s, o, r, l) {
|
|
838
|
+
const a = this.ctx, c = a.createOscillator();
|
|
839
|
+
c.frequency.value = e, c.type = s;
|
|
840
|
+
const u = a.createGain();
|
|
841
|
+
u.gain.value = o, c.connect(u).connect(this.output);
|
|
842
|
+
const n = a.createOscillator();
|
|
843
|
+
n.frequency.value = r, n.type = "sine";
|
|
844
|
+
const h = a.createGain();
|
|
845
|
+
h.gain.value = l, n.connect(h).connect(c.frequency), n.start(), c.start();
|
|
846
|
+
const v = e < 200 ? "bass" : e < 1100 ? "mid" : "treble";
|
|
847
|
+
this.voices.push({ base: e, baseGain: o, band: v, osc: c, lfo: n, lfoGain: h, gain: u });
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Modulate the synth from the cursor. Position controls the bass/treble
|
|
851
|
+
* balance (top-right = bright/airy; bottom-left = bassy/warm); velocity
|
|
852
|
+
* triggers a beat envelope on the master gain. The cursor becomes the
|
|
853
|
+
* instrument driving the milkdrop preset.
|
|
854
|
+
*
|
|
855
|
+
* @param x01 cursor X normalised to 0..1 (left .. right)
|
|
856
|
+
* @param y01 cursor Y normalised to 0..1 (top .. bottom)
|
|
857
|
+
* @param vel01 cursor speed normalised to 0..1
|
|
858
|
+
*/
|
|
859
|
+
setCursorModulation(e, s, o) {
|
|
860
|
+
if (this.stopped) return;
|
|
861
|
+
const r = this.ctx.currentTime, l = 0.12, a = Math.max(0, Math.min(1, e)), c = Math.max(0, Math.min(1, s)), u = Math.max(0, Math.min(1, o)), n = 0.55 + (1 - c) * 0.9 + u * 0.15, h = 0.55 + a * 0.9 + u * 0.2, v = 0.7 + u * 0.7;
|
|
862
|
+
for (const m of this.voices) {
|
|
863
|
+
const f = m.band === "bass" ? m.baseGain * n : m.band === "treble" ? m.baseGain * h : m.baseGain * v;
|
|
864
|
+
m.gain.gain.cancelScheduledValues(r), m.gain.gain.setValueAtTime(m.gain.gain.value, r), m.gain.gain.linearRampToValueAtTime(f, r + l);
|
|
865
|
+
}
|
|
866
|
+
if (u > 0.45 && r - this.lastCursorBeatAt > 0.22) {
|
|
867
|
+
const m = 0.95 + u * 0.45;
|
|
868
|
+
this.output.gain.cancelScheduledValues(r), this.output.gain.setValueAtTime(this.output.gain.value, r), this.output.gain.linearRampToValueAtTime(m, r + 0.035), this.output.gain.exponentialRampToValueAtTime(0.52, r + 0.22), this.lastCursorBeatAt = r;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Fire a bass-kick envelope — for hooking up heartbeats, MIDI clicks, or
|
|
873
|
+
* any external rhythmic trigger. Sharp attack + bass voice swell so the
|
|
874
|
+
* spectrum butterchurn sees registers as a clean bass beat.
|
|
875
|
+
*
|
|
876
|
+
* @param intensity 0..1, scales the peak
|
|
877
|
+
*/
|
|
878
|
+
pulseBeat(e = 0.8) {
|
|
879
|
+
if (this.stopped) return;
|
|
880
|
+
const s = this.ctx.currentTime, o = Math.max(0, Math.min(1, e)), r = 0.95 + o * 0.55;
|
|
881
|
+
this.output.gain.cancelScheduledValues(s), this.output.gain.setValueAtTime(this.output.gain.value, s), this.output.gain.linearRampToValueAtTime(r, s + 0.035), this.output.gain.exponentialRampToValueAtTime(0.42, s + 0.26);
|
|
882
|
+
for (const l of this.voices) {
|
|
883
|
+
if (l.band !== "bass") continue;
|
|
884
|
+
const a = l.baseGain * (1.6 + o * 1.4);
|
|
885
|
+
l.gain.gain.cancelScheduledValues(s), l.gain.gain.setValueAtTime(l.gain.gain.value, s), l.gain.gain.linearRampToValueAtTime(a, s + 0.025), l.gain.gain.exponentialRampToValueAtTime(
|
|
886
|
+
Math.max(0.01, l.baseGain),
|
|
887
|
+
s + 0.34
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
/** Periodic "beat" — short amplitude burst on the master gain. */
|
|
892
|
+
scheduleBeats() {
|
|
893
|
+
const e = () => {
|
|
894
|
+
if (this.stopped) return;
|
|
895
|
+
const s = this.ctx.currentTime, o = 0.95 + Math.random() * 0.35;
|
|
896
|
+
this.output.gain.cancelScheduledValues(s), this.output.gain.setValueAtTime(this.output.gain.value, s), this.output.gain.linearRampToValueAtTime(o, s + 0.04), this.output.gain.exponentialRampToValueAtTime(0.45, s + 0.28);
|
|
897
|
+
const r = 600 + Math.random() * 1e3;
|
|
898
|
+
this.beatTimer = window.setTimeout(e, r);
|
|
899
|
+
};
|
|
900
|
+
this.beatTimer = window.setTimeout(e, 900);
|
|
901
|
+
}
|
|
902
|
+
/** Every ~20–35 s, smoothly mutate one voice's base frequency over 8 s. */
|
|
903
|
+
scheduleMutations() {
|
|
904
|
+
const e = () => {
|
|
905
|
+
if (this.stopped) return;
|
|
906
|
+
const s = this.voices[Math.floor(Math.random() * this.voices.length)], o = this.ctx.currentTime, r = 0.65 + Math.random() * 0.7, l = Math.max(20, Math.min(6e3, s.base * r));
|
|
907
|
+
s.osc.frequency.cancelScheduledValues(o), s.osc.frequency.setValueAtTime(s.osc.frequency.value, o), s.osc.frequency.linearRampToValueAtTime(l, o + 7.5), s.base = l, this.mutationTimer = window.setTimeout(e, 18e3 + Math.random() * 16e3);
|
|
908
|
+
};
|
|
909
|
+
this.mutationTimer = window.setTimeout(e, 6e3);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
class Ct {
|
|
913
|
+
constructor(e) {
|
|
914
|
+
/** AudioContext driving both backends + the default synthetic signal.
|
|
915
|
+
* Created on construction unless one was passed in `opts.audioCtx`. */
|
|
916
|
+
i(this, "audioCtx");
|
|
917
|
+
/** Default audio driver: a silent "pink-noise-ish" pad that keeps the
|
|
918
|
+
* visualization animated when no real audio is connected. Kept alive
|
|
919
|
+
* for the lifetime of the player — call `player.synth.stop()` if you
|
|
920
|
+
* want to free it after switching to a real audio source. */
|
|
921
|
+
i(this, "synth");
|
|
922
|
+
/** Milkdrop (butterchurn) backend handle. Cold-opens on a random
|
|
923
|
+
* preset (or `initialPresetName` if you passed one). */
|
|
924
|
+
i(this, "milkdrop");
|
|
925
|
+
/** Shadertoy backend handle. Idle until a graph with `lf.shadertoy` is
|
|
926
|
+
* loaded (or you call `shadertoy.loadFromUrl` directly). */
|
|
927
|
+
i(this, "shadertoy");
|
|
928
|
+
/** Graph executor — dispatches to the right backend based on the
|
|
929
|
+
* graph's light-field generator node. */
|
|
930
|
+
i(this, "runtime");
|
|
931
|
+
/** Tracks which backend's canvas is currently visible. */
|
|
932
|
+
i(this, "activeBackend", "milkdrop");
|
|
933
|
+
i(this, "milkdropCanvas");
|
|
934
|
+
i(this, "shadertoyCanvas");
|
|
935
|
+
i(this, "ownsAudioCtx");
|
|
936
|
+
/** Default hold per image when `image` is a URL list; set in ctor. */
|
|
937
|
+
i(this, "defaultHoldSeconds");
|
|
938
|
+
/** Owned media resources (MediaStreams we started, <video> elements
|
|
939
|
+
* we created internally, headless slideshow). Cleaned up by
|
|
940
|
+
* connectImage() before re-binding and by destroy() on teardown. */
|
|
941
|
+
i(this, "currentSlideshow", null);
|
|
942
|
+
i(this, "currentVideo", null);
|
|
943
|
+
i(this, "currentStream", null);
|
|
944
|
+
/** Audio MediaStream the player started itself ("mic" / "tab"). Held
|
|
945
|
+
* so disconnectAudio() can stop the tracks. Null if the caller
|
|
946
|
+
* passed in their own stream/node (we never stop tracks we don't own). */
|
|
947
|
+
i(this, "currentAudioOwnedStream", null);
|
|
948
|
+
const s = Tt(e.container);
|
|
949
|
+
if (this.audioCtx = e.audioCtx ?? new AudioContext(), this.ownsAudioCtx = e.audioCtx === void 0, this.defaultHoldSeconds = e.holdSeconds ?? 6, this.synth = new St(this.audioCtx), this.milkdropCanvas = V("milkdrop"), this.shadertoyCanvas = V("shadertoy"), this.shadertoyCanvas.classList.add("bg-canvas--hidden"), s.appendChild(this.milkdropCanvas), s.appendChild(this.shadertoyCanvas), this.milkdrop = ee(
|
|
950
|
+
this.audioCtx,
|
|
951
|
+
this.milkdropCanvas,
|
|
952
|
+
this.synth.getOutput(),
|
|
953
|
+
e.onReady,
|
|
954
|
+
{ initialPresetName: e.initialPresetName }
|
|
955
|
+
), this.shadertoy = ie(
|
|
956
|
+
this.audioCtx,
|
|
957
|
+
this.shadertoyCanvas,
|
|
958
|
+
this.synth.getOutput()
|
|
959
|
+
), e.defaultImage && this.shadertoy.bindImage(e.defaultImage).catch((o) => {
|
|
960
|
+
var r;
|
|
961
|
+
(r = e.onError) == null || r.call(e, o);
|
|
962
|
+
}), this.runtime = new wt({
|
|
963
|
+
milkdrop: this.milkdrop,
|
|
964
|
+
shadertoy: this.shadertoy,
|
|
965
|
+
setActiveBackend: (o) => this.setActiveBackend(o)
|
|
966
|
+
}), e.graph !== void 0) {
|
|
967
|
+
const o = this.load(e.graph);
|
|
968
|
+
!o.ok && e.onError && e.onError(new Error(o.error ?? "graph apply failed"));
|
|
969
|
+
}
|
|
970
|
+
e.audio !== void 0 && this.connectAudio(e.audio).catch((o) => {
|
|
971
|
+
var r;
|
|
972
|
+
return (r = e.onError) == null ? void 0 : r.call(e, o);
|
|
973
|
+
}), e.image !== void 0 && this.connectImage(e.image).catch((o) => {
|
|
974
|
+
var r;
|
|
975
|
+
return (r = e.onError) == null ? void 0 : r.call(e, o);
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
/** Swap to a new graph. Accepts either a full PrismGraph object or a
|
|
979
|
+
* 6-char short_id string from the bundled registry. Returns the
|
|
980
|
+
* ApplyResult the runtime emits so the caller can react to backend
|
|
981
|
+
* switches / errors. An unknown short_id returns
|
|
982
|
+
* `{ ok: false, error: "unknown short_id ..." }` without touching
|
|
983
|
+
* the running visualization. */
|
|
984
|
+
load(e, s) {
|
|
985
|
+
if (typeof e == "string") {
|
|
986
|
+
const o = vt(e);
|
|
987
|
+
return o ? this.runtime.apply(o, s) : { ok: !1, error: `unknown short_id: ${e}` };
|
|
988
|
+
}
|
|
989
|
+
return this.runtime.apply(e, s);
|
|
990
|
+
}
|
|
991
|
+
/** Connect a new audio source. Accepts:
|
|
992
|
+
* - "mic" — getUserMedia({ audio: true })
|
|
993
|
+
* - "tab" — getDisplayMedia({ audio: true })
|
|
994
|
+
* - MediaStream — wrapped in a MediaStreamAudioSourceNode
|
|
995
|
+
* - AudioNode — connected directly
|
|
996
|
+
* Routes the source to both backends so whichever one is active sees
|
|
997
|
+
* reactivity. Tracks any MediaStream the player started itself so
|
|
998
|
+
* disconnectAudio() can stop the tracks (mic indicator off, etc.). */
|
|
999
|
+
async connectAudio(e) {
|
|
1000
|
+
const { node: s, owned: o } = await this.resolveAudioNode(e);
|
|
1001
|
+
return this.milkdrop.connectAudio(s), this.shadertoy.connectAudio(s), this.currentAudioOwnedStream = o, s;
|
|
1002
|
+
}
|
|
1003
|
+
/** Disconnect the current audio source and revert both backends to
|
|
1004
|
+
* the built-in SyntheticSignal. Stops any MediaStream tracks the
|
|
1005
|
+
* player started itself (mic / tab capture indicator goes off).
|
|
1006
|
+
* Streams or AudioNodes the caller passed in are left untouched —
|
|
1007
|
+
* the caller owns their lifetime. Idempotent. */
|
|
1008
|
+
disconnectAudio() {
|
|
1009
|
+
if (this.currentAudioOwnedStream) {
|
|
1010
|
+
for (const s of this.currentAudioOwnedStream.getTracks()) s.stop();
|
|
1011
|
+
this.currentAudioOwnedStream = null;
|
|
1012
|
+
}
|
|
1013
|
+
const e = this.synth.getOutput();
|
|
1014
|
+
this.milkdrop.connectAudio(e), this.shadertoy.connectAudio(e);
|
|
1015
|
+
}
|
|
1016
|
+
/** Pipe a live source (e.g. a slideshow's canvas) into iChannel1 — its
|
|
1017
|
+
* contents are re-uploaded each frame. Pass null to disable.
|
|
1018
|
+
* Most embedders should prefer connectImage(), which handles
|
|
1019
|
+
* webcam/tab/slideshow plumbing for you. */
|
|
1020
|
+
setLiveSource(e) {
|
|
1021
|
+
this.shadertoy.setLiveSource(e);
|
|
1022
|
+
}
|
|
1023
|
+
/** Connect an image source for the shader's iChannel1. Symmetric to
|
|
1024
|
+
* connectAudio. Replaces any prior image feed; old MediaStream
|
|
1025
|
+
* tracks are stopped and internal slideshow timers are cleared.
|
|
1026
|
+
* See ImageSource for the accepted shapes. */
|
|
1027
|
+
async connectImage(e) {
|
|
1028
|
+
if (this.teardownImageFeed(), typeof e == "string") {
|
|
1029
|
+
if (e === "webcam") {
|
|
1030
|
+
const s = await navigator.mediaDevices.getUserMedia({ video: !0, audio: !1 });
|
|
1031
|
+
this.bindStream(s);
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
if (e === "tab") {
|
|
1035
|
+
const s = await navigator.mediaDevices.getDisplayMedia({ video: !0, audio: !1 });
|
|
1036
|
+
this.bindStream(s);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
this.setLiveSource(null), await this.shadertoy.bindImage(e);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
if (Array.isArray(e)) {
|
|
1043
|
+
const s = new ae(e, { holdSeconds: this.defaultHoldSeconds });
|
|
1044
|
+
this.currentSlideshow = s, this.setLiveSource(s.canvas);
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
if (e instanceof MediaStream) {
|
|
1048
|
+
this.bindStream(e);
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
this.setLiveSource(e);
|
|
1052
|
+
}
|
|
1053
|
+
/** Stop the current image feed and unbind from the shader. Releases
|
|
1054
|
+
* resources the player owned: slideshow timer cleared, MediaStream
|
|
1055
|
+
* tracks stopped (webcam light off), internal <video> detached.
|
|
1056
|
+
* Canvas/video elements the caller passed in are left untouched.
|
|
1057
|
+
* After this, the shader reverts to whatever was last bound via
|
|
1058
|
+
* `defaultImage` or `shadertoy.bindImage()` (or the 1×1 placeholder).
|
|
1059
|
+
* Idempotent. */
|
|
1060
|
+
disconnectImage() {
|
|
1061
|
+
this.teardownImageFeed();
|
|
1062
|
+
}
|
|
1063
|
+
/** Toggle which backend's canvas is visible. Called by GraphRuntime;
|
|
1064
|
+
* callers can flip it manually too (rare). */
|
|
1065
|
+
setActiveBackend(e) {
|
|
1066
|
+
this.activeBackend = e, e === "milkdrop" ? (this.milkdropCanvas.classList.remove("bg-canvas--hidden"), this.milkdropCanvas.classList.add("bg-canvas--active"), this.shadertoyCanvas.classList.add("bg-canvas--hidden"), this.shadertoyCanvas.classList.remove("bg-canvas--active")) : (this.shadertoyCanvas.classList.remove("bg-canvas--hidden"), this.shadertoyCanvas.classList.add("bg-canvas--active"), this.milkdropCanvas.classList.add("bg-canvas--hidden"), this.milkdropCanvas.classList.remove("bg-canvas--active"));
|
|
1067
|
+
}
|
|
1068
|
+
/** Stop animation, free GL resources, detach canvases, close the
|
|
1069
|
+
* AudioContext (only if the player created it itself). */
|
|
1070
|
+
destroy() {
|
|
1071
|
+
if (this.teardownImageFeed(), this.currentAudioOwnedStream) {
|
|
1072
|
+
for (const e of this.currentAudioOwnedStream.getTracks()) e.stop();
|
|
1073
|
+
this.currentAudioOwnedStream = null;
|
|
1074
|
+
}
|
|
1075
|
+
this.milkdrop.destroy(), this.shadertoy.destroy(), this.synth.stop(), this.milkdropCanvas.remove(), this.shadertoyCanvas.remove(), this.ownsAudioCtx && this.audioCtx.close();
|
|
1076
|
+
}
|
|
1077
|
+
/** Wrap a MediaStream in an autoplaying <video> and bind that as the
|
|
1078
|
+
* live source. The video element is held internally; teardown is
|
|
1079
|
+
* handled by teardownImageFeed(). */
|
|
1080
|
+
bindStream(e) {
|
|
1081
|
+
const s = document.createElement("video");
|
|
1082
|
+
s.srcObject = e, s.autoplay = !0, s.muted = !0, s.playsInline = !0, s.play().catch(() => {
|
|
1083
|
+
}), this.currentVideo = s, this.currentStream = e, this.setLiveSource(s);
|
|
1084
|
+
}
|
|
1085
|
+
/** Stop the current image feed (slideshow timer, MediaStream tracks,
|
|
1086
|
+
* internal <video>) and unbind from the shader. Idempotent. */
|
|
1087
|
+
teardownImageFeed() {
|
|
1088
|
+
if (this.currentSlideshow && (this.currentSlideshow.destroy(), this.currentSlideshow = null), this.currentStream) {
|
|
1089
|
+
for (const e of this.currentStream.getTracks()) e.stop();
|
|
1090
|
+
this.currentStream = null;
|
|
1091
|
+
}
|
|
1092
|
+
this.currentVideo && (this.currentVideo.srcObject = null, this.currentVideo = null), this.setLiveSource(null);
|
|
1093
|
+
}
|
|
1094
|
+
async resolveAudioNode(e) {
|
|
1095
|
+
if (e instanceof AudioNode) return { node: e, owned: null };
|
|
1096
|
+
let s, o = !1;
|
|
1097
|
+
return e instanceof MediaStream ? s = e : e === "mic" ? (s = await navigator.mediaDevices.getUserMedia({ audio: !0, video: !1 }), o = !0) : (s = await navigator.mediaDevices.getDisplayMedia({ audio: !0, video: !1 }), o = !0), {
|
|
1098
|
+
node: this.audioCtx.createMediaStreamSource(s),
|
|
1099
|
+
owned: o ? s : null
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
function Tt(t) {
|
|
1104
|
+
if (typeof t != "string") return t;
|
|
1105
|
+
const e = document.getElementById(t);
|
|
1106
|
+
if (!e)
|
|
1107
|
+
throw new Error(`PrismPlayer: no element found with id "${t}"`);
|
|
1108
|
+
return e;
|
|
1109
|
+
}
|
|
1110
|
+
function V(t) {
|
|
1111
|
+
const e = document.createElement("canvas");
|
|
1112
|
+
return e.id = t, e.className = "bg-canvas", e.setAttribute("aria-hidden", "true"), e;
|
|
1113
|
+
}
|
|
1114
|
+
class Pt {
|
|
1115
|
+
constructor(e = {}) {
|
|
1116
|
+
i(this, "element");
|
|
1117
|
+
i(this, "mount");
|
|
1118
|
+
i(this, "className");
|
|
1119
|
+
i(this, "thumbW");
|
|
1120
|
+
i(this, "thumbH");
|
|
1121
|
+
i(this, "thumbMargin", 16);
|
|
1122
|
+
i(this, "statusBarH");
|
|
1123
|
+
i(this, "minVisible");
|
|
1124
|
+
i(this, "minWidth");
|
|
1125
|
+
i(this, "minHeight");
|
|
1126
|
+
i(this, "onChange");
|
|
1127
|
+
i(this, "_rect");
|
|
1128
|
+
i(this, "_collapsed", !1);
|
|
1129
|
+
i(this, "uncollapsedRect", null);
|
|
1130
|
+
i(this, "drag", null);
|
|
1131
|
+
i(this, "destroyed", !1);
|
|
1132
|
+
i(this, "onWindowResize", () => {
|
|
1133
|
+
this._collapsed && (this._rect = this.thumbRect(), this.applyRectToDom(), this.emit());
|
|
1134
|
+
});
|
|
1135
|
+
i(this, "onPointerDown", (e) => {
|
|
1136
|
+
const s = e.target;
|
|
1137
|
+
if (!s.closest(`.${this.className}__collapse`)) {
|
|
1138
|
+
if (this._collapsed) {
|
|
1139
|
+
e.preventDefault(), this.expand(), this.emit();
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
e.preventDefault(), this.element.setPointerCapture(e.pointerId), this.drag = {
|
|
1143
|
+
startCard: { ...this._rect },
|
|
1144
|
+
startPointer: { x: e.clientX, y: e.clientY },
|
|
1145
|
+
handle: s.classList.contains(`${this.className}__handle`) ? s.dataset.handle ?? null : null
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
i(this, "onPointerMove", (e) => {
|
|
1150
|
+
if (!this.drag) return;
|
|
1151
|
+
e.preventDefault();
|
|
1152
|
+
const s = e.clientX - this.drag.startPointer.x, o = e.clientY - this.drag.startPointer.y, r = this.drag.startCard, l = this.drag.handle;
|
|
1153
|
+
if (l === null)
|
|
1154
|
+
this._rect = this.clampRect({ x: r.x + s, y: r.y + o, w: r.w, h: r.h });
|
|
1155
|
+
else {
|
|
1156
|
+
let a = r.x, c = r.y, u = r.w, n = r.h;
|
|
1157
|
+
l.includes("r") && (u = Math.max(this.minWidth, r.w + s)), l.includes("l") && (u = Math.max(this.minWidth, r.w - s), a = r.x + (r.w - u)), l.includes("b") && (n = Math.max(this.minHeight, r.h + o)), l.includes("t") && (n = Math.max(this.minHeight, r.h - o), c = r.y + (r.h - n)), this._rect = { x: a, y: c, w: u, h: n };
|
|
1158
|
+
}
|
|
1159
|
+
this.applyRectToDom(), this.emit();
|
|
1160
|
+
});
|
|
1161
|
+
i(this, "onPointerEnd", (e) => {
|
|
1162
|
+
if (this.drag) {
|
|
1163
|
+
try {
|
|
1164
|
+
this.element.releasePointerCapture(e.pointerId);
|
|
1165
|
+
} catch {
|
|
1166
|
+
}
|
|
1167
|
+
this.drag = null;
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
this.mount = e.mount ?? document.body, this.className = e.className ?? "prism-overlay", this.thumbW = e.thumbWidth ?? 200, this.thumbH = this.thumbW * (9 / 16), this.minVisible = e.minVisible ?? 60, this.statusBarH = e.topMargin ?? 36, this.minWidth = e.minWidth ?? 80, this.minHeight = e.minHeight ?? 45, this.onChange = e.onChange, this._rect = e.initialRect ?? this.defaultRect(), this.element = this.buildDom(), this.mount.appendChild(this.element), this.applyRectToDom(), window.addEventListener("resize", this.onWindowResize, { passive: !0 });
|
|
1171
|
+
}
|
|
1172
|
+
/** Current card rect (live; do not mutate — call setRect instead). */
|
|
1173
|
+
get rect() {
|
|
1174
|
+
return { ...this._rect };
|
|
1175
|
+
}
|
|
1176
|
+
isCollapsed() {
|
|
1177
|
+
return this._collapsed;
|
|
1178
|
+
}
|
|
1179
|
+
/** Programmatically set the rect. Silent: does NOT call onChange.
|
|
1180
|
+
* Use this to push externally-managed state into the overlay
|
|
1181
|
+
* without echoing back into your own change handler. The internal
|
|
1182
|
+
* drag/resize handlers emit onChange themselves — that's the only
|
|
1183
|
+
* source of change notifications. */
|
|
1184
|
+
setRect(e) {
|
|
1185
|
+
this._rect = { ...e }, this.applyRectToDom();
|
|
1186
|
+
}
|
|
1187
|
+
/** Programmatically collapse. Silent — see setRect. */
|
|
1188
|
+
collapse() {
|
|
1189
|
+
this._collapsed || (this.uncollapsedRect = { ...this._rect }, this._rect = this.thumbRect(), this._collapsed = !0, this.element.setAttribute("data-collapsed", ""), this.applyRectToDom());
|
|
1190
|
+
}
|
|
1191
|
+
/** Programmatically expand. Silent — see setRect. */
|
|
1192
|
+
expand() {
|
|
1193
|
+
this._collapsed && (this._rect = this.uncollapsedRect ?? this.defaultRect(), this._collapsed = !1, this.element.removeAttribute("data-collapsed"), this.applyRectToDom());
|
|
1194
|
+
}
|
|
1195
|
+
show() {
|
|
1196
|
+
this.element.removeAttribute("data-hidden");
|
|
1197
|
+
}
|
|
1198
|
+
hide() {
|
|
1199
|
+
this.element.setAttribute("data-hidden", "");
|
|
1200
|
+
}
|
|
1201
|
+
/** Whether the card is currently visible (DOM attribute is the
|
|
1202
|
+
* source of truth, so this stays accurate if anyone toggles it
|
|
1203
|
+
* externally for testing). */
|
|
1204
|
+
isVisible() {
|
|
1205
|
+
return !this.element.hasAttribute("data-hidden");
|
|
1206
|
+
}
|
|
1207
|
+
destroy() {
|
|
1208
|
+
this.destroyed || (this.destroyed = !0, window.removeEventListener("resize", this.onWindowResize), this.element.remove());
|
|
1209
|
+
}
|
|
1210
|
+
// ── internals ──────────────────────────────────────────────
|
|
1211
|
+
buildDom() {
|
|
1212
|
+
const e = document.createElement("div");
|
|
1213
|
+
e.className = this.className, e.setAttribute("data-hidden", "");
|
|
1214
|
+
const s = document.createElement("button");
|
|
1215
|
+
s.type = "button", s.className = `${this.className}__collapse`, s.title = "Collapse to thumbnail", s.setAttribute("aria-label", "Collapse");
|
|
1216
|
+
const o = document.createElement("span");
|
|
1217
|
+
o.setAttribute("aria-hidden", "true"), o.textContent = "−", s.appendChild(o), s.addEventListener("click", (r) => {
|
|
1218
|
+
r.stopPropagation(), this.collapse(), this.emit();
|
|
1219
|
+
}), e.appendChild(s);
|
|
1220
|
+
for (const r of ["tl", "tr", "bl", "br"]) {
|
|
1221
|
+
const l = document.createElement("span");
|
|
1222
|
+
l.className = `${this.className}__handle ${this.className}__handle--${r}`, l.dataset.handle = r, l.setAttribute("aria-hidden", "true"), e.appendChild(l);
|
|
1223
|
+
}
|
|
1224
|
+
return e.addEventListener("pointerdown", this.onPointerDown), e.addEventListener("pointermove", this.onPointerMove), e.addEventListener("pointerup", this.onPointerEnd), e.addEventListener("pointercancel", this.onPointerEnd), e;
|
|
1225
|
+
}
|
|
1226
|
+
applyRectToDom() {
|
|
1227
|
+
const e = this._rect;
|
|
1228
|
+
this.element.style.left = `${e.x}px`, this.element.style.top = `${e.y}px`, this.element.style.width = `${e.w}px`, this.element.style.height = `${e.h}px`;
|
|
1229
|
+
}
|
|
1230
|
+
emit() {
|
|
1231
|
+
var e;
|
|
1232
|
+
(e = this.onChange) == null || e.call(this, { rect: { ...this._rect }, collapsed: this._collapsed });
|
|
1233
|
+
}
|
|
1234
|
+
defaultRect() {
|
|
1235
|
+
const e = window.innerWidth, s = window.innerHeight, o = e * 0.58, r = Math.min(o * (9 / 16), s * 0.54);
|
|
1236
|
+
return { x: (e - o) / 2, y: s * 0.16, w: o, h: r };
|
|
1237
|
+
}
|
|
1238
|
+
thumbRect() {
|
|
1239
|
+
return {
|
|
1240
|
+
x: window.innerWidth - this.thumbW - this.thumbMargin,
|
|
1241
|
+
y: this.statusBarH + this.thumbMargin,
|
|
1242
|
+
w: this.thumbW,
|
|
1243
|
+
h: this.thumbH
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
clampRect(e) {
|
|
1247
|
+
return {
|
|
1248
|
+
x: Math.max(-(e.w - this.minVisible), Math.min(window.innerWidth - this.minVisible, e.x)),
|
|
1249
|
+
y: Math.max(this.statusBarH, Math.min(window.innerHeight - this.minVisible, e.y)),
|
|
1250
|
+
w: e.w,
|
|
1251
|
+
h: e.h
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
export {
|
|
1256
|
+
wt as GraphRuntime,
|
|
1257
|
+
ae as HeadlessSlideshow,
|
|
1258
|
+
Pt as ImageOverlay,
|
|
1259
|
+
Ct as PrismPlayer,
|
|
1260
|
+
O as SCHEMA_VERSION,
|
|
1261
|
+
St as SyntheticSignal,
|
|
1262
|
+
ee as createMilkdropBackground,
|
|
1263
|
+
ie as createShadertoyBackground,
|
|
1264
|
+
xt as lookup,
|
|
1265
|
+
Gt as makeMilkdropGraph,
|
|
1266
|
+
ft as nodesByRole,
|
|
1267
|
+
gt as roleOf,
|
|
1268
|
+
vt as shortIdToGraph,
|
|
1269
|
+
At as shortIds
|
|
1270
|
+
};
|
|
1271
|
+
//# sourceMappingURL=prism.mjs.map
|