@woosh/meep-engine 3.46.0 → 3.47.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 (230) hide show
  1. package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
  2. package/editor/actions/concrete/TransformModifyAction.js +10 -2
  3. package/editor/ecs/component/FieldDescriptor.js +15 -0
  4. package/editor/ecs/component/createObjectEditor.js +41 -12
  5. package/editor/ecs/component/editors/ecs/Transform64Editor.d.ts.map +1 -1
  6. package/editor/ecs/component/editors/ecs/Transform64Editor.js +77 -70
  7. package/editor/tools/TransformToolV2.d.ts.map +1 -1
  8. package/editor/tools/TransformToolV2.js +4 -0
  9. package/editor/tools/v2/TransformControls.d.ts.map +1 -1
  10. package/editor/tools/v2/TransformControls.js +7 -0
  11. package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
  12. package/editor/view/ecs/EntityEditor.js +4 -2
  13. package/package.json +1 -1
  14. package/src/core/collection/array/array_insert_at.d.ts +16 -0
  15. package/src/core/collection/array/array_insert_at.d.ts.map +1 -0
  16. package/src/core/collection/array/array_insert_at.js +32 -0
  17. package/src/core/collection/array/array_remove_at.d.ts +15 -0
  18. package/src/core/collection/array/array_remove_at.d.ts.map +1 -0
  19. package/src/core/collection/array/array_remove_at.js +30 -0
  20. package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts +37 -0
  21. package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts.map +1 -0
  22. package/src/core/geom/3d/quaternion/quat3_look_rotation.js +172 -0
  23. package/src/core/geom/Quaternion.d.ts +1 -0
  24. package/src/core/geom/Quaternion.d.ts.map +1 -1
  25. package/src/core/geom/Quaternion.js +12 -48
  26. package/src/engine/Engine.d.ts.map +1 -1
  27. package/src/engine/Engine.js +9 -4
  28. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  29. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +10 -0
  30. package/src/engine/ecs/transform/t64_look_rotation.d.ts +4 -4
  31. package/src/engine/ecs/transform/t64_look_rotation.d.ts.map +1 -1
  32. package/src/engine/ecs/transform/t64_look_rotation.js +7 -18
  33. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  34. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +30 -1
  35. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -0
  36. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  37. package/src/engine/graphics3/GPUParticleEmitterSystem.js +72 -29
  38. package/src/engine/input/devices/KeyboardDevice.d.ts +1 -0
  39. package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
  40. package/src/engine/input/devices/KeyboardDevice.js +7 -6
  41. package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
  42. package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +15 -2
  43. package/src/engine/network/CONGESTION_CONTROL.md +9 -9
  44. package/src/engine/network/MESSAGE_TRANSPORT.md +364 -0
  45. package/src/engine/network/NetworkSession.d.ts +31 -11
  46. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  47. package/src/engine/network/NetworkSession.js +453 -286
  48. package/src/engine/network/README.md +77 -27
  49. package/src/engine/network/SMOOTHNESS_DESIGN.md +13 -5
  50. package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
  51. package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
  52. package/src/engine/network/orchestrator/HostJoin.d.ts +111 -0
  53. package/src/engine/network/orchestrator/HostJoin.d.ts.map +1 -0
  54. package/src/engine/network/orchestrator/HostJoin.js +271 -0
  55. package/src/engine/network/orchestrator/NetworkPeer.d.ts +151 -112
  56. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  57. package/src/engine/network/orchestrator/NetworkPeer.js +450 -499
  58. package/src/engine/network/orchestrator/PendingSlices.d.ts +30 -0
  59. package/src/engine/network/orchestrator/PendingSlices.d.ts.map +1 -0
  60. package/src/engine/network/orchestrator/PendingSlices.js +83 -0
  61. package/src/engine/network/orchestrator/ReliableFrames.d.ts +34 -0
  62. package/src/engine/network/orchestrator/ReliableFrames.d.ts.map +1 -0
  63. package/src/engine/network/orchestrator/ReliableFrames.js +96 -0
  64. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +77 -10
  65. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  66. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +236 -61
  67. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +20 -6
  68. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  69. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +33 -8
  70. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  71. package/src/engine/network/replication/Replicator.js +7 -1
  72. package/src/engine/network/sim/ActionLog.d.ts +32 -5
  73. package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
  74. package/src/engine/network/sim/ActionLog.js +47 -5
  75. package/src/engine/network/sim/SimActionExecutor.d.ts +42 -2
  76. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  77. package/src/engine/network/sim/SimActionExecutor.js +100 -4
  78. package/src/engine/network/sim/Snapshotter.d.ts +12 -0
  79. package/src/engine/network/sim/Snapshotter.d.ts.map +1 -1
  80. package/src/engine/network/sim/Snapshotter.js +43 -0
  81. package/src/engine/network/state/Baseline.d.ts +1 -1
  82. package/src/engine/network/state/Baseline.js +1 -1
  83. package/src/engine/network/state/FrameBufferRing.d.ts +25 -6
  84. package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
  85. package/src/engine/network/state/FrameBufferRing.js +51 -6
  86. package/src/engine/network/state/InputRing.d.ts +4 -0
  87. package/src/engine/network/state/InputRing.d.ts.map +1 -1
  88. package/src/engine/network/state/InputRing.js +7 -0
  89. package/src/engine/network/transport/DeferredTransport.d.ts.map +1 -1
  90. package/src/engine/network/transport/DeferredTransport.js +1 -0
  91. package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
  92. package/src/engine/network/transport/LoopbackTransport.js +4 -2
  93. package/src/engine/network/transport/Transport.d.ts +7 -0
  94. package/src/engine/network/transport/Transport.d.ts.map +1 -1
  95. package/src/engine/network/transport/Transport.js +8 -0
  96. package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
  97. package/src/engine/network/transport/adapters/NodeUDPTransport.js +20 -5
  98. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
  99. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +8 -0
  100. package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
  101. package/src/engine/network/transport/adapters/WebTransportTransport.js +6 -0
  102. package/src/engine/network/transport/connection/Connection.d.ts +191 -0
  103. package/src/engine/network/transport/connection/Connection.d.ts.map +1 -0
  104. package/src/engine/network/transport/connection/Connection.js +1262 -0
  105. package/src/engine/network/transport/connection/RangeSet.d.ts +94 -0
  106. package/src/engine/network/transport/connection/RangeSet.d.ts.map +1 -0
  107. package/src/engine/network/transport/connection/RangeSet.js +260 -0
  108. package/src/engine/network/transport/connection/RxStream.d.ts +48 -0
  109. package/src/engine/network/transport/connection/RxStream.d.ts.map +1 -0
  110. package/src/engine/network/transport/connection/RxStream.js +211 -0
  111. package/src/engine/network/transport/connection/TxStream.d.ts +90 -0
  112. package/src/engine/network/transport/connection/TxStream.d.ts.map +1 -0
  113. package/src/engine/network/transport/connection/TxStream.js +243 -0
  114. package/src/engine/network/transport/connection/bytes_copy.d.ts +17 -0
  115. package/src/engine/network/transport/connection/bytes_copy.d.ts.map +1 -0
  116. package/src/engine/network/transport/connection/bytes_copy.js +34 -0
  117. package/src/engine/network/transport/connection/varint.d.ts +46 -0
  118. package/src/engine/network/transport/connection/varint.d.ts.map +1 -0
  119. package/src/engine/network/transport/connection/varint.js +107 -0
  120. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  121. package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +38 -7
  122. package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
  123. package/src/engine/sound/ecs/audio/AudioEmitter.js +35 -7
  124. package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.d.ts.map +1 -1
  125. package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js +5 -1
  126. package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts +18 -0
  127. package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts.map +1 -0
  128. package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js +48 -0
  129. package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +12 -2
  130. package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
  131. package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +173 -9
  132. package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +9 -3
  133. package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -1
  134. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +28 -8
  135. package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +8 -0
  136. package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -1
  137. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -1
  138. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +5 -1
  139. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts +18 -0
  140. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts.map +1 -0
  141. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js +51 -0
  142. package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -1
  143. package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +15 -1
  144. package/src/engine/sound/sopra/README.md +768 -644
  145. package/src/engine/sound/sopra/SopraEngine.d.ts +104 -8
  146. package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
  147. package/src/engine/sound/sopra/SopraEngine.js +327 -12
  148. package/src/engine/sound/sopra/definition/EventDescription.d.ts +28 -2
  149. package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
  150. package/src/engine/sound/sopra/definition/EventDescription.js +55 -5
  151. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +10 -0
  152. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
  153. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +77 -55
  154. package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts +31 -0
  155. package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts.map +1 -0
  156. package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.js +75 -0
  157. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +38 -9
  158. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -1
  159. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +34 -5
  160. package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +7 -2
  161. package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -1
  162. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +137 -122
  163. package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +3 -1
  164. package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -1
  165. package/src/engine/sound/sopra/definition/effect/EqEffect.js +146 -131
  166. package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +1 -0
  167. package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
  168. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +6 -1
  169. package/src/engine/sound/sopra/runtime/BusGraph.d.ts +44 -2
  170. package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
  171. package/src/engine/sound/sopra/runtime/BusGraph.js +83 -43
  172. package/src/engine/sound/sopra/runtime/EffectChain.d.ts +96 -0
  173. package/src/engine/sound/sopra/runtime/EffectChain.d.ts.map +1 -0
  174. package/src/engine/sound/sopra/runtime/EffectChain.js +286 -0
  175. package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts +123 -0
  176. package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts.map +1 -0
  177. package/src/engine/sound/sopra/runtime/EffectParamOverrides.js +320 -0
  178. package/src/engine/sound/sopra/runtime/EventInstance.d.ts +55 -5
  179. package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
  180. package/src/engine/sound/sopra/runtime/EventInstance.js +201 -26
  181. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +2 -1
  182. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -1
  183. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +6 -1
  184. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +15 -0
  185. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -1
  186. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +32 -0
  187. package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -1
  188. package/src/engine/sound/sopra/util/MockAudioContext.js +3 -0
  189. package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +13 -3
  190. package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -1
  191. package/src/engine/sound/sopra/util/fadeOutAndStop.js +25 -13
  192. package/src/shade/RENDERER_CONTRACT.md +6 -3
  193. package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts +24 -0
  194. package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts.map +1 -0
  195. package/src/shade/device/SHADE_DEVICE_FLOOR.js +34 -0
  196. package/src/shade/device/ShadeDeviceFailure.d.ts +12 -5
  197. package/src/shade/device/ShadeDeviceFailure.d.ts.map +1 -1
  198. package/src/shade/device/ShadeDeviceFailure.js +17 -8
  199. package/src/shade/device/ShadeDeviceFailureReason.d.ts +1 -1
  200. package/src/shade/device/ShadeDeviceFailureReason.js +2 -2
  201. package/src/shade/device/shade_device_floor_unmet.d.ts +13 -0
  202. package/src/shade/device/shade_device_floor_unmet.d.ts.map +1 -0
  203. package/src/shade/device/shade_device_floor_unmet.js +32 -0
  204. package/src/shade/renderer/Renderer.d.ts +2 -0
  205. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  206. package/src/shade/renderer/Renderer.js +29 -55
  207. package/src/shade/renderer/buffer/GPUBufferAllocator.d.ts.map +1 -1
  208. package/src/shade/renderer/buffer/GPUBufferAllocator.js +9 -0
  209. package/src/shade/renderer/buffer/buffer_pool_ops.d.ts +21 -12
  210. package/src/shade/renderer/buffer/buffer_pool_ops.d.ts.map +1 -1
  211. package/src/shade/renderer/buffer/buffer_pool_ops.js +18 -19
  212. package/src/shade/renderer/gpu_primitive/test/gpu_test.d.ts.map +1 -1
  213. package/src/shade/renderer/gpu_primitive/test/gpu_test.js +8 -11
  214. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  215. package/src/shade/renderer/pool/TransientResourcePool.d.ts +24 -0
  216. package/src/shade/renderer/pool/TransientResourcePool.d.ts.map +1 -1
  217. package/src/shade/renderer/pool/TransientResourcePool.js +41 -10
  218. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  219. package/src/shade/renderer/shader/ComputeShader.js +18 -2
  220. package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
  221. package/src/shade/renderer/shader/ImageShader.js +230 -218
  222. package/src/view/graphics/GraphicsContextFailureView.d.ts +1 -2
  223. package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
  224. package/src/view/graphics/GraphicsContextFailureView.js +1 -2
  225. package/src/engine/network/transport/Channel.js +0 -336
  226. package/src/engine/network/transport/ReliableCommandPipeline.js +0 -335
  227. package/src/engine/network/transport/fragments/FragmentAssembler.js +0 -350
  228. package/src/engine/network/transport/fragments/FragmentRetention.js +0 -191
  229. package/src/engine/network/transport/fragments/fragment_send.js +0 -157
  230. package/src/engine/network/transport/fragments/packet_size.js +0 -107
