@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,67 @@
1
+ /**
2
+ * `.dope` CONTENT + TYPOGRAPHY consumers (Phase 3).
3
+ *
4
+ * Phase 0–2 moved an effect's numeric/palette/tempo params + its icon geometry
5
+ * into the `.dope`. Phase 3 finishes the job for the last code-shaped data:
6
+ *
7
+ * - `content.words` / `content.checkToken` — Comic's affirmation pool + the
8
+ * checkmark sentinel, picked per-fire by seed.
9
+ * - `content.glyphBands` — Solarbloom's whimsy→check-glyph (face + char) bands.
10
+ * - `typography` — Comic's mood→face baselines + the whimsy/intensity CURVE
11
+ * table (skew/stretch/tracking/outlineLayers/extrude/jitter/roundness),
12
+ * evaluated with the mapping grammar (extended with mix/max/min).
13
+ *
14
+ * These resolvers reproduce the legacy `mood.ts` arithmetic EXACTLY (the legacy
15
+ * functions stay as the parity reference, just like the numeric path), so a
16
+ * built-in's output is byte-identical while reskinning (different words, font,
17
+ * curves) becomes pure `.dope` editing.
18
+ */
19
+ import { type ExprNode } from "./loader.js";
20
+ /**
21
+ * Deterministically pick one of `list` from a seed. Matches Comic's `pickWord`:
22
+ * `mulberry32(seed>>>0)()` → index. Same seed → same pick; un-pinned scatters.
23
+ */
24
+ export declare function pickFromList<T>(list: readonly T[], seed: number): T;
25
+ /**
26
+ * Pick a band by whimsy (0..1), splitting the slider into equal bands. Matches
27
+ * Solarbloom's `pickCheckGlyph`: `floor(w * n)` clamped to the last band.
28
+ */
29
+ export declare function pickBand<T>(bands: readonly T[], whimsy: number): T;
30
+ /** Per-mood typographic baselines (the `ComicBaseline` typographic fields). */
31
+ export interface TypographyMoodBaseline {
32
+ face: string;
33
+ skew: number;
34
+ tilt: number;
35
+ stretchX: number;
36
+ tracking: number;
37
+ roundness: number;
38
+ }
39
+ /** The `typography` section of a `.dope`. */
40
+ export interface DopeTypography {
41
+ /** Robust CSS fallback chain appended after the mood's primary face. */
42
+ fallbackStack: string;
43
+ /** Per-mood baselines, keyed by mood name. */
44
+ perMood: Record<string, TypographyMoodBaseline>;
45
+ /**
46
+ * Derived numeric fields, each an expression over `control` (intensity/whimsy)
47
+ * + `baseline` (the per-mood typographic baseline). String fields (fontStack)
48
+ * are assembled separately. clamp01/round flags mirror the param specs.
49
+ */
50
+ fields: Record<string, {
51
+ from: ExprNode;
52
+ clamp01?: boolean;
53
+ round?: boolean;
54
+ }>;
55
+ }
56
+ /** Resolved typography (the numeric fields + the assembled font stack). */
57
+ export interface ResolvedTypography {
58
+ fontStack: string;
59
+ [field: string]: number | string;
60
+ }
61
+ /**
62
+ * Evaluate a typography table for a mood + intensity + whimsy. Pure; the
63
+ * `baseline` context is the per-mood typographic baseline so a field expr can
64
+ * reference e.g. `{ "baseline": "stretchX" }` or `{ "baseline": "roundness" }`.
65
+ */
66
+ export declare function resolveTypography(typo: DopeTypography, mood: string, intensity: number, whimsy: number): ResolvedTypography;
67
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/framework/content.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKpE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAInE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,CAIlE;AAMD,+EAA+E;AAC/E,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,aAAa,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAChD;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAChF;AAED,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,kBAAkB,CAwBpB"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * `.dope` CONTENT + TYPOGRAPHY consumers (Phase 3).
3
+ *
4
+ * Phase 0–2 moved an effect's numeric/palette/tempo params + its icon geometry
5
+ * into the `.dope`. Phase 3 finishes the job for the last code-shaped data:
6
+ *
7
+ * - `content.words` / `content.checkToken` — Comic's affirmation pool + the
8
+ * checkmark sentinel, picked per-fire by seed.
9
+ * - `content.glyphBands` — Solarbloom's whimsy→check-glyph (face + char) bands.
10
+ * - `typography` — Comic's mood→face baselines + the whimsy/intensity CURVE
11
+ * table (skew/stretch/tracking/outlineLayers/extrude/jitter/roundness),
12
+ * evaluated with the mapping grammar (extended with mix/max/min).
13
+ *
14
+ * These resolvers reproduce the legacy `mood.ts` arithmetic EXACTLY (the legacy
15
+ * functions stay as the parity reference, just like the numeric path), so a
16
+ * built-in's output is byte-identical while reskinning (different words, font,
17
+ * curves) becomes pure `.dope` editing.
18
+ */
19
+ import { evalExpr } from "./loader.js";
20
+ import { mulberry32 } from "../engine/seed.js";
21
+ const clamp01 = (x) => (x < 0 ? 0 : x > 1 ? 1 : x);
22
+ /**
23
+ * Deterministically pick one of `list` from a seed. Matches Comic's `pickWord`:
24
+ * `mulberry32(seed>>>0)()` → index. Same seed → same pick; un-pinned scatters.
25
+ */
26
+ export function pickFromList(list, seed) {
27
+ const r = mulberry32(seed >>> 0)();
28
+ const idx = Math.min(list.length - 1, Math.floor(r * list.length));
29
+ return list[idx];
30
+ }
31
+ /**
32
+ * Pick a band by whimsy (0..1), splitting the slider into equal bands. Matches
33
+ * Solarbloom's `pickCheckGlyph`: `floor(w * n)` clamped to the last band.
34
+ */
35
+ export function pickBand(bands, whimsy) {
36
+ const w = clamp01(whimsy);
37
+ const idx = Math.min(bands.length - 1, Math.floor(w * bands.length));
38
+ return bands[idx];
39
+ }
40
+ /**
41
+ * Evaluate a typography table for a mood + intensity + whimsy. Pure; the
42
+ * `baseline` context is the per-mood typographic baseline so a field expr can
43
+ * reference e.g. `{ "baseline": "stretchX" }` or `{ "baseline": "roundness" }`.
44
+ */
45
+ export function resolveTypography(typo, mood, intensity, whimsy) {
46
+ // Degrade an undeclared mood to the first declared typography mood (not a
47
+ // hardcoded "celebratory"), matching the loader's own-default fallback.
48
+ const base = typo.perMood[mood] ?? typo.perMood[Object.keys(typo.perMood)[0]];
49
+ const ctx = {
50
+ controls: { intensity: clamp01(intensity), whimsy: clamp01(whimsy) },
51
+ // Only the numeric baselines are visible to the grammar.
52
+ baseline: {
53
+ skew: base.skew,
54
+ tilt: base.tilt,
55
+ stretchX: base.stretchX,
56
+ tracking: base.tracking,
57
+ roundness: base.roundness,
58
+ },
59
+ consts: {},
60
+ };
61
+ const out = { fontStack: `${base.face}, ${typo.fallbackStack}` };
62
+ for (const [name, spec] of Object.entries(typo.fields)) {
63
+ let v = evalExpr(spec.from, ctx);
64
+ if (spec.round)
65
+ v = Math.round(v);
66
+ if (spec.clamp01)
67
+ v = clamp01(v);
68
+ out[name] = v;
69
+ }
70
+ return out;
71
+ }
72
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/framework/content.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAA+B,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnE;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAI,IAAkB,EAAE,IAAY;IAC9D,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,GAAG,CAAE,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAI,KAAmB,EAAE,MAAc;IAC7D,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,OAAO,KAAK,CAAC,GAAG,CAAE,CAAC;AACrB,CAAC;AAoCD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAoB,EACpB,IAAY,EACZ,SAAiB,EACjB,MAAc;IAEd,0EAA0E;IAC1E,wEAAwE;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,CAAE,CAAC;IAChF,MAAM,GAAG,GAAY;QACnB,QAAQ,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE;QACpE,yDAAyD;QACzD,QAAQ,EAAE;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B;QACD,MAAM,EAAE,EAAE;KACX,CAAC;IACF,MAAM,GAAG,GAAuB,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;IACrF,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,KAAK;YAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,OAAO;YAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACjC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Generic DATA-DRIVEN pass factory — instantiates a pure-shader effect from
3
+ * `(dope, shader, hooks)` with no per-effect factory code.
4
+ *
5
+ * For a datafied effect the `.dope` carries everything the hand-written
6
+ * per-effect `PassConfig` used to: the per-frame logic (`tempo.frame`), the
7
+ * shadow height (`render.shadowHeightFrac`), the per-pass uniforms
8
+ * (`render.pass`), the SDF-sourced samplers (`binding.samplers[].outline`),
9
+ * the loop-cap consts (`render.consts`), the runner config
10
+ * (`render.config.usesOrigin`), the reduced-motion peak/hold
11
+ * (`tempo.reducedMotion`) and the uniform-binding contract (`binding`). This
12
+ * module derives the `PassConfig` from that data — uniform names by the same
13
+ * `name → u<Name>` convention `computeScalarBinds` applies, exceptions from
14
+ * the binding contract — so the only hand-written web source left for such an
15
+ * effect is its GLSL.
16
+ *
17
+ * The honest boundary stays honest: anything genuinely code-shaped (a sprite
18
+ * panel, frame arrays, a host-rasterized aux texture) is passed through
19
+ * `hooks`, the same seams `PassConfig` always had — and a hook overrides the
20
+ * derived `auxTextures`/`passUniforms` when both exist.
21
+ */
22
+ import { type DopeDoc } from "./loader.js";
23
+ import { type PassConfig, type PassParams } from "./pass-runner.js";
24
+ import { type PanelConfig, type PanelDraw } from "./panel-runner.js";
25
+ import { type RenderProgram } from "./programs.js";
26
+ import type { EffectFactory } from "./effect.js";
27
+ /** The code-shaped escape hatches a datafied effect may still need. */
28
+ export type DopePassHooks = Partial<Pick<PassConfig, "auxTextures" | "passUniforms" | "panel" | "frameArrays">> & {
29
+ /** Additional uniform names (beyond the derived set) the shader reads. */
30
+ extraUniforms?: readonly string[];
31
+ /**
32
+ * The Canvas2D draw for a PASS effect's dynamic sprite panel (`render.panel`
33
+ * with the doc still pass-shaped — e.g. solarbloom's motes). The `.dope`
34
+ * `render.panel` block supplies the unit + sampler; this hook supplies only
35
+ * the genuinely code-shaped draw. Ignored when `hooks.panel` is given whole.
36
+ */
37
+ panelDraw?: NonNullable<PassConfig["panel"]>["draw"];
38
+ };
39
+ /** The vertex + fragment GLSL pair (the per-effect look — code by design). */
40
+ export interface DopeShader {
41
+ vertex: string;
42
+ fragment: string;
43
+ }
44
+ /**
45
+ * Derive a {@link PassConfig} from a datafied `.dope` + its shader (+ optional
46
+ * code hooks). The derived contract is pinned by the per-effect dope-config
47
+ * vitests:
48
+ *
49
+ * - `uniforms`: every `render.params` key not in `binding.excludeParams` and
50
+ * not the scatter key → `u<Name>`; the scatter key contributes
51
+ * `binding.scatterWeb` when present (else it is not a shader uniform); every
52
+ * `binding.extras[].web`; every `binding.samplers[].web`; every
53
+ * `binding.arrays[].web` (the `frameArrays` uniform arrays); plus
54
+ * `hooks.extraUniforms`.
55
+ * - `bindings`: the scatter key → `scatterWeb` (or `null`), plus `null` for
56
+ * each excluded param that would otherwise auto-bind. (`style` and
57
+ * `durationMs` need no entry: `durationMs` is skipped by
58
+ * `computeScalarBinds`, and `style`'s conventional `uStyle` auto-bind is the
59
+ * same value the runner already sets as a standard uniform.)
60
+ * - `frame`: `tempo.frame.amp` + `tempo.frame.extras` evaluated per frame
61
+ * (extras keyed by canonical name, emitted under their `binding` web name).
62
+ * - `shadowHeightFrac`: `render.shadowHeightFrac` (bare number passes
63
+ * through; an expression is params-only — `{input}` throws).
64
+ * - `passUniforms`: `render.pass` evaluated ONCE PER PASS (canonical names →
65
+ * `binding` web names) over the resolved params + the pass-geometry inputs
66
+ * (`targetMinDimPx`, plus `sdfRange`/`sdfViewBoxW` from the first sampler
67
+ * with an `outline` source).
68
+ * - `auxTextures`: every `binding.samplers` entry with an `outline` whose
69
+ * baked SDF decodes → a `kind:"sdf"` spec at its `texture` unit, flipping
70
+ * its `on` extra to 1; absent/undecodable → analytic fallback.
71
+ * - `usesOrigin`: `render.config.usesOrigin`.
72
+ */
73
+ export declare function dopePassConfig(doc: DopeDoc, shader: DopeShader, hooks?: DopePassHooks): PassConfig;
74
+ /**
75
+ * Derive a {@link PanelConfig} (the Canvas2D-panel runner's config) from a
76
+ * datafied PANEL `.dope` + its shader + the one genuinely code-shaped piece —
77
+ * the per-frame Canvas2D `draw`. The derivation rules are the SAME as
78
+ * {@link dopePassConfig} (uniforms / bindings / `tempo.frame` /
79
+ * `render.shadowHeightFrac` / `render.pass`), with the panel runner's shape:
80
+ *
81
+ * - `panelSampler`: `render.panel.sampler` (required; `render.panel.texture`
82
+ * must be 0 — the panel runner binds the panel at TEXTURE0, the
83
+ * cross-platform panel slot).
84
+ * - `frame`: evaluated with `animMs := elapsedMs` — the panel runner never
85
+ * snaps "on twos" (declared as `render.config.stepping: "none"`).
86
+ * - `passUniforms`: `render.pass` over the resolved params + the pass inputs
87
+ * (`targetMinDimPx` from the targeted element box, `dpr`, and the SDF
88
+ * metadata when a sampler declares an outline).
89
+ */
90
+ export declare function dopePanelConfig(doc: DopeDoc, shader: DopeShader, draw: PanelDraw, hooks?: Pick<DopePassHooks, "extraUniforms">): PanelConfig;
91
+ /** Options for {@link registerDopeEffect}. */
92
+ export interface RegisterDopeEffectOptions {
93
+ /** Code-shaped escape hatches forwarded to {@link dopePassConfig}. */
94
+ hooks?: DopePassHooks;
95
+ /**
96
+ * The registered effect/program name. Defaults to the last segment of
97
+ * `doc.id` (e.g. `dopamine.success.aurora` → `aurora`); pass explicitly when
98
+ * the public name differs (e.g. `dopamine.success.verdict` → `inkstroke`).
99
+ */
100
+ name?: string;
101
+ /** Also register as a bundled program for `loadEffect()`. Default true. */
102
+ program?: boolean;
103
+ /**
104
+ * Compose non-numeric, code-shaped params on top of the loader bag — applied
105
+ * to the factory's `resolve` AND forwarded to the bundled program.
106
+ */
107
+ composeParams?: RenderProgram["composeParams"];
108
+ /** Override `tempo.reducedMotion`. */
109
+ reducedMotion?: {
110
+ peakMs?: number;
111
+ holdMs?: number;
112
+ };
113
+ }
114
+ /**
115
+ * Build + register a fully data-driven effect from `(dope, shader, hooks)`:
116
+ * `resolve` is the `.dope` loader (with `render.consts` and the binding's
117
+ * scatter key), `create` is the generic pass runner over the derived config,
118
+ * and `reducedMotion` comes from `tempo.reducedMotion`. Registers the
119
+ * `EffectFactory` (and, by default, a bundled program under the same name) and
120
+ * returns the factory — the whole per-effect web factory, datafied.
121
+ */
122
+ export declare function registerDopeEffect(doc: DopeDoc, shader: DopeShader, opts?: RegisterDopeEffectOptions): EffectFactory<PassParams>;
123
+ /**
124
+ * Build + register a data-driven Canvas2D-PANEL effect from
125
+ * `(dope, shader, draw)`: the same registration as {@link registerDopeEffect}
126
+ * but `create` is the generic PANEL runner over the {@link dopePanelConfig}
127
+ * derivation. The only hand-written web sources left for such an effect are
128
+ * its GLSL and the Canvas2D `draw` — the per-platform panel-draw seam.
129
+ */
130
+ export declare function registerDopePanelEffect(doc: DopeDoc, shader: DopeShader, draw: PanelDraw, opts?: RegisterDopeEffectOptions): EffectFactory<PassParams>;
131
+ //# sourceMappingURL=dope-pass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dope-pass.d.ts","sourceRoot":"","sources":["../../src/framework/dope-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAAiC,KAAK,OAAO,EAAoB,MAAM,aAAa,CAAC;AAE5F,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAuB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE1F,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAiB,aAAa,EAAgC,MAAM,aAAa,CAAC;AAE9F,uEAAuE;AACvE,MAAM,MAAM,aAAa,GAAG,OAAO,CACjC,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,aAAa,CAAC,CAC3E,GAAG;IACF,0EAA0E;IAC1E,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACtD,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,GAAE,aAAkB,GAAG,UAAU,CAoFtG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,EACf,KAAK,GAAE,IAAI,CAAC,aAAa,EAAE,eAAe,CAAM,GAC/C,WAAW,CAwDb;AAED,8CAA8C;AAC9C,MAAM,WAAW,yBAAyB;IACxC,sEAAsE;IACtE,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,sCAAsC;IACtC,aAAa,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,yBAA8B,GACnC,aAAa,CAAC,UAAU,CAAC,CAK3B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,EACf,IAAI,GAAE,yBAA8B,GACnC,aAAa,CAAC,UAAU,CAAC,CAK3B"}
@@ -0,0 +1,346 @@
1
+ /**
2
+ * Generic DATA-DRIVEN pass factory — instantiates a pure-shader effect from
3
+ * `(dope, shader, hooks)` with no per-effect factory code.
4
+ *
5
+ * For a datafied effect the `.dope` carries everything the hand-written
6
+ * per-effect `PassConfig` used to: the per-frame logic (`tempo.frame`), the
7
+ * shadow height (`render.shadowHeightFrac`), the per-pass uniforms
8
+ * (`render.pass`), the SDF-sourced samplers (`binding.samplers[].outline`),
9
+ * the loop-cap consts (`render.consts`), the runner config
10
+ * (`render.config.usesOrigin`), the reduced-motion peak/hold
11
+ * (`tempo.reducedMotion`) and the uniform-binding contract (`binding`). This
12
+ * module derives the `PassConfig` from that data — uniform names by the same
13
+ * `name → u<Name>` convention `computeScalarBinds` applies, exceptions from
14
+ * the binding contract — so the only hand-written web source left for such an
15
+ * effect is its GLSL.
16
+ *
17
+ * The honest boundary stays honest: anything genuinely code-shaped (a sprite
18
+ * panel, frame arrays, a host-rasterized aux texture) is passed through
19
+ * `hooks`, the same seams `PassConfig` always had — and a hook overrides the
20
+ * derived `auxTextures`/`passUniforms` when both exist.
21
+ */
22
+ import { decodeSdf } from "../engine/sdf.js";
23
+ import { evalFrameExpr, evalParamExpr, evalPassExpr } from "./frame-expr.js";
24
+ import { getOutline, resolveDopeParams } from "./loader.js";
25
+ import { cap } from "./pass-common.js";
26
+ import { createPassInstance, } from "./pass-runner.js";
27
+ import { createPanelInstance } from "./panel-runner.js";
28
+ import { registerEffect } from "./registry.js";
29
+ import { registerProgram } from "./programs.js";
30
+ /**
31
+ * The shared pass/panel derivation over a datafied `.dope`: the uniform list,
32
+ * the binding exceptions, the per-frame and per-pass expression tables and the
33
+ * declared SDF pass inputs — everything both `dopePassConfig` and
34
+ * `dopePanelConfig` read identically (the rules in the {@link dopePassConfig}
35
+ * doc comment).
36
+ */
37
+ function deriveDope(doc, extraUniforms) {
38
+ const binding = doc.binding ?? {};
39
+ const exclude = binding.excludeParams ?? [];
40
+ const scatterKey = binding.scatterKey ?? undefined;
41
+ const extraDefs = binding.extras ?? [];
42
+ const frameSpec = doc.tempo.frame;
43
+ if (!frameSpec)
44
+ throw new Error(`dope: ${doc.id} has no tempo.frame (not a datafied effect)`);
45
+ const loopPeriodMs = doc.tempo.loop?.periodMs;
46
+ const shadowSpec = doc.render.shadowHeightFrac;
47
+ if (shadowSpec === undefined) {
48
+ throw new Error(`dope: ${doc.id} has no render.shadowHeightFrac (not a datafied effect)`);
49
+ }
50
+ // --- uniforms ------------------------------------------------------------
51
+ const uniforms = new Set();
52
+ for (const name of Object.keys(doc.render.params)) {
53
+ if (exclude.includes(name) || name === scatterKey)
54
+ continue;
55
+ uniforms.add(cap(name));
56
+ }
57
+ if (scatterKey && binding.scatterWeb)
58
+ uniforms.add(binding.scatterWeb);
59
+ for (const e of extraDefs)
60
+ if (e.web)
61
+ uniforms.add(e.web);
62
+ for (const s of binding.samplers ?? [])
63
+ uniforms.add(typeof s === "string" ? s : s.web);
64
+ for (const a of binding.arrays ?? [])
65
+ uniforms.add(a.web);
66
+ for (const u of extraUniforms ?? [])
67
+ uniforms.add(u);
68
+ // --- bindings (exceptions to the `name → u<Name>` auto-bind) --------------
69
+ const bindings = {};
70
+ if (scatterKey)
71
+ bindings[scatterKey] = binding.scatterWeb ?? null;
72
+ for (const name of exclude) {
73
+ if (name === "style" || name === "durationMs")
74
+ continue; // see doc comment
75
+ bindings[name] = null;
76
+ }
77
+ // --- per-frame extras: canonical name → web uniform name ------------------
78
+ const extraExprs = Object.entries(frameSpec.extras ?? {}).map(([name, expr]) => {
79
+ const def = extraDefs.find((e) => e.name === name);
80
+ if (!def?.web) {
81
+ throw new Error(`dope: ${doc.id} tempo.frame.extras."${name}" has no binding.extras web name`);
82
+ }
83
+ return [def.web, expr];
84
+ });
85
+ // --- per-PASS uniforms (`render.pass`): canonical name → web uniform name --
86
+ // (a "note" key is documentation, not an expression — same convention as
87
+ // `binding.note`.)
88
+ const passExprs = Object.entries(doc.render.pass ?? {})
89
+ .filter(([name]) => name !== "note")
90
+ .map(([name, expr]) => {
91
+ const def = extraDefs.find((e) => e.name === name);
92
+ if (!def?.web) {
93
+ throw new Error(`dope: ${doc.id} render.pass."${name}" has no binding.extras web name`);
94
+ }
95
+ return [def.web, expr];
96
+ });
97
+ // SDF-sourced samplers: the first `outline` sampler supplies the pass-expr
98
+ // SDF inputs (declared metadata — readable even where the bitmap isn't bound).
99
+ const samplerDefs = (binding.samplers ?? []).filter((s) => typeof s !== "string");
100
+ const sdfOutline = samplerDefs.find((s) => s.outline);
101
+ const sdfSrc = sdfOutline ? getOutline(doc, sdfOutline.outline)?.sdf : undefined;
102
+ const sdfInputs = { range: sdfSrc?.range ?? 0, viewBoxW: sdfSrc?.viewBox?.[2] ?? 0 };
103
+ return { binding, frameSpec, loopPeriodMs, shadowSpec, uniforms, bindings, extraExprs, passExprs, sdfInputs };
104
+ }
105
+ /**
106
+ * Derive a {@link PassConfig} from a datafied `.dope` + its shader (+ optional
107
+ * code hooks). The derived contract is pinned by the per-effect dope-config
108
+ * vitests:
109
+ *
110
+ * - `uniforms`: every `render.params` key not in `binding.excludeParams` and
111
+ * not the scatter key → `u<Name>`; the scatter key contributes
112
+ * `binding.scatterWeb` when present (else it is not a shader uniform); every
113
+ * `binding.extras[].web`; every `binding.samplers[].web`; every
114
+ * `binding.arrays[].web` (the `frameArrays` uniform arrays); plus
115
+ * `hooks.extraUniforms`.
116
+ * - `bindings`: the scatter key → `scatterWeb` (or `null`), plus `null` for
117
+ * each excluded param that would otherwise auto-bind. (`style` and
118
+ * `durationMs` need no entry: `durationMs` is skipped by
119
+ * `computeScalarBinds`, and `style`'s conventional `uStyle` auto-bind is the
120
+ * same value the runner already sets as a standard uniform.)
121
+ * - `frame`: `tempo.frame.amp` + `tempo.frame.extras` evaluated per frame
122
+ * (extras keyed by canonical name, emitted under their `binding` web name).
123
+ * - `shadowHeightFrac`: `render.shadowHeightFrac` (bare number passes
124
+ * through; an expression is params-only — `{input}` throws).
125
+ * - `passUniforms`: `render.pass` evaluated ONCE PER PASS (canonical names →
126
+ * `binding` web names) over the resolved params + the pass-geometry inputs
127
+ * (`targetMinDimPx`, plus `sdfRange`/`sdfViewBoxW` from the first sampler
128
+ * with an `outline` source).
129
+ * - `auxTextures`: every `binding.samplers` entry with an `outline` whose
130
+ * baked SDF decodes → a `kind:"sdf"` spec at its `texture` unit, flipping
131
+ * its `on` extra to 1; absent/undecodable → analytic fallback.
132
+ * - `usesOrigin`: `render.config.usesOrigin`.
133
+ */
134
+ export function dopePassConfig(doc, shader, hooks = {}) {
135
+ const { binding, frameSpec, loopPeriodMs, shadowSpec, uniforms, bindings, extraExprs, passExprs, sdfInputs } = deriveDope(doc, hooks.extraUniforms);
136
+ const derivedPassUniforms = passExprs.length
137
+ ? (_canvas, params, targetPx, dpr) => {
138
+ const pass = {
139
+ targetMinDimPx: Math.min(targetPx.width, targetPx.height),
140
+ sdfRange: sdfInputs.range,
141
+ sdfViewBoxW: sdfInputs.viewBoxW,
142
+ dpr,
143
+ };
144
+ const out = {};
145
+ for (const [web, expr] of passExprs)
146
+ out[web] = evalPassExpr(expr, params, pass);
147
+ return out;
148
+ }
149
+ : undefined;
150
+ // The declarative dynamic-panel WIRING (`render.panel`): the unit + sampler
151
+ // are data; the Canvas2D draw is the code-shaped hook. (A whole `hooks.panel`
152
+ // still overrides, like the other hooks.)
153
+ const panelSpec = doc.render.panel;
154
+ const derivedPanel = panelSpec && hooks.panelDraw
155
+ ? { unit: panelSpec.texture ?? 0, sampler: panelSpec.sampler, draw: hooks.panelDraw }
156
+ : undefined;
157
+ // Declarative aux textures: each sampler with an `outline` whose baked SDF
158
+ // decodes becomes a kind:"sdf" spec (its `on` extra flips to 1 when bound);
159
+ // an absent/undecodable SDF contributes nothing — the analytic fallback.
160
+ const extraDefs = binding.extras ?? [];
161
+ const samplerDefs = (binding.samplers ?? []).filter((s) => typeof s !== "string");
162
+ const sdfAux = [];
163
+ for (const s of samplerDefs) {
164
+ if (!s.outline)
165
+ continue;
166
+ const baked = getOutline(doc, s.outline)?.sdf;
167
+ if (!baked)
168
+ continue;
169
+ try {
170
+ const onDef = s.on ? extraDefs.find((e) => e.name === s.on) : undefined;
171
+ sdfAux.push({
172
+ kind: "sdf",
173
+ unit: s.texture ?? 0,
174
+ sdf: decodeSdf(baked),
175
+ sampler: s.web,
176
+ onUniform: onDef?.web,
177
+ });
178
+ }
179
+ catch {
180
+ /* undecodable → analytic fallback */
181
+ }
182
+ }
183
+ const derivedAux = sdfAux.length ? () => sdfAux : undefined;
184
+ return {
185
+ vertex: shader.vertex,
186
+ fragment: shader.fragment,
187
+ uniforms: [...uniforms],
188
+ usesOrigin: doc.render.config?.usesOrigin ?? false,
189
+ loopPeriodMs,
190
+ bindings,
191
+ shadowHeightFrac: typeof shadowSpec === "number" ? shadowSpec : (params) => evalParamExpr(shadowSpec, params),
192
+ frame(info, params) {
193
+ // Loop clocks (0 without tempo.loop) — the SAME formula the runner uses
194
+ // for uLoopS/uPhase, so a `{input:"phase"}` amp matches the shader.
195
+ const loopMs = loopPeriodMs ? info.animMs % loopPeriodMs : 0;
196
+ const ctx = {
197
+ animMs: info.animMs,
198
+ life: info.life,
199
+ elapsedMs: info.elapsedMs,
200
+ params,
201
+ loopS: loopMs / 1000,
202
+ phase: loopPeriodMs ? loopMs / loopPeriodMs : 0,
203
+ };
204
+ const out = {
205
+ amp: evalFrameExpr(frameSpec.amp, ctx),
206
+ };
207
+ for (const [web, expr] of extraExprs)
208
+ out[web] = evalFrameExpr(expr, ctx);
209
+ return out;
210
+ },
211
+ auxTextures: hooks.auxTextures ?? derivedAux,
212
+ passUniforms: hooks.passUniforms ?? derivedPassUniforms,
213
+ panel: hooks.panel ?? derivedPanel,
214
+ frameArrays: hooks.frameArrays,
215
+ };
216
+ }
217
+ /**
218
+ * Derive a {@link PanelConfig} (the Canvas2D-panel runner's config) from a
219
+ * datafied PANEL `.dope` + its shader + the one genuinely code-shaped piece —
220
+ * the per-frame Canvas2D `draw`. The derivation rules are the SAME as
221
+ * {@link dopePassConfig} (uniforms / bindings / `tempo.frame` /
222
+ * `render.shadowHeightFrac` / `render.pass`), with the panel runner's shape:
223
+ *
224
+ * - `panelSampler`: `render.panel.sampler` (required; `render.panel.texture`
225
+ * must be 0 — the panel runner binds the panel at TEXTURE0, the
226
+ * cross-platform panel slot).
227
+ * - `frame`: evaluated with `animMs := elapsedMs` — the panel runner never
228
+ * snaps "on twos" (declared as `render.config.stepping: "none"`).
229
+ * - `passUniforms`: `render.pass` over the resolved params + the pass inputs
230
+ * (`targetMinDimPx` from the targeted element box, `dpr`, and the SDF
231
+ * metadata when a sampler declares an outline).
232
+ */
233
+ export function dopePanelConfig(doc, shader, draw, hooks = {}) {
234
+ const { frameSpec, shadowSpec, uniforms, bindings, extraExprs, passExprs, sdfInputs } = deriveDope(doc, hooks.extraUniforms);
235
+ const panelSpec = doc.render.panel;
236
+ if (!panelSpec)
237
+ throw new Error(`dope: ${doc.id} has no render.panel (not a panel effect)`);
238
+ if ((panelSpec.texture ?? 0) !== 0) {
239
+ throw new Error(`dope: ${doc.id} render.panel.texture must be 0 for a panel-kind effect (TEXTURE0 is the panel slot)`);
240
+ }
241
+ if (doc.tempo.loop)
242
+ throw new Error(`dope: ${doc.id} tempo.loop is not supported by the panel runner`);
243
+ const derivedPassUniforms = passExprs.length
244
+ ? (_canvas, params, dpr, targetPx) => {
245
+ const pass = {
246
+ targetMinDimPx: Math.min(targetPx.width, targetPx.height),
247
+ sdfRange: sdfInputs.range,
248
+ sdfViewBoxW: sdfInputs.viewBoxW,
249
+ dpr,
250
+ };
251
+ const out = {};
252
+ for (const [web, expr] of passExprs)
253
+ out[web] = evalPassExpr(expr, params, pass);
254
+ return out;
255
+ }
256
+ : undefined;
257
+ return {
258
+ vertex: shader.vertex,
259
+ fragment: shader.fragment,
260
+ uniforms: [...uniforms],
261
+ panelSampler: panelSpec.sampler,
262
+ bindings,
263
+ shadowHeightFrac: typeof shadowSpec === "number" ? shadowSpec : (params) => evalParamExpr(shadowSpec, params),
264
+ draw,
265
+ frame(info, params) {
266
+ // Panels never snap on twos (`render.config.stepping: "none"`), so the
267
+ // snapped clock IS the wall clock — `animMs := elapsedMs`.
268
+ const ctx = {
269
+ animMs: info.elapsedMs,
270
+ life: info.life,
271
+ elapsedMs: info.elapsedMs,
272
+ params,
273
+ loopS: 0,
274
+ phase: 0,
275
+ };
276
+ const out = {
277
+ amp: evalFrameExpr(frameSpec.amp, ctx),
278
+ };
279
+ for (const [web, expr] of extraExprs)
280
+ out[web] = evalFrameExpr(expr, ctx);
281
+ return out;
282
+ },
283
+ passUniforms: derivedPassUniforms,
284
+ };
285
+ }
286
+ /**
287
+ * Build + register a fully data-driven effect from `(dope, shader, hooks)`:
288
+ * `resolve` is the `.dope` loader (with `render.consts` and the binding's
289
+ * scatter key), `create` is the generic pass runner over the derived config,
290
+ * and `reducedMotion` comes from `tempo.reducedMotion`. Registers the
291
+ * `EffectFactory` (and, by default, a bundled program under the same name) and
292
+ * returns the factory — the whole per-effect web factory, datafied.
293
+ */
294
+ export function registerDopeEffect(doc, shader, opts = {}) {
295
+ const config = dopePassConfig(doc, shader, opts.hooks);
296
+ const create = (params, ctx) => createPassInstance(config, params, ctx);
297
+ return registerDerived(doc, create, opts);
298
+ }
299
+ /**
300
+ * Build + register a data-driven Canvas2D-PANEL effect from
301
+ * `(dope, shader, draw)`: the same registration as {@link registerDopeEffect}
302
+ * but `create` is the generic PANEL runner over the {@link dopePanelConfig}
303
+ * derivation. The only hand-written web sources left for such an effect are
304
+ * its GLSL and the Canvas2D `draw` — the per-platform panel-draw seam.
305
+ */
306
+ export function registerDopePanelEffect(doc, shader, draw, opts = {}) {
307
+ const config = dopePanelConfig(doc, shader, draw, { extraUniforms: opts.hooks?.extraUniforms });
308
+ const create = (params, ctx) => createPanelInstance(config, params, ctx);
309
+ return registerDerived(doc, create, opts);
310
+ }
311
+ /** The shared registration tail: resolve/reducedMotion/loop + the bundled program. */
312
+ function registerDerived(doc, create, opts) {
313
+ const scatterKey = doc.binding?.scatterKey;
314
+ if (!scatterKey)
315
+ throw new Error(`dope: ${doc.id} has no binding.scatterKey`);
316
+ const consts = doc.render.consts ?? {};
317
+ const name = opts.name ?? doc.id.split(".").pop();
318
+ const reducedMotion = opts.reducedMotion ?? doc.tempo.reducedMotion;
319
+ const factory = {
320
+ name,
321
+ resolve: (feeling) => {
322
+ const numeric = resolveDopeParams(doc, feeling, consts, scatterKey);
323
+ return (opts.composeParams
324
+ ? opts.composeParams(numeric, feeling)
325
+ : numeric);
326
+ },
327
+ create,
328
+ reducedMotion,
329
+ // The continuous-loop contract: the conductor re-arms at durationMs instead
330
+ // of tearing down (the host stops it via the returned handle).
331
+ loop: doc.tempo.loop ? { periodMs: doc.tempo.loop.periodMs } : undefined,
332
+ };
333
+ if (opts.program !== false) {
334
+ // Expose as a bundled program so loadEffect() can bind host-authored
335
+ // variants of this effect's .dope with no code.
336
+ registerProgram(name, {
337
+ create,
338
+ scatterKey,
339
+ consts,
340
+ reducedMotion,
341
+ ...(opts.composeParams ? { composeParams: opts.composeParams } : {}),
342
+ });
343
+ }
344
+ return registerEffect(factory);
345
+ }
346
+ //# sourceMappingURL=dope-pass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dope-pass.js","sourceRoot":"","sources":["../../src/framework/dope-pass.ts"],"names":[],"mappings":"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"}