@codexo/exojs 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +2 -4
  3. package/dist/esm/animation/Tween.d.ts.map +1 -1
  4. package/dist/esm/animation/Tween.js +0 -1
  5. package/dist/esm/animation/Tween.js.map +1 -1
  6. package/dist/esm/animation/TweenManager.d.ts +44 -5
  7. package/dist/esm/animation/TweenManager.d.ts.map +1 -1
  8. package/dist/esm/animation/TweenManager.js +57 -5
  9. package/dist/esm/animation/TweenManager.js.map +1 -1
  10. package/dist/esm/animation/TweenSequencer.d.ts +139 -0
  11. package/dist/esm/animation/TweenSequencer.d.ts.map +1 -0
  12. package/dist/esm/animation/TweenSequencer.js +305 -0
  13. package/dist/esm/animation/TweenSequencer.js.map +1 -0
  14. package/dist/esm/animation/index.d.ts +1 -0
  15. package/dist/esm/animation/index.d.ts.map +1 -1
  16. package/dist/esm/audio/Playable.d.ts +6 -1
  17. package/dist/esm/audio/Playable.d.ts.map +1 -1
  18. package/dist/esm/audio/WorkletEffect.d.ts +34 -20
  19. package/dist/esm/audio/WorkletEffect.d.ts.map +1 -1
  20. package/dist/esm/audio/WorkletEffect.js +92 -25
  21. package/dist/esm/audio/WorkletEffect.js.map +1 -1
  22. package/dist/esm/core/Application.d.ts +43 -5
  23. package/dist/esm/core/Application.d.ts.map +1 -1
  24. package/dist/esm/core/Application.js +83 -9
  25. package/dist/esm/core/Application.js.map +1 -1
  26. package/dist/esm/core/BuildInfo.js +2 -2
  27. package/dist/esm/core/Codec.d.ts +41 -0
  28. package/dist/esm/core/Codec.d.ts.map +1 -0
  29. package/dist/esm/core/Codec.js +79 -0
  30. package/dist/esm/core/Codec.js.map +1 -0
  31. package/dist/esm/core/FixedTimestep.d.ts +28 -0
  32. package/dist/esm/core/FixedTimestep.d.ts.map +1 -0
  33. package/dist/esm/core/FixedTimestep.js +62 -0
  34. package/dist/esm/core/FixedTimestep.js.map +1 -0
  35. package/dist/esm/core/Scene.d.ts +14 -0
  36. package/dist/esm/core/Scene.d.ts.map +1 -1
  37. package/dist/esm/core/Scene.js +18 -0
  38. package/dist/esm/core/Scene.js.map +1 -1
  39. package/dist/esm/core/SceneManager.d.ts +7 -0
  40. package/dist/esm/core/SceneManager.d.ts.map +1 -1
  41. package/dist/esm/core/SceneManager.js +20 -4
  42. package/dist/esm/core/SceneManager.js.map +1 -1
  43. package/dist/esm/core/SceneNode.d.ts +46 -7
  44. package/dist/esm/core/SceneNode.d.ts.map +1 -1
  45. package/dist/esm/core/SceneNode.js +73 -12
  46. package/dist/esm/core/SceneNode.js.map +1 -1
  47. package/dist/esm/core/Stage.d.ts +7 -0
  48. package/dist/esm/core/Stage.d.ts.map +1 -1
  49. package/dist/esm/core/SystemRegistry.d.ts +5 -0
  50. package/dist/esm/core/SystemRegistry.d.ts.map +1 -1
  51. package/dist/esm/core/SystemRegistry.js +10 -0
  52. package/dist/esm/core/SystemRegistry.js.map +1 -1
  53. package/dist/esm/core/index.d.ts +4 -0
  54. package/dist/esm/core/index.d.ts.map +1 -1
  55. package/dist/esm/core/logging.d.ts +34 -0
  56. package/dist/esm/core/logging.d.ts.map +1 -0
  57. package/dist/esm/core/logging.js +59 -0
  58. package/dist/esm/core/logging.js.map +1 -0
  59. package/dist/esm/core/serialization/commonFields.d.ts.map +1 -1
  60. package/dist/esm/core/serialization/commonFields.js +6 -0
  61. package/dist/esm/core/serialization/commonFields.js.map +1 -1
  62. package/dist/esm/core/serialization/renderingSerializers.d.ts.map +1 -1
  63. package/dist/esm/core/serialization/renderingSerializers.js +14 -5
  64. package/dist/esm/core/serialization/renderingSerializers.js.map +1 -1
  65. package/dist/esm/debug/BoundingBoxesLayer.d.ts.map +1 -1
  66. package/dist/esm/debug/BoundingBoxesLayer.js +2 -1
  67. package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -1
  68. package/dist/esm/debug/HitTestLayer.js +4 -4
  69. package/dist/esm/debug/HitTestLayer.js.map +1 -1
  70. package/dist/esm/debug/PerformanceLayer.js +1 -1
  71. package/dist/esm/debug/PerformanceLayer.js.map +1 -1
  72. package/dist/esm/debug/RenderPassInspectorLayer.js +2 -2
  73. package/dist/esm/debug/RenderPassInspectorLayer.js.map +1 -1
  74. package/dist/esm/index.js +7 -2
  75. package/dist/esm/index.js.map +1 -1
  76. package/dist/esm/input/Gamepad.d.ts +10 -0
  77. package/dist/esm/input/Gamepad.d.ts.map +1 -1
  78. package/dist/esm/input/Gamepad.js +12 -0
  79. package/dist/esm/input/Gamepad.js.map +1 -1
  80. package/dist/esm/input/InputManager.d.ts.map +1 -1
  81. package/dist/esm/input/InputManager.js +5 -0
  82. package/dist/esm/input/InputManager.js.map +1 -1
  83. package/dist/esm/input/InteractionManager.js +4 -4
  84. package/dist/esm/input/InteractionManager.js.map +1 -1
  85. package/dist/esm/math/AbstractVector.d.ts +4 -3
  86. package/dist/esm/math/AbstractVector.d.ts.map +1 -1
  87. package/dist/esm/math/AbstractVector.js +5 -4
  88. package/dist/esm/math/AbstractVector.js.map +1 -1
  89. package/dist/esm/math/ObservableVector.d.ts +2 -0
  90. package/dist/esm/math/ObservableVector.d.ts.map +1 -1
  91. package/dist/esm/math/ObservableVector.js +9 -0
  92. package/dist/esm/math/ObservableVector.js.map +1 -1
  93. package/dist/esm/math/Polygon.d.ts.map +1 -1
  94. package/dist/esm/math/Polygon.js +4 -1
  95. package/dist/esm/math/Polygon.js.map +1 -1
  96. package/dist/esm/math/collision-detection.d.ts.map +1 -1
  97. package/dist/esm/math/collision-detection.js +14 -14
  98. package/dist/esm/math/collision-detection.js.map +1 -1
  99. package/dist/esm/math/collision-primitives.d.ts +1 -1
  100. package/dist/esm/math/collision-primitives.d.ts.map +1 -1
  101. package/dist/esm/math/collision-primitives.js +4 -1
  102. package/dist/esm/math/collision-primitives.js.map +1 -1
  103. package/dist/esm/rendering/BackendTargetPass.d.ts +1 -1
  104. package/dist/esm/rendering/BackendTargetPass.d.ts.map +1 -1
  105. package/dist/esm/rendering/CallbackRenderPass.d.ts +14 -10
  106. package/dist/esm/rendering/CallbackRenderPass.d.ts.map +1 -1
  107. package/dist/esm/rendering/CallbackRenderPass.js +16 -11
  108. package/dist/esm/rendering/CallbackRenderPass.js.map +1 -1
  109. package/dist/esm/rendering/DrawContext.d.ts +48 -0
  110. package/dist/esm/rendering/DrawContext.d.ts.map +1 -0
  111. package/dist/esm/rendering/PassContext.d.ts +42 -0
  112. package/dist/esm/rendering/PassContext.d.ts.map +1 -0
  113. package/dist/esm/rendering/PassContext.js +48 -0
  114. package/dist/esm/rendering/PassContext.js.map +1 -0
  115. package/dist/esm/rendering/RenderBackend.d.ts +14 -0
  116. package/dist/esm/rendering/RenderBackend.d.ts.map +1 -1
  117. package/dist/esm/rendering/RenderNode.d.ts.map +1 -1
  118. package/dist/esm/rendering/RenderNode.js +2 -2
  119. package/dist/esm/rendering/RenderNode.js.map +1 -1
  120. package/dist/esm/rendering/RenderNodePass.d.ts +1 -1
  121. package/dist/esm/rendering/RenderNodePass.d.ts.map +1 -1
  122. package/dist/esm/rendering/RenderingContext.d.ts +47 -16
  123. package/dist/esm/rendering/RenderingContext.d.ts.map +1 -1
  124. package/dist/esm/rendering/RenderingContext.js +134 -36
  125. package/dist/esm/rendering/RenderingContext.js.map +1 -1
  126. package/dist/esm/rendering/TransformBuffer.d.ts +23 -0
  127. package/dist/esm/rendering/TransformBuffer.d.ts.map +1 -1
  128. package/dist/esm/rendering/TransformBuffer.js +58 -0
  129. package/dist/esm/rendering/TransformBuffer.js.map +1 -1
  130. package/dist/esm/rendering/View.d.ts +38 -0
  131. package/dist/esm/rendering/View.d.ts.map +1 -1
  132. package/dist/esm/rendering/View.js +37 -0
  133. package/dist/esm/rendering/View.js.map +1 -1
  134. package/dist/esm/rendering/filters/WebGpuShaderFilter.d.ts.map +1 -1
  135. package/dist/esm/rendering/filters/WebGpuShaderFilter.js +9 -2
  136. package/dist/esm/rendering/filters/WebGpuShaderFilter.js.map +1 -1
  137. package/dist/esm/rendering/material/MeshMaterial.d.ts +20 -1
  138. package/dist/esm/rendering/material/MeshMaterial.d.ts.map +1 -1
  139. package/dist/esm/rendering/material/MeshMaterial.js +17 -0
  140. package/dist/esm/rendering/material/MeshMaterial.js.map +1 -1
  141. package/dist/esm/rendering/material/SpriteMaterial.d.ts +20 -1
  142. package/dist/esm/rendering/material/SpriteMaterial.d.ts.map +1 -1
  143. package/dist/esm/rendering/material/SpriteMaterial.js +17 -0
  144. package/dist/esm/rendering/material/SpriteMaterial.js.map +1 -1
  145. package/dist/esm/rendering/plan/RenderEffectExecutor.d.ts.map +1 -1
  146. package/dist/esm/rendering/plan/RenderEffectExecutor.js +7 -2
  147. package/dist/esm/rendering/plan/RenderEffectExecutor.js.map +1 -1
  148. package/dist/esm/rendering/plan/RenderInstruction.d.ts +5 -2
  149. package/dist/esm/rendering/plan/RenderInstruction.d.ts.map +1 -1
  150. package/dist/esm/rendering/plan/RenderPlanBuilder.d.ts.map +1 -1
  151. package/dist/esm/rendering/plan/RenderPlanBuilder.js +23 -5
  152. package/dist/esm/rendering/plan/RenderPlanBuilder.js.map +1 -1
  153. package/dist/esm/rendering/plan/RenderScope.d.ts +7 -0
  154. package/dist/esm/rendering/plan/RenderScope.d.ts.map +1 -1
  155. package/dist/esm/rendering/primitives/Graphics.d.ts +17 -1
  156. package/dist/esm/rendering/primitives/Graphics.d.ts.map +1 -1
  157. package/dist/esm/rendering/primitives/Graphics.js +50 -15
  158. package/dist/esm/rendering/primitives/Graphics.js.map +1 -1
  159. package/dist/esm/rendering/public.d.ts +5 -5
  160. package/dist/esm/rendering/public.d.ts.map +1 -1
  161. package/dist/esm/rendering/sprite/AnimatedSprite.d.ts +57 -19
  162. package/dist/esm/rendering/sprite/AnimatedSprite.d.ts.map +1 -1
  163. package/dist/esm/rendering/sprite/AnimatedSprite.js +138 -31
  164. package/dist/esm/rendering/sprite/AnimatedSprite.js.map +1 -1
  165. package/dist/esm/rendering/sprite/Sprite.d.ts.map +1 -1
  166. package/dist/esm/rendering/sprite/Sprite.js +8 -0
  167. package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
  168. package/dist/esm/rendering/text/BitmapText.d.ts.map +1 -1
  169. package/dist/esm/rendering/text/BitmapText.js +2 -0
  170. package/dist/esm/rendering/text/BitmapText.js.map +1 -1
  171. package/dist/esm/rendering/text/HTMLText.d.ts.map +1 -1
  172. package/dist/esm/rendering/text/HTMLText.js +2 -2
  173. package/dist/esm/rendering/text/HTMLText.js.map +1 -1
  174. package/dist/esm/rendering/text/Text.d.ts.map +1 -1
  175. package/dist/esm/rendering/text/Text.js +2 -0
  176. package/dist/esm/rendering/text/Text.js.map +1 -1
  177. package/dist/esm/rendering/text/TextLayout.d.ts.map +1 -1
  178. package/dist/esm/rendering/text/TextLayout.js +2 -3
  179. package/dist/esm/rendering/text/TextLayout.js.map +1 -1
  180. package/dist/esm/rendering/types.d.ts +37 -13
  181. package/dist/esm/rendering/types.d.ts.map +1 -1
  182. package/dist/esm/rendering/types.js +37 -13
  183. package/dist/esm/rendering/types.js.map +1 -1
  184. package/dist/esm/rendering/webgl2/WebGl2BackdropBlendCompositor.d.ts +41 -0
  185. package/dist/esm/rendering/webgl2/WebGl2BackdropBlendCompositor.d.ts.map +1 -0
  186. package/dist/esm/rendering/webgl2/WebGl2BackdropBlendCompositor.js +222 -0
  187. package/dist/esm/rendering/webgl2/WebGl2BackdropBlendCompositor.js.map +1 -0
  188. package/dist/esm/rendering/webgl2/WebGl2Backend.d.ts +34 -1
  189. package/dist/esm/rendering/webgl2/WebGl2Backend.d.ts.map +1 -1
  190. package/dist/esm/rendering/webgl2/WebGl2Backend.js +108 -60
  191. package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
  192. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.d.ts.map +1 -1
  193. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js +50 -11
  194. package/dist/esm/rendering/webgl2/WebGl2TextRenderer.js.map +1 -1
  195. package/dist/esm/rendering/webgl2/glsl/backdrop-blend.frag.js +4 -0
  196. package/dist/esm/rendering/webgl2/glsl/backdrop-blend.frag.js.map +1 -0
  197. package/dist/esm/rendering/webgl2/glsl/backdrop-blend.vert.js +4 -0
  198. package/dist/esm/rendering/webgl2/glsl/backdrop-blend.vert.js.map +1 -0
  199. package/dist/esm/rendering/webgl2/glsl/text.vert.js +1 -1
  200. package/dist/esm/rendering/webgpu/WebGpuBackdropBlendCompositor.d.ts +72 -0
  201. package/dist/esm/rendering/webgpu/WebGpuBackdropBlendCompositor.d.ts.map +1 -0
  202. package/dist/esm/rendering/webgpu/WebGpuBackdropBlendCompositor.js +494 -0
  203. package/dist/esm/rendering/webgpu/WebGpuBackdropBlendCompositor.js.map +1 -0
  204. package/dist/esm/rendering/webgpu/WebGpuBackend.d.ts +27 -0
  205. package/dist/esm/rendering/webgpu/WebGpuBackend.d.ts.map +1 -1
  206. package/dist/esm/rendering/webgpu/WebGpuBackend.js +157 -60
  207. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  208. package/dist/esm/rendering/webgpu/WebGpuBlendState.d.ts.map +1 -1
  209. package/dist/esm/rendering/webgpu/WebGpuBlendState.js +5 -29
  210. package/dist/esm/rendering/webgpu/WebGpuBlendState.js.map +1 -1
  211. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.d.ts +2 -0
  212. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.d.ts.map +1 -1
  213. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +2 -1
  214. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
  215. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts +4 -0
  216. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.d.ts.map +1 -1
  217. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js +3 -1
  218. package/dist/esm/rendering/webgpu/WebGpuMeshRenderer.js.map +1 -1
  219. package/dist/esm/rendering/webgpu/WebGpuNineSliceSpriteRenderer.d.ts +2 -0
  220. package/dist/esm/rendering/webgpu/WebGpuNineSliceSpriteRenderer.d.ts.map +1 -1
  221. package/dist/esm/rendering/webgpu/WebGpuNineSliceSpriteRenderer.js +2 -1
  222. package/dist/esm/rendering/webgpu/WebGpuNineSliceSpriteRenderer.js.map +1 -1
  223. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.d.ts +8 -0
  224. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.d.ts.map +1 -1
  225. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.js +20 -0
  226. package/dist/esm/rendering/webgpu/WebGpuPassCoordinator.js.map +1 -1
  227. package/dist/esm/rendering/webgpu/WebGpuRepeatingSpriteRenderer.d.ts +6 -0
  228. package/dist/esm/rendering/webgpu/WebGpuRepeatingSpriteRenderer.d.ts.map +1 -1
  229. package/dist/esm/rendering/webgpu/WebGpuRepeatingSpriteRenderer.js +4 -1
  230. package/dist/esm/rendering/webgpu/WebGpuRepeatingSpriteRenderer.js.map +1 -1
  231. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.d.ts +2 -0
  232. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.d.ts.map +1 -1
  233. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js +2 -1
  234. package/dist/esm/rendering/webgpu/WebGpuSpriteRenderer.js.map +1 -1
  235. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.d.ts +2 -0
  236. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.d.ts.map +1 -1
  237. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.js +2 -1
  238. package/dist/esm/rendering/webgpu/WebGpuStencilClipper.js.map +1 -1
  239. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.d.ts +2 -0
  240. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.d.ts.map +1 -1
  241. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js +3 -2
  242. package/dist/esm/rendering/webgpu/WebGpuTextRenderer.js.map +1 -1
  243. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.d.ts +3 -1
  244. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.d.ts.map +1 -1
  245. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.js +29 -5
  246. package/dist/esm/rendering/webgpu/WebGpuTransformStorage.js.map +1 -1
  247. package/dist/esm/resources/Loader.d.ts +13 -0
  248. package/dist/esm/resources/Loader.d.ts.map +1 -1
  249. package/dist/esm/resources/Loader.js +67 -7
  250. package/dist/esm/resources/Loader.js.map +1 -1
  251. package/dist/esm/resources/coreAssetBindings.d.ts +11 -0
  252. package/dist/esm/resources/coreAssetBindings.d.ts.map +1 -1
  253. package/dist/esm/resources/coreAssetBindings.js +10 -2
  254. package/dist/esm/resources/coreAssetBindings.js.map +1 -1
  255. package/dist/esm/ui/ScrollContainer.d.ts +63 -0
  256. package/dist/esm/ui/ScrollContainer.d.ts.map +1 -0
  257. package/dist/esm/ui/ScrollContainer.js +99 -0
  258. package/dist/esm/ui/ScrollContainer.js.map +1 -0
  259. package/dist/esm/ui/Tooltip.d.ts +67 -0
  260. package/dist/esm/ui/Tooltip.d.ts.map +1 -0
  261. package/dist/esm/ui/Tooltip.js +133 -0
  262. package/dist/esm/ui/Tooltip.js.map +1 -0
  263. package/dist/esm/ui/index.d.ts +4 -0
  264. package/dist/esm/ui/index.d.ts.map +1 -1
  265. package/dist/exo.debug.esm.js +1 -1
  266. package/dist/exo.debug.esm.js.map +1 -1
  267. package/dist/exo.esm.js +1 -1
  268. package/dist/exo.esm.js.map +1 -1
  269. package/dist/exo.iife.js +45273 -0
  270. package/dist/exo.iife.js.map +1 -0
  271. package/dist/exo.iife.min.js +2 -0
  272. package/dist/exo.iife.min.js.map +1 -0
  273. package/package.json +15 -3
  274. package/dist/esm/rendering/Camera.d.ts +0 -34
  275. package/dist/esm/rendering/Camera.d.ts.map +0 -1
  276. package/dist/esm/rendering/Camera.js +0 -38
  277. package/dist/esm/rendering/Camera.js.map +0 -1
