@pmndrs/klipp 0.0.0-stage → 0.14.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 (270) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -2
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/core/CameraState.d.ts +32 -0
  5. package/dist/core/CameraState.js +97 -0
  6. package/dist/core/EventDispatcher.d.ts +18 -0
  7. package/dist/core/EventDispatcher.js +28 -0
  8. package/dist/core/Klipp.d.ts +109 -0
  9. package/dist/core/Klipp.js +253 -0
  10. package/dist/core/TargetExtent.d.ts +11 -0
  11. package/dist/core/TargetExtent.js +54 -0
  12. package/dist/core/TargetPose.d.ts +13 -0
  13. package/dist/core/TargetPose.js +21 -0
  14. package/dist/core/VirtualCamera.d.ts +102 -0
  15. package/dist/core/VirtualCamera.js +290 -0
  16. package/dist/core/aim/HardLookAtAim.d.ts +10 -0
  17. package/dist/core/aim/HardLookAtAim.js +19 -0
  18. package/dist/core/aim/PanTiltAim.d.ts +26 -0
  19. package/dist/core/aim/PanTiltAim.js +38 -0
  20. package/dist/core/aim/RotateWithFollowTargetAim.d.ts +19 -0
  21. package/dist/core/aim/RotateWithFollowTargetAim.js +23 -0
  22. package/dist/core/aim/RotationComposerAim.d.ts +27 -0
  23. package/dist/core/aim/RotationComposerAim.js +27 -0
  24. package/dist/core/aim/hardLookAt.d.ts +4 -0
  25. package/dist/core/aim/hardLookAt.js +13 -0
  26. package/dist/core/aim/index.d.ts +11 -0
  27. package/dist/core/aim/lookRotation.d.ts +6 -0
  28. package/dist/core/aim/lookRotation.js +46 -0
  29. package/dist/core/aim/panTilt.d.ts +16 -0
  30. package/dist/core/aim/panTilt.js +121 -0
  31. package/dist/core/aim/rotateWithFollowTarget.d.ts +20 -0
  32. package/dist/core/aim/rotateWithFollowTarget.js +35 -0
  33. package/dist/core/aim/rotationComposer.d.ts +58 -0
  34. package/dist/core/aim/rotationComposer.js +284 -0
  35. package/dist/core/blend/BlendCurves.d.ts +19 -0
  36. package/dist/core/blend/BlendCurves.js +22 -0
  37. package/dist/core/blend/BlendDefinition.d.ts +21 -0
  38. package/dist/core/blend/BlendDefinition.js +9 -0
  39. package/dist/core/blend/BlendDriver.d.ts +23 -0
  40. package/dist/core/blend/BlendDriver.js +42 -0
  41. package/dist/core/blend/BlendHints.d.ts +9 -0
  42. package/dist/core/blend/BlendHints.js +13 -0
  43. package/dist/core/blend/blend.d.ts +41 -0
  44. package/dist/core/blend/blend.js +110 -0
  45. package/dist/core/blend/index.d.ts +6 -0
  46. package/dist/core/blend/lerpCameraState.d.ts +4 -0
  47. package/dist/core/blend/lerpCameraState.js +143 -0
  48. package/dist/core/body/BindingModes.d.ts +9 -0
  49. package/dist/core/body/BindingModes.js +11 -0
  50. package/dist/core/body/FollowBody.d.ts +24 -0
  51. package/dist/core/body/FollowBody.js +26 -0
  52. package/dist/core/body/HardLockToTargetBody.d.ts +17 -0
  53. package/dist/core/body/HardLockToTargetBody.js +20 -0
  54. package/dist/core/body/OrbitFollowBody.d.ts +47 -0
  55. package/dist/core/body/OrbitFollowBody.js +48 -0
  56. package/dist/core/body/PositionComposerBody.d.ts +28 -0
  57. package/dist/core/body/PositionComposerBody.js +27 -0
  58. package/dist/core/body/follow.d.ts +33 -0
  59. package/dist/core/body/follow.js +83 -0
  60. package/dist/core/body/hardLockToTarget.d.ts +17 -0
  61. package/dist/core/body/hardLockToTarget.js +26 -0
  62. package/dist/core/body/index.d.ts +17 -0
  63. package/dist/core/body/orbitFollow.d.ts +76 -0
  64. package/dist/core/body/orbitFollow.js +336 -0
  65. package/dist/core/body/positionComposer.d.ts +56 -0
  66. package/dist/core/body/positionComposer.js +207 -0
  67. package/dist/core/body/safeFromToRotation.d.ts +3 -0
  68. package/dist/core/body/safeFromToRotation.js +39 -0
  69. package/dist/core/body/threeRing.d.ts +28 -0
  70. package/dist/core/body/threeRing.js +100 -0
  71. package/dist/core/body/tracker.d.ts +42 -0
  72. package/dist/core/body/tracker.js +193 -0
  73. package/dist/core/damping/Damper.d.ts +11 -0
  74. package/dist/core/damping/Damper.js +22 -0
  75. package/dist/core/damping/damping.d.ts +30 -0
  76. package/dist/core/damping/damping.js +119 -0
  77. package/dist/core/damping/index.d.ts +5 -0
  78. package/dist/core/damping/predictor.d.ts +16 -0
  79. package/dist/core/damping/predictor.js +56 -0
  80. package/dist/core/debug/debugZones.d.ts +16 -0
  81. package/dist/core/debug/debugZones.js +38 -0
  82. package/dist/core/debug/index.d.ts +2 -0
  83. package/dist/core/extension/GroupFramingExtension.d.ts +26 -0
  84. package/dist/core/extension/GroupFramingExtension.js +24 -0
  85. package/dist/core/extension/LensExtension.d.ts +20 -0
  86. package/dist/core/extension/LensExtension.js +12 -0
  87. package/dist/core/extension/groupFraming.d.ts +62 -0
  88. package/dist/core/extension/groupFraming.js +271 -0
  89. package/dist/core/extension/index.d.ts +6 -0
  90. package/dist/core/extension/lens.d.ts +35 -0
  91. package/dist/core/extension/lens.js +57 -0
  92. package/dist/core/groups/ClearShot.d.ts +32 -0
  93. package/dist/core/groups/MixingCamera.d.ts +20 -0
  94. package/dist/core/groups/Sequencer.d.ts +24 -0
  95. package/dist/core/groups/StateDrivenCamera.d.ts +26 -0
  96. package/dist/core/groups/clearShotState.d.ts +32 -0
  97. package/dist/core/groups/index.d.ts +11 -0
  98. package/dist/core/groups/mixCameraStates.d.ts +13 -0
  99. package/dist/core/groups/sequencerState.d.ts +26 -0
  100. package/dist/core/groups/stateDrivenState.d.ts +28 -0
  101. package/dist/core/impulse/ImpulseField.d.ts +15 -0
  102. package/dist/core/impulse/ImpulseField.js +22 -0
  103. package/dist/core/impulse/ImpulseListenerNoise.d.ts +19 -0
  104. package/dist/core/impulse/ImpulseListenerNoise.js +29 -0
  105. package/dist/core/impulse/impulseListener.d.ts +13 -0
  106. package/dist/core/impulse/impulseListener.js +14 -0
  107. package/dist/core/impulse/impulses.d.ts +54 -0
  108. package/dist/core/impulse/impulses.js +84 -0
  109. package/dist/core/impulse/index.d.ts +6 -0
  110. package/dist/core/index.d.ts +20 -0
  111. package/dist/core/index.js +52 -0
  112. package/dist/core/input/InputAxis.d.ts +29 -0
  113. package/dist/core/input/InputAxis.js +28 -0
  114. package/dist/core/input/InputAxisOwner.d.ts +6 -0
  115. package/dist/core/input/InputAxisOwner.js +4 -0
  116. package/dist/core/input/InputController.d.ts +15 -0
  117. package/dist/core/input/InputController.js +24 -0
  118. package/dist/core/input/axis.d.ts +52 -0
  119. package/dist/core/input/axis.js +89 -0
  120. package/dist/core/input/consumedInput.d.ts +37 -0
  121. package/dist/core/input/consumedInput.js +34 -0
  122. package/dist/core/input/index.d.ts +9 -0
  123. package/dist/core/input/inputMapping.d.ts +46 -0
  124. package/dist/core/input/inputMapping.js +55 -0
  125. package/dist/core/input/shortestWrappedDelta.d.ts +2 -0
  126. package/dist/core/input/shortestWrappedDelta.js +11 -0
  127. package/dist/core/internal.d.ts +16 -0
  128. package/dist/core/internal.js +19 -0
  129. package/dist/core/klippState.d.ts +78 -0
  130. package/dist/core/klippState.js +124 -0
  131. package/dist/core/noise/BasicMultiChannelPerlinNoise.d.ts +21 -0
  132. package/dist/core/noise/BasicMultiChannelPerlinNoise.js +13 -0
  133. package/dist/core/noise/index.d.ts +3 -0
  134. package/dist/core/noise/perlinNoise.d.ts +36 -0
  135. package/dist/core/noise/perlinNoise.js +110 -0
  136. package/dist/core/params.d.ts +2 -0
  137. package/dist/core/params.js +12 -0
  138. package/dist/dom/DebugOverlay.d.ts +11 -0
  139. package/dist/dom/DebugOverlay.js +96 -0
  140. package/dist/dom/InputControllerDom.d.ts +15 -0
  141. package/dist/dom/InputControllerDom.js +31 -0
  142. package/dist/dom/InputSystem.d.ts +40 -0
  143. package/dist/dom/InputSystem.js +113 -0
  144. package/dist/dom/index.d.ts +3 -0
  145. package/dist/dom/index.js +5 -0
  146. package/dist/input-sources/buttonInput.d.ts +15 -0
  147. package/dist/input-sources/buttonInput.js +23 -0
  148. package/dist/input-sources/isInsideInteractiveArea.d.ts +9 -0
  149. package/dist/input-sources/isInsideInteractiveArea.js +11 -0
  150. package/dist/input-sources/mouse.d.ts +47 -0
  151. package/dist/input-sources/mouse.js +171 -0
  152. package/dist/input-sources/safariGesture.d.ts +32 -0
  153. package/dist/input-sources/safariGesture.js +107 -0
  154. package/dist/input-sources/suppressNativeGestures.d.ts +5 -0
  155. package/dist/input-sources/suppressNativeGestures.js +32 -0
  156. package/dist/input-sources/touch.d.ts +47 -0
  157. package/dist/input-sources/touch.js +173 -0
  158. package/dist/input-sources/wheel.d.ts +28 -0
  159. package/dist/input-sources/wheel.js +44 -0
  160. package/dist/react/CameraFrustumHelper.d.ts +13 -0
  161. package/dist/react/CameraFrustumHelper.js +32 -0
  162. package/dist/react/DebugZoneOverlay.d.ts +7 -0
  163. package/dist/react/DebugZoneOverlay.js +23 -0
  164. package/dist/react/Klipp.d.ts +20 -0
  165. package/dist/react/Klipp.js +47 -0
  166. package/dist/react/KlippContext.d.ts +5 -0
  167. package/dist/react/KlippContext.js +11 -0
  168. package/dist/react/VirtualCamera.d.ts +28 -0
  169. package/dist/react/VirtualCamera.js +81 -0
  170. package/dist/react/VirtualCameraContext.d.ts +11 -0
  171. package/dist/react/VirtualCameraContext.js +21 -0
  172. package/dist/react/aim/Aim.d.ts +11 -0
  173. package/dist/react/aim/Aim.js +14 -0
  174. package/dist/react/aim/HardLookAt.d.ts +10 -0
  175. package/dist/react/aim/HardLookAt.js +15 -0
  176. package/dist/react/aim/PanTilt.d.ts +31 -0
  177. package/dist/react/aim/PanTilt.js +38 -0
  178. package/dist/react/aim/RotateWithFollowTarget.d.ts +10 -0
  179. package/dist/react/aim/RotateWithFollowTarget.js +18 -0
  180. package/dist/react/aim/RotationComposer.d.ts +12 -0
  181. package/dist/react/aim/RotationComposer.js +34 -0
  182. package/dist/react/body/Body.d.ts +11 -0
  183. package/dist/react/body/Body.js +14 -0
  184. package/dist/react/body/CameraControls.d.ts +50 -0
  185. package/dist/react/body/CameraControls.js +106 -0
  186. package/dist/react/body/Follow.d.ts +10 -0
  187. package/dist/react/body/Follow.js +20 -0
  188. package/dist/react/body/HardLockToTarget.d.ts +10 -0
  189. package/dist/react/body/HardLockToTarget.js +18 -0
  190. package/dist/react/body/OrbitFollow.d.ts +25 -0
  191. package/dist/react/body/OrbitFollow.js +67 -0
  192. package/dist/react/body/PositionComposer.d.ts +12 -0
  193. package/dist/react/body/PositionComposer.js +32 -0
  194. package/dist/react/body/camera-controls.d.ts +2 -0
  195. package/dist/react/body/camera-controls.js +3 -0
  196. package/dist/react/extension/Extension.d.ts +7 -0
  197. package/dist/react/extension/Extension.js +10 -0
  198. package/dist/react/extension/GroupFraming.d.ts +14 -0
  199. package/dist/react/extension/GroupFraming.js +52 -0
  200. package/dist/react/extension/Lens.d.ts +7 -0
  201. package/dist/react/extension/Lens.js +31 -0
  202. package/dist/react/impulse/ImpulseListener.d.ts +12 -0
  203. package/dist/react/impulse/ImpulseListener.js +33 -0
  204. package/dist/react/index.d.ts +24 -0
  205. package/dist/react/index.js +24 -0
  206. package/dist/react/input/InputAxisOwnerContext.d.ts +3 -0
  207. package/dist/react/input/InputAxisOwnerContext.js +6 -0
  208. package/dist/react/input/InputController.d.ts +53 -0
  209. package/dist/react/input/InputController.js +115 -0
  210. package/dist/react/noise/BasicMultiChannelPerlin.d.ts +7 -0
  211. package/dist/react/noise/BasicMultiChannelPerlin.js +14 -0
  212. package/dist/react/noise/Noise.d.ts +5 -0
  213. package/dist/react/noise/Noise.js +6 -0
  214. package/dist/react/noise/useBasicMultiChannelPerlinNoise.d.ts +4 -0
  215. package/dist/react/noise/useBasicMultiChannelPerlinNoise.js +21 -0
  216. package/dist/react/useCameraTransitionEvent.d.ts +12 -0
  217. package/dist/react/useCameraTransitionEvent.js +14 -0
  218. package/dist/three/CameraFrustumHelperThree.d.ts +11 -0
  219. package/dist/three/CameraFrustumHelperThree.js +44 -0
  220. package/dist/three/KlippThree.d.ts +18 -0
  221. package/dist/three/KlippThree.js +50 -0
  222. package/dist/three/VirtualCameraThree.d.ts +35 -0
  223. package/dist/three/VirtualCameraThree.js +108 -0
  224. package/dist/three/aim/HardLookAtAimThree.d.ts +10 -0
  225. package/dist/three/aim/HardLookAtAimThree.js +14 -0
  226. package/dist/three/aim/PanTiltAimThree.d.ts +10 -0
  227. package/dist/three/aim/PanTiltAimThree.js +15 -0
  228. package/dist/three/aim/RotateWithFollowTargetAimThree.d.ts +11 -0
  229. package/dist/three/aim/RotateWithFollowTargetAimThree.js +15 -0
  230. package/dist/three/aim/RotationComposerAimThree.d.ts +26 -0
  231. package/dist/three/aim/RotationComposerAimThree.js +35 -0
  232. package/dist/three/body/CameraControlsBodyThree.d.ts +30 -0
  233. package/dist/three/body/CameraControlsBodyThree.js +54 -0
  234. package/dist/three/body/FollowBodyThree.d.ts +16 -0
  235. package/dist/three/body/FollowBodyThree.js +23 -0
  236. package/dist/three/body/HardLockToTargetBodyThree.d.ts +11 -0
  237. package/dist/three/body/HardLockToTargetBodyThree.js +14 -0
  238. package/dist/three/body/OrbitFollowBodyThree.d.ts +16 -0
  239. package/dist/three/body/OrbitFollowBodyThree.js +23 -0
  240. package/dist/three/body/OrbitFollowHelperThree.d.ts +23 -0
  241. package/dist/three/body/OrbitFollowHelperThree.js +85 -0
  242. package/dist/three/body/PositionComposerBodyThree.d.ts +24 -0
  243. package/dist/three/body/PositionComposerBodyThree.js +31 -0
  244. package/dist/three/camera.d.ts +10 -0
  245. package/dist/three/camera.js +39 -0
  246. package/dist/three/damping/Predictor.d.ts +12 -0
  247. package/dist/three/damping/Predictor.js +30 -0
  248. package/dist/three/damping/QuaternionDamper.d.ts +10 -0
  249. package/dist/three/damping/QuaternionDamper.js +28 -0
  250. package/dist/three/damping/Vector3Damper.d.ts +10 -0
  251. package/dist/three/damping/Vector3Damper.js +26 -0
  252. package/dist/three/extension/GroupFramingExtensionThree.d.ts +13 -0
  253. package/dist/three/extension/GroupFramingExtensionThree.js +23 -0
  254. package/dist/three/extension/TargetGroup.d.ts +32 -0
  255. package/dist/three/extension/TargetGroup.js +53 -0
  256. package/dist/three/index.d.ts +24 -0
  257. package/dist/three/index.js +25 -0
  258. package/dist/three/noise/BasicMultiChannelPerlinNoiseThree.d.ts +16 -0
  259. package/dist/three/noise/BasicMultiChannelPerlinNoiseThree.js +17 -0
  260. package/dist/three/readTargetExtent.d.ts +9 -0
  261. package/dist/three/readTargetExtent.js +25 -0
  262. package/dist/three/readTargetPose.d.ts +8 -0
  263. package/dist/three/readTargetPose.js +21 -0
  264. package/dist/three/resolve/Target.d.ts +17 -0
  265. package/dist/three/resolve/Target.js +62 -0
  266. package/dist/three/resolve/TargetRegistry.d.ts +27 -0
  267. package/dist/three/resolve/TargetRegistry.js +78 -0
  268. package/dist/three/resolve/resolveVector3.d.ts +12 -0
  269. package/dist/three/resolve/resolveVector3.js +29 -0
  270. package/package.json +120 -4