@@ -5,6 +5,7 @@ import Vector1 from "../../../../core/geom/Vector1.js";
5
5
  import { computeHashFloat } from "../../../../core/primitives/numbers/computeHashFloat.js";
6
6
  import { AcousticDirectivity } from "../../simulation/definition/AcousticDirectivity.js";
7
7
  import { EventDescription } from "../../sopra/definition/EventDescription.js";
8
+ import { EffectParamOverrides } from "../../sopra/runtime/EffectParamOverrides.js";
8
9
 
9
10
  const DEFAULT_SOURCE_RADIUS = 0.05;
10
11
 
@@ -22,13 +23,14 @@ export class AudioEmitter {
22
23
  /**
23
24
  * The authored event this emitter plays.
24
25
  *
25
- * Authored data: fixed for as long as the emitter is playing. Routing (`busId`, `is3D`,
26
- * `panningModel`) decides the shape of the instance's audio graph, which is built once when the
27
- * voice starts; and `distanceMin`, `distanceMax`, `maxInstances` and the attenuation curve all take
28
- * part in {@link EventDescription.hash}, which the `VoiceManager` buckets live instances by — so
29
- * editing any of them in place on a sounding emitter files that instance under a hash it can no
30
- * longer be found by. Change them by re-linking the component (remove and re-add it), which tears
31
- * the voice down and re-reads the description cleanly.
26
+ * Authored data: fixed for as long as the emitter is linked, playing or dormant. Routing (`busId`,
27
+ * `is3D`, `panningModel`) decides the shape of the instance's audio graph, which is built once when
28
+ * the voice starts; and `distanceMin`, `distanceMax`, `maxInstances`, the attenuation curve and the
29
+ * insert `effects` (every field of every effect) all take part in {@link EventDescription.hash}, which
30
+ * the `VoiceManager` buckets live instances by — so editing any of them in place on a sounding emitter
31
+ * files that instance under a hash it can no longer be found by. Change them by re-linking the
32
+ * component (remove and re-add it), which tears the voice down and re-reads the description cleanly.
33
+ * A playing effect's parameters move through {@link effectOverrides}, never through the definition.
32
34
  *
33
35
  * @type {EventDescription}
34
36
  */
@@ -71,6 +73,32 @@ export class AudioEmitter {
71
73
  */
72
74
  directivity = new AcousticDirectivity();
73
75
 
76
+ /**
77
+ * This emitter's own values for its event's insert-effect parameters ({@link EventDescription.effects}):
78
+ * a lowpass closing over one torch as a door shuts on it, while every other torch playing the same
79
+ * event stays bright.
80
+ *
81
+ * Live state, the way {@link volume} is live — plumbed by `AudioEmitterSystem` onto whichever instance
82
+ * is current, and put onto every new one. A spatially managed emitter's instance is torn down when it
83
+ * is demoted and built afresh when it is promoted again, and is built at these values, not the event's;
84
+ * a value moved straight on an instance (`AudioEmitterSystem.instanceFor(entity).setEffectParam`) lasts
85
+ * only as long as that instance.
86
+ *
87
+ * Not authored data, so absent from {@link toJSON}, {@link equals} and {@link hash}: two emitters that
88
+ * differ only in where a filter has been turned are the same emitter, and the overrides must change
89
+ * neither what a save contains nor which polyphony bucket a voice is filed under.
90
+ *
91
+ * Checked against the event: while the emitter is linked, an override its event has no such parameter
92
+ * for throws where it is written, and is not kept; one written before the link is checked by the link,
93
+ * which throws instead of playing. So {@link EffectParamOverrides#clear} them before re-adding the
94
+ * component with a different event. One entity per `AudioEmitter`: a second link of the same component
95
+ * throws, since the overrides can follow only one playing instance.
96
+ *
97
+ * @readonly
98
+ * @type {EffectParamOverrides}
99
+ */
100
+ effectOverrides = new EffectParamOverrides();
101
+
74
102
  /**
75
103
  * Observation surface, not authored state — deliberately absent from {@link toJSON}, {@link equals}
76
104
  * and {@link hash}: two emitters that differ only in who is listening are the same emitter, and a
@@ -1 +1 @@
1
- {"version":3,"file":"AudioEmitterSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH;;IACI,2BAAqB;IAarB;;;OAGG;IACH,mFAEC;IAED;;;OAGG;IACH,uCAFW,YAAY,QAWtB;IAED;;;OAGG;IACH,yCAFW,YAAY,QAWtB;;CACJ;gDAnE+C,gEAAgE;6BAGnF,mBAAmB"}
1
+ {"version":3,"file":"AudioEmitterSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH;;IACI,2BAAqB;IAiBrB;;;OAGG;IACH,mFAEC;IAED;;;OAGG;IACH,uCAFW,YAAY,QAWtB;IAED;;;OAGG;IACH,yCAFW,YAAY,QAWtB;;CACJ;gDAvE+C,gEAAgE;6BAGnF,mBAAmB"}
@@ -16,7 +16,11 @@ import { AudioEmitter } from "./AudioEmitter.js";
16
16
  */
17
17
  export class AudioEmitterSerializationAdapter extends BinaryClassSerializationAdapter {
18
18
  klass = AudioEmitter;
19
- version = 0;
19
+ /**
20
+ * 1: the embedded event record moved to its format 1 (insert effects) — `AudioEmitterSerializationUpgrader_0_1`.
21
+ * @type {number}
22
+ */
23
+ version = 1;
20
24
 
21
25
  /**
22
26
  * @type {EventDescriptionSerializationAdapter}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @typedef {import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry} BinarySerializationRegistry
3
+ */
4
+ /**
5
+ * Version 0 → 1: the embedded {@link EventDescription} record moved to its own format 1 (insert effects).
6
+ * The record leads the component and carries no version tag of its own, so the component's version is what
7
+ * says which layout it is in; every field after it is unchanged.
8
+ */
9
+ export class AudioEmitterSerializationUpgrader_0_1 extends BinaryClassUpgrader {
10
+ /**
11
+ * @param {BinarySerializationRegistry} registry where the event's clip types are registered
12
+ */
13
+ constructor(registry: BinarySerializationRegistry);
14
+ #private;
15
+ }
16
+ export type BinarySerializationRegistry = import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry;
17
+ import { BinaryClassUpgrader } from "../../../ecs/storage/binary/BinaryClassUpgrader.js";
18
+ //# sourceMappingURL=AudioEmitterSerializationUpgrader_0_1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioEmitterSerializationUpgrader_0_1.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js"],"names":[],"mappings":"AAMA;;GAEG;AAEH;;;;GAIG;AACH;IASI;;OAEG;IACH,sBAFW,2BAA2B,EAMrC;;CAgBJ;0CAxCY,OAAO,4DAA4D,EAAE,2BAA2B;oCANzE,oDAAoD"}
@@ -0,0 +1,48 @@
1
+ import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
2
+ import { BinaryClassUpgrader } from "../../../ecs/storage/binary/BinaryClassUpgrader.js";
3
+ import {
4
+ EventDescriptionSerializationUpgrader_0_1
5
+ } from "../../sopra/definition/EventDescriptionSerializationUpgrader_0_1.js";
6
+
7
+ /**
8
+ * @typedef {import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry} BinarySerializationRegistry
9
+ */
10
+
11
+ /**
12
+ * Version 0 → 1: the embedded {@link EventDescription} record moved to its own format 1 (insert effects).
13
+ * The record leads the component and carries no version tag of its own, so the component's version is what
14
+ * says which layout it is in; every field after it is unchanged.
15
+ */
16
+ export class AudioEmitterSerializationUpgrader_0_1 extends BinaryClassUpgrader {
17
+ __startVersion = 0;
18
+ __targetVersion = 1;
19
+
20
+ /**
21
+ * @type {EventDescriptionSerializationUpgrader_0_1}
22
+ */
23
+ #event;
24
+
25
+ /**
26
+ * @param {BinarySerializationRegistry} registry where the event's clip types are registered
27
+ */
28
+ constructor(registry) {
29
+ super();
30
+
31
+ this.#event = new EventDescriptionSerializationUpgrader_0_1(registry);
32
+ }
33
+
34
+ /**
35
+ * @param {BinaryBuffer} source
36
+ * @param {BinaryBuffer} target
37
+ */
38
+ upgrade(source, target) {
39
+ this.#event.upgrade(source, target);
40
+
41
+ BinaryBuffer.copyFloat32(source, target); // volume
42
+ BinaryBuffer.copyUint8(source, target); // autoplay
43
+ BinaryBuffer.copyUint8(source, target); // acoustic
44
+ BinaryBuffer.copyFloat32(source, target); // sourceRadius
45
+ BinaryBuffer.copyFloat32(source, target); // directivity.dipoleWeight
46
+ BinaryBuffer.copyFloat32(source, target); // directivity.dipolePower
47
+ }
48
+ }
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Drives {@link AudioEmitter} components through the shared sopra engine. Each emitter owns its
3
3
  * {@link EventDescription} directly (no track translation); the entity's {@link Transform64} feeds
4
- * position; `volume` changes plumb to the instance gain. Each frame it forwards the listener pose,
4
+ * position; `volume` changes plumb to the instance gain, and `effectOverrides` to the instance's effect
5
+ * parameters — both put onto every instance the emitter gets. Each frame it forwards the listener pose,
5
6
  * refreshes the spatial live set, and ticks sopra.
6
7
  *
7
8
  * **Two play paths**, chosen once at {@link link} (routing is fixed for the lifetime of the link —
@@ -50,7 +51,7 @@ export class AudioEmitterSystem extends System<any> {
50
51
  */
51
52
  acousticLive: EventInstance[];
52
53
  /**
53
- * Per-entity records: { emitter, transform, managed, instance, onVolume }. For a managed (3D)
54
+ * Per-entity records: { emitter, transform, managed, instance, onVolume, effectOverrides, onEffectOverride, ... }. For a managed (3D)
54
55
  * emitter the playing instance lives in {@link liveSet} (record.instance stays null); for a
55
56
  * direct (2D) emitter it is held here.
56
57
  * @type {object[]}
@@ -112,6 +113,15 @@ export class AudioEmitterSystem extends System<any> {
112
113
  * @returns {EventInstance|null}
113
114
  */
114
115
  instanceFor(entity: number): EventInstance | null;
116
+ /**
117
+ * @param {EntityComponentDataset} dataset
118
+ */
119
+ handleDatasetDetached(dataset: EntityComponentDataset): void;
120
+ /**
121
+ * @param {EntityManager} entityManager
122
+ * @returns {Promise<void>}
123
+ */
124
+ shutdown(entityManager: EntityManager): Promise<void>;
115
125
  update(timeDelta: any): void;
116
126
  #private;
117
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AudioEmitterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSystem.js"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IAgCI;;;;;OAKG;IACH,0FAHW;QAAC,MAAM,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAA;KAAC,qBA+C1E;IAjFD,2DAA2C;IAE3C;;;;;OAKG;IACH,iBAFU,kBAAkB,CAEA;IAE5B;;;OAGG;IACH,cAFU,eAAe,CAEP;IAElB;;;;;OAKG;IACH,MAFU,MAAM,EAAE,CAER;IAEV;;;;OAIG;IACH,aAFU,sBAAoB,IAAI,CAEf;IAWf;;;;;OAKG;IACH,aAFU,oBAAkB,IAAI,CAEF;IAE9B;;OAEG;IACH,yBAA8B;IAE9B;;OAEG;IACH,iBAFU,YAAY,CAEoB;IAE1C;;OAEG;IACH,2BAAgC;IAQhC;;;OAGG;IACH,mBAAkF;IAElF;;;;OAIG;IACH,SAFU,cAAc,CAE4C;IAGxE;;;;OAIG;IACH,cAJW,YAAY,aACZ,WAAW,UACX,MAAM,QA4ChB;IAED;;;;OAIG;IACH,gBAJW,YAAY,aACZ,WAAW,UACX,MAAM,QA+BhB;IAED;;;;;;OAMG;IACH,oBAHW,MAAM,GACJ,gBAAc,IAAI,CAe9B;IAqDD,6BAoFC;;CACJ;uBAvXsB,wBAAwB;4BAGnB,uCAAuC;6BAKtC,mBAAmB;+BACjB,qBAAqB"}
1
+ {"version":3,"file":"AudioEmitterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSystem.js"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAgCI;;;;;OAKG;IACH,0FAHW;QAAC,MAAM,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAA;KAAC,qBA+C1E;IAjFD,2DAA2C;IAE3C;;;;;OAKG;IACH,iBAFU,kBAAkB,CAEA;IAE5B;;;OAGG;IACH,cAFU,eAAe,CAEP;IAElB;;;;;OAKG;IACH,MAFU,MAAM,EAAE,CAER;IAEV;;;;OAIG;IACH,aAFU,sBAAoB,IAAI,CAEf;IAWf;;;;;OAKG;IACH,aAFU,oBAAkB,IAAI,CAEF;IAE9B;;OAEG;IACH,yBAA8B;IAE9B;;OAEG;IACH,iBAFU,YAAY,CAEoB;IAE1C;;OAEG;IACH,2BAAgC;IAQhC;;;OAGG;IACH,mBAAkF;IAElF;;;;OAIG;IACH,SAFU,cAAc,CAE4C;IAGxE;;;;OAIG;IACH,cAJW,YAAY,aACZ,WAAW,UACX,MAAM,QAyEhB;IAED;;;;OAIG;IACH,gBAJW,YAAY,aACZ,WAAW,UACX,MAAM,QAkChB;IAED;;;;;;OAMG;IACH,oBAHW,MAAM,GACJ,gBAAc,IAAI,CAe9B;IAoJD;;OAEG;IACH,6DAKC;IAED;;;OAGG;IACH,wCAFa,QAAQ,IAAI,CAAC,CAKzB;IAmBD,6BAoFC;;CACJ;uBA3hBsB,wBAAwB;4BAGnB,uCAAuC;6BAKtC,mBAAmB;+BACjB,qBAAqB"}
@@ -25,7 +25,8 @@ const LISTENER_ROTATION = new Quaternion();
25
25
  /**
26
26
  * Drives {@link AudioEmitter} components through the shared sopra engine. Each emitter owns its
27
27
  * {@link EventDescription} directly (no track translation); the entity's {@link Transform64} feeds
28
- * position; `volume` changes plumb to the instance gain. Each frame it forwards the listener pose,
28
+ * position; `volume` changes plumb to the instance gain, and `effectOverrides` to the instance's effect
29
+ * parameters — both put onto every instance the emitter gets. Each frame it forwards the listener pose,
29
30
  * refreshes the spatial live set, and ticks sopra.
30
31
  *
31
32
  * **Two play paths**, chosen once at {@link link} (routing is fixed for the lifetime of the link —
@@ -66,7 +67,7 @@ export class AudioEmitterSystem extends System {
66
67
  acousticLive = [];
67
68
 
68
69
  /**
69
- * Per-entity records: { emitter, transform, managed, instance, onVolume }. For a managed (3D)
70
+ * Per-entity records: { emitter, transform, managed, instance, onVolume, effectOverrides, onEffectOverride, ... }. For a managed (3D)
70
71
  * emitter the playing instance lives in {@link liveSet} (record.instance stays null); for a
71
72
  * direct (2D) emitter it is held here.
72
73
  * @type {object[]}
@@ -144,11 +145,25 @@ export class AudioEmitterSystem extends System {
144
145
  // class doc.
145
146
  const managed = emitter.autoplay && emitter.event.is3D && emitter.event.rootClip.loops();
146
147
 
147
- const record = { emitter, transform, managed, instance: null, onVolume: null, onEnded: null, onMoved: null };
148
+ const record = {
149
+ emitter, transform, managed, instance: null, onVolume: null, onEnded: null, onMoved: null,
150
+ // held here, so unlink detaches what link attached even if the field was replaced since
151
+ effectOverrides: emitter.effectOverrides,
152
+ onEffectOverride: null
153
+ };
154
+
155
+ // Effect overrides move whichever instance is current, on either route. Checked first: an override
156
+ // written before the link that the event has no parameter for throws HERE, before anything is
157
+ // registered or played. They are attached - and every later write checked as it is written - once
158
+ // the record is stored, below, when nothing left in the link can fail and leave them attached to a
159
+ // record that never was.
160
+ record.effectOverrides.checkAttach(emitter.event);
161
+ record.onEffectOverride = (effectIndex, name, value, timeConstant) => this.#moveEffectParam(record, entity, effectIndex, name, value, timeConstant);
148
162
 
149
163
  if (managed) {
150
164
  const pathing = emitter.acoustic && this.acousticSim !== null && this.acousticSim.pathing;
151
- this.liveSet.add(entity, emitter.event, transform.translation, volume2dB(emitter.volume.getValue()), emitter.acoustic, pathing, emitter.sourceRadius, transform.rotation, emitter.directivity);
165
+ // the live set puts the overrides onto every instance it promotes
166
+ this.liveSet.add(entity, emitter.event, transform.translation, volume2dB(emitter.volume.getValue()), emitter.acoustic, pathing, emitter.sourceRadius, transform.rotation, emitter.directivity, record.effectOverrides);
152
167
  record.onVolume = () => this.liveSet.setGainDb(entity, volume2dB(emitter.volume.getValue()));
153
168
 
154
169
  // The live set reads the translation through a live view, but a Transform64 cannot say it
@@ -166,12 +181,27 @@ export class AudioEmitterSystem extends System {
166
181
  }
167
182
  }
168
183
  record.onVolume = () => this.#applyVolume(record);
184
+
185
+ if (record.instance !== null && emitter.event.is3D) {
186
+ // The instance holds the translation's live view, and reads it only when told it moved -
187
+ // the announcement is how it is told, as it is for the live set below
188
+ record.onMoved = () => record.instance?.moved();
189
+
190
+ this.entityManager.dataset.addEntityEventListener(entity, TRANSFORM64_EVENT_CHANGE, record.onMoved);
191
+ }
169
192
  }
170
193
 
171
194
  emitter.volume.onChanged.add(record.onVolume);
172
195
 
173
196
  this.data[entity] = record;
174
197
 
198
+ record.effectOverrides.attach(emitter.event, record.onEffectOverride);
199
+
200
+ // a direct instance was built above, at the event's definition
201
+ if (record.instance !== null && record.instance.state !== EventInstanceState.Stopped) {
202
+ record.effectOverrides.applyTo(record.instance);
203
+ }
204
+
175
205
  // A one-shot whose buffers are already decoded resolves its timeline inside playEvent and can
176
206
  // finish there and then — before the subscription in #play exists, and while the record is still
177
207
  // unreachable. Report that end here instead, once the link is complete, so an `on.ended` handler
@@ -197,10 +227,13 @@ export class AudioEmitterSystem extends System {
197
227
  delete this.data[entity];
198
228
 
199
229
  emitter.volume.onChanged.remove(record.onVolume);
230
+ record.effectOverrides.detach(record.onEffectOverride);
200
231
 
201
- if (record.managed) {
232
+ if (record.onMoved !== null) {
202
233
  this.entityManager.dataset.removeEntityEventListener(entity, TRANSFORM64_EVENT_CHANGE, record.onMoved);
234
+ }
203
235
 
236
+ if (record.managed) {
204
237
  this.liveSet.remove(entity); // demotes (hard cut) if live, then unregisters
205
238
  } else if (record.instance !== null) {
206
239
  this.directInstances.delete(record.instance);
@@ -255,7 +288,7 @@ export class AudioEmitterSystem extends System {
255
288
 
256
289
  const instance = this.sopra.playEvent(event, {
257
290
  busId: event.busId,
258
- // a live view over the transform's buffer, so it still tracks the entity as it moves
291
+ // a live view over the transform's buffer, read again each time the entity announces a move
259
292
  position: transform.translation,
260
293
  oneShot,
261
294
  acoustic: emitter.acoustic,
@@ -290,6 +323,137 @@ export class AudioEmitterSystem extends System {
290
323
  }
291
324
  }
292
325
 
326
+ /**
327
+ * Carry one change of an emitter's {@link AudioEmitter.effectOverrides} to its current instance. With
328
+ * none — dormant, or a one-shot that has ended — there is nothing to move: the next instance is built
329
+ * at the overrides as they then stand. A contention fade is not current; like the gain, it finishes
330
+ * as it was.
331
+ * @param {object} record the emitter's link record
332
+ * @param {number} entity
333
+ * @param {number} effectIndex
334
+ * @param {string} name
335
+ * @param {number} value
336
+ * @param {number} timeConstant 0 moves it now; above 0 glides
337
+ */
338
+ #moveEffectParam(record, entity, effectIndex, name, value, timeConstant) {
339
+ // entity ids are reused: a record that is no longer the entity's must not move whoever has it now
340
+ if (this.data[entity] !== record) {
341
+ return;
342
+ }
343
+
344
+ const instance = this.instanceFor(entity);
345
+
346
+ if (instance === null || instance.state === EventInstanceState.Stopped) {
347
+ return;
348
+ }
349
+
350
+ if (timeConstant > 0) {
351
+ instance.approachEffectParam(effectIndex, name, value, timeConstant);
352
+ } else {
353
+ instance.setEffectParam(effectIndex, name, value);
354
+ }
355
+ }
356
+
357
+ /**
358
+ * The listener this system follows: its dataset, entity and transform, and the transform's
359
+ * translation view handed to sopra, taken once rather than read off the transform each frame (that
360
+ * getter builds a new view on every read). Null until a listener is seen.
361
+ * @type {EntityComponentDataset|null}
362
+ */
363
+ #listener_ecd = null;
364
+
365
+ /** @type {number} */
366
+ #listener_entity = -1;
367
+
368
+ /** @type {Transform64|null} */
369
+ #listener_transform = null;
370
+
371
+ /** @type {Float64Array|null} */
372
+ #listener_position = null;
373
+
374
+ /**
375
+ * Tells sopra the listener moved, when its transform announces a write: every 3D instance re-attenuates
376
+ * on the next tick, and none does between moves.
377
+ */
378
+ #on_listener_moved = () => {
379
+ this.sopra.setListener(this.#listener_position);
380
+ };
381
+
382
+ /**
383
+ * The followed listener's entity was removed, and its listeners with it. Forget it, so the next
384
+ * update follows whatever listener there is then — the same entity rebuilt from the same components
385
+ * included, which comes back with the same id and transform and would otherwise look followed already.
386
+ * sopra keeps the last listener position until then, as it does with no listener at all.
387
+ */
388
+ #on_listener_removed = () => {
389
+ this.#listener_ecd = null;
390
+ this.#listener_entity = -1;
391
+ this.#listener_transform = null;
392
+ };
393
+
394
+ /**
395
+ * Follow `entity` as the listener, if it is not the one followed already: subscribe to its transform's
396
+ * announcements and hand sopra its position, which is itself a move.
397
+ *
398
+ * @param {EntityComponentDataset} ecd
399
+ * @param {number} entity
400
+ * @param {Transform64} transform
401
+ */
402
+ #follow_listener(ecd, entity, transform) {
403
+ // the transform too: an entity id is reused, and a dataset can be swapped
404
+ if (ecd === this.#listener_ecd && entity === this.#listener_entity && transform === this.#listener_transform) {
405
+ return;
406
+ }
407
+
408
+ this.#unfollow_listener();
409
+
410
+ this.#listener_ecd = ecd;
411
+ this.#listener_entity = entity;
412
+ this.#listener_transform = transform;
413
+ this.#listener_position = transform.translation;
414
+
415
+ ecd.addEntityEventListener(entity, TRANSFORM64_EVENT_CHANGE, this.#on_listener_moved);
416
+ ecd.addEntityEventListener(entity, EventType.EntityRemoved, this.#on_listener_removed);
417
+
418
+ this.sopra.setListener(this.#listener_position);
419
+ }
420
+
421
+ /**
422
+ * @param {EntityComponentDataset} dataset
423
+ */
424
+ handleDatasetDetached(dataset) {
425
+ // the listener followed lives in that dataset: leave nothing subscribed there
426
+ if (dataset === this.#listener_ecd) {
427
+ this.#unfollow_listener();
428
+ }
429
+ }
430
+
431
+ /**
432
+ * @param {EntityManager} entityManager
433
+ * @returns {Promise<void>}
434
+ */
435
+ async shutdown(entityManager) {
436
+ // a removed system keeps no listener subscription, nor through it itself alive
437
+ this.#unfollow_listener();
438
+ }
439
+
440
+ /**
441
+ * Stop following the listener followed now, if any.
442
+ */
443
+ #unfollow_listener() {
444
+ const ecd = this.#listener_ecd;
445
+
446
+ if (ecd === null) {
447
+ return;
448
+ }
449
+
450
+ // false, harmlessly, when that entity is gone: its listeners went with it
451
+ ecd.removeEntityEventListener(this.#listener_entity, TRANSFORM64_EVENT_CHANGE, this.#on_listener_moved);
452
+ ecd.removeEntityEventListener(this.#listener_entity, EventType.EntityRemoved, this.#on_listener_removed);
453
+
454
+ this.#on_listener_removed();
455
+ }
456
+
293
457
  update(timeDelta) {
294
458
  const sopra = this.sopra;
295
459
 
@@ -309,18 +473,18 @@ export class AudioEmitterSystem extends System {
309
473
  const listenerTransform = ecd.getComponent(soundListener.entity, Transform64);
310
474
 
311
475
  if (listenerTransform !== undefined) {
476
+ this.#follow_listener(ecd, soundListener.entity, listenerTransform);
477
+
312
478
  /*
313
479
  The position stays the transform's own view: it is a live one, so a listener that
314
480
  walks needs no second write, and every consumer of it below indexes the three
315
481
  numbers rather than reading `.x`. The reverb is the exception, and reads them
316
482
  off the transform by component where it is called.
317
483
  */
318
- listenerPosition = listenerTransform.translation;
484
+ listenerPosition = this.#listener_position;
319
485
 
320
486
  // the rotation, by contrast, is handed to a renderer that steers by `q.x`
321
487
  listenerRotation = t64_read_rotation(LISTENER_ROTATION, listenerTransform);
322
-
323
- sopra.setListener(listenerPosition);
324
488
  }
325
489
  }
326
490
  }
@@ -65,14 +65,19 @@ export class LiveEmitterSet {
65
65
  * @param {number} [sourceRadius] apparent acoustic radius for volumetric occlusion (default 0.5)
66
66
  * @param {Quaternion|null} [orientation] shared source orientation ref (tracks the entity), for directivity
67
67
  * @param {AcousticDirectivity|null} [directivity] source radiation directivity (null = omni)
68
+ * @param {EffectParamOverrides|null} [effectOverrides] the emitter's own effect parameters, held by
69
+ * reference and put onto every promoted instance (null = none). Moving the live instance as they
70
+ * change is the owner's business: they reach it through {@link instanceOf}.
68
71
  */
69
- add(entity: number, event: EventDescription, position: Float64Array, gainDb?: number, acoustic?: boolean, pathing?: boolean, sourceRadius?: number, orientation?: Quaternion | null, directivity?: AcousticDirectivity | null): void;
72
+ add(entity: number, event: EventDescription, position: Float64Array, gainDb?: number, acoustic?: boolean, pathing?: boolean, sourceRadius?: number, orientation?: Quaternion | null, directivity?: AcousticDirectivity | null, effectOverrides?: EffectParamOverrides | null): void;
70
73
  /**
71
- * Report that a registered emitter moved, so the broadphase refits it. No-op for an unknown entity.
74
+ * Report that a registered emitter moved, so the broadphase refits it and its instance, if it is
75
+ * sounding, puts itself where it now is. No-op for an unknown entity.
72
76
  *
73
77
  * The position is a live view, so whatever reads it reads the current value - what the set cannot
74
78
  * do is notice that it was written. {@link refresh} considers only what this reported, which is
75
- * what keeps a dormant emitter free: nothing visits it until it moves.
79
+ * what keeps a dormant emitter free: nothing visits it until it moves. The instance is the same: it
80
+ * reads the view only when told ({@link EventInstance#moved}), a fading one included.
76
81
  * @param {number} entity
77
82
  */
78
83
  moved(entity: number): void;
@@ -107,4 +112,5 @@ export class LiveEmitterSet {
107
112
  refresh(listenerPosition: number[] | Float64Array): void;
108
113
  #private;
109
114
  }
115
+ export type EffectParamOverrides = import("../../sopra/runtime/EffectParamOverrides.js").EffectParamOverrides;
110
116
  //# sourceMappingURL=LiveEmitterSet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LiveEmitterSet.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/LiveEmitterSet.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH;IA2EI;;;OAGG;IACH,6EAFW;QAAC,MAAM,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAA;KAAC,EAO1E;IAED;;OAEG;IACH,wBAEC;IAED;;OAEG;IACH,mBAEC;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,gBAAc,SAAS,CAInC;IAED;;;;;;;;;;;OAWG;IACH,YAVW,MAAM,qCAEN,YAAY,WACZ,MAAM,aACN,OAAO,YACP,OAAO,iBACP,MAAM,gBACN,aAAW,IAAI,gBACf,sBAAoB,IAAI,QAOlC;IAED;;;;;;;OAOG;IACH,cAFW,MAAM,QAIhB;IAED;;;;OAIG;IACH,+CAFmC,IAAI,QAMtC;IAED;;;;;;;OAOG;IACH,kBAHW,MAAM,UACN,MAAM,QAehB;IAED;;;OAGG;IACH,eAFW,MAAM,QAwBhB;IAED;;;;;;;OAOG;IACH,0BAFW,MAAM,EAAE,GAAC,YAAY,QA+D/B;;CAgFJ"}
1
+ {"version":3,"file":"LiveEmitterSet.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/LiveEmitterSet.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH;IA4EI;;;OAGG;IACH,6EAFW;QAAC,MAAM,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAA;KAAC,EAO1E;IAED;;OAEG;IACH,wBAEC;IAED;;OAEG;IACH,mBAEC;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,gBAAc,SAAS,CAInC;IAED;;;;;;;;;;;;;;OAcG;IACH,YAbW,MAAM,qCAEN,YAAY,WACZ,MAAM,aACN,OAAO,YACP,OAAO,iBACP,MAAM,gBACN,aAAW,IAAI,gBACf,sBAAoB,IAAI,oBACxB,oBAAoB,GAAC,IAAI,QASnC;IAED;;;;;;;;;OASG;IACH,cAFW,MAAM,QAOhB;IAED;;;;OAIG;IACH,+CAFmC,IAAI,QAMtC;IAED;;;;;;;OAOG;IACH,kBAHW,MAAM,UACN,MAAM,QAehB;IAED;;;OAGG;IACH,eAFW,MAAM,QAwBhB;IAED;;;;;;;OAOG;IACH,0BAFW,MAAM,EAAE,GAAC,YAAY,QA+D/B;;CAuFJ;mCA/ZY,OAAO,6CAA6C,EAAE,oBAAoB"}
@@ -2,6 +2,10 @@ import { EventInstanceState } from "../../sopra/runtime/EventInstance.js";
2
2
  import { SpatialAudioIndex } from "./SpatialAudioIndex.js";
3
3
  import { v3_distance } from "../../../../core/geom/vec3/v3_distance.js";
4
4
 
5
+ /**
6
+ * @typedef {import("../../sopra/runtime/EffectParamOverrides.js").EffectParamOverrides} EffectParamOverrides
7
+ */
8
+
5
9
  /**
6
10
  * Sort rank entries nearest-first by effective (stickiness-discounted) distance.
7
11
  * @param {{effective:number}} a
@@ -72,10 +76,11 @@ export class LiveEmitterSet {
72
76
  #fadeOutSeconds;
73
77
 
74
78
  /**
75
- * entity -> { event, position, gainDb, playingSince }. `gainDb` is the per-emitter instance gain
76
- * (e.g. the owning `AudioEmitter.volume` in dB) re-applied on every promotion so it survives a
77
- * demote→re-promote cycle; `playingSince` carries the continuous-clock phase (see {@link add}).
78
- * @type {Map<number, {event: EventDescription, position: Float64Array, gainDb: number, playingSince: number, acoustic: boolean, pathing: boolean, sourceRadius: number, orientation: Quaternion|null, directivity: AcousticDirectivity|null}>}
79
+ * entity -> { event, position, gainDb, playingSince, effectOverrides, ... }. `gainDb` is the per-emitter
80
+ * instance gain (e.g. the owning `AudioEmitter.volume` in dB) and `effectOverrides` the emitter's own
81
+ * effect parameters, both re-applied on every promotion so they survive a demote→re-promote cycle;
82
+ * `playingSince` carries the continuous-clock phase (see {@link add}).
83
+ * @type {Map<number, {event: EventDescription, position: Float64Array, gainDb: number, playingSince: number, acoustic: boolean, pathing: boolean, sourceRadius: number, orientation: Quaternion|null, directivity: AcousticDirectivity|null, effectOverrides: EffectParamOverrides|null}>}
79
84
  */
80
85
  #emitters = new Map();
81
86
 
@@ -167,24 +172,32 @@ export class LiveEmitterSet {
167
172
  * @param {number} [sourceRadius] apparent acoustic radius for volumetric occlusion (default 0.5)
168
173
  * @param {Quaternion|null} [orientation] shared source orientation ref (tracks the entity), for directivity
169
174
  * @param {AcousticDirectivity|null} [directivity] source radiation directivity (null = omni)
175
+ * @param {EffectParamOverrides|null} [effectOverrides] the emitter's own effect parameters, held by
176
+ * reference and put onto every promoted instance (null = none). Moving the live instance as they
177
+ * change is the owner's business: they reach it through {@link instanceOf}.
170
178
  */
171
- add(entity, event, position, gainDb = 0, acoustic = false, pathing = false, sourceRadius = 0.5, orientation = null, directivity = null) {
179
+ add(entity, event, position, gainDb = 0, acoustic = false, pathing = false, sourceRadius = 0.5, orientation = null, directivity = null, effectOverrides = null) {
172
180
  this.#index.add(entity, event, position);
173
181
  // playingSince: continuous-clock semantics — the emitter has been "playing" since it linked, so a
174
182
  // later promotion resumes the loop at the phase it should be at (see #promote + EventInstance startTime).
175
- this.#emitters.set(entity, { event, position, gainDb, playingSince: this.#sopra.currentTime, acoustic, pathing, sourceRadius, orientation, directivity });
183
+ this.#emitters.set(entity, { event, position, gainDb, playingSince: this.#sopra.currentTime, acoustic, pathing, sourceRadius, orientation, directivity, effectOverrides });
176
184
  }
177
185
 
178
186
  /**
179
- * Report that a registered emitter moved, so the broadphase refits it. No-op for an unknown entity.
187
+ * Report that a registered emitter moved, so the broadphase refits it and its instance, if it is
188
+ * sounding, puts itself where it now is. No-op for an unknown entity.
180
189
  *
181
190
  * The position is a live view, so whatever reads it reads the current value - what the set cannot
182
191
  * do is notice that it was written. {@link refresh} considers only what this reported, which is
183
- * what keeps a dormant emitter free: nothing visits it until it moves.
192
+ * what keeps a dormant emitter free: nothing visits it until it moves. The instance is the same: it
193
+ * reads the view only when told ({@link EventInstance#moved}), a fading one included.
184
194
  * @param {number} entity
185
195
  */
186
196
  moved(entity) {
187
197
  this.#index.refresh(entity);
198
+
199
+ this.#live.get(entity)?.moved();
200
+ this.#fading.get(entity)?.moved();
188
201
  }
189
202
 
190
203
  /**
@@ -370,6 +383,13 @@ export class LiveEmitterSet {
370
383
  this.#fading.delete(entity);
371
384
  }
372
385
  });
386
+
387
+ // and the emitter's effect parameters, the way the gain is replayed: the fresh instance was built at
388
+ // the event's definition. Last, once the instance is tracked: an override the event cannot take
389
+ // throws, and must not leave a sounding instance nobody will ever stop.
390
+ if (record.effectOverrides !== null) {
391
+ record.effectOverrides.applyTo(instance);
392
+ }
373
393
  }
374
394
 
375
395
  /**
@@ -67,6 +67,10 @@ export class AudioEventTriggerRule {
67
67
  priority: number;
68
68
  stealMode: number;
69
69
  virtualThresholdDb: number;
70
+ effects: {
71
+ type: string;
72
+ data: any;
73
+ }[];
70
74
  };
71
75
  };
72
76
  fromJSON(json: any): void;
@@ -131,6 +135,10 @@ export class AudioEventTrigger {
131
135
  priority: number;
132
136
  stealMode: number;
133
137
  virtualThresholdDb: number;
138
+ effects: {
139
+ type: string;
140
+ data: any;
141
+ }[];
134
142
  };
135
143
  }[];
136
144
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AudioEventTrigger.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTrigger.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH;IAuBI;;;;;OAKG;IACH,wBALW,MAAM,SACN,gBAAgB,cAChB,MAAM,GAAC,IAAI,GACT,qBAAqB,CAUjC;IAuCD;;;OAGG;IACH,4BAFa,qBAAqB,CAMjC;IAlFD;;;;OAIG;IACH,YAFU,MAAM,CAEA;IAEhB;;;;OAIG;IACH,WAFU,MAAM,GAAC,IAAI,CAEJ;IAEjB;;;;OAIG;IACH,OAFU,gBAAgB,CAEK;IAkB/B;;;OAGG;IACH,cAHW,qBAAqB,GACnB,OAAO,CAMnB;IAED,eAMC;IAED;;;;;;;;;;;;;;;;;;;;;;;MAMC;IAED,0BASC;CAWJ;AAED;;;;;;;;GAQG;AACH;IAcI;;;OAGG;IACH,mBAHW,qBAAqB,EAAE,GACrB,iBAAiB,CAQ7B;IA6CD;;;OAGG;IACH,4BAFa,iBAAiB,CAM7B;IA3ED;;;;;;;;;OASG;IACH,OAFU,qBAAqB,EAAE,CAEtB;IAcX;;;OAGG;IACH,cAHW,iBAAiB,GACf,OAAO,CAiBnB;IAED,eAUC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;MAIC;IAED,0BAEC;CAWJ;;;;iCA1LgC,4CAA4C"}
1
+ {"version":3,"file":"AudioEventTrigger.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTrigger.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH;IAuBI;;;;;OAKG;IACH,wBALW,MAAM,SACN,gBAAgB,cAChB,MAAM,GAAC,IAAI,GACT,qBAAqB,CAUjC;IAuCD;;;OAGG;IACH,4BAFa,qBAAqB,CAMjC;IAlFD;;;;OAIG;IACH,YAFU,MAAM,CAEA;IAEhB;;;;OAIG;IACH,WAFU,MAAM,GAAC,IAAI,CAEJ;IAEjB;;;;OAIG;IACH,OAFU,gBAAgB,CAEK;IAkB/B;;;OAGG;IACH,cAHW,qBAAqB,GACnB,OAAO,CAMnB;IAED,eAMC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;MAMC;IAED,0BASC;CAWJ;AAED;;;;;;;;GAQG;AACH;IAcI;;;OAGG;IACH,mBAHW,qBAAqB,EAAE,GACrB,iBAAiB,CAQ7B;IA6CD;;;OAGG;IACH,4BAFa,iBAAiB,CAM7B;IA3ED;;;;;;;;;OASG;IACH,OAFU,qBAAqB,EAAE,CAEtB;IAcX;;;OAGG;IACH,cAHW,iBAAiB,GACf,OAAO,CAiBnB;IAED,eAUC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAIC;IAED,0BAEC;CAWJ;;;;iCA1LgC,4CAA4C"}
@@ -1 +1 @@
1
- {"version":3,"file":"AudioEventTriggerSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH;;IACI,gCAA0B;IAQ1B;;;OAGG;IACH,mFAEC;IAED;;;OAGG;IACH,uCAFW,iBAAiB,QAuB3B;IAED;;;OAGG;IACH,yCAFW,iBAAiB,QAmB3B;;CACJ;gDAhF+C,gEAAgE;kCAEvD,wBAAwB"}
1
+ {"version":3,"file":"AudioEventTriggerSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH;;IACI,gCAA0B;IAY1B;;;OAGG;IACH,mFAEC;IAED;;;OAGG;IACH,uCAFW,iBAAiB,QAuB3B;IAED;;;OAGG;IACH,yCAFW,iBAAiB,QAmB3B;;CACJ;gDApF+C,gEAAgE;kCAEvD,wBAAwB"}
@@ -14,7 +14,11 @@ import { AudioEventTrigger, AudioEventTriggerRule } from "./AudioEventTrigger.js
14
14
  */
15
15
  export class AudioEventTriggerSerializationAdapter extends BinaryClassSerializationAdapter {
16
16
  klass = AudioEventTrigger;
17
- version = 0;
17
+ /**
18
+ * 1: the embedded event record moved to its format 1 (insert effects) — `AudioEventTriggerSerializationUpgrader_0_1`.
19
+ * @type {number}
20
+ */
21
+ version = 1;
18
22
 
19
23
  /**
20
24
  * @type {EventDescriptionSerializationAdapter}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @typedef {import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry} BinarySerializationRegistry
3
+ */
4
+ /**
5
+ * Version 0 → 1: each rule's embedded {@link EventDescription} record moved to its own format 1 (insert
6
+ * effects). The record carries no version tag of its own, so the component's version is what says which
7
+ * layout it is in; the rule's other fields are unchanged.
8
+ */
9
+ export class AudioEventTriggerSerializationUpgrader_0_1 extends BinaryClassUpgrader {
10
+ /**
11
+ * @param {BinarySerializationRegistry} registry where the events' clip types are registered
12
+ */
13
+ constructor(registry: BinarySerializationRegistry);
14
+ #private;
15
+ }
16
+ export type BinarySerializationRegistry = import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry;
17
+ import { BinaryClassUpgrader } from "../../../ecs/storage/binary/BinaryClassUpgrader.js";
18
+ //# sourceMappingURL=AudioEventTriggerSerializationUpgrader_0_1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioEventTriggerSerializationUpgrader_0_1.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js"],"names":[],"mappings":"AAMA;;GAEG;AAEH;;;;GAIG;AACH;IASI;;OAEG;IACH,sBAFW,2BAA2B,EAMrC;;CAmBJ;0CA3CY,OAAO,4DAA4D,EAAE,2BAA2B;oCANzE,oDAAoD"}