@@ -0,0 +1,305 @@
1
+ import { TweenState } from './types.js';
2
+
3
+ /**
4
+ * Lifecycle states of a {@link TweenSequencer}. Mirrors {@link TweenState}
5
+ * semantics: starts `Idle`, becomes `Active` on {@link TweenSequencer.start},
6
+ * and ends in `Complete` (all stages exhausted) or `Stopped` (cancelled via
7
+ * {@link TweenSequencer.stop}). `Paused` is reachable from `Active` only.
8
+ */
9
+ var TweenSequencerState;
10
+ (function (TweenSequencerState) {
11
+ TweenSequencerState["Idle"] = "idle";
12
+ TweenSequencerState["Active"] = "active";
13
+ TweenSequencerState["Paused"] = "paused";
14
+ TweenSequencerState["Complete"] = "complete";
15
+ TweenSequencerState["Stopped"] = "stopped";
16
+ })(TweenSequencerState || (TweenSequencerState = {}));
17
+ /**
18
+ * Composes multiple {@link Tween} instances into a multi-stage animation.
19
+ *
20
+ * Each stage added via {@link TweenSequencer.then} plays after the previous
21
+ * one finishes. Within a single stage, multiple tweens run simultaneously
22
+ * (parallel); the stage advances when **all** of them complete.
23
+ *
24
+ * Delay stages inserted via {@link TweenSequencer.wait} create a timed pause
25
+ * between stages without needing a dummy tween.
26
+ *
27
+ * The sequencer integrates with {@link TweenManager} via
28
+ * {@link TweenManager.addTicker} so it is driven automatically each frame.
29
+ * It can also be used stand-alone by calling {@link TweenSequencer.update}
30
+ * manually — in that mode the sequencer also advances its child tweens.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * app.tweens.createSequencer()
35
+ * .then(fadeIn)
36
+ * .wait(0.5)
37
+ * .then([moveLeft, scaleUp])
38
+ * .then(fadeOut)
39
+ * .onComplete(() => console.log('done!'))
40
+ * .start();
41
+ * ```
42
+ * @stable
43
+ */
44
+ class TweenSequencer {
45
+ _stages = [];
46
+ _state = TweenSequencerState.Idle;
47
+ _manager;
48
+ /** Index into `_stages` for the current pass (0-based). */
49
+ _currentStageIndex = 0;
50
+ /** 1 = forward through stages, -1 = reversed (yoyo pass). */
51
+ _direction = 1;
52
+ /** Remaining repeat cycles. -1 = infinite. */
53
+ _repeatCount = 0;
54
+ /** The value configured by {@link TweenSequencer.repeat}. Preserved for restart. */
55
+ _repeatTotal = 0;
56
+ _yoyo = false;
57
+ /** Accumulated seconds within the current delay stage. */
58
+ _delayElapsed = 0;
59
+ _onStartCb = null;
60
+ _onCompleteCb = null;
61
+ _startFired = false;
62
+ constructor(manager) {
63
+ this._manager = manager ?? null;
64
+ }
65
+ // ── State ────────────────────────────────────────────────────────────────
66
+ /** Current lifecycle state of the sequencer. */
67
+ get state() {
68
+ return this._state;
69
+ }
70
+ /**
71
+ * Playback progress in 0..1, advancing in discrete steps as each stage
72
+ * completes. Equals `1` when the entire sequence has finished.
73
+ */
74
+ get progress() {
75
+ const n = this._stages.length;
76
+ if (n === 0)
77
+ return 1;
78
+ return Math.min(this._currentStageIndex / n, 1);
79
+ }
80
+ // ── Builder ──────────────────────────────────────────────────────────────
81
+ /**
82
+ * Append a stage to the sequence.
83
+ *
84
+ * - **Single tween**: the stage plays that tween, then advances.
85
+ * - **Array of tweens**: all start simultaneously; the stage advances when
86
+ * every tween in the array has completed.
87
+ */
88
+ then(tween) {
89
+ const tweens = Array.isArray(tween) ? tween : [tween];
90
+ this._stages.push({ type: 'tweens', tweens });
91
+ return this;
92
+ }
93
+ /** Insert a fixed pause of `seconds` between stages. */
94
+ wait(seconds) {
95
+ this._stages.push({ type: 'delay', seconds });
96
+ return this;
97
+ }
98
+ /**
99
+ * Number of additional repeat cycles. -1 = infinite. Default 0 (plays once).
100
+ *
101
+ * `repeat(2)` plays the full sequence three times total (initial pass + 2
102
+ * repeats).
103
+ */
104
+ repeat(count) {
105
+ this._repeatTotal = count;
106
+ return this;
107
+ }
108
+ /**
109
+ * Reverse stage order on each repeat cycle. Only meaningful when combined
110
+ * with {@link TweenSequencer.repeat}.
111
+ */
112
+ yoyo(enabled = true) {
113
+ this._yoyo = enabled;
114
+ return this;
115
+ }
116
+ /**
117
+ * Register a callback fired once on the first {@link TweenSequencer.update}
118
+ * call after {@link TweenSequencer.start}.
119
+ */
120
+ onStart(cb) {
121
+ this._onStartCb = cb;
122
+ return this;
123
+ }
124
+ /**
125
+ * Register a callback fired when the sequence finishes naturally (all stages
126
+ * and repeat cycles exhausted). Does NOT fire when stopped via
127
+ * {@link TweenSequencer.stop}.
128
+ */
129
+ onComplete(cb) {
130
+ this._onCompleteCb = cb;
131
+ return this;
132
+ }
133
+ // ── Control ──────────────────────────────────────────────────────────────
134
+ /**
135
+ * Start (or restart) the sequence from stage 0. Resets all internal state
136
+ * and re-registers with the manager if one is attached.
137
+ */
138
+ start() {
139
+ this._state = TweenSequencerState.Active;
140
+ this._currentStageIndex = 0;
141
+ this._direction = 1;
142
+ this._repeatCount = this._repeatTotal;
143
+ this._startFired = false;
144
+ this._manager?.addTicker(this);
145
+ this._startCurrentStage();
146
+ return this;
147
+ }
148
+ /**
149
+ * Pause the sequence. Tweens in the current stage are also paused. The
150
+ * elapsed timer in delay stages is frozen.
151
+ */
152
+ pause() {
153
+ if (this._state === TweenSequencerState.Active) {
154
+ this._state = TweenSequencerState.Paused;
155
+ this._pauseCurrentStageTweens();
156
+ }
157
+ return this;
158
+ }
159
+ /** Resume a paused sequence (and its current-stage tweens) from where they left off. */
160
+ resume() {
161
+ if (this._state === TweenSequencerState.Paused) {
162
+ this._state = TweenSequencerState.Active;
163
+ this._resumeCurrentStageTweens();
164
+ }
165
+ return this;
166
+ }
167
+ /**
168
+ * Stop the sequence without finishing. Active tweens are stopped.
169
+ * {@link TweenSequencer.onComplete} does NOT fire. The sequencer is removed
170
+ * from its manager if one is assigned.
171
+ */
172
+ stop() {
173
+ if (this._state === TweenSequencerState.Active || this._state === TweenSequencerState.Paused) {
174
+ this._state = TweenSequencerState.Stopped;
175
+ this._stopCurrentStageTweens();
176
+ this._manager?.removeTicker(this);
177
+ }
178
+ return this;
179
+ }
180
+ // ── Ticker ───────────────────────────────────────────────────────────────
181
+ /**
182
+ * Advance the sequencer by `deltaSeconds`. Called automatically by the
183
+ * attached {@link TweenManager} each frame. When used stand-alone (no
184
+ * manager), call this manually and child tweens will also be advanced.
185
+ */
186
+ update(deltaSeconds) {
187
+ if (this._state !== TweenSequencerState.Active)
188
+ return;
189
+ if (!this._startFired) {
190
+ this._startFired = true;
191
+ this._onStartCb?.();
192
+ }
193
+ if (this._stages.length === 0) {
194
+ this._finish();
195
+ return;
196
+ }
197
+ const stageIndex = this._getActualStageIndex();
198
+ const stage = this._stages[stageIndex];
199
+ if (stage === undefined)
200
+ return;
201
+ if (stage.type === 'delay') {
202
+ this._delayElapsed += deltaSeconds;
203
+ if (this._delayElapsed >= stage.seconds) {
204
+ this._advanceStage();
205
+ }
206
+ }
207
+ else {
208
+ // In stand-alone mode (no manager), the sequencer ticks tweens itself.
209
+ if (this._manager === null) {
210
+ for (const tween of stage.tweens) {
211
+ if (tween.state === TweenState.Active) {
212
+ tween.update(deltaSeconds);
213
+ }
214
+ }
215
+ }
216
+ // Advance as soon as every tween in this stage has settled.
217
+ const allDone = stage.tweens.every(t => t.state === TweenState.Complete || t.state === TweenState.Stopped);
218
+ if (allDone) {
219
+ this._advanceStage();
220
+ }
221
+ }
222
+ }
223
+ // ── Private helpers ──────────────────────────────────────────────────────
224
+ /**
225
+ * Map the logical `_currentStageIndex` to the real index in `_stages`,
226
+ * accounting for yoyo reversal.
227
+ */
228
+ _getActualStageIndex() {
229
+ if (this._direction === 1)
230
+ return this._currentStageIndex;
231
+ return this._stages.length - 1 - this._currentStageIndex;
232
+ }
233
+ _startCurrentStage() {
234
+ const stageIndex = this._getActualStageIndex();
235
+ const stage = this._stages[stageIndex];
236
+ if (stage === undefined)
237
+ return;
238
+ this._delayElapsed = 0;
239
+ if (stage.type === 'tweens') {
240
+ for (const tween of stage.tweens) {
241
+ if (this._manager !== null) {
242
+ // Register with manager so the manager ticks it each frame.
243
+ this._manager.add(tween);
244
+ }
245
+ tween.start();
246
+ }
247
+ }
248
+ // Delay stages need only the elapsed counter reset (done above).
249
+ }
250
+ _advanceStage() {
251
+ this._currentStageIndex++;
252
+ if (this._currentStageIndex >= this._stages.length) {
253
+ // All stages in this pass are done.
254
+ const hasMoreRepeats = this._repeatCount === -1 || this._repeatCount > 0;
255
+ if (hasMoreRepeats) {
256
+ if (this._repeatCount !== -1) {
257
+ this._repeatCount--;
258
+ }
259
+ if (this._yoyo) {
260
+ this._direction = this._direction === 1 ? -1 : 1;
261
+ }
262
+ this._currentStageIndex = 0;
263
+ this._startCurrentStage();
264
+ }
265
+ else {
266
+ this._finish();
267
+ }
268
+ }
269
+ else {
270
+ this._startCurrentStage();
271
+ }
272
+ }
273
+ _finish() {
274
+ this._state = TweenSequencerState.Complete;
275
+ this._manager?.removeTicker(this);
276
+ this._onCompleteCb?.();
277
+ }
278
+ _getCurrentStageTweens() {
279
+ if (this._stages.length === 0)
280
+ return [];
281
+ const stageIndex = this._getActualStageIndex();
282
+ const stage = this._stages[stageIndex];
283
+ if (stage?.type === 'tweens')
284
+ return stage.tweens;
285
+ return [];
286
+ }
287
+ _pauseCurrentStageTweens() {
288
+ for (const tween of this._getCurrentStageTweens()) {
289
+ tween.pause();
290
+ }
291
+ }
292
+ _resumeCurrentStageTweens() {
293
+ for (const tween of this._getCurrentStageTweens()) {
294
+ tween.resume();
295
+ }
296
+ }
297
+ _stopCurrentStageTweens() {
298
+ for (const tween of this._getCurrentStageTweens()) {
299
+ tween.stop();
300
+ }
301
+ }
302
+ }
303
+
304
+ export { TweenSequencer, TweenSequencerState };
305
+ //# sourceMappingURL=TweenSequencer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TweenSequencer.js","sources":["../../../../src/animation/TweenSequencer.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAgBA;;;;;AAKG;IACS;AAAZ,CAAA,UAAY,mBAAmB,EAAA;AAC7B,IAAA,mBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACjB,IAAA,mBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB,IAAA,mBAAA,CAAA,SAAA,CAAA,GAAA,SAAmB;AACrB,CAAC,EANW,mBAAmB,KAAnB,mBAAmB,GAAA,EAAA,CAAA,CAAA;AAQ/B;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;MACU,cAAc,CAAA;IACR,OAAO,GAAY,EAAE;AAC9B,IAAA,MAAM,GAAwB,mBAAmB,CAAC,IAAI;AAC7C,IAAA,QAAQ;;IAGjB,kBAAkB,GAAG,CAAC;;IAGtB,UAAU,GAAW,CAAC;;IAGtB,YAAY,GAAG,CAAC;;IAEhB,YAAY,GAAG,CAAC;IAChB,KAAK,GAAG,KAAK;;IAGb,aAAa,GAAG,CAAC;IAEjB,UAAU,GAAwB,IAAI;IACtC,aAAa,GAAwB,IAAI;IACzC,WAAW,GAAG,KAAK;AAE3B,IAAA,WAAA,CAAmB,OAAsB,EAAA;AACvC,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,IAAI;IACjC;;;AAKA,IAAA,IAAW,KAAK,GAAA;QACd,OAAO,IAAI,CAAC,MAAM;IACpB;AAEA;;;AAGG;AACH,IAAA,IAAW,QAAQ,GAAA;AACjB,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM;QAC7B,IAAI,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,CAAC;AACrB,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,GAAG,CAAC,EAAE,CAAC,CAAC;IACjD;;AAIA;;;;;;AAMG;AACI,IAAA,IAAI,CAAC,KAAsB,EAAA;AAChC,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC;AACrD,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AAC7C,QAAA,OAAO,IAAI;IACb;;AAGO,IAAA,IAAI,CAAC,OAAe,EAAA;AACzB,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC7C,QAAA,OAAO,IAAI;IACb;AAEA;;;;;AAKG;AACI,IAAA,MAAM,CAAC,KAAa,EAAA;AACzB,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,OAAO,IAAI;IACb;AAEA;;;AAGG;IACI,IAAI,CAAC,OAAO,GAAG,IAAI,EAAA;AACxB,QAAA,IAAI,CAAC,KAAK,GAAG,OAAO;AACpB,QAAA,OAAO,IAAI;IACb;AAEA;;;AAGG;AACI,IAAA,OAAO,CAAC,EAAc,EAAA;AAC3B,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE;AACpB,QAAA,OAAO,IAAI;IACb;AAEA;;;;AAIG;AACI,IAAA,UAAU,CAAC,EAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,aAAa,GAAG,EAAE;AACvB,QAAA,OAAO,IAAI;IACb;;AAIA;;;AAGG;IACI,KAAK,GAAA;AACV,QAAA,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM;AACxC,QAAA,IAAI,CAAC,kBAAkB,GAAG,CAAC;AAC3B,QAAA,IAAI,CAAC,UAAU,GAAG,CAAC;AACnB,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY;AACrC,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;AACxB,QAAA,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,kBAAkB,EAAE;AACzB,QAAA,OAAO,IAAI;IACb;AAEA;;;AAGG;IACI,KAAK,GAAA;QACV,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM,EAAE;AAC9C,YAAA,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM;YACxC,IAAI,CAAC,wBAAwB,EAAE;QACjC;AACA,QAAA,OAAO,IAAI;IACb;;IAGO,MAAM,GAAA;QACX,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM,EAAE;AAC9C,YAAA,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM;YACxC,IAAI,CAAC,yBAAyB,EAAE;QAClC;AACA,QAAA,OAAO,IAAI;IACb;AAEA;;;;AAIG;IACI,IAAI,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM,EAAE;AAC5F,YAAA,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,OAAO;YACzC,IAAI,CAAC,uBAAuB,EAAE;AAC9B,YAAA,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC;QACnC;AACA,QAAA,OAAO,IAAI;IACb;;AAIA;;;;AAIG;AACI,IAAA,MAAM,CAAC,YAAoB,EAAA;AAChC,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM;YAAE;AAEhD,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AACrB,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;AACvB,YAAA,IAAI,CAAC,UAAU,IAAI;QACrB;QAEA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;YAC7B,IAAI,CAAC,OAAO,EAAE;YACd;QACF;AAEA,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,EAAE;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QACtC,IAAI,KAAK,KAAK,SAAS;YAAE;AAEzB,QAAA,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE;AAC1B,YAAA,IAAI,CAAC,aAAa,IAAI,YAAY;YAClC,IAAI,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,OAAO,EAAE;gBACvC,IAAI,CAAC,aAAa,EAAE;YACtB;QACF;aAAO;;AAEL,YAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE;AAC1B,gBAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE;oBAChC,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,CAAC,MAAM,EAAE;AACrC,wBAAA,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;oBAC5B;gBACF;YACF;;AAGA,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,OAAO,CAAC;YAE1G,IAAI,OAAO,EAAE;gBACX,IAAI,CAAC,aAAa,EAAE;YACtB;QACF;IACF;;AAIA;;;AAGG;IACK,oBAAoB,GAAA;AAC1B,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,kBAAkB;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,kBAAkB;IAC1D;IAEQ,kBAAkB,GAAA;AACxB,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,EAAE;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QACtC,IAAI,KAAK,KAAK,SAAS;YAAE;AAEzB,QAAA,IAAI,CAAC,aAAa,GAAG,CAAC;AAEtB,QAAA,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;AAC3B,YAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE;AAChC,gBAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE;;AAE1B,oBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;gBAC1B;gBACA,KAAK,CAAC,KAAK,EAAE;YACf;QACF;;IAEF;IAEQ,aAAa,GAAA;QACnB,IAAI,CAAC,kBAAkB,EAAE;QAEzB,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;;AAElD,YAAA,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,KAAK,EAAE,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC;YAExE,IAAI,cAAc,EAAE;AAClB,gBAAA,IAAI,IAAI,CAAC,YAAY,KAAK,EAAE,EAAE;oBAC5B,IAAI,CAAC,YAAY,EAAE;gBACrB;AAEA,gBAAA,IAAI,IAAI,CAAC,KAAK,EAAE;AACd,oBAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;gBAClD;AAEA,gBAAA,IAAI,CAAC,kBAAkB,GAAG,CAAC;gBAC3B,IAAI,CAAC,kBAAkB,EAAE;YAC3B;iBAAO;gBACL,IAAI,CAAC,OAAO,EAAE;YAChB;QACF;aAAO;YACL,IAAI,CAAC,kBAAkB,EAAE;QAC3B;IACF;IAEQ,OAAO,GAAA;AACb,QAAA,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,QAAQ;AAC1C,QAAA,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC;AACjC,QAAA,IAAI,CAAC,aAAa,IAAI;IACxB;IAEQ,sBAAsB,GAAA;AAC5B,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,EAAE;AACxC,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,EAAE;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;AACtC,QAAA,IAAI,KAAK,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,MAAM;AACjD,QAAA,OAAO,EAAE;IACX;IAEQ,wBAAwB,GAAA;QAC9B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,sBAAsB,EAAE,EAAE;YACjD,KAAK,CAAC,KAAK,EAAE;QACf;IACF;IAEQ,yBAAyB,GAAA;QAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,sBAAsB,EAAE,EAAE;YACjD,KAAK,CAAC,MAAM,EAAE;QAChB;IACF;IAEQ,uBAAuB,GAAA;QAC7B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,sBAAsB,EAAE,EAAE;YACjD,KAAK,CAAC,IAAI,EAAE;QACd;IACF;AACD;;;;"}
@@ -2,6 +2,7 @@ export type { EasingFunction } from './Easing';
2
2
  export { Ease } from './Easing';
