@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,54 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
+ import { vec3 } from "math";
3
+ //#region src/core/TargetExtent.ts
4
+ var TargetExtent_exports = /* @__PURE__ */ __exportAll({
5
+ create: () => create,
6
+ project: () => project
7
+ });
8
+ var create = () => ({
9
+ radius: 0,
10
+ size: [
11
+ 0,
12
+ 0,
13
+ 0
14
+ ],
15
+ rotation: [
16
+ 0,
17
+ 0,
18
+ 0,
19
+ 1
20
+ ],
21
+ hasSize: false
22
+ });
23
+ var scratchAxisX = [
24
+ 0,
25
+ 0,
26
+ 0
27
+ ];
28
+ var scratchAxisY = [
29
+ 0,
30
+ 0,
31
+ 0
32
+ ];
33
+ var scratchAxisZ = [
34
+ 0,
35
+ 0,
36
+ 0
37
+ ];
38
+ /** Half-extents of `extent` along two world axes. */
39
+ function project(out, extent, axisA, axisB) {
40
+ if (!extent.hasSize) {
41
+ out[0] = extent.radius;
42
+ out[1] = extent.radius;
43
+ return out;
44
+ }
45
+ const { size, rotation } = extent;
46
+ vec3.transformQuat(scratchAxisX, vec3.set(scratchAxisX, size[0] * .5, 0, 0), rotation);
47
+ vec3.transformQuat(scratchAxisY, vec3.set(scratchAxisY, 0, size[1] * .5, 0), rotation);
48
+ vec3.transformQuat(scratchAxisZ, vec3.set(scratchAxisZ, 0, 0, size[2] * .5), rotation);
49
+ out[0] = Math.abs(vec3.dot(scratchAxisX, axisA)) + Math.abs(vec3.dot(scratchAxisY, axisA)) + Math.abs(vec3.dot(scratchAxisZ, axisA));
50
+ out[1] = Math.abs(vec3.dot(scratchAxisX, axisB)) + Math.abs(vec3.dot(scratchAxisY, axisB)) + Math.abs(vec3.dot(scratchAxisZ, axisB));
51
+ return out;
52
+ }
53
+ //#endregion
54
+ export { TargetExtent_exports, create, project };
@@ -0,0 +1,13 @@
1
+ import type { Quat, Vec3 } from 'math';
2
+ import type { TargetExtent } from './TargetExtent.js';
3
+ /**
4
+ * A target's world transform and how far it reaches. `rotation` is only meaningful when `hasRotation` is true
5
+ * (not for fixed points). `extent` is only read by the composers.
6
+ */
7
+ export type TargetPose = {
8
+ position: Vec3;
9
+ rotation: Quat;
10
+ hasRotation: boolean;
11
+ extent: TargetExtent;
12
+ };
13
+ export declare const create: () => TargetPose;
@@ -0,0 +1,21 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
+ import { create as create$1 } from "./TargetExtent.js";
3
+ //#region src/core/TargetPose.ts
4
+ var TargetPose_exports = /* @__PURE__ */ __exportAll({ create: () => create });
5
+ var create = () => ({
6
+ position: [
7
+ 0,
8
+ 0,
9
+ 0
10
+ ],
11
+ rotation: [
12
+ 0,
13
+ 0,
14
+ 0,
15
+ 1
16
+ ],
17
+ hasRotation: false,
18
+ extent: create$1()
19
+ });
20
+ //#endregion
21
+ export { TargetPose_exports, create };
@@ -0,0 +1,102 @@
1
+ import type { CameraState } from './CameraState.js';
2
+ import { EventDispatcher } from './EventDispatcher.js';
3
+ import { attachTo, prepare, run, skip } from './internal.js';
4
+ import type { CameraTransitionEventMap, Klipp } from './Klipp.js';
5
+ import { BlendHints } from './blend/BlendHints.js';
6
+ import type { InputAxisData } from './input/axis.js';
7
+ import { type InputAxisOwner } from './input/InputAxisOwner.js';
8
+ /** Writes `out` for one frame. Return `true` when more work remains for a later frame. */
9
+ export type CameraStateWriter = (out: CameraState, dt: number, justActivated: boolean) => boolean | void;
10
+ /** A Body, Aim, Extension or Noise: anything with an `update` that writes the camera state. */
11
+ export type CameraPiece = {
12
+ update: CameraStateWriter;
13
+ };
14
+ /** How a camera updates while another one is on screen: every frame, one camera per frame in turn, or not at all. */
15
+ export type StandbyUpdate = 'always' | 'roundRobin' | 'never';
16
+ export type VirtualCameraOptions = {
17
+ /** The active camera with the highest priority is on screen. */
18
+ priority?: number;
19
+ /** Whether this camera takes part in arbitration and updates. */
20
+ active?: boolean;
21
+ /** Blend hints for transitions involving this camera. */
22
+ hints?: BlendHints;
23
+ /** Starting pose and lens, applied over the `Klipp`'s `initialCameraState` when first added. */
24
+ initialState?: Partial<CameraState>;
25
+ /** How this camera updates while another one is on screen. */
26
+ standbyUpdate?: StandbyUpdate;
27
+ };
28
+ /** One shot: its state, the pieces that write it, and its place in a `Klipp`'s arbitration. */
29
+ export declare class VirtualCamera extends EventDispatcher<CameraTransitionEventMap> implements InputAxisOwner {
30
+ /** This camera's own state, written by its pieces every frame. */
31
+ readonly state: CameraState;
32
+ /** How this camera updates while another one is on screen. */
33
+ standbyUpdate: StandbyUpdate;
34
+ /** Every piece, in no particular order. */
35
+ protected readonly pieces: Set<CameraPiece>;
36
+ private readonly initialState;
37
+ private _name;
38
+ private _priority;
39
+ private _hints;
40
+ private _active;
41
+ private _klipp;
42
+ private seeded;
43
+ private stopTracking;
44
+ private unregister;
45
+ private justActivated;
46
+ private hasRun;
47
+ private skippedTime;
48
+ private _body;
49
+ private _aim;
50
+ private removeBody;
51
+ private removeAim;
52
+ private readonly extensions;
53
+ private readonly noises;
54
+ private _inputAxes;
55
+ constructor(name: string, options?: VirtualCameraOptions);
56
+ /** The `Klipp` this camera was added to, if any. */
57
+ get klipp(): Klipp | null;
58
+ get name(): string;
59
+ /** Renaming a registered camera registers it again under the new name. */
60
+ set name(name: string);
61
+ get priority(): number;
62
+ set priority(priority: number);
63
+ get hints(): BlendHints;
64
+ set hints(hints: BlendHints);
65
+ /** Whether this camera takes part. Turning it back on starts it fresh, like a first activation. */
66
+ get active(): boolean;
67
+ set active(active: boolean);
68
+ /** Every input axis of this camera's pieces, by name. A new object whenever the pieces change. */
69
+ get inputAxes(): Record<string, InputAxisData>;
70
+ get body(): CameraPiece | null;
71
+ /** Replace the Body. */
72
+ set body(body: CameraPiece | null);
73
+ get aim(): CameraPiece | null;
74
+ /** Replace the Aim. */
75
+ set aim(aim: CameraPiece | null);
76
+ /** Add the Body. A second one replaces it with a warning. Returns a function that removes it, unless replaced. */
77
+ setBody(body: CameraPiece | null): () => void;
78
+ /** Add the Aim. Like `setBody`, a second one replaces it with a warning. */
79
+ setAim(aim: CameraPiece | null): () => void;
80
+ /** Add an Extension. They run in the order added. Returns a function that removes it. */
81
+ addExtension(extension: CameraPiece): () => void;
82
+ /** Add a Noise. They run in the order added, after every Extension. Returns a function that removes it. */
83
+ addNoise(noise: CameraPiece): () => void;
84
+ /** Join `klipp`'s arbitration, or leave it with `null`. Only `Klipp.add` and `remove` call this. */
85
+ [attachTo](klipp: Klipp | null): void;
86
+ /** Pass the viewport size, once known, on to pieces that frame by it. Called by `Klipp` before the frame. */
87
+ [prepare](width: number, height: number): void;
88
+ /** Run the pieces for one frame, if registered. Returns `true` while one is still moving. Called by `Klipp`. */
89
+ [run](dt: number): boolean;
90
+ /** Skip this frame, adding its time to the next run. Called by `Klipp` for cameras in standby. */
91
+ [skip](dt: number): void;
92
+ /** Called when a piece is removed, for layers that hold per-piece resources. */
93
+ protected removePiece(piece: CameraPiece): void;
94
+ private addPiece;
95
+ private collectInputAxes;
96
+ private registration;
97
+ private syncRegistration;
98
+ /** Re-dispatch events for this camera only when it participates in the transition. */
99
+ private trackEvents;
100
+ /** Run every piece against `out` once, in order. Each frame runs it with the camera's own state. */
101
+ update: (out: CameraState, dt: number, justActivated: boolean) => boolean;
102
+ }
@@ -0,0 +1,290 @@
1
+ import { EventDispatcher } from "./EventDispatcher.js";
2
+ import { BlendHints } from "./blend/BlendHints.js";
3
+ import { copy, create, merge } from "./CameraState.js";
4
+ import { attachTo, checkName, prepare, register, run, setHints, setPriority, skip } from "./internal.js";
5
+ import { isInputAxisOwner } from "./input/InputAxisOwner.js";
6
+ import { quat } from "math";
7
+ //#region src/core/VirtualCamera.ts
8
+ /** Warn when a second Body or Aim replaces an existing one. */
9
+ function warnDoubleRegistration(slot, name) {
10
+ console.warn(`Virtual camera "${name}": a second ${slot} replaced the first. A camera runs one ${slot}.`);
11
+ }
12
+ var noop = () => {};
13
+ /** One shot: its state, the pieces that write it, and its place in a `Klipp`'s arbitration. */
14
+ var VirtualCamera = class extends EventDispatcher {
15
+ /** This camera's own state, written by its pieces every frame. */
16
+ state;
17
+ /** How this camera updates while another one is on screen. */
18
+ standbyUpdate;
19
+ /** Every piece, in no particular order. */
20
+ pieces = /* @__PURE__ */ new Set();
21
+ initialState;
22
+ _name;
23
+ _priority;
24
+ _hints;
25
+ _active;
26
+ _klipp = null;
27
+ seeded = false;
28
+ stopTracking = null;
29
+ unregister = null;
30
+ justActivated = true;
31
+ hasRun = false;
32
+ skippedTime = 0;
33
+ _body = null;
34
+ _aim = null;
35
+ removeBody = noop;
36
+ removeAim = noop;
37
+ extensions = /* @__PURE__ */ new Set();
38
+ noises = /* @__PURE__ */ new Set();
39
+ _inputAxes = null;
40
+ constructor(name, options = {}) {
41
+ super();
42
+ this._name = name;
43
+ this._priority = options.priority ?? 0;
44
+ this._hints = options.hints ?? BlendHints.none;
45
+ this._active = options.active ?? true;
46
+ this.standbyUpdate = options.standbyUpdate ?? "roundRobin";
47
+ this.initialState = options.initialState;
48
+ this.state = merge(create(), options.initialState ?? {});
49
+ }
50
+ /** The `Klipp` this camera was added to, if any. */
51
+ get klipp() {
52
+ return this._klipp;
53
+ }
54
+ get name() {
55
+ return this._name;
56
+ }
57
+ /** Renaming a registered camera registers it again under the new name. */
58
+ set name(name) {
59
+ if (name === this._name) return;
60
+ this._name = name;
61
+ this._klipp?.[checkName](this);
62
+ if (this.unregister) {
63
+ this.unregister();
64
+ this.unregister = this._klipp[register](this.registration());
65
+ }
66
+ }
67
+ get priority() {
68
+ return this._priority;
69
+ }
70
+ set priority(priority) {
71
+ this._priority = priority;
72
+ if (this.unregister) this._klipp[setPriority](this._name, priority);
73
+ }
74
+ get hints() {
75
+ return this._hints;
76
+ }
77
+ set hints(hints) {
78
+ this._hints = hints;
79
+ if (this.unregister) this._klipp[setHints](this._name, hints);
80
+ }
81
+ /** Whether this camera takes part. Turning it back on starts it fresh, like a first activation. */
82
+ get active() {
83
+ return this._active;
84
+ }
85
+ set active(active) {
86
+ this._active = active;
87
+ this.syncRegistration();
88
+ }
89
+ /** Every input axis of this camera's pieces, by name. A new object whenever the pieces change. */
90
+ get inputAxes() {
91
+ return this._inputAxes ??= this.collectInputAxes();
92
+ }
93
+ get body() {
94
+ return this._body;
95
+ }
96
+ /** Replace the Body. */
97
+ set body(body) {
98
+ this.removeBody();
99
+ this.setBody(body);
100
+ }
101
+ get aim() {
102
+ return this._aim;
103
+ }
104
+ /** Replace the Aim. */
105
+ set aim(aim) {
106
+ this.removeAim();
107
+ this.setAim(aim);
108
+ }
109
+ /** Add the Body. A second one replaces it with a warning. Returns a function that removes it, unless replaced. */
110
+ setBody(body) {
111
+ if (this._body) {
112
+ if (body) warnDoubleRegistration("Body", this._name);
113
+ this.removePiece(this._body);
114
+ }
115
+ this._body = body;
116
+ if (!body) return this.removeBody = noop;
117
+ this.addPiece(body);
118
+ if (!this.hasRun && this.initialState?.position && "primeFrom" in body) body.primeFrom(this.state.position);
119
+ return this.removeBody = () => {
120
+ if (this._body !== body) return;
121
+ this.removePiece(body);
122
+ this._body = null;
123
+ this.removeBody = noop;
124
+ };
125
+ }
126
+ /** Add the Aim. Like `setBody`, a second one replaces it with a warning. */
127
+ setAim(aim) {
128
+ if (this._aim) {
129
+ if (aim) warnDoubleRegistration("Aim", this._name);
130
+ this.removePiece(this._aim);
131
+ }
132
+ this._aim = aim;
133
+ if (!aim) return this.removeAim = noop;
134
+ this.addPiece(aim);
135
+ if (!this.hasRun && this.initialState?.quaternion && "primeFrom" in aim) aim.primeFrom(this.state.quaternion, this.state.referenceUp);
136
+ return this.removeAim = () => {
137
+ if (this._aim !== aim) return;
138
+ this.removePiece(aim);
139
+ this._aim = null;
140
+ this.removeAim = noop;
141
+ };
142
+ }
143
+ /** Add an Extension. They run in the order added. Returns a function that removes it. */
144
+ addExtension(extension) {
145
+ this.addPiece(extension);
146
+ this.extensions.add(extension);
147
+ return () => this.removePiece(extension);
148
+ }
149
+ /** Add a Noise. They run in the order added, after every Extension. Returns a function that removes it. */
150
+ addNoise(noise) {
151
+ this.addPiece(noise);
152
+ this.noises.add(noise);
153
+ return () => this.removePiece(noise);
154
+ }
155
+ /** Join `klipp`'s arbitration, or leave it with `null`. Only `Klipp.add` and `remove` call this. */
156
+ [attachTo](klipp) {
157
+ this.stopTracking?.();
158
+ this.stopTracking = null;
159
+ this._klipp = klipp;
160
+ if (klipp) {
161
+ if (!this.seeded) {
162
+ copy(this.state, klipp.initialCameraState);
163
+ if (this.initialState) merge(this.state, this.initialState);
164
+ this.seeded = true;
165
+ }
166
+ this.stopTracking = this.trackEvents(klipp);
167
+ }
168
+ this.syncRegistration();
169
+ }
170
+ /** Pass the viewport size, once known, on to pieces that frame by it. Called by `Klipp` before the frame. */
171
+ [prepare](width, height) {
172
+ if (width <= 0 || height <= 0) return;
173
+ for (const piece of this.pieces) {
174
+ if ("aspect" in piece) piece.aspect = width / height;
175
+ if ("viewportWidth" in piece) {
176
+ piece.viewportWidth = width;
177
+ piece.viewportHeight = height;
178
+ }
179
+ }
180
+ }
181
+ /** Run the pieces for one frame, if registered. Returns `true` while one is still moving. Called by `Klipp`. */
182
+ [run](dt) {
183
+ if (!this.unregister) return false;
184
+ const stillInFlight = this.update(this.state, dt + this.skippedTime, this.justActivated);
185
+ this.skippedTime = 0;
186
+ this.justActivated = false;
187
+ this.hasRun = true;
188
+ return stillInFlight;
189
+ }
190
+ /** Skip this frame, adding its time to the next run. Called by `Klipp` for cameras in standby. */
191
+ [skip](dt) {
192
+ if (this.unregister) this.skippedTime += dt;
193
+ }
194
+ /** Called when a piece is removed, for layers that hold per-piece resources. */
195
+ removePiece(piece) {
196
+ this.pieces.delete(piece);
197
+ this.extensions.delete(piece);
198
+ this.noises.delete(piece);
199
+ this._inputAxes = null;
200
+ }
201
+ addPiece(piece) {
202
+ this.pieces.add(piece);
203
+ this._inputAxes = null;
204
+ }
205
+ collectInputAxes() {
206
+ const axes = {};
207
+ for (const piece of this.pieces) {
208
+ if (!isInputAxisOwner(piece)) continue;
209
+ for (const name in piece.inputAxes) if (name in axes) console.warn(`Virtual camera "${this._name}": two pieces have an input axis named "${name}". Using the first.`);
210
+ else axes[name] = piece.inputAxes[name];
211
+ }
212
+ return axes;
213
+ }
214
+ registration() {
215
+ return {
216
+ id: this._name,
217
+ priority: this._priority,
218
+ state: this.state,
219
+ hints: this._hints
220
+ };
221
+ }
222
+ syncRegistration() {
223
+ const shouldRegister = this._klipp !== null && this._active;
224
+ if (shouldRegister && !this.unregister) {
225
+ this.unregister = this._klipp[register](this.registration());
226
+ this.justActivated = true;
227
+ this.skippedTime = 0;
228
+ } else if (!shouldRegister && this.unregister) {
229
+ this.unregister();
230
+ this.unregister = null;
231
+ }
232
+ }
233
+ /** Re-dispatch events for this camera only when it participates in the transition. */
234
+ trackEvents(core) {
235
+ const onActivated = (event) => {
236
+ if (event.incoming === this.name) this.dispatchEvent({
237
+ type: "activated",
238
+ ...event
239
+ });
240
+ };
241
+ const onDeactivated = (event) => {
242
+ if (event.outgoing === this.name) this.dispatchEvent({
243
+ type: "deactivated",
244
+ ...event
245
+ });
246
+ };
247
+ const onBlendCreated = (event) => {
248
+ if (event.incoming === this.name || event.outgoing === this.name) this.dispatchEvent({
249
+ type: "blendCreated",
250
+ ...event
251
+ });
252
+ };
253
+ const onBlendFinished = (event) => {
254
+ if (event.liveId === this.name) this.dispatchEvent({
255
+ type: "blendFinished",
256
+ ...event
257
+ });
258
+ };
259
+ const onCut = (event) => {
260
+ if (event.incoming === this.name || event.outgoing === this.name) this.dispatchEvent({
261
+ type: "cut",
262
+ ...event
263
+ });
264
+ };
265
+ core.addEventListener("activated", onActivated);
266
+ core.addEventListener("deactivated", onDeactivated);
267
+ core.addEventListener("blendCreated", onBlendCreated);
268
+ core.addEventListener("blendFinished", onBlendFinished);
269
+ core.addEventListener("cut", onCut);
270
+ return () => {
271
+ core.removeEventListener("activated", onActivated);
272
+ core.removeEventListener("deactivated", onDeactivated);
273
+ core.removeEventListener("blendCreated", onBlendCreated);
274
+ core.removeEventListener("blendFinished", onBlendFinished);
275
+ core.removeEventListener("cut", onCut);
276
+ };
277
+ }
278
+ /** Run every piece against `out` once, in order. Each frame runs it with the camera's own state. */
279
+ update = (out, dt, justActivated) => {
280
+ let stillInFlight = false;
281
+ quat.identity(out.rotationDampingBypass);
282
+ if (this._body?.update(out, dt, justActivated) === true) stillInFlight = true;
283
+ if (this._aim?.update(out, dt, justActivated) === true) stillInFlight = true;
284
+ for (const extension of this.extensions) if (extension.update(out, dt, justActivated) === true) stillInFlight = true;
285
+ for (const noise of this.noises) if (noise.update(out, dt, justActivated) === true) stillInFlight = true;
286
+ return stillInFlight;
287
+ };
288
+ };
289
+ //#endregion
290
+ export { VirtualCamera };
@@ -0,0 +1,10 @@
1
+ import type { CameraState } from '../CameraState.js';
2
+ import type { TargetPose } from '../TargetPose.js';
3
+ /** Rotates so the target is dead-center. Layers override `readTarget` to read their own targets. */
4
+ export declare class HardLookAtAim<T = TargetPose | null> {
5
+ target: T;
6
+ constructor(target: T);
7
+ update: (out: CameraState) => void;
8
+ /** This frame's target pose, or `null` when there is none. */
9
+ protected readTarget(): TargetPose | null;
10
+ }
@@ -0,0 +1,19 @@
1
+ import { update } from "./hardLookAt.js";
2
+ //#region src/core/aim/HardLookAtAim.ts
3
+ /** Rotates so the target is dead-center. Layers override `readTarget` to read their own targets. */
4
+ var HardLookAtAim = class {
5
+ target;
6
+ constructor(target) {
7
+ this.target = target;
8
+ }
9
+ update = (out) => {
10
+ const pose = this.readTarget();
11
+ if (pose) update(out, pose.position);
12
+ };
13
+ /** This frame's target pose, or `null` when there is none. */
14
+ readTarget() {
15
+ return this.target;
16
+ }
17
+ };
18
+ //#endregion
19
+ export { HardLookAtAim };
@@ -0,0 +1,26 @@
1
+ import type { Quat, Vec3 } from 'math';
2
+ import type { CameraState } from '../CameraState.js';
3
+ import type { TargetPose } from '../TargetPose.js';
4
+ import type { InputAxisOwner } from '../input/InputAxisOwner.js';
5
+ import * as panTilt from './panTilt.js';
6
+ /** Rotation from two `InputAxis`: `pan` (yaw) and `tilt` (pitch), relative to an optional target's rotation. */
7
+ export declare class PanTiltAim<T = TargetPose | null> implements InputAxisOwner {
8
+ readonly state: panTilt.PanTiltState;
9
+ readonly pan: import("../index.js").InputAxis;
10
+ readonly tilt: import("../index.js").InputAxis;
11
+ readonly inputAxes: {
12
+ pan: import("../index.js").InputAxis;
13
+ tilt: import("../index.js").InputAxis;
14
+ };
15
+ /** Makes `pan` and `tilt` relative to this target's rotation. */
16
+ target: T;
17
+ constructor(target?: T);
18
+ update: (out: CameraState, dt: number) => boolean;
19
+ /** Seeds `pan`/`tilt` from `rotation`'s forward direction, relative to the current reference frame. */
20
+ setFromRotation: (rotation: Quat, referenceUp: Vec3) => void;
21
+ /** Start facing `rotation`, with both axes settled there instead of easing in. */
22
+ primeFrom: (rotation: Quat, referenceUp: Vec3) => void;
23
+ /** This frame's target pose, or `null` when there is none. Only its rotation is read. */
24
+ protected readTarget(): TargetPose | null;
25
+ private targetRotation;
26
+ }
@@ -0,0 +1,38 @@
1
+ import { createState, seed, update } from "./panTilt.js";
2
+ //#region src/core/aim/PanTiltAim.ts
3
+ /** Rotation from two `InputAxis`: `pan` (yaw) and `tilt` (pitch), relative to an optional target's rotation. */
4
+ var PanTiltAim = class {
5
+ state = createState();
6
+ pan = this.state.pan;
7
+ tilt = this.state.tilt;
8
+ inputAxes = {
9
+ pan: this.pan,
10
+ tilt: this.tilt
11
+ };
12
+ /** Makes `pan` and `tilt` relative to this target's rotation. */
13
+ target;
14
+ constructor(target = null) {
15
+ this.target = target;
16
+ }
17
+ update = (out, dt) => update(out, this.state, this.targetRotation(), dt);
18
+ /** Seeds `pan`/`tilt` from `rotation`'s forward direction, relative to the current reference frame. */
19
+ setFromRotation = (rotation, referenceUp) => {
20
+ seed(this.state, this.targetRotation(), rotation, referenceUp);
21
+ };
22
+ /** Start facing `rotation`, with both axes settled there instead of easing in. */
23
+ primeFrom = (rotation, referenceUp) => {
24
+ this.setFromRotation(rotation, referenceUp);
25
+ this.pan.reset();
26
+ this.tilt.reset();
27
+ };
28
+ /** This frame's target pose, or `null` when there is none. Only its rotation is read. */
29
+ readTarget() {
30
+ return this.target;
31
+ }
32
+ targetRotation() {
33
+ const pose = this.readTarget();
34
+ return pose?.hasRotation ? pose.rotation : null;
35
+ }
36
+ };
37
+ //#endregion
38
+ export { PanTiltAim };
@@ -0,0 +1,19 @@
1
+ import type { Quat } from 'math';
2
+ import type { CameraState } from '../CameraState.js';
3
+ import type { TargetPose } from '../TargetPose.js';
4
+ import type { DampingConstant } from '../damping/damping.js';
5
+ import * as rotateWithFollowTarget from './rotateWithFollowTarget.js';
6
+ import type { RotateWithFollowTargetParams } from './rotateWithFollowTarget.js';
7
+ export type RotateWithFollowTargetOptions = Partial<RotateWithFollowTargetParams>;
8
+ /** Follows the target's rotation. Layers override `readTarget` to read their own targets. */
9
+ export declare class RotateWithFollowTargetAim<T = TargetPose | null> implements RotateWithFollowTargetParams {
10
+ target: T;
11
+ damping: DampingConstant;
12
+ maxSpeed: number;
13
+ readonly state: rotateWithFollowTarget.RotateWithFollowTargetState;
14
+ constructor(target: T, options?: RotateWithFollowTargetOptions);
15
+ update: (out: CameraState, dt: number, justActivated: boolean) => void;
16
+ primeFrom: (rotation: Quat) => void;
17
+ /** This frame's target pose, or `null` when there is none. Only its rotation is read. */
18
+ protected readTarget(): TargetPose | null;
19
+ }
@@ -0,0 +1,23 @@
1
+ import { createParams, createState, prime, update } from "./rotateWithFollowTarget.js";
2
+ //#region src/core/aim/RotateWithFollowTargetAim.ts
3
+ /** Follows the target's rotation. Layers override `readTarget` to read their own targets. */
4
+ var RotateWithFollowTargetAim = class {
5
+ target;
6
+ state = createState();
7
+ constructor(target, options) {
8
+ this.target = target;
9
+ Object.assign(this, createParams(options));
10
+ }
11
+ update = (out, dt, justActivated) => {
12
+ const pose = this.readTarget();
13
+ const rotation = pose?.hasRotation ? pose.rotation : null;
14
+ update(out, this.state, this, rotation, dt, justActivated);
15
+ };
16
+ primeFrom = (rotation) => prime(this.state, this, rotation);
17
+ /** This frame's target pose, or `null` when there is none. Only its rotation is read. */
18
+ readTarget() {
19
+ return this.target;
20
+ }
21
+ };
22
+ //#endregion
23
+ export { RotateWithFollowTargetAim };
@@ -0,0 +1,27 @@
1
+ import type { Quat, Vec3 } from 'math';
2
+ import type { CameraState } from '../CameraState.js';
3
+ import type { TargetPose } from '../TargetPose.js';
4
+ import type { DampingConstant } from '../damping/damping.js';
5
+ import * as rotationComposer from './rotationComposer.js';
6
+ import type { RotationComposerParams } from './rotationComposer.js';
7
+ /** Rotates the camera to place a target at `screenPosition`. Layers override `readTarget`. */
8
+ export declare class RotationComposerAim<T = TargetPose | null> implements RotationComposerParams {
9
+ target: T;
10
+ screenPosition: [number, number];
11
+ aspect: number;
12
+ deadZone: [number, number];
13
+ damping: DampingConstant;
14
+ maxSpeed: number;
15
+ hardLimit: [number, number];
16
+ targetOffset: Vec3;
17
+ lookaheadTime: number;
18
+ lookaheadSmoothing: number;
19
+ lookaheadIgnoreY: boolean;
20
+ readonly state: rotationComposer.RotationComposerState;
21
+ private lastTarget;
22
+ constructor(target: T, options?: Partial<RotationComposerParams>);
23
+ primeFrom: (rotation: Quat) => void;
24
+ update: (out: CameraState, dt: number, justActivated: boolean) => void;
25
+ /** This frame's target pose with its extent, or `null` when there is none. */
26
+ protected readTarget(): TargetPose | null;
27
+ }
@@ -0,0 +1,27 @@
1
+ import { createParams, createState, prime, retarget, update } from "./rotationComposer.js";
2
+ //#region src/core/aim/RotationComposerAim.ts
3
+ /** Rotates the camera to place a target at `screenPosition`. Layers override `readTarget`. */
4
+ var RotationComposerAim = class {
5
+ target;
6
+ state = createState();
7
+ lastTarget = void 0;
8
+ constructor(target, options) {
9
+ this.target = target;
10
+ Object.assign(this, createParams(options));
11
+ }
12
+ primeFrom = (rotation) => prime(this.state, this, rotation);
13
+ update = (out, dt, justActivated) => {
14
+ const pose = this.readTarget();
15
+ if (pose) {
16
+ if (this.target !== this.lastTarget) retarget(this.state);
17
+ this.lastTarget = this.target;
18
+ }
19
+ update(out, this.state, this, pose, dt, justActivated);
20
+ };
21
+ /** This frame's target pose with its extent, or `null` when there is none. */
22
+ readTarget() {
23
+ return this.target;
24
+ }
25
+ };
26
+ //#endregion
27
+ export { RotationComposerAim };