@dopaminefx/core 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.
Files changed (136) hide show
  1. package/dist/engine/color.d.ts +71 -0
  2. package/dist/engine/color.d.ts.map +1 -0
  3. package/dist/engine/color.js +107 -0
  4. package/dist/engine/color.js.map +1 -0
  5. package/dist/engine/context.d.ts +54 -0
  6. package/dist/engine/context.d.ts.map +1 -0
  7. package/dist/engine/context.js +0 -0
  8. package/dist/engine/context.js.map +1 -0
  9. package/dist/engine/gl.d.ts +9 -0
  10. package/dist/engine/gl.d.ts.map +1 -0
  11. package/dist/engine/gl.js +39 -0
  12. package/dist/engine/gl.js.map +1 -0
  13. package/dist/engine/look/glsl.d.ts +95 -0
  14. package/dist/engine/look/glsl.d.ts.map +1 -0
  15. package/dist/engine/look/glsl.js +171 -0
  16. package/dist/engine/look/glsl.js.map +1 -0
  17. package/dist/engine/look/particles.glsl.d.ts +21 -0
  18. package/dist/engine/look/particles.glsl.d.ts.map +1 -0
  19. package/dist/engine/look/particles.glsl.js +44 -0
  20. package/dist/engine/look/particles.glsl.js.map +1 -0
  21. package/dist/engine/sdf.d.ts +77 -0
  22. package/dist/engine/sdf.d.ts.map +1 -0
  23. package/dist/engine/sdf.js +255 -0
  24. package/dist/engine/sdf.js.map +1 -0
  25. package/dist/engine/seed.d.ts +10 -0
  26. package/dist/engine/seed.d.ts.map +1 -0
  27. package/dist/engine/seed.js +20 -0
  28. package/dist/engine/seed.js.map +1 -0
  29. package/dist/engine/shadow.d.ts +41 -0
  30. package/dist/engine/shadow.d.ts.map +1 -0
  31. package/dist/engine/shadow.js +39 -0
  32. package/dist/engine/shadow.js.map +1 -0
  33. package/dist/engine/tempo.d.ts +33 -0
  34. package/dist/engine/tempo.d.ts.map +1 -0
  35. package/dist/engine/tempo.js +51 -0
  36. package/dist/engine/tempo.js.map +1 -0
  37. package/dist/framework/conductor.d.ts +100 -0
  38. package/dist/framework/conductor.d.ts.map +1 -0
  39. package/dist/framework/conductor.js +493 -0
  40. package/dist/framework/conductor.js.map +1 -0
  41. package/dist/framework/content.d.ts +67 -0
  42. package/dist/framework/content.d.ts.map +1 -0
  43. package/dist/framework/content.js +72 -0
  44. package/dist/framework/content.js.map +1 -0
  45. package/dist/framework/dope-pass.d.ts +131 -0
  46. package/dist/framework/dope-pass.d.ts.map +1 -0
  47. package/dist/framework/dope-pass.js +346 -0
  48. package/dist/framework/dope-pass.js.map +1 -0
  49. package/dist/framework/dope-zip.d.ts +22 -0
  50. package/dist/framework/dope-zip.d.ts.map +1 -0
  51. package/dist/framework/dope-zip.js +116 -0
  52. package/dist/framework/dope-zip.js.map +1 -0
  53. package/dist/framework/effect.d.ts +128 -0
  54. package/dist/framework/effect.d.ts.map +1 -0
  55. package/dist/framework/effect.js +19 -0
  56. package/dist/framework/effect.js.map +1 -0
  57. package/dist/framework/frame-expr.d.ts +124 -0
  58. package/dist/framework/frame-expr.d.ts.map +1 -0
  59. package/dist/framework/frame-expr.js +135 -0
  60. package/dist/framework/frame-expr.js.map +1 -0
  61. package/dist/framework/load-effect.d.ts +77 -0
  62. package/dist/framework/load-effect.d.ts.map +1 -0
  63. package/dist/framework/load-effect.js +135 -0
  64. package/dist/framework/load-effect.js.map +1 -0
  65. package/dist/framework/loader.d.ts +309 -0
  66. package/dist/framework/loader.d.ts.map +1 -0
  67. package/dist/framework/loader.js +266 -0
  68. package/dist/framework/loader.js.map +1 -0
  69. package/dist/framework/mood-registry.d.ts +58 -0
  70. package/dist/framework/mood-registry.d.ts.map +1 -0
  71. package/dist/framework/mood-registry.js +58 -0
  72. package/dist/framework/mood-registry.js.map +1 -0
  73. package/dist/framework/panel-runner.d.ts +96 -0
  74. package/dist/framework/panel-runner.d.ts.map +1 -0
  75. package/dist/framework/panel-runner.js +137 -0
  76. package/dist/framework/panel-runner.js.map +1 -0
  77. package/dist/framework/pass-common.d.ts +97 -0
  78. package/dist/framework/pass-common.d.ts.map +1 -0
  79. package/dist/framework/pass-common.js +178 -0
  80. package/dist/framework/pass-common.js.map +1 -0
  81. package/dist/framework/pass-runner.d.ts +183 -0
  82. package/dist/framework/pass-runner.d.ts.map +1 -0
  83. package/dist/framework/pass-runner.js +212 -0
  84. package/dist/framework/pass-runner.js.map +1 -0
  85. package/dist/framework/programs.d.ts +54 -0
  86. package/dist/framework/programs.d.ts.map +1 -0
  87. package/dist/framework/programs.js +33 -0
  88. package/dist/framework/programs.js.map +1 -0
  89. package/dist/framework/registry.d.ts +29 -0
  90. package/dist/framework/registry.d.ts.map +1 -0
  91. package/dist/framework/registry.js +38 -0
  92. package/dist/framework/registry.js.map +1 -0
  93. package/dist/framework/runtime.d.ts +19 -0
  94. package/dist/framework/runtime.d.ts.map +1 -0
  95. package/dist/framework/runtime.js +37 -0
  96. package/dist/framework/runtime.js.map +1 -0
  97. package/dist/index.d.ts +63 -0
  98. package/dist/index.d.ts.map +1 -0
  99. package/dist/index.js +126 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/overlay.d.ts +46 -0
  102. package/dist/overlay.d.ts.map +1 -0
  103. package/dist/overlay.js +79 -0
  104. package/dist/overlay.js.map +1 -0
  105. package/dist/types.d.ts +68 -0
  106. package/dist/types.d.ts.map +1 -0
  107. package/dist/types.js +10 -0
  108. package/dist/types.js.map +1 -0
  109. package/package.json +37 -0
  110. package/src/engine/color.ts +154 -0
  111. package/src/engine/context.ts +0 -0
  112. package/src/engine/gl.ts +46 -0
  113. package/src/engine/look/glsl.ts +183 -0
  114. package/src/engine/look/particles.glsl.ts +44 -0
  115. package/src/engine/sdf.ts +298 -0
  116. package/src/engine/seed.ts +23 -0
  117. package/src/engine/shadow.ts +66 -0
  118. package/src/engine/tempo.ts +54 -0
  119. package/src/framework/conductor.ts +604 -0
  120. package/src/framework/content.ts +113 -0
  121. package/src/framework/dope-pass.ts +432 -0
  122. package/src/framework/dope-zip.ts +125 -0
  123. package/src/framework/effect.ts +127 -0
  124. package/src/framework/frame-expr.ts +217 -0
  125. package/src/framework/load-effect.ts +204 -0
  126. package/src/framework/loader.ts +502 -0
  127. package/src/framework/mood-registry.ts +87 -0
  128. package/src/framework/panel-runner.ts +233 -0
  129. package/src/framework/pass-common.ts +222 -0
  130. package/src/framework/pass-runner.ts +391 -0
  131. package/src/framework/programs.ts +62 -0
  132. package/src/framework/registry.ts +44 -0
  133. package/src/framework/runtime.ts +38 -0
  134. package/src/index.ts +227 -0
  135. package/src/overlay.ts +109 -0
  136. package/src/types.ts +63 -0
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Generic fullscreen-pass runner — the shared backbone for PURE-SHADER effects.
3
+ *
4
+ * A pure-shader effect (Solarbloom, Calligraphic Verdict, the Fail stamp) is a
5
+ * full-screen triangle that runs a fragment shader twice — once into the light
6
+ * (screen) context and, when present, once into the shadow (multiply) context.
7
+ * Before this runner, each effect hand-wired the SAME plumbing: link/bind the
8
+ * program + VAO, set the standard uniforms (resolution, origin, time, life,
9
+ * envelope amp, palette, style, the shadow-pass uniforms), upload + bind any aux
10
+ * textures (a baked SDF icon) into BOTH contexts, run the two passes, and free
11
+ * the per-fire GPU resources. That ~120 lines of identical glue is now here,
12
+ * once.
13
+ *
14
+ * What stays per-effect (the honest boundary): the GLSL itself, and a tiny
15
+ * `frame()` hook that computes the genuinely effect-specific TIME-VARYING values
16
+ * (which envelope, which confirm/draw/stamp progress, any shake) into named
17
+ * uniforms. Everything else — standard uniforms, scalar `render.params` →
18
+ * `u<Name>` auto-binding, aux-texture upload/bind, the light+shadow loop, the
19
+ * "animate on twos" stepping, dispose — is generic and data-driven from a small
20
+ * config object.
21
+ *
22
+ * The output is byte-identical to the bespoke renderers it replaces: it sets the
23
+ * same uniforms, in a superset that the shader samples by name, and uses the same
24
+ * `shadowGeometry` / envelope / progress math (supplied by the config).
25
+ */
26
+ import { NPR_TIME_STEP_MS } from "../engine/tempo.js";
27
+ import { STANDARD_COMMON, allocTexture, applyFloatMap, beginProgram, bindFrameUniforms, bindPalette, bindScalars, bindShadowGeometry, bindTarget, compositeLightFragment, computeScalarBinds, resolveTargetPx, } from "./pass-common.js";
28
+ // The pure-shader runner adds `uOrigin` (anchored radial effects) to the shared
29
+ // standard set.
30
+ const STANDARD = ["uOrigin", ...STANDARD_COMMON];
31
+ /** Upload a decoded SDF as a single-channel R8 texture (FLIP_Y, edge-clamped). */
32
+ function uploadSdf(glc, sdf) {
33
+ const { gl } = glc;
34
+ const tex = gl.createTexture();
35
+ gl.bindTexture(gl.TEXTURE_2D, tex);
36
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
37
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
38
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, sdf.size, sdf.size, 0, gl.RED, gl.UNSIGNED_BYTE, sdf.bytes);
39
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
40
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
41
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
42
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
43
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
44
+ return tex;
45
+ }
46
+ /**
47
+ * Build a drawable {@link EffectInstance} for a pure-shader effect from its
48
+ * config + resolved params + the runtime context. This is the `create()` an
49
+ * effect (or a registered program) hands to the conductor.
50
+ */
51
+ export function createPassInstance(config, params, ctx) {
52
+ const pal = params.palette;
53
+ const dpr = ctx.dpr;
54
+ const panelCfg = config.panel;
55
+ // In backdrop-aware mode the LIGHT pass emits premultiplied light (alpha =
56
+ // brightness) so it composites source-over and stays visible on any surface;
57
+ // the SHADOW pass keeps the original opaque fragment for its multiply blend.
58
+ const lightFragment = ctx.composite?.premultiplied
59
+ ? compositeLightFragment(config.fragment)
60
+ : config.fragment;
61
+ const allUniforms = [
62
+ ...new Set([...STANDARD, ...config.uniforms, ...(panelCfg ? [panelCfg.sampler] : [])]),
63
+ ];
64
+ // Optional dynamic sprite panel (drawn once per frame, uploaded to both passes).
65
+ const panelCanvas = panelCfg ? document.createElement("canvas") : null;
66
+ const panelCtx2d = panelCanvas ? panelCanvas.getContext("2d", { alpha: true }) : null;
67
+ const panelTexLight = panelCfg ? allocTexture(ctx.light) : null;
68
+ const panelTexShadow = panelCfg && ctx.shadow ? allocTexture(ctx.shadow) : null;
69
+ // The numeric params that auto-bind to a uniform: `name → u<Name>` unless an
70
+ // explicit binding overrides it (or maps it to null to skip).
71
+ const scalarBinds = computeScalarBinds(params, config.bindings ?? {});
72
+ // Aux textures. SDF sources upload up front (static R8 data); canvas sources
73
+ // allocate the texture now but upload pixels lazily on first bind (the canvas
74
+ // may still be drawn after create()).
75
+ const auxSpecs = config.auxTextures?.(params, ctx) ?? [];
76
+ const uploaded = new WeakSet();
77
+ const aux = auxSpecs.map((spec) => {
78
+ if (spec.kind === "sdf") {
79
+ return { spec, light: uploadSdf(ctx.light, spec.sdf), shadow: ctx.shadow ? uploadSdf(ctx.shadow, spec.sdf) : null };
80
+ }
81
+ return { spec, light: allocTexture(ctx.light), shadow: ctx.shadow ? allocTexture(ctx.shadow) : null };
82
+ });
83
+ const heightFrac = () => typeof config.shadowHeightFrac === "function" ? config.shadowHeightFrac(params) : config.shadowHeightFrac;
84
+ const bindFrameArrays = (gl, u, arrays) => {
85
+ if (!arrays)
86
+ return;
87
+ for (const a of arrays) {
88
+ const loc = u[a.name];
89
+ if (!loc)
90
+ continue;
91
+ if (a.size === 2)
92
+ gl.uniform2fv(loc, a.data);
93
+ else if (a.size === 3)
94
+ gl.uniform3fv(loc, a.data);
95
+ else
96
+ gl.uniform4fv(loc, a.data);
97
+ }
98
+ };
99
+ const drawPass = (glc, info, frameUniforms, isShadow, frameArrs) => {
100
+ const { gl } = glc;
101
+ const c = glc.canvas;
102
+ const { u } = beginProgram(glc, config.vertex, isShadow ? config.fragment : lightFragment, allUniforms);
103
+ // Aux textures (baked SDF icons / rasterized canvas glyphs).
104
+ for (const a of aux) {
105
+ const tex = isShadow ? a.shadow : a.light;
106
+ if (tex) {
107
+ gl.activeTexture(gl.TEXTURE0 + a.spec.unit);
108
+ gl.bindTexture(gl.TEXTURE_2D, tex);
109
+ // Canvas sources upload their pixels lazily, once per texture.
110
+ if (a.spec.kind === "canvas" && !uploaded.has(tex)) {
111
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
112
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
113
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, a.spec.source);
114
+ uploaded.add(tex);
115
+ }
116
+ const loc = u[a.spec.sampler];
117
+ if (loc)
118
+ gl.uniform1i(loc, a.spec.unit);
119
+ }
120
+ if (a.spec.onUniform && u[a.spec.onUniform])
121
+ gl.uniform1f(u[a.spec.onUniform], tex ? 1 : 0);
122
+ applyFloatMap(gl, u, a.spec.uniforms?.(c, params));
123
+ }
124
+ // Dynamic sprite panel (drawn this frame in renderAt): upload + bind here.
125
+ if (panelCfg && panelCanvas) {
126
+ const tex = isShadow ? panelTexShadow : panelTexLight;
127
+ if (tex) {
128
+ gl.activeTexture(gl.TEXTURE0 + panelCfg.unit);
129
+ gl.bindTexture(gl.TEXTURE_2D, tex);
130
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
131
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
132
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, panelCanvas);
133
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
134
+ if (u[panelCfg.sampler])
135
+ gl.uniform1i(u[panelCfg.sampler], panelCfg.unit);
136
+ }
137
+ }
138
+ // Extra per-pass scalar uniforms (canvas/target-size-dependent, non-aux).
139
+ applyFloatMap(gl, u, config.passUniforms?.(c, params, resolveTargetPx(c, ctx.targetSize, dpr), dpr));
140
+ // Standard uniforms.
141
+ gl.uniform2f(u.uResolution, c.width, c.height);
142
+ bindTarget(gl, u, c, ctx.targetSize, dpr);
143
+ if (config.usesOrigin && u.uOrigin) {
144
+ // gl_FragCoord origin is bottom-left, so flip the anchor's y.
145
+ gl.uniform2f(u.uOrigin, ctx.anchor.x * dpr, c.height - ctx.anchor.y * dpr);
146
+ }
147
+ gl.uniform1f(u.uLife, info.life);
148
+ gl.uniform1f(u.uTimeS, info.animMs / 1000);
149
+ if (config.loopPeriodMs) {
150
+ // Standard periodic clocks for a looping effect, off the SAME snapped
151
+ // clock as uTimeS (so the on-twos seam guarantee carries over).
152
+ const loopMs = info.animMs % config.loopPeriodMs;
153
+ gl.uniform1f(u.uLoopS, loopMs / 1000);
154
+ gl.uniform1f(u.uPhase, loopMs / config.loopPeriodMs);
155
+ }
156
+ gl.uniform1f(u.uStyle, params.style);
157
+ bindPalette(gl, u, pal);
158
+ bindScalars(gl, u, params, scalarBinds);
159
+ bindFrameUniforms(gl, u, frameUniforms);
160
+ bindFrameArrays(gl, u, frameArrs);
161
+ gl.uniform1f(u.uShadow, isShadow ? 1 : 0);
162
+ if (isShadow)
163
+ bindShadowGeometry(gl, u, c, heightFrac(), frameUniforms.amp, params.style);
164
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
165
+ };
166
+ let disposed = false;
167
+ return {
168
+ durationMs: params.durationMs,
169
+ renderAt(elapsedMs) {
170
+ if (disposed)
171
+ return;
172
+ // "Animate on twos": snap the clock toward a coarse grid as style rises.
173
+ const stepped = Math.floor(elapsedMs / NPR_TIME_STEP_MS) * NPR_TIME_STEP_MS;
174
+ const animMs = elapsedMs + (stepped - elapsedMs) * params.style;
175
+ const life = Math.min(Math.max(animMs, 0) / params.durationMs, 1);
176
+ const info = { animMs, life, elapsedMs };
177
+ const frameUniforms = config.frame(info, params);
178
+ // Draw the dynamic sprite panel once (shared by both passes), if present.
179
+ if (panelCfg && panelCanvas && panelCtx2d) {
180
+ const c = ctx.light.canvas;
181
+ if (panelCanvas.width !== c.width || panelCanvas.height !== c.height) {
182
+ panelCanvas.width = c.width;
183
+ panelCanvas.height = c.height;
184
+ }
185
+ const centerPx = { x: ctx.anchor.x * dpr, y: ctx.anchor.y * dpr };
186
+ panelCfg.draw(panelCtx2d, c.width, c.height, params, { ...info, centerPx, dpr });
187
+ }
188
+ // Per-frame array uniforms (CPU-precomputed geometry), computed once.
189
+ const c = ctx.light.canvas;
190
+ const origin = { x: ctx.anchor.x * dpr, y: c.height - ctx.anchor.y * dpr };
191
+ const frameArrs = config.frameArrays?.(info, params, { width: c.width, height: c.height, dpr, origin });
192
+ if (ctx.shadow)
193
+ drawPass(ctx.shadow, info, frameUniforms, true, frameArrs);
194
+ drawPass(ctx.light, info, frameUniforms, false, frameArrs);
195
+ },
196
+ dispose() {
197
+ if (disposed)
198
+ return;
199
+ disposed = true;
200
+ for (const a of aux) {
201
+ ctx.light.gl.deleteTexture(a.light);
202
+ if (a.shadow && ctx.shadow)
203
+ ctx.shadow.gl.deleteTexture(a.shadow);
204
+ }
205
+ if (panelTexLight)
206
+ ctx.light.gl.deleteTexture(panelTexLight);
207
+ if (panelTexShadow && ctx.shadow)
208
+ ctx.shadow.gl.deleteTexture(panelTexShadow);
209
+ },
210
+ };
211
+ }
212
+ //# sourceMappingURL=pass-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pass-runner.js","sourceRoot":"","sources":["../../src/framework/pass-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKtD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,UAAU,EACV,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAoJ1B,gFAAgF;AAChF,gBAAgB;AAChB,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,GAAG,eAAe,CAAU,CAAC;AAE1D,kFAAkF;AAClF,SAAS,SAAS,CAAC,GAAc,EAAE,GAAe;IAChD,MAAM,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACnB,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;IAC/B,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACnC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;IAC7C,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;IACvC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACnG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAClE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAClE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC;IACrE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC;IACrE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,GAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAkB,EAClB,MAAkB,EAClB,GAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAgB,CAAC;IACpC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;IAC9B,2EAA2E;IAC3E,6EAA6E;IAC7E,6EAA6E;IAC7E,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,EAAE,aAAa;QAChD,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,QAAQ,CAAC;QACzC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IACpB,MAAM,WAAW,GAAG;QAClB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACvF,CAAC;IAEF,iFAAiF;IACjF,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtF,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,MAAM,cAAc,GAAG,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEhF,6EAA6E;IAC7E,8DAA8D;IAC9D,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAEtE,6EAA6E;IAC7E,8EAA8E;IAC9E,sCAAsC;IACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAgB,CAAC;IAC7C,MAAM,GAAG,GAAc,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtH,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,GAAW,EAAE,CAC9B,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC;IAE5G,MAAM,eAAe,GAAG,CACtB,EAA0B,EAC1B,CAA8C,EAC9C,MAAwF,EAClF,EAAE;QACR,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACtB,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;gBAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;iBACxC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;gBAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;;gBAC7C,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CACf,GAAc,EACd,IAAe,EACf,aAAuD,EACvD,QAAiB,EACjB,SAAgF,EAC1E,EAAE;QACR,MAAM,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;QACnB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;QACrB,MAAM,EAAE,CAAC,EAAE,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QAExG,6DAA6D;QAC7D,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAC1C,IAAI,GAAG,EAAE,CAAC;gBACR,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBACnC,+DAA+D;gBAC/D,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnD,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;oBAC7C,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;oBACzD,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACnF,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;gBACD,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC9B,IAAI,GAAG;oBAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,CAAC;YACD,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;gBAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5F,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,2EAA2E;QAC3E,IAAI,QAAQ,IAAI,WAAW,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC;YACtD,IAAI,GAAG,EAAE,CAAC;gBACR,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC9C,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBACnC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;gBAC7C,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;gBACzD,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;gBACjF,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;gBAC9C,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAErG,qBAAqB;QACrB,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/C,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACnC,8DAA8D;YAC9D,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QAC7E,CAAC;QACD,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,sEAAsE;YACtE,gEAAgE;YAChE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC;YACjD,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;YACtC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QACvD,CAAC;QACD,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACrC,WAAW,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QACxB,WAAW,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QACxC,iBAAiB,CAAC,EAAE,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC;QACxC,eAAe,CAAC,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAElC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,QAAQ;YAAE,kBAAkB,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1F,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC;IAEF,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,QAAQ,CAAC,SAAiB;YACxB,IAAI,QAAQ;gBAAE,OAAO;YACrB,yEAAyE;YACzE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,gBAAgB,CAAC,GAAG,gBAAgB,CAAC;YAC5E,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,OAAO,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;YAChE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YAClE,MAAM,IAAI,GAAc,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;YACpD,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACjD,0EAA0E;YAC1E,IAAI,QAAQ,IAAI,WAAW,IAAI,UAAU,EAAE,CAAC;gBAC1C,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;gBAC3B,IAAI,WAAW,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;oBACrE,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;oBAC5B,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;gBAChC,CAAC;gBACD,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC;gBAClE,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,sEAAsE;YACtE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;YAC3B,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC;YAC3E,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;YACxG,IAAI,GAAG,CAAC,MAAM;gBAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;YAC3E,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;gBACpB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBACpC,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM;oBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACpE,CAAC;YACD,IAAI,aAAa;gBAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YAC7D,IAAI,cAAc,IAAI,GAAG,CAAC,MAAM;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAChF,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Render-program registry — the seam that makes `loadEffect()` real.
3
+ *
4
+ * A `.dope` is renderer-agnostic data, but it references a SHADER PROGRAM by key
5
+ * (`render.backends.webgl2.shader.program`, e.g. "solarbloom"). The runtime ships
6
+ * a small set of bundled programs; each is a `create(params, ctx)` renderer (the
7
+ * GLSL body + uniform plumbing) plus the metadata the loader needs to resolve the
8
+ * `.dope` into that renderer's params: the per-fire scatter key (moteSeed /
9
+ * inkSeed / …), the integer-clamp consts (MAX_MOTES / MAX_DROPS), whether it
10
+ * casts a shadow, and its reduced-motion peak.
11
+ *
12
+ * Built-in effects register their renderer here (in addition to registering
13
+ * themselves as an `EffectFactory`), so `loadEffect(anyDopeDoc)` can bind an
14
+ * arbitrary, host-authored `.dope` to a bundled program with NO new code — the
15
+ * whole point of the format. This is "the format references shader bodies; it is
16
+ * not a transpiler" made concrete: the doc carries data + a program key; the
17
+ * runtime owns the GLSL the key resolves to.
18
+ */
19
+ import type { EffectContext, EffectInstance } from "./effect.js";
20
+ /** A bundled renderer + the metadata the loader needs to feed it from a `.dope`. */
21
+ export interface RenderProgram<Params = Record<string, unknown>> {
22
+ /** Build a drawable instance from resolved params (same shape as EffectFactory.create). */
23
+ create(params: Params, ctx: EffectContext): EffectInstance;
24
+ /** The per-fire scatter-offset key this renderer reads (moteSeed / inkSeed / …). */
25
+ scatterKey: string;
26
+ /** Integer-clamp constants referenced by the `.dope` mapping (MAX_MOTES, …). */
27
+ consts: Record<string, number>;
28
+ /** Whether the renderer wants a shadow (multiply) companion canvas. Default true. */
29
+ castsShadow?: boolean;
30
+ /** Reduced-motion peak/hold (ms). */
31
+ reducedMotion?: {
32
+ holdMs?: number;
33
+ peakMs?: number;
34
+ };
35
+ /**
36
+ * Optional hook to compose NON-numeric, code-shaped params on top of the
37
+ * loader's numeric/palette bag (e.g. Solarbloom's whimsy-picked check glyph,
38
+ * Comic's word + typography). Pure; receives the feeling. Most data-driven
39
+ * effects (incl. the fail effect) need none.
40
+ */
41
+ composeParams?(numeric: Record<string, unknown>, feeling: {
42
+ mood: string;
43
+ intensity: number;
44
+ whimsy: number;
45
+ seed: number;
46
+ }): Record<string, unknown>;
47
+ }
48
+ /** Register (or override) a bundled render program by key. */
49
+ export declare function registerProgram<P>(name: string, program: RenderProgram<P>): RenderProgram<P>;
50
+ /** Look up a bundled render program by key. */
51
+ export declare function getProgram(name: string): RenderProgram | undefined;
52
+ /** Names of all registered render programs. */
53
+ export declare function programNames(): string[];
54
+ //# sourceMappingURL=programs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"programs.d.ts","sourceRoot":"","sources":["../../src/framework/programs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,oFAAoF;AACpF,MAAM,WAAW,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7D,2FAA2F;IAC3F,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,cAAc,CAAC;IAC3D,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,qFAAqF;IACrF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qCAAqC;IACrC,aAAa,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD;;;;;OAKG;IACH,aAAa,CAAC,CACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GACzE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5B;AAID,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAG5F;AAED,+CAA+C;AAC/C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAElE;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Render-program registry — the seam that makes `loadEffect()` real.
3
+ *
4
+ * A `.dope` is renderer-agnostic data, but it references a SHADER PROGRAM by key
5
+ * (`render.backends.webgl2.shader.program`, e.g. "solarbloom"). The runtime ships
6
+ * a small set of bundled programs; each is a `create(params, ctx)` renderer (the
7
+ * GLSL body + uniform plumbing) plus the metadata the loader needs to resolve the
8
+ * `.dope` into that renderer's params: the per-fire scatter key (moteSeed /
9
+ * inkSeed / …), the integer-clamp consts (MAX_MOTES / MAX_DROPS), whether it
10
+ * casts a shadow, and its reduced-motion peak.
11
+ *
12
+ * Built-in effects register their renderer here (in addition to registering
13
+ * themselves as an `EffectFactory`), so `loadEffect(anyDopeDoc)` can bind an
14
+ * arbitrary, host-authored `.dope` to a bundled program with NO new code — the
15
+ * whole point of the format. This is "the format references shader bodies; it is
16
+ * not a transpiler" made concrete: the doc carries data + a program key; the
17
+ * runtime owns the GLSL the key resolves to.
18
+ */
19
+ const programs = new Map();
20
+ /** Register (or override) a bundled render program by key. */
21
+ export function registerProgram(name, program) {
22
+ programs.set(name, program);
23
+ return program;
24
+ }
25
+ /** Look up a bundled render program by key. */
26
+ export function getProgram(name) {
27
+ return programs.get(name);
28
+ }
29
+ /** Names of all registered render programs. */
30
+ export function programNames() {
31
+ return [...programs.keys()];
32
+ }
33
+ //# sourceMappingURL=programs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/framework/programs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA4BH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAElD,8DAA8D;AAC9D,MAAM,UAAU,eAAe,CAAI,IAAY,EAAE,OAAyB;IACxE,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAwB,CAAC,CAAC;IAC7C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Effect registry — the lookup table the runtime uses to find an effect by name.
3
+ *
4
+ * Effects self-register on import (see `effects/*.ts`), which keeps the registry
5
+ * tree-shakeable: if you never import an effect, it never lands in the bundle
6
+ * *or* the registry. The public `play({ effect })` / element / React surfaces
7
+ * all route through here.
8
+ */
9
+ import type { EffectFactory } from "./effect.js";
10
+ /**
11
+ * Register (or override) an effect. Returns the factory so registration can be
12
+ * the module's export pattern:
13
+ *
14
+ * ```ts
15
+ * export default registerEffect({
16
+ * name: "confetti",
17
+ * resolve(feeling, mood) { ... },
18
+ * create(params, ctx) { ... },
19
+ * });
20
+ * ```
21
+ */
22
+ export declare function registerEffect<P>(factory: EffectFactory<P>): EffectFactory<P>;
23
+ /** Look up an effect by name, or `undefined` if it hasn't been registered. */
24
+ export declare function getEffect(name: string): EffectFactory | undefined;
25
+ /** Whether an effect name is registered. */
26
+ export declare function hasEffect(name: string): boolean;
27
+ /** Names of all registered effects. */
28
+ export declare function effectNames(): string[];
29
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/framework/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAG7E;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEjE;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED,uCAAuC;AACvC,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Effect registry — the lookup table the runtime uses to find an effect by name.
3
+ *
4
+ * Effects self-register on import (see `effects/*.ts`), which keeps the registry
5
+ * tree-shakeable: if you never import an effect, it never lands in the bundle
6
+ * *or* the registry. The public `play({ effect })` / element / React surfaces
7
+ * all route through here.
8
+ */
9
+ const effects = new Map();
10
+ /**
11
+ * Register (or override) an effect. Returns the factory so registration can be
12
+ * the module's export pattern:
13
+ *
14
+ * ```ts
15
+ * export default registerEffect({
16
+ * name: "confetti",
17
+ * resolve(feeling, mood) { ... },
18
+ * create(params, ctx) { ... },
19
+ * });
20
+ * ```
21
+ */
22
+ export function registerEffect(factory) {
23
+ effects.set(factory.name, factory);
24
+ return factory;
25
+ }
26
+ /** Look up an effect by name, or `undefined` if it hasn't been registered. */
27
+ export function getEffect(name) {
28
+ return effects.get(name);
29
+ }
30
+ /** Whether an effect name is registered. */
31
+ export function hasEffect(name) {
32
+ return effects.has(name);
33
+ }
34
+ /** Names of all registered effects. */
35
+ export function effectNames() {
36
+ return [...effects.keys()];
37
+ }
38
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/framework/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAI,OAAyB;IACzD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAwB,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Runtime-environment guards. Every access to a browser-only global
3
+ * (`document`, `window`, `matchMedia`, `devicePixelRatio`) goes through here so
4
+ * the whole library is SSR-safe: importing `@dopaminefx/core` on a server, or
5
+ * calling `celebrate()` where there is no DOM, is a no-op rather than a crash.
6
+ */
7
+ /** True only in a real browser with a DOM we can mount an overlay into. */
8
+ export declare function isBrowser(): boolean;
9
+ /** Whether the document is currently hidden (background tab). SSR-safe. */
10
+ export declare function isDocumentHidden(): boolean;
11
+ /**
12
+ * Whether the user has asked for reduced motion. SSR-safe and defensive: if
13
+ * `matchMedia` is unavailable or throws we assume motion is fine (the prior
14
+ * default behaviour).
15
+ */
16
+ export declare function prefersReducedMotion(): boolean;
17
+ /** Device-pixel ratio, capped at 2 to bound fill cost under software WebGL. */
18
+ export declare function deviceDpr(): number;
19
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/framework/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2EAA2E;AAC3E,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAS9C;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,IAAI,MAAM,CAGlC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Runtime-environment guards. Every access to a browser-only global
3
+ * (`document`, `window`, `matchMedia`, `devicePixelRatio`) goes through here so
4
+ * the whole library is SSR-safe: importing `@dopaminefx/core` on a server, or
5
+ * calling `celebrate()` where there is no DOM, is a no-op rather than a crash.
6
+ */
7
+ /** True only in a real browser with a DOM we can mount an overlay into. */
8
+ export function isBrowser() {
9
+ return typeof document !== "undefined" && typeof window !== "undefined";
10
+ }
11
+ /** Whether the document is currently hidden (background tab). SSR-safe. */
12
+ export function isDocumentHidden() {
13
+ return typeof document !== "undefined" && document.visibilityState === "hidden";
14
+ }
15
+ /**
16
+ * Whether the user has asked for reduced motion. SSR-safe and defensive: if
17
+ * `matchMedia` is unavailable or throws we assume motion is fine (the prior
18
+ * default behaviour).
19
+ */
20
+ export function prefersReducedMotion() {
21
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
22
+ return false;
23
+ }
24
+ try {
25
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /** Device-pixel ratio, capped at 2 to bound fill cost under software WebGL. */
32
+ export function deviceDpr() {
33
+ if (typeof window === "undefined")
34
+ return 1;
35
+ return Math.min(window.devicePixelRatio || 1, 2);
36
+ }
37
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/framework/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2EAA2E;AAC3E,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,QAAQ,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW,CAAC;AAC1E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QAC7E,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,SAAS;IACvB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @dopaminefx/core — the EFFECT-FREE runtime + public API.
3
+ *
4
+ * This is the slim runtime: the conductor (overlay + shared program-cached GL
5
+ * contexts + RAF loop), the registry, the mood registry, the `.dope` loader +
6
+ * `loadEffect`, the generic runners (pass + panel), the shared engine bits
7
+ * (color, sdf, shadow, seed, context, gl, the `look/` GLSL chunks, tempo
8
+ * PRIMITIVES) and the generic `play(name, …)` / `prepare(name, …)` API.
9
+ *
10
+ * Core imports + registers NO effect. Each effect ships as its own
11
+ * `@dopaminefx/effect-<name>` package that depends on this and self-registers on
12
+ * import; the `@dopaminefx/effects` umbrella bundles all nine + the `celebrate*`
13
+ * conveniences + the `<dopamine-success>` element.
14
+ */
15
+ import { type PlayHandle } from "./framework/conductor.js";
16
+ import type { DopamineSuccessOptions } from "./types.js";
17
+ export type { DopamineMood, DopamineSuccessOptions } from "./types.js";
18
+ export type { RGB, OKLCH } from "./engine/color.js";
19
+ export { buildPalette, oklchToLinearSrgb, wrapHue, GOLDEN_ANGLE_DEG, type PaletteParams } from "./engine/color.js";
20
+ export { mulberry32, randomSeed, type Rng } from "./engine/seed.js";
21
+ export type { Effect, EffectFactory, EffectInstance, EffectContext, FeelingInput, Anchor, } from "./framework/effect.js";
22
+ export { registerEffect, getEffect, hasEffect, effectNames } from "./framework/registry.js";
23
+ export { registerMood, resolveMood, hasMood, moodNames, type MoodSpec, type ResolvedMood, } from "./framework/mood-registry.js";
24
+ export { teardown, type PreparedHandle, type PlayHandle } from "./framework/conductor.js";
25
+ export { loadEffect, loadEffectSync, type LoadEffectOptions, type LoadOverrides, type LoadedEffect, } from "./framework/load-effect.js";
26
+ export { registerProgram, getProgram, programNames, type RenderProgram } from "./framework/programs.js";
27
+ export { parseDope, resolveDopeParams, getOutline, type DopeDoc, type DopeOutline, type DopeBinding, type DopeSampler, type DopeFrameSpec, type DopeLoopSpec, } from "./framework/loader.js";
28
+ export { dopePassConfig, dopePanelConfig, registerDopeEffect, registerDopePanelEffect, type DopePassHooks, type DopeShader, type RegisterDopeEffectOptions, } from "./framework/dope-pass.js";
29
+ export { evalFrameExpr, evalParamExpr, evalPassExpr, type FrameExprNode, type FrameExprCtx, type PassExprInputs, } from "./framework/frame-expr.js";
30
+ export { pickFromList, pickBand, resolveTypography, type DopeTypography, } from "./framework/content.js";
31
+ export { bakeSdf, decodeSdf, parseSvgPath, type BakedSdf, type DecodedSdf } from "./engine/sdf.js";
32
+ export { createPassInstance, type PassConfig, type PassParams, type AuxTextureSpec, type FrameInfo, } from "./framework/pass-runner.js";
33
+ export { createPanelInstance, type PanelConfig, type PanelDraw, type PanelFrameInfo, } from "./framework/panel-runner.js";
34
+ export { clamp01, easeOutCubic, easeOutBack, envelope, NPR_TIME_STEP_MS, } from "./engine/tempo.js";
35
+ export * from "./engine/look/glsl.js";
36
+ export { GLSL_PARTICLES } from "./engine/look/particles.glsl.js";
37
+ /**
38
+ * Generic real-time fire: play a registered effect by name. Resolves when the
39
+ * animation has fully played out. A CONTINUOUS effect (one whose `.dope`
40
+ * declares `tempo.loop`, e.g. halo) loops seamlessly until the host calls the
41
+ * returned handle's `stop()`. The handle's `pause()`/`resume()` freeze and
42
+ * resume the timeline drift-free (parking a perpetual loop so it costs no
43
+ * battery; the conductor also auto-pauses on a hidden tab). SSR-safe (resolves
44
+ * immediately off-DOM). The effect must already be registered (import
45
+ * `@dopaminefx/effect-<name>` or the `@dopaminefx/effects` umbrella, or load one
46
+ * via `loadEffect`).
47
+ */
48
+ export declare function play(effect: string, options?: DopamineSuccessOptions): PlayHandle;
49
+ /** A prepared, manually-driven effect handle (offline capture / external clock). */
50
+ export interface PreparedEffect {
51
+ readonly durationMs: number;
52
+ /** Draw the frame at `elapsedMs` since the start. */
53
+ renderAt(elapsedMs: number): void;
54
+ /** Dispose the renderer *and* release the overlay. */
55
+ dispose(): void;
56
+ }
57
+ /**
58
+ * Generic prepared effect: mount the overlay and return a renderer you drive
59
+ * yourself via `renderAt(elapsedMs)`. Call `dispose()` when finished. Returns
60
+ * `null` in non-DOM environments.
61
+ */
62
+ export declare function prepare(effect: string, options?: DopamineSuccessOptions): PreparedEffect | null;
63
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}