@@ -0,0 +1,271 @@
1
+ import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
+ import { createState as createState$1, damp, reset } from "../damping/damping.js";
3
+ import { create } from "../TargetExtent.js";
4
+ import { withDefaults } from "../params.js";
5
+ import { clamp, degreesToRadians, vec3 } from "math";
6
+ //#region src/core/extension/groupFraming.ts
7
+ var groupFraming_exports = /* @__PURE__ */ __exportAll({
8
+ computeBounds: () => computeBounds,
9
+ createMember: () => createMember,
10
+ createParams: () => createParams,
11
+ createState: () => createState,
12
+ horizontalHalfFov: () => horizontalHalfFov,
13
+ update: () => update
14
+ });
15
+ var createMember = () => ({
16
+ position: [
17
+ 0,
18
+ 0,
19
+ 0
20
+ ],
21
+ extent: create(),
22
+ weight: 1,
23
+ resolved: true
24
+ });
25
+ /** Every setting from `settings`, or its default. */
26
+ var createParams = (settings) => withDefaults({
27
+ padding: 0,
28
+ viewportWidth: 1,
29
+ viewportHeight: 1,
30
+ damping: 0,
31
+ maxSpeed: Infinity,
32
+ screenPosition: [0, 0],
33
+ fitMode: "ceiling",
34
+ minDistance: 0,
35
+ maxDistance: Infinity,
36
+ framingMode: "horizontalAndVertical"
37
+ }, settings);
38
+ var createState = () => ({
39
+ distanceDamper: createState$1(),
40
+ screenPositionXDamper: createState$1(),
41
+ screenPositionYDamper: createState$1(),
42
+ currentDistance: 0,
43
+ currentScreenPosition: [0, 0]
44
+ });
45
+ var scratchMin = [
46
+ 0,
47
+ 0,
48
+ 0
49
+ ];
50
+ var scratchMax = [
51
+ 0,
52
+ 0,
53
+ 0
54
+ ];
55
+ var scratchAccumulator = [
56
+ 0,
57
+ 0,
58
+ 0
59
+ ];
60
+ var scratchGroupPosition = [
61
+ 0,
62
+ 0,
63
+ 0
64
+ ];
65
+ var scratchRight = [
66
+ 0,
67
+ 0,
68
+ 0
69
+ ];
70
+ var scratchUp = [
71
+ 0,
72
+ 0,
73
+ 0
74
+ ];
75
+ var scratchForward = [
76
+ 0,
77
+ 0,
78
+ 0
79
+ ];
80
+ var scratchOffset = [
81
+ 0,
82
+ 0,
83
+ 0
84
+ ];
85
+ var scratchAxisX = [
86
+ 0,
87
+ 0,
88
+ 0
89
+ ];
90
+ var scratchAxisY = [
91
+ 0,
92
+ 0,
93
+ 0
94
+ ];
95
+ var scratchAxisZ = [
96
+ 0,
97
+ 0,
98
+ 0
99
+ ];
100
+ var scratchBackward = [
101
+ 0,
102
+ 0,
103
+ 0
104
+ ];
105
+ var rightAxis = [
106
+ 1,
107
+ 0,
108
+ 0
109
+ ];
110
+ var upAxis = [
111
+ 0,
112
+ 1,
113
+ 0
114
+ ];
115
+ var forwardAxis = [
116
+ 0,
117
+ 0,
118
+ -1
119
+ ];
120
+ var backwardAxis = [
121
+ 0,
122
+ 0,
123
+ 1
124
+ ];
125
+ var CORNER_SIGNS = [-1, 1];
126
+ /** A member's enclosing radius: a box's half-diagonal, otherwise its sphere radius. */
127
+ var fallbackRadius = (member) => member.extent.hasSize ? vec3.length(member.extent.size) / 2 : member.extent.radius;
128
+ function computeCenterPosition(out, members) {
129
+ let any = false;
130
+ for (const member of members) {
131
+ if (!member.resolved) continue;
132
+ const radius = fallbackRadius(member);
133
+ const p = member.position;
134
+ if (!any) {
135
+ vec3.subtractScalar(scratchMin, p, radius);
136
+ vec3.addScalar(scratchMax, p, radius);
137
+ any = true;
138
+ continue;
139
+ }
140
+ scratchMin[0] = Math.min(scratchMin[0], p[0] - radius);
141
+ scratchMin[1] = Math.min(scratchMin[1], p[1] - radius);
142
+ scratchMin[2] = Math.min(scratchMin[2], p[2] - radius);
143
+ scratchMax[0] = Math.max(scratchMax[0], p[0] + radius);
144
+ scratchMax[1] = Math.max(scratchMax[1], p[1] + radius);
145
+ scratchMax[2] = Math.max(scratchMax[2], p[2] + radius);
146
+ }
147
+ if (!any) return false;
148
+ vec3.scale(out, vec3.add(out, scratchMin, scratchMax), .5);
149
+ return true;
150
+ }
151
+ function computeAveragePosition(out, members) {
152
+ let totalWeight = 0;
153
+ vec3.set(scratchAccumulator, 0, 0, 0);
154
+ for (const member of members) {
155
+ if (member.weight <= 0 || !member.resolved) continue;
156
+ vec3.scaleAndAdd(scratchAccumulator, scratchAccumulator, member.position, member.weight);
157
+ totalWeight += member.weight;
158
+ }
159
+ if (totalWeight <= 0) return false;
160
+ vec3.scale(out, scratchAccumulator, 1 / totalWeight);
161
+ return true;
162
+ }
163
+ /**
164
+ * Writes the group position to `outPosition` and returns a conservative enclosing radius, or -1 (leaving
165
+ * `outPosition` untouched) when no member is resolved.
166
+ */
167
+ function computeBounds(outPosition, members, mode) {
168
+ if (!(mode === "groupAverage" ? computeAveragePosition(outPosition, members) : computeCenterPosition(outPosition, members))) return -1;
169
+ let radius = 0;
170
+ for (const member of members) {
171
+ if (!member.resolved) continue;
172
+ const reach = vec3.distance(member.position, outPosition) + fallbackRadius(member);
173
+ if (reach > radius) radius = reach;
174
+ }
175
+ return radius;
176
+ }
177
+ /** Half the horizontal field of view, in radians, for a vertical half-FOV and aspect ratio. */
178
+ var horizontalHalfFov = (verticalHalfFov, aspect) => Math.atan(Math.tan(verticalHalfFov) * aspect);
179
+ /**
180
+ * Keeps the group inside the frame by moving `out` along its own view axis and easing `viewOffset` to
181
+ * `screenPosition`. Returns true while still moving.
182
+ */
183
+ function update(out, state, params, members, positionMode, dt, justActivated) {
184
+ if (justActivated) {
185
+ reset(state.distanceDamper);
186
+ reset(state.screenPositionXDamper);
187
+ reset(state.screenPositionYDamper);
188
+ }
189
+ const boundsRadius = computeBounds(scratchGroupPosition, members, positionMode);
190
+ if (boundsRadius < 0 || boundsRadius === 0 && params.padding <= 0) return false;
191
+ const verticalHalfFov = degreesToRadians(out.fov) / 2;
192
+ const horizontalHalf = horizontalHalfFov(verticalHalfFov, params.viewportWidth / params.viewportHeight);
193
+ vec3.transformQuat(scratchRight, rightAxis, out.quaternion);
194
+ vec3.transformQuat(scratchUp, upAxis, out.quaternion);
195
+ vec3.transformQuat(scratchForward, forwardAxis, out.quaternion);
196
+ const includeVertical = params.framingMode !== "horizontal";
197
+ const includeHorizontal = params.framingMode !== "vertical";
198
+ const padding = Math.max(0, params.padding);
199
+ const tanVertical = Math.tan(verticalHalfFov);
200
+ const tanHorizontal = Math.tan(horizontalHalf);
201
+ const sinVertical = Math.sin(verticalHalfFov);
202
+ const sinHorizontal = Math.sin(horizontalHalf);
203
+ const cosVertical = Math.cos(verticalHalfFov);
204
+ const cosHorizontal = Math.cos(horizontalHalf);
205
+ let requiredDistance = 0;
206
+ for (const member of members) {
207
+ if (!member.resolved) continue;
208
+ vec3.subtract(scratchOffset, member.position, scratchGroupPosition);
209
+ const offsetUp = vec3.dot(scratchOffset, scratchUp);
210
+ const offsetRight = vec3.dot(scratchOffset, scratchRight);
211
+ const offsetForward = vec3.dot(scratchOffset, scratchForward);
212
+ const { extent } = member;
213
+ if (extent.hasSize) {
214
+ const { size, rotation } = extent;
215
+ vec3.transformQuat(scratchAxisX, vec3.set(scratchAxisX, size[0] * .5, 0, 0), rotation);
216
+ vec3.transformQuat(scratchAxisY, vec3.set(scratchAxisY, 0, size[1] * .5, 0), rotation);
217
+ vec3.transformQuat(scratchAxisZ, vec3.set(scratchAxisZ, 0, 0, size[2] * .5), rotation);
218
+ const axisXUp = vec3.dot(scratchAxisX, scratchUp);
219
+ const axisYUp = vec3.dot(scratchAxisY, scratchUp);
220
+ const axisZUp = vec3.dot(scratchAxisZ, scratchUp);
221
+ const axisXRight = vec3.dot(scratchAxisX, scratchRight);
222
+ const axisYRight = vec3.dot(scratchAxisY, scratchRight);
223
+ const axisZRight = vec3.dot(scratchAxisZ, scratchRight);
224
+ const axisXForward = vec3.dot(scratchAxisX, scratchForward);
225
+ const axisYForward = vec3.dot(scratchAxisY, scratchForward);
226
+ const axisZForward = vec3.dot(scratchAxisZ, scratchForward);
227
+ for (const sx of CORNER_SIGNS) for (const sy of CORNER_SIGNS) for (const sz of CORNER_SIGNS) {
228
+ const cornerUp = offsetUp + sx * axisXUp + sy * axisYUp + sz * axisZUp;
229
+ const cornerRight = offsetRight + sx * axisXRight + sy * axisYRight + sz * axisZRight;
230
+ const cornerForward = offsetForward + sx * axisXForward + sy * axisYForward + sz * axisZForward;
231
+ if (includeVertical) requiredDistance = Math.max(requiredDistance, (Math.abs(cornerUp) + padding) / tanVertical - cornerForward);
232
+ if (includeHorizontal) requiredDistance = Math.max(requiredDistance, (Math.abs(cornerRight) + padding) / tanHorizontal - cornerForward);
233
+ }
234
+ } else {
235
+ const effectiveRadius = extent.radius + padding;
236
+ if (includeVertical) {
237
+ const vertical = (effectiveRadius + Math.abs(offsetUp) * cosVertical) / sinVertical - offsetForward;
238
+ requiredDistance = Math.max(requiredDistance, vertical);
239
+ }
240
+ if (includeHorizontal) {
241
+ const horizontal = (effectiveRadius + Math.abs(offsetRight) * cosHorizontal) / sinHorizontal - offsetForward;
242
+ requiredDistance = Math.max(requiredDistance, horizontal);
243
+ }
244
+ }
245
+ }
246
+ const clampedRequiredDistance = clamp(requiredDistance, params.minDistance, params.maxDistance);
247
+ const distance = params.fitMode === "rigid" ? clampedRequiredDistance : Math.max(vec3.distance(out.position, scratchGroupPosition), clampedRequiredDistance);
248
+ const instant = typeof params.damping === "number" && params.damping <= 0;
249
+ if (instant) state.currentDistance = distance;
250
+ else {
251
+ state.distanceDamper.value = state.currentDistance;
252
+ state.currentDistance = damp(state.distanceDamper, distance, params.damping, dt, params.maxSpeed).value;
253
+ }
254
+ vec3.transformQuat(scratchBackward, backwardAxis, out.quaternion);
255
+ vec3.scaleAndAdd(out.position, scratchGroupPosition, scratchBackward, state.currentDistance);
256
+ const current = state.currentScreenPosition;
257
+ if (instant) {
258
+ current[0] = params.screenPosition[0];
259
+ current[1] = params.screenPosition[1];
260
+ } else {
261
+ state.screenPositionXDamper.value = current[0];
262
+ current[0] = damp(state.screenPositionXDamper, params.screenPosition[0], params.damping, dt).value;
263
+ state.screenPositionYDamper.value = current[1];
264
+ current[1] = damp(state.screenPositionYDamper, params.screenPosition[1], params.damping, dt).value;
265
+ }
266
+ out.viewOffset[0] = current[0];
267
+ out.viewOffset[1] = current[1];
268
+ return state.currentDistance !== distance || current[0] !== params.screenPosition[0] || current[1] !== params.screenPosition[1];
269
+ }
270
+ //#endregion
271
+ export { computeBounds, createMember, createParams, createState, groupFraming_exports, horizontalHalfFov, update };
@@ -0,0 +1,6 @@
1
+ export { LensExtension, type LensOptions } from './LensExtension.js';
2
+ export * as lens from './lens.js';
3
+ export type { LensParams, LensState } from './lens.js';
4
+ export { GroupFramingExtension, type GroupFramingOptions } from './GroupFramingExtension.js';
5
+ export * as groupFraming from './groupFraming.js';
6
+ export type { GroupMember, GroupPositionMode, GroupFramingParams, GroupFramingState, GroupFramingFitMode, GroupFramingMode, } from './groupFraming.js';
@@ -0,0 +1,35 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { DamperState, DampingConstant } from '../damping/damping.js';
3
+ export type LensParams = {
4
+ /** Overrides the camera's field of view, in degrees. `undefined` leaves the current value untouched. */
5
+ fov?: number;
6
+ /** Overrides the near clip plane. `undefined` leaves the current value untouched. */
7
+ near?: number;
8
+ /** Overrides the far clip plane. `undefined` leaves the current value untouched. */
9
+ far?: number;
10
+ /** Spring response time to `fov` as it changes. `0` is instant. */
11
+ fovDamping: DampingConstant;
12
+ /** Spring response time to `near` as it changes. `0` is instant. */
13
+ nearDamping: DampingConstant;
14
+ /** Spring response time to `far` as it changes. `0` is instant. */
15
+ farDamping: DampingConstant;
16
+ /** Caps how fast `fovDamping` can close the gap, in degrees/sec. `Infinity` means no cap. */
17
+ fovMaxSpeed: number;
18
+ /** Caps how fast `nearDamping` can close the gap, in world units/sec. `Infinity` means no cap. */
19
+ nearMaxSpeed: number;
20
+ /** Caps how fast `farDamping` can close the gap, in world units/sec. `Infinity` means no cap. */
21
+ farMaxSpeed: number;
22
+ };
23
+ /** Every setting from `settings`, or its default. */
24
+ export declare const createParams: (settings?: Partial<LensParams>) => LensParams;
25
+ export type LensState = {
26
+ fovDamper: DamperState;
27
+ nearDamper: DamperState;
28
+ farDamper: DamperState;
29
+ currentFov: number;
30
+ currentNear: number;
31
+ currentFar: number;
32
+ };
33
+ export declare const createState: () => LensState;
34
+ /** Overrides the lens fields that are set in `params`, each with its own damping. Returns true while still moving. */
35
+ export declare function update(out: CameraState, state: LensState, params: LensParams, dt: number, justActivated: boolean): boolean;
@@ -0,0 +1,57 @@
1
+ import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
+ import { createState as createState$1, damp, reset } from "../damping/damping.js";
3
+ import { withDefaults } from "../params.js";
4
+ //#region src/core/extension/lens.ts
5
+ var lens_exports = /* @__PURE__ */ __exportAll({
6
+ createParams: () => createParams,
7
+ createState: () => createState,
8
+ update: () => update
9
+ });
10
+ /** Every setting from `settings`, or its default. */
11
+ var createParams = (settings) => withDefaults({
12
+ fov: void 0,
13
+ near: void 0,
14
+ far: void 0,
15
+ fovDamping: 0,
16
+ nearDamping: 0,
17
+ farDamping: 0,
18
+ fovMaxSpeed: Infinity,
19
+ nearMaxSpeed: Infinity,
20
+ farMaxSpeed: Infinity
21
+ }, settings);
22
+ var createState = () => ({
23
+ fovDamper: createState$1(),
24
+ nearDamper: createState$1(),
25
+ farDamper: createState$1(),
26
+ currentFov: 0,
27
+ currentNear: 0,
28
+ currentFar: 0
29
+ });
30
+ function dampLensField(damper, current, target, dampingTime, dt, maxSpeed) {
31
+ if (typeof dampingTime === "number" && dampingTime <= 0) return target;
32
+ damper.value = current;
33
+ return damp(damper, target, dampingTime, dt, maxSpeed).value;
34
+ }
35
+ /** Overrides the lens fields that are set in `params`, each with its own damping. Returns true while still moving. */
36
+ function update(out, state, params, dt, justActivated) {
37
+ if (justActivated) {
38
+ reset(state.fovDamper);
39
+ reset(state.nearDamper);
40
+ reset(state.farDamper);
41
+ }
42
+ if (params.fov !== void 0) {
43
+ state.currentFov = dampLensField(state.fovDamper, state.currentFov, params.fov, params.fovDamping, dt, params.fovMaxSpeed);
44
+ out.fov = state.currentFov;
45
+ }
46
+ if (params.near !== void 0) {
47
+ state.currentNear = dampLensField(state.nearDamper, state.currentNear, params.near, params.nearDamping, dt, params.nearMaxSpeed);
48
+ out.near = state.currentNear;
49
+ }
50
+ if (params.far !== void 0) {
51
+ state.currentFar = dampLensField(state.farDamper, state.currentFar, params.far, params.farDamping, dt, params.farMaxSpeed);
52
+ out.far = state.currentFar;
53
+ }
54
+ return params.fov !== void 0 && state.currentFov !== params.fov || params.near !== void 0 && state.currentNear !== params.near || params.far !== void 0 && state.currentFar !== params.far;
55
+ }
56
+ //#endregion
57
+ export { createParams, createState, lens_exports, update };
@@ -0,0 +1,32 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BlendDefinition } from '../blend/BlendDefinition.js';
3
+ import * as clearShotState from './clearShotState.js';
4
+ import type { ClearShotCandidate, ShotQualityEvaluator } from './clearShotState.js';
5
+ export type ClearShotOptions = {
6
+ evaluator: ShotQualityEvaluator;
7
+ defaultBlend?: BlendDefinition;
8
+ /** Seconds a new best candidate must stay the best, uninterrupted, before it's actually committed to. */
9
+ activateAfter?: number;
10
+ /** Seconds the live camera must stay live before yielding to another candidate on quality alone.
11
+ * Gates internal switches only - an external, higher-priority camera preempting the whole `ClearShot`
12
+ * from outside isn't modeled here, this class can't see that. */
13
+ minDuration?: number;
14
+ /** Pick randomly among exactly-tied (quality AND priority) candidates instead of list order. */
15
+ randomizeChoice?: boolean;
16
+ random?: () => number;
17
+ };
18
+ /**
19
+ * Picks the child with the best shot quality - `priority` only breaks quality ties.
20
+ * `activateAfter` debounces the pick (a new best must hold that title continuously before it's committed,
21
+ * anti-flicker); `minDuration` then protects the committed camera from being swapped out again too soon.
22
+ */
23
+ export declare class ClearShot {
24
+ readonly state: clearShotState.ClearShotState;
25
+ private readonly params;
26
+ constructor(candidates: ClearShotCandidate[], options: ClearShotOptions);
27
+ get liveCameraId(): string | null;
28
+ get isBlending(): boolean;
29
+ /** The candidate currently being debounced toward (`activateAfter`), before it's committed to. */
30
+ get pendingCameraId(): string | null;
31
+ tick(dt: number): CameraState;
32
+ }
@@ -0,0 +1,20 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import { type MixingCameraSlot } from './mixCameraStates.js';
3
+ /**
4
+ * Continuous N-way cross-fade of up to 8 fixed slots, weighted by `weight / sum(weights)` - unlike
5
+ * `Klipp`/`Sequencer`, there's no winner and no time-driven curve; the caller drives the mix by
6
+ * mutating `weight` directly (e.g. an authored slider blend between two cameras).
7
+ *
8
+ * Position/lens average in a plain weighted sum. Quaternions have no closed-form weighted average, so
9
+ * they're combined incrementally: start from the first contributing camera, then `slerp` each next one
10
+ * in by its share of the weight accumulated so far - exact for 2 cameras, a standard approximation for
11
+ * more.
12
+ */
13
+ export declare class MixingCamera {
14
+ private readonly slots;
15
+ private readonly output;
16
+ constructor(slots: MixingCameraSlot[]);
17
+ /** Recomputes the weighted mix from the slots' current weights and returns it - same scratch instance
18
+ * every call. If every weight is zero (or negative), returns the previous output unchanged. */
19
+ tick(): CameraState;
20
+ }
@@ -0,0 +1,24 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BlendDefinition } from '../blend/BlendDefinition.js';
3
+ import * as sequencerState from './sequencerState.js';
4
+ import type { SequencerInstruction } from './sequencerState.js';
5
+ export type SequencerOptions = {
6
+ defaultBlend?: BlendDefinition;
7
+ /** Wrap to the first instruction after the last one's hold elapses, instead of holding forever. */
8
+ loop?: boolean;
9
+ };
10
+ /**
11
+ * Steps through a fixed list of camera instructions in order, holding each for its own duration before
12
+ * blending to the next. Holds the last instruction forever once reached, unless `loop`.
13
+ */
14
+ export declare class Sequencer {
15
+ readonly state: sequencerState.SequencerState;
16
+ private readonly params;
17
+ constructor(instructions: SequencerInstruction[], options?: SequencerOptions);
18
+ /** The settled instruction; during a blend, still the one being left. `0` before the first tick. */
19
+ get currentIndex(): number;
20
+ get currentCameraId(): string;
21
+ get isBlending(): boolean;
22
+ /** Advances by `dt` and returns the composited `CameraState` - same scratch instance every call. */
23
+ tick(dt: number): CameraState;
24
+ }
@@ -0,0 +1,26 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BlendDefinition } from '../blend/BlendDefinition.js';
3
+ import * as stateDrivenState from './stateDrivenState.js';
4
+ import type { StateDrivenCandidate } from './stateDrivenState.js';
5
+ export type StateDrivenCameraOptions = {
6
+ defaultBlend?: BlendDefinition;
7
+ };
8
+ /**
9
+ * Maps an externally-driven state (`setState()`, e.g. mirroring an animator's current state) to a child
10
+ * camera. Several candidates can target the same state - then the highest `priority` wins, and on a
11
+ * priority tie the FIRST one in the candidate list wins - deliberately simpler than `Klipp`'s
12
+ * "most recently activated" tie-break, since there's no activation order here, just a fixed list.
13
+ *
14
+ * If the current state matches no candidate, holds whatever was live before (nothing to switch to).
15
+ */
16
+ export declare class StateDrivenCamera {
17
+ readonly state: stateDrivenState.StateDrivenState;
18
+ private readonly params;
19
+ constructor(candidates: StateDrivenCandidate[], options?: StateDrivenCameraOptions);
20
+ setState(state: string): void;
21
+ get currentState(): string | null;
22
+ get liveCameraId(): string | null;
23
+ get isBlending(): boolean;
24
+ /** Advances any in-progress blend by `dt` and returns the composited `CameraState` - same scratch instance every call. */
25
+ tick(dt: number): CameraState;
26
+ }
@@ -0,0 +1,32 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BlendState } from '../blend/blend.js';
3
+ import type { BlendDefinition } from '../blend/BlendDefinition.js';
4
+ export type ClearShotCandidate = {
5
+ cameraId: string;
6
+ /** Live reference - read fresh every `tick()`. */
7
+ state: CameraState;
8
+ priority: number;
9
+ };
10
+ /** Scores a candidate's shot quality - higher wins. No built-in scorer yet (a real one needs scene/
11
+ * collider access, e.g. a future Deoccluder-based evaluator) - this is just the plug point. */
12
+ export type ShotQualityEvaluator = (candidate: ClearShotCandidate) => number;
13
+ export type ClearShotParams = {
14
+ candidates: readonly ClearShotCandidate[];
15
+ evaluator: ShotQualityEvaluator;
16
+ defaultBlend: BlendDefinition;
17
+ activateAfter: number;
18
+ minDuration: number;
19
+ randomizeChoice: boolean;
20
+ random: () => number;
21
+ };
22
+ export type ClearShotState = {
23
+ /** Seconds since the last commit (initial swap or mid-blend retarget). */
24
+ liveElapsed: number;
25
+ /** The candidate being debounced toward (`activateAfter`), before it is committed to. */
26
+ pendingId: string | null;
27
+ pendingElapsed: number;
28
+ blend: BlendState<string>;
29
+ };
30
+ export declare const create: () => ClearShotState;
31
+ /** Re-evaluates the candidates, advances any blend by `dt` and returns the output. */
32
+ export declare function tick(state: ClearShotState, params: ClearShotParams, dt: number): CameraState;
@@ -0,0 +1,11 @@
1
+ export { Sequencer, type SequencerOptions } from './Sequencer.js';
2
+ export * as sequencerState from './sequencerState.js';
3
+ export type { SequencerInstruction, SequencerParams, SequencerState } from './sequencerState.js';
4
+ export { MixingCamera } from './MixingCamera.js';
5
+ export type { MixingCameraSlot } from './mixCameraStates.js';
6
+ export { StateDrivenCamera, type StateDrivenCameraOptions } from './StateDrivenCamera.js';
7
+ export * as stateDrivenState from './stateDrivenState.js';
8
+ export type { StateDrivenCandidate, StateDrivenParams, StateDrivenState } from './stateDrivenState.js';
9
+ export { ClearShot, type ClearShotOptions } from './ClearShot.js';
10
+ export * as clearShotState from './clearShotState.js';
11
+ export type { ClearShotCandidate, ShotQualityEvaluator, ClearShotParams, ClearShotState } from './clearShotState.js';
@@ -0,0 +1,13 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ export type MixingCameraSlot = {
3
+ cameraId: string;
4
+ /** Live reference - read fresh every `tick()`. */
5
+ state: CameraState;
6
+ /** Mutable - this camera's contribution is `weight / sum(weights)`. Zero/negative = no contribution. */
7
+ weight: number;
8
+ };
9
+ /**
10
+ * Writes the weighted mix of `slots` into `out`, weighted by `weight / sum(weights)`. If every weight is
11
+ * zero (or negative), `out` is left unchanged.
12
+ */
13
+ export declare function mix(out: CameraState, slots: readonly MixingCameraSlot[]): CameraState;
@@ -0,0 +1,26 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BlendState } from '../blend/blend.js';
3
+ import type { BlendDefinition } from '../blend/BlendDefinition.js';
4
+ export type SequencerInstruction = {
5
+ cameraId: string;
6
+ /** Live reference - `Sequencer` reads it directly. */
7
+ state: CameraState;
8
+ /** Seconds to hold this camera before advancing. Ignored on the last instruction unless `loop`. */
9
+ hold: number;
10
+ /** Transition into the NEXT instruction. Falls back to `defaultBlend` if omitted. */
11
+ blend?: BlendDefinition;
12
+ };
13
+ export type SequencerParams = {
14
+ instructions: readonly SequencerInstruction[];
15
+ defaultBlend: BlendDefinition;
16
+ loop: boolean;
17
+ };
18
+ export type SequencerState = {
19
+ holdElapsed: number;
20
+ blend: BlendState<number>;
21
+ };
22
+ export declare const create: () => SequencerState;
23
+ /** The settled instruction; during a blend, still the one being left. `0` before the first tick. */
24
+ export declare const index: (state: SequencerState) => number;
25
+ /** Advances the sequence by `dt` and returns the composited output. */
26
+ export declare function tick(state: SequencerState, params: SequencerParams, dt: number): CameraState;
@@ -0,0 +1,28 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BlendState } from '../blend/blend.js';
3
+ import type { BlendDefinition } from '../blend/BlendDefinition.js';
4
+ export type StateDrivenCandidate = {
5
+ cameraId: string;
6
+ /** Live reference - read fresh every `tick()`. */
7
+ state: CameraState;
8
+ priority: number;
9
+ /** Which driving state (`setState()`) this candidate applies to. */
10
+ forState: string;
11
+ };
12
+ export type StateDrivenParams = {
13
+ candidates: readonly StateDrivenCandidate[];
14
+ defaultBlend: BlendDefinition;
15
+ };
16
+ export type StateDrivenState = {
17
+ drivingState: string | null;
18
+ winnerId: string | null;
19
+ blend: BlendState<string>;
20
+ };
21
+ export declare const create: () => StateDrivenState;
22
+ /** Select the camera for `drivingState`: highest priority, first in the list on a tie. */
23
+ export declare function setDrivingState(state: StateDrivenState, params: StateDrivenParams, drivingState: string): void;
24
+ /**
25
+ * Advances any blend toward the selected camera and returns the output. Before any matching state has
26
+ * been set, this is the untouched default `CameraState`.
27
+ */
28
+ export declare function tick(state: StateDrivenState, params: StateDrivenParams, dt: number): CameraState;
@@ -0,0 +1,15 @@
1
+ import type { Vec3 } from 'math';
2
+ import * as impulses from './impulses.js';
3
+ import type { GenerateImpulseOptions, ImpulseClockSeconds } from './impulses.js';
4
+ /** Stores one-shot impulses and samples their combined effect at a world position. */
5
+ export declare class ImpulseField {
6
+ readonly state: impulses.ImpulseFieldState;
7
+ /** Register a new impulse event. */
8
+ generate(options: GenerateImpulseOptions, now?: ImpulseClockSeconds): void;
9
+ /** Write the summed offset into `outPositionOffset` and return its current strength. */
10
+ sampleAt(outPositionOffset: Vec3, samplePosition: Vec3, channelMask?: number, gain?: number, now?: ImpulseClockSeconds): number;
11
+ /** Whether any event remains within its lifetime. */
12
+ get hasEvents(): boolean;
13
+ }
14
+ /** Shared impulse field. Create another instance for an isolated event stream. */
15
+ export declare const impulseField: ImpulseField;
@@ -0,0 +1,22 @@
1
+ import { createFieldState, generate, now, sample } from "./impulses.js";
2
+ //#region src/core/impulse/ImpulseField.ts
3
+ /** Stores one-shot impulses and samples their combined effect at a world position. */
4
+ var ImpulseField = class {
5
+ state = createFieldState();
6
+ /** Register a new impulse event. */
7
+ generate(options, now$2 = now()) {
8
+ generate(this.state, options, now$2);
9
+ }
10
+ /** Write the summed offset into `outPositionOffset` and return its current strength. */
11
+ sampleAt(outPositionOffset, samplePosition, channelMask = 1, gain = 1, now$1 = now()) {
12
+ return sample(outPositionOffset, this.state, samplePosition, channelMask, gain, now$1);
13
+ }
14
+ /** Whether any event remains within its lifetime. */
15
+ get hasEvents() {
16
+ return this.state.events.length > 0;
17
+ }
18
+ };
19
+ /** Shared impulse field. Create another instance for an isolated event stream. */
20
+ var impulseField = new ImpulseField();
21
+ //#endregion
22
+ export { ImpulseField, impulseField };
@@ -0,0 +1,19 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { BasicMultiChannelPerlinNoise } from '../noise/BasicMultiChannelPerlinNoise.js';
3
+ import type { ImpulseField } from './ImpulseField.js';
4
+ import type { ImpulseListenerParams } from './impulseListener.js';
5
+ export type ImpulseListenerOptions = Partial<ImpulseListenerParams> & {
6
+ /** Perlin shake driven by the impulse strength. */
7
+ shake?: BasicMultiChannelPerlinNoise;
8
+ };
9
+ /** Applies impulse offsets and optional strength-driven Perlin shake. */
10
+ export declare class ImpulseListenerNoise implements ImpulseListenerParams {
11
+ field: ImpulseField;
12
+ channelMask: number;
13
+ gain: number;
14
+ cameraSpace: boolean;
15
+ shake?: BasicMultiChannelPerlinNoise;
16
+ constructor(options?: ImpulseListenerOptions);
17
+ /** Apply the current impulse effect and report whether events remain active. */
18
+ update: (out: CameraState, dt: number, justActivated: boolean, now?: number) => boolean;
19
+ }