3
3
  export { Tween } from './Tween';
4
4
  export { TweenManager } from './TweenManager';
5
+ export { TweenSequencer, TweenSequencerState } from './TweenSequencer';
5
6
  export type { TweenLifecycleCallback, TweenUpdateCallback } from './types';
6
7
  export { TweenState } from './types';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/animation/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/animation/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvE,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
@@ -81,7 +81,12 @@ export interface RatePitched {
81
81
  /** A voice that can be positioned in 2D space and optionally track a node. */
82
82
  export interface Spatializable {
83
83
  /** World-space position of the source, or `null` when not spatialized. */
84
- position: Vector | null;
84
+ get position(): Vector | null;
85
+ /** Accepts any `{ x, y }` point — implementations copy the values. */
86
+ set position(value: Vector | {
87
+ x: number;
88
+ y: number;
89
+ } | null);
85
90
  /**
86
91
  * Track a {@link SceneNode}: the voice reads the node's global translation
87
92
  * each frame. Pass `null` to stop following and fall back to
@@ -1 +1 @@
1
- {"version":3,"file":"Playable.d.ts","sourceRoot":"","sources":["../../../src/audio/Playable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,KAAK;IACpB;;;;OAIG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,6EAA6E;IAC7E,GAAG,EAAE,QAAQ,CAAC;IACd;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,oGAAoG;IACpG,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CACzC;AAED,oDAAoD;AACpD,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,uDAAuD;AACvD,MAAM,WAAW,QAAQ;IACvB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,qCAAqC;AACrC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;;;OAOG;IACH,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,GAAG,KAAK,CAAC;CAClE"}
1
+ {"version":3,"file":"Playable.d.ts","sourceRoot":"","sources":["../../../src/audio/Playable.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,26 @@
1
1
  import { AudioEffect } from '#audio/AudioEffect';
2
2
  /**
3
3
  * Base class for filters implemented as AudioWorkletProcessors. Subclasses
4
- * declare the worklet's name, source code, and node options; this class
5
- * handles the async lifecycle.
4
+ * declare the worklet's name, source code, and node options; this class owns
5
+ * the async lifecycle AND the dry/wet gain staging.
6
6
  *
7
- * Stable input/output nodes (GainNodes) are created immediately on setup.
8
- * While the worklet loads asynchronously, audio passes through directly
9
- * (effectively bypassing the filter for ~10-50ms during initial load).
10
- * Once the worklet loads, it's inserted into the chain and audio routes
11
- * through it.
12
- *
13
- * Subclasses can override `_onWorkletReady` to perform additional wiring
14
- * (e.g., sidechain inputs).
7
+ * Stable input/output nodes are created immediately. The worklet emits a pure
8
+ * wet signal; the base mixes it against the dry signal via `_dryGain`/`_wetGain`
9
+ * (`dryGain = 1 - wet`, `wetGain = wet * _wetMakeupGain`). An optional
10
+ * `_dryDelay` time-aligns the dry path with the worklet's algorithmic latency.
11
+ * While the worklet loads, the wet path is silent and dry passes at unity, so
12
+ * the effect is a clean passthrough (no volume dip) until it is ready.
15
13
  * @advanced
16
14
  */
17
15
  export declare abstract class WorkletEffect extends AudioEffect {
18
16
  protected _inputGain: GainNode | null;
19
17
  protected _outputGain: GainNode | null;
18
+ protected _dryGain: GainNode | null;
19
+ protected _wetGain: GainNode | null;
20
+ protected _dryDelay: DelayNode | null;
20
21
  protected _workletNode: AudioWorkletNode | null;
21
22
  protected _ready: Promise<void> | null;
23
+ protected _wet: number;
22
24
  private readonly _onAudioContextReady;
23
25
  /** The processor name registered via `registerProcessor()` in the worklet source. */
24
26
  protected abstract get _workletName(): string;
@@ -26,26 +28,38 @@ export declare abstract class WorkletEffect extends AudioEffect {
26
28
  protected abstract get _workletSource(): string;
27
29
  /** AudioWorkletNode constructor options. Default: 1 input, 1 output. */
28
30
  protected get _workletOptions(): AudioWorkletNodeOptions;
31
+ /**
32
+ * Dry-path delay in seconds, time-aligning the dry signal with the worklet's
33
+ * algorithmic latency so intermediate `wet` values do not comb-filter.
34
+ * Default 0 (no delay). Override in subclasses with buffering latency.
35
+ */
36
+ protected get _dryLatencySeconds(): number;
37
+ /** Static makeup multiplier folded into the wet path (`wetGain = wet * this`). Default 1. */
38
+ protected get _wetMakeupGain(): number;
39
+ /**
40
+ * The audio context's sample rate in Hz, or 48000 if the context is not yet
41
+ * available. Populated as soon as the audio context is ready (i.e. once
42
+ * `_setup` runs). Safe to read from `_dryLatencySeconds`.
43
+ */
44
+ protected get _sampleRate(): number;
29
45
  constructor();
30
46
  get inputNode(): AudioNode;
31
47
  get outputNode(): AudioNode;
32
- /**
33
- * Resolves once the underlying worklet is loaded and inserted into the
34
- * audio chain. Use this if you need to wait before applying parameters
35
- * that depend on the worklet node.
36
- */
48
+ /** Wet (processed) mix level, 0..1. The dry level is automatically `1 - wet`. Ramped smoothly. */
49
+ get wet(): number;
50
+ set wet(value: number);
51
+ /** Resolves once the worklet is loaded and inserted into the wet path. */
37
52
  get ready(): Promise<void>;
38
53
  /** Disconnects all nodes, cancels any pending worklet load, and releases resources. */
39
54
  destroy(): void;
40
55
  /**
41
- * Subclass hook — called once when the worklet has loaded and the
42
- * AudioWorkletNode is inserted into the chain. Use this for additional
43
- * wiring (e.g., connecting a sidechain input).
56
+ * Subclass hook — called once the worklet is loaded and inserted into the
57
+ * wet path. Use for additional wiring (e.g. a sidechain input).
44
58
  */
45
59
  protected _onWorkletReady?(audioContext: AudioContext): void;
46
60
  /**
47
- * Ramps an `AudioParam` on the underlying `AudioWorkletNode` to `value`
48
- * using a short exponential ramp. No-ops if the worklet is not yet loaded.
61
+ * Ramps an `AudioParam` on the underlying `AudioWorkletNode` to `value` using
62
+ * a short exponential ramp. No-ops if the worklet is not yet loaded.
49
63
  * @internal
50
64
  */
51
65
  protected _setAudioParam(name: string, value: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"WorkletEffect.d.ts","sourceRoot":"","sources":["../../../src/audio/WorkletEffect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;;;GAcG;AACH,8BAAsB,aAAc,SAAQ,WAAW;IACrD,SAAS,CAAC,UAAU,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC7C,SAAS,CAAC,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC9C,SAAS,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACvD,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC9C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAGnC;IAEF,qFAAqF;IACrF,SAAS,CAAC,QAAQ,KAAK,YAAY,IAAI,MAAM,CAAC;IAC9C,2DAA2D;IAC3D,SAAS,CAAC,QAAQ,KAAK,cAAc,IAAI,MAAM,CAAC;IAChD,wEAAwE;IACxE,SAAS,KAAK,eAAe,IAAI,uBAAuB,CAEvD;;IAWD,IAAW,SAAS,IAAI,SAAS,CAKhC;IAED,IAAW,UAAU,IAAI,SAAS,CAKjC;IAED;;;;OAIG;IACH,IAAoB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzC;IAED,uFAAuF;IACvE,OAAO,IAAI,IAAI;IAW/B;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAE5D;;;;OAIG;IACH,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3D,OAAO,CAAC,MAAM;CAyBf"}
1
+ {"version":3,"file":"WorkletEffect.d.ts","sourceRoot":"","sources":["../../../src/audio/WorkletEffect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;GAYG;AACH,8BAAsB,aAAc,SAAQ,WAAW;IACrD,SAAS,CAAC,UAAU,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC7C,SAAS,CAAC,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC9C,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC3C,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAC3C,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC7C,SAAS,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACvD,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC9C,SAAS,CAAC,IAAI,SAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAGnC;IAEF,qFAAqF;IACrF,SAAS,CAAC,QAAQ,KAAK,YAAY,IAAI,MAAM,CAAC;IAC9C,2DAA2D;IAC3D,SAAS,CAAC,QAAQ,KAAK,cAAc,IAAI,MAAM,CAAC;IAChD,wEAAwE;IACxE,SAAS,KAAK,eAAe,IAAI,uBAAuB,CAEvD;IAED;;;;OAIG;IACH,SAAS,KAAK,kBAAkB,IAAI,MAAM,CAEzC;IAED,6FAA6F;IAC7F,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED;;;;OAIG;IACH,SAAS,KAAK,WAAW,IAAI,MAAM,CAElC;;IAWD,IAAW,SAAS,IAAI,SAAS,CAKhC;IAED,IAAW,UAAU,IAAI,SAAS,CAKjC;IAED,kGAAkG;IAClG,IAAW,GAAG,IAAI,MAAM,CAEvB;IAED,IAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAO3B;IAED,0EAA0E;IAC1E,IAAoB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzC;IAED,uFAAuF;IACvE,OAAO,IAAI,IAAI;IAiB/B;;;OAGG;IACH,SAAS,CAAC,eAAe,CAAC,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAE5D;;;;OAIG;IACH,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3D,OAAO,CAAC,MAAM;CA6Df"}
@@ -4,24 +4,26 @@ import { registerAudioWorkletProcessor } from './worklet/registerWorklet.js';
4
4
 
5
5
  /**
6
6
  * Base class for filters implemented as AudioWorkletProcessors. Subclasses
7
- * declare the worklet's name, source code, and node options; this class
8
- * handles the async lifecycle.
7
+ * declare the worklet's name, source code, and node options; this class owns
8
+ * the async lifecycle AND the dry/wet gain staging.
9
9
  *
10
- * Stable input/output nodes (GainNodes) are created immediately on setup.
11
- * While the worklet loads asynchronously, audio passes through directly
12
- * (effectively bypassing the filter for ~10-50ms during initial load).
13
- * Once the worklet loads, it's inserted into the chain and audio routes
14
- * through it.
15
- *
16
- * Subclasses can override `_onWorkletReady` to perform additional wiring
17
- * (e.g., sidechain inputs).
10
+ * Stable input/output nodes are created immediately. The worklet emits a pure
11
+ * wet signal; the base mixes it against the dry signal via `_dryGain`/`_wetGain`
12
+ * (`dryGain = 1 - wet`, `wetGain = wet * _wetMakeupGain`). An optional
13
+ * `_dryDelay` time-aligns the dry path with the worklet's algorithmic latency.
14
+ * While the worklet loads, the wet path is silent and dry passes at unity, so
15
+ * the effect is a clean passthrough (no volume dip) until it is ready.
18
16
  * @advanced
19
17
  */
20
18
  class WorkletEffect extends AudioEffect {
21
19
  _inputGain = null;
22
20
  _outputGain = null;
21
+ _dryGain = null;
22
+ _wetGain = null;
23
+ _dryDelay = null;
23
24
  _workletNode = null;
24
25
  _ready = null;
26
+ _wet = 1;
25
27
  _onAudioContextReady = (ctx) => {
26
28
  onAudioContextReady.remove(this._onAudioContextReady);
27
29
  this._setup(ctx);
@@ -30,6 +32,26 @@ class WorkletEffect extends AudioEffect {
30
32
  get _workletOptions() {
31
33
  return { numberOfInputs: 1, numberOfOutputs: 1 };
32
34
  }
35
+ /**
36
+ * Dry-path delay in seconds, time-aligning the dry signal with the worklet's
37
+ * algorithmic latency so intermediate `wet` values do not comb-filter.
38
+ * Default 0 (no delay). Override in subclasses with buffering latency.
39
+ */
40
+ get _dryLatencySeconds() {
41
+ return 0;
42
+ }
43
+ /** Static makeup multiplier folded into the wet path (`wetGain = wet * this`). Default 1. */
44
+ get _wetMakeupGain() {
45
+ return 1;
46
+ }
47
+ /**
48
+ * The audio context's sample rate in Hz, or 48000 if the context is not yet
49
+ * available. Populated as soon as the audio context is ready (i.e. once
50
+ * `_setup` runs). Safe to read from `_dryLatencySeconds`.
51
+ */
52
+ get _sampleRate() {
53
+ return this._outputGain?.context.sampleRate ?? 48000;
54
+ }
33
55
  constructor() {
34
56
  super();
35
57
  if (isAudioContextReady()) {
@@ -51,11 +73,19 @@ class WorkletEffect extends AudioEffect {
51
73
  }
52
74
  return this._outputGain;
53
75
  }
54
- /**
55
- * Resolves once the underlying worklet is loaded and inserted into the
56
- * audio chain. Use this if you need to wait before applying parameters
57
- * that depend on the worklet node.
58
- */
76
+ /** Wet (processed) mix level, 0..1. The dry level is automatically `1 - wet`. Ramped smoothly. */
77
+ get wet() {
78
+ return this._wet;
79
+ }
80
+ set wet(value) {
81
+ this._wet = Math.max(0, Math.min(1, value));
82
+ if (this._dryGain && this._wetGain) {
83
+ const ctx = this._wetGain.context;
84
+ this._dryGain.gain.setTargetAtTime(1 - this._wet, ctx.currentTime, 0.01);
85
+ this._wetGain.gain.setTargetAtTime(this._wet * this._wetMakeupGain, ctx.currentTime, 0.01);
86
+ }
87
+ }
88
+ /** Resolves once the worklet is loaded and inserted into the wet path. */
59
89
  get ready() {
60
90
  return this._ready ?? Promise.resolve();
61
91
  }
@@ -65,14 +95,20 @@ class WorkletEffect extends AudioEffect {
65
95
  this._workletNode?.disconnect();
66
96
  this._inputGain?.disconnect();
67
97
  this._outputGain?.disconnect();
98
+ this._dryGain?.disconnect();
99
+ this._wetGain?.disconnect();
100
+ this._dryDelay?.disconnect();
68
101
  this._workletNode = null;
69
102
  this._inputGain = null;
70
103
  this._outputGain = null;
104
+ this._dryGain = null;
105
+ this._wetGain = null;
106
+ this._dryDelay = null;
71
107
  this._ready = null;
72
108
  }
73
109
  /**
74
- * Ramps an `AudioParam` on the underlying `AudioWorkletNode` to `value`
75
- * using a short exponential ramp. No-ops if the worklet is not yet loaded.
110
+ * Ramps an `AudioParam` on the underlying `AudioWorkletNode` to `value` using
111
+ * a short exponential ramp. No-ops if the worklet is not yet loaded.
76
112
  * @internal
77
113
  */
78
114
  _setAudioParam(name, value) {
@@ -84,23 +120,54 @@ class WorkletEffect extends AudioEffect {
84
120
  }
85
121
  }
86
122
  _setup(audioContext) {
87
- // Create stable input/output gains immediately (bus can wire them now).
88
123
  const inputGain = audioContext.createGain();
89
124
  const outputGain = audioContext.createGain();
90
- // Bypass: input → output until worklet loads.
91
- inputGain.connect(outputGain);
125
+ const dryGain = audioContext.createGain();
126
+ const wetGain = audioContext.createGain();
127
+ // Assign gain references immediately so inputNode/outputNode are accessible
128
+ // and _sampleRate (which reads this._outputGain.context.sampleRate) returns
129
+ // the real context rate for subclass use in _dryLatencySeconds.
92
130
  this._inputGain = inputGain;
93
131
  this._outputGain = outputGain;
94
- // Async-load the worklet, then re-route through it.
132
+ // Dry path: input dryGain → output. A time-alignment DelayNode is
133
+ // inserted in the worklet-ready callback below once _dryLatencySeconds is
134
+ // safe to read. The addModule Promise always settles asynchronously, so the
135
+ // subclass constructor is fully done by then (post-super() fields such as
136
+ // PitchShiftEffect._grainSize are guaranteed initialized).
137
+ inputGain.connect(dryGain);
138
+ dryGain.connect(outputGain);
139
+ // Wet path output stage exists immediately but is silent until the worklet
140
+ // loads. Dry passes at unity meanwhile → clean passthrough, no volume dip.
141
+ dryGain.gain.setValueAtTime(1, audioContext.currentTime);
142
+ wetGain.gain.setValueAtTime(0, audioContext.currentTime);
143
+ wetGain.connect(outputGain);
144
+ this._dryGain = dryGain;
145
+ this._wetGain = wetGain;
95
146
  this._ready = registerAudioWorkletProcessor(audioContext, this._workletName, this._workletSource).then(() => {
96
- if (!this._inputGain || !this._outputGain)
147
+ if (!this._inputGain || !this._dryGain || !this._wetGain)
97
148
  return; // destroyed during load
149
+ // Read _dryLatencySeconds here, not in _setup(), because the addModule
150
+ // Promise always resolves asynchronously — by this point the subclass
151
+ // constructor has fully run and any post-super() fields are valid.
152
+ const dryLatency = this._dryLatencySeconds;
153
+ if (dryLatency > 0) {
154
+ const dryDelay = audioContext.createDelay(Math.max(1, dryLatency * 2));
155
+ dryDelay.delayTime.setValueAtTime(dryLatency, audioContext.currentTime);
156
+ this._dryDelay = dryDelay;
157
+ // Re-route dry path to insert the delay: inputGain → dryDelay → dryGain.
158
+ // Use the destination-argument form of disconnect so only this edge is
159
+ // moved; the inputGain → worklet connection (added below) is unaffected.
160
+ this._inputGain.disconnect(this._dryGain);
161
+ this._inputGain.connect(dryDelay);
162
+ dryDelay.connect(this._dryGain);
163
+ }
98
164
  const node = new AudioWorkletNode(audioContext, this._workletName, this._workletOptions);
99
165
  this._workletNode = node;
100
- // Re-route: input → worklet → output
101
- this._inputGain.disconnect();
166
+ // Wet path: input → worklet → wetGain.
102
167
  this._inputGain.connect(node);
103
- node.connect(this._outputGain);
168
+ node.connect(this._wetGain);
169
+ // Apply the configured mix now that the wet path carries signal.
170
+ this.wet = this._wet;
104
171
  this._onWorkletReady?.(audioContext);
105
172
  });
106
173
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WorkletEffect.js","sources":["../../../../src/audio/WorkletEffect.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAIA;;;;;;;;;;;;;;AAcG;AACG,MAAgB,aAAc,SAAQ,WAAW,CAAA;IAC3C,UAAU,GAAoB,IAAI;IAClC,WAAW,GAAoB,IAAI;IACnC,YAAY,GAA4B,IAAI;IAC5C,MAAM,GAAyB,IAAI;AAC5B,IAAA,oBAAoB,GAAG,CAAC,GAAiB,KAAU;AAClE,QAAA,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;AACrD,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;AAClB,IAAA,CAAC;;AAOD,IAAA,IAAc,eAAe,GAAA;QAC3B,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE;IAClD;AAEA,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,IAAI,mBAAmB,EAAE,EAAE;AACzB,YAAA,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QAChC;aAAO;AACL,YAAA,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC;QACpD;IACF;AAEA,IAAA,IAAW,SAAS,GAAA;AAClB,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,MAAM,IAAI,KAAK,CAAC,CAAA,EAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA,oDAAA,CAAsD,CAAC;QACjG;QACA,OAAO,IAAI,CAAC,UAAU;IACxB;AAEA,IAAA,IAAW,UAAU,GAAA;AACnB,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YACrB,MAAM,IAAI,KAAK,CAAC,CAAA,EAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA,qDAAA,CAAuD,CAAC;QAClG;QACA,OAAO,IAAI,CAAC,WAAW;IACzB;AAEA;;;;AAIG;AACH,IAAA,IAAoB,KAAK,GAAA;QACvB,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE;IACzC;;IAGgB,OAAO,GAAA;AACrB,QAAA,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;AACrD,QAAA,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE;AAC/B,QAAA,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE;AAC7B,QAAA,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE;AAC9B,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI;AACxB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI;AACtB,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;AACvB,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;IACpB;AASA;;;;AAIG;IACO,cAAc,CAAC,IAAY,EAAE,KAAa,EAAA;QAClD,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE;AACxB,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QACzD,IAAI,UAAU,EAAE;AACd,YAAA,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC;QAChF;IACF;AAEQ,IAAA,MAAM,CAAC,YAA0B,EAAA;;AAEvC,QAAA,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,EAAE;AAC3C,QAAA,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE;;AAE5C,QAAA,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC;AAE7B,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS;AAC3B,QAAA,IAAI,CAAC,WAAW,GAAG,UAAU;;AAG7B,QAAA,IAAI,CAAC,MAAM,GAAG,6BAA6B,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,MAAK;YAC1G,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW;AAAE,gBAAA,OAAO;AAElD,YAAA,MAAM,IAAI,GAAG,IAAI,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC;AACxF,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;;AAGxB,YAAA,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AAC5B,YAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;AAC7B,YAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;AAE9B,YAAA,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC;AACtC,QAAA,CAAC,CAAC;IACJ;AACD;;;;"}
1
+ {"version":3,"file":"WorkletEffect.js","sources":["../../../../src/audio/WorkletEffect.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}