@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,31 @@
1
+ import { type ReactNode, type Ref } from 'react';
2
+ import type { DampingConstant } from '../../core/damping/damping.js';
3
+ import type { InputAxisRecentering } from '../../core/input/axis.js';
4
+ import { PanTiltAimThree } from '../../three/aim/PanTiltAimThree.js';
5
+ import type { Target } from '../../three/resolve/Target.js';
6
+ export type PanTiltProps = {
7
+ /** Rotation frame `pan`/`tilt` compose on top of.
8
+ * `null`/`undefined`/omitted is world (`referenceUp`-aware) */
9
+ target?: Target;
10
+ /** Applied to both `pan.damping` and `tilt.damping`. */
11
+ damping?: DampingConstant;
12
+ /** Applied to both `pan.maxSpeed` and `tilt.maxSpeed` - caps how fast `damping` can close the gap, in degrees/sec. */
13
+ maxSpeed?: number;
14
+ /** `pan.autoNormalize`. Only applies while `panWrap` is `true`. */
15
+ autoNormalize?: boolean;
16
+ /** `pan.wrap` - loops at `panRange`'s edges or hard-clamps them. */
17
+ panWrap?: boolean;
18
+ /** `tilt.wrap` - see `panWrap`. */
19
+ tiltWrap?: boolean;
20
+ /** `pan.range` - its edges wrap or clamp depending on `panWrap`. */
21
+ panRange?: [number, number];
22
+ /** `tilt.range` - its edges wrap or clamp depending on `tiltWrap`. */
23
+ tiltRange?: [number, number];
24
+ /** Applied to both `pan.recentering` and `tilt.recentering`. */
25
+ recentering?: InputAxisRecentering;
26
+ ref?: Ref<PanTiltAimThree>;
27
+ /** Nested `<InputController>` picks up `pan`/`tilt` automatically without an explicit `target`. */
28
+ children?: ReactNode;
29
+ };
30
+ /** Thin wrapper around `PanTiltAimThree`. */
31
+ export declare function PanTilt({ target, damping, maxSpeed, autoNormalize, panWrap, tiltWrap, panRange, tiltRange, recentering, ref, children, }: PanTiltProps): import("react").JSX.Element;
@@ -0,0 +1,38 @@
1
+ import { PanTiltAimThree } from "../../three/aim/PanTiltAimThree.js";
2
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
3
+ import { InputAxisOwnerContext } from "../input/InputAxisOwnerContext.js";
4
+ import { useEffect, useImperativeHandle, useState } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/react/aim/PanTilt.tsx
7
+ var defaultPanRange = [-180, 180];
8
+ var defaultTiltRange = [-90, 90];
9
+ var defaultRecentering = {
10
+ enabled: false,
11
+ wait: 1,
12
+ time: 1
13
+ };
14
+ /** Thin wrapper around `PanTiltAimThree`. */
15
+ function PanTilt({ target, damping = 0, maxSpeed = Infinity, autoNormalize = false, panWrap = true, tiltWrap = false, panRange = defaultPanRange, tiltRange = defaultTiltRange, recentering = defaultRecentering, ref, children }) {
16
+ const camera = useVirtualCamera();
17
+ const [aim] = useState(() => new PanTiltAimThree());
18
+ aim.target = target;
19
+ aim.pan.damping = damping;
20
+ aim.pan.maxSpeed = maxSpeed;
21
+ aim.pan.autoNormalize = autoNormalize;
22
+ aim.pan.wrap = panWrap;
23
+ aim.pan.range = panRange;
24
+ aim.pan.recentering = recentering;
25
+ aim.tilt.damping = damping;
26
+ aim.tilt.maxSpeed = maxSpeed;
27
+ aim.tilt.wrap = tiltWrap;
28
+ aim.tilt.range = tiltRange;
29
+ aim.tilt.recentering = recentering;
30
+ useImperativeHandle(ref, () => aim, [aim]);
31
+ useEffect(() => camera.setAim(aim), [camera, aim]);
32
+ return /* @__PURE__ */ jsx(InputAxisOwnerContext.Provider, {
33
+ value: aim,
34
+ children
35
+ });
36
+ }
37
+ //#endregion
38
+ export { PanTilt };
@@ -0,0 +1,10 @@
1
+ import { type Ref } from 'react';
2
+ import { RotateWithFollowTargetAimThree, type RotateWithFollowTargetOptions } from '../../three/aim/RotateWithFollowTargetAimThree.js';
3
+ import type { Target } from '../../three/resolve/Target.js';
4
+ export type RotateWithFollowTargetProps = RotateWithFollowTargetOptions & {
5
+ /** Target rotation to copy. Unresolved targets are ignored. */
6
+ target?: Target;
7
+ ref?: Ref<RotateWithFollowTargetAimThree>;
8
+ };
9
+ /** Thin wrapper around `RotateWithFollowTargetAimThree`. */
10
+ export declare function RotateWithFollowTarget({ target, ref, ...settings }: RotateWithFollowTargetProps): null;
@@ -0,0 +1,18 @@
1
+ import { createParams } from "../../core/aim/rotateWithFollowTarget.js";
2
+ import { RotateWithFollowTargetAimThree } from "../../three/aim/RotateWithFollowTargetAimThree.js";
3
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
4
+ import { useEffect, useImperativeHandle, useState } from "react";
5
+ //#region src/react/aim/RotateWithFollowTarget.tsx
6
+ /** Thin wrapper around `RotateWithFollowTargetAimThree`. */
7
+ function RotateWithFollowTarget({ target, ref, ...settings }) {
8
+ const camera = useVirtualCamera();
9
+ const params = createParams(settings);
10
+ const [aim] = useState(() => new RotateWithFollowTargetAimThree(target, params));
11
+ aim.target = target;
12
+ Object.assign(aim, params);
13
+ useImperativeHandle(ref, () => aim, [aim]);
14
+ useEffect(() => camera.setAim(aim), [camera, aim]);
15
+ return null;
16
+ }
17
+ //#endregion
18
+ export { RotateWithFollowTarget };
@@ -0,0 +1,12 @@
1
+ import { type Ref } from 'react';
2
+ import { RotationComposerAimThree, type RotationComposerThreeOptions } from '../../three/aim/RotationComposerAimThree.js';
3
+ import type { Target } from '../../three/resolve/Target.js';
4
+ export type RotationComposerProps = Omit<RotationComposerThreeOptions, 'aspect'> & {
5
+ /** Target to compose at `screenPosition`. Unresolved targets are ignored. */
6
+ target?: Target;
7
+ /** Draws the `deadZone` and `hardLimit` overlays. */
8
+ debug?: boolean;
9
+ ref?: Ref<RotationComposerAimThree>;
10
+ };
11
+ /** Keeps a target within a chosen screen region by rotating the camera. */
12
+ export declare function RotationComposer({ target, targetOffset, debug, ref, ...settings }: RotationComposerProps): import("react").JSX.Element | null;
@@ -0,0 +1,34 @@
1
+ import { createParams } from "../../core/aim/rotationComposer.js";
2
+ import { composer } from "../../core/debug/debugZones.js";
3
+ import { resolveVec3 } from "../../three/resolve/resolveVector3.js";
4
+ import { RotationComposerAimThree } from "../../three/aim/RotationComposerAimThree.js";
5
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
6
+ import { DebugZoneOverlay } from "../DebugZoneOverlay.js";
7
+ import { useThree } from "@react-three/fiber";
8
+ import { useEffect, useImperativeHandle, useState } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ //#region src/react/aim/RotationComposer.tsx
11
+ /** Keeps a target within a chosen screen region by rotating the camera. */
12
+ function RotationComposer({ target, targetOffset, debug = false, ref, ...settings }) {
13
+ const camera = useVirtualCamera();
14
+ const aspect = useThree((state) => state.viewport.aspect);
15
+ const { targetOffset: defaultTargetOffset, ...params } = createParams({
16
+ ...settings,
17
+ aspect
18
+ });
19
+ const [aim] = useState(() => new RotationComposerAimThree(target, params));
20
+ aim.target = target;
21
+ Object.assign(aim, params);
22
+ resolveVec3(aim.targetOffset, targetOffset ?? defaultTargetOffset);
23
+ aim.radius = settings.radius;
24
+ aim.size = settings.size;
25
+ useImperativeHandle(ref, () => aim, [aim]);
26
+ useEffect(() => camera.setAim(aim), [camera, aim]);
27
+ if (!debug) return null;
28
+ return /* @__PURE__ */ jsx(DebugZoneOverlay, {
29
+ zones: composer(aim.screenPosition, aim.deadZone, aim.hardLimit),
30
+ crosshair: aim.screenPosition
31
+ });
32
+ }
33
+ //#endregion
34
+ export { RotationComposer };
@@ -0,0 +1,11 @@
1
+ import { Follow } from './Follow.js';
2
+ import { HardLockToTarget } from './HardLockToTarget.js';
3
+ import { OrbitFollow } from './OrbitFollow.js';
4
+ import { PositionComposer } from './PositionComposer.js';
5
+ /** Body components control a `<VirtualCamera>`'s position. Use at most one per camera. */
6
+ export declare const Body: {
7
+ HardLockToTarget: typeof HardLockToTarget;
8
+ Follow: typeof Follow;
9
+ PositionComposer: typeof PositionComposer;
10
+ OrbitFollow: typeof OrbitFollow;
11
+ };
@@ -0,0 +1,14 @@
1
+ import { Follow } from "./Follow.js";
2
+ import { HardLockToTarget } from "./HardLockToTarget.js";
3
+ import { OrbitFollow } from "./OrbitFollow.js";
4
+ import { PositionComposer } from "./PositionComposer.js";
5
+ //#region src/react/body/Body.ts
6
+ /** Body components control a `<VirtualCamera>`'s position. Use at most one per camera. */
7
+ var Body = {
8
+ HardLockToTarget,
9
+ Follow,
10
+ PositionComposer,
11
+ OrbitFollow
12
+ };
13
+ //#endregion
14
+ export { Body };
@@ -0,0 +1,50 @@
1
+ import type { ThreeElement, Vector3 as Vector3Like } from '@react-three/fiber';
2
+ import CameraControlsImpl, { EventDispatcher } from 'camera-controls';
3
+ import { type Ref } from 'react';
4
+ import { CameraControlsBodyThree } from '../../three/body/CameraControlsBodyThree.js';
5
+ import type { Target } from '../../three/resolve/Target.js';
6
+ type Overwrite<T, U> = Omit<T, keyof U> & U;
7
+ export type CameraControlsProps = Omit<Overwrite<ThreeElement<typeof CameraControlsImpl>, {
8
+ /** Target for orbiting and dollying. Omit for free camera controls. */
9
+ target?: Target;
10
+ /** World-space starting position, applied at construction regardless of `target`'s state. */
11
+ initialPosition?: Vector3Like;
12
+ /** `camera-controls`' own transition-easing argument for every call this makes. */
13
+ enableTransition?: boolean;
14
+ /** Custom `CameraControlsImpl` subclass to instantiate instead of the base class. */
15
+ impl?: typeof CameraControlsImpl;
16
+ /** Wait for an in-progress blend into this camera before listening to input. */
17
+ waitForBlend?: boolean;
18
+ /** Registers this instance as r3f's `state.controls` while it accepts input. */
19
+ makeDefault?: boolean;
20
+ ref?: Ref<CameraControlsBodyThree>;
21
+ /** Also lowers r3f's render quality while dragging/transitioning. */
22
+ regress?: boolean;
23
+ onControlStart?: (event: {
24
+ type: 'controlstart';
25
+ }) => void;
26
+ onControl?: (event: {
27
+ type: 'control';
28
+ }) => void;
29
+ onControlEnd?: (event: {
30
+ type: 'controlend';
31
+ }) => void;
32
+ onTransitionStart?: (event: {
33
+ type: 'transitionstart';
34
+ }) => void;
35
+ onUpdate?: (event: {
36
+ type: 'update';
37
+ }) => void;
38
+ onWake?: (event: {
39
+ type: 'wake';
40
+ }) => void;
41
+ onRest?: (event: {
42
+ type: 'rest';
43
+ }) => void;
44
+ onSleep?: (event: {
45
+ type: 'sleep';
46
+ }) => void;
47
+ }>, 'args' | keyof EventDispatcher>;
48
+ /** Connects `camera-controls` to the active virtual camera. */
49
+ export declare function CameraControls({ target, initialPosition, enableTransition, impl, waitForBlend, makeDefault, ref, regress, onControlStart, onControl, onControlEnd, onTransitionStart, onUpdate, onWake, onRest, onSleep, ...controlsProps }: CameraControlsProps): import("react").JSX.Element;
50
+ export {};
@@ -0,0 +1,106 @@
1
+ import { resolveVector3 } from "../../three/resolve/resolveVector3.js";
2
+ import { CameraControlsBodyThree } from "../../three/body/CameraControlsBodyThree.js";
3
+ import { useIsActiveVirtualCamera, useIsLiveVirtualCamera, useVirtualCamera } from "../VirtualCameraContext.js";
4
+ import { Vector3 } from "three";
5
+ import CameraControls from "camera-controls";
6
+ import { useThree } from "@react-three/fiber";
7
+ import { useEffect, useEffectEvent, useImperativeHandle, useState } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/react/body/CameraControls.tsx
10
+ /** Connects `camera-controls` to the active virtual camera. */
11
+ function CameraControls$1({ target, initialPosition, enableTransition = false, impl = CameraControls, waitForBlend = true, makeDefault = false, ref, regress = false, onControlStart, onControl, onControlEnd, onTransitionStart, onUpdate, onWake, onRest, onSleep, ...controlsProps }) {
12
+ const camera = useVirtualCamera();
13
+ const isActive = useIsActiveVirtualCamera();
14
+ const isLive = useIsLiveVirtualCamera();
15
+ const shouldConnect = isActive && (waitForBlend ? isLive : true);
16
+ const aspect = useThree((state) => state.viewport.aspect);
17
+ const domElement = useThree((state) => state.gl.domElement);
18
+ const invalidate = useThree((state) => state.invalidate);
19
+ const performance = useThree((state) => state.performance);
20
+ const set = useThree((state) => state.set);
21
+ const get = useThree((state) => state.get);
22
+ const [body] = useState(() => new CameraControlsBodyThree(target, {
23
+ aspect,
24
+ initialPosition: initialPosition ? resolveVector3(new Vector3(), initialPosition) : null,
25
+ impl,
26
+ enableTransition
27
+ }));
28
+ body.target = target;
29
+ body.aspect = aspect;
30
+ body.enableTransition = enableTransition;
31
+ useImperativeHandle(ref, () => body, [body]);
32
+ useEffect(() => camera.setBody(body), [camera, body]);
33
+ useEffect(() => {
34
+ if (!makeDefault || !shouldConnect) return;
35
+ const previous = get().controls;
36
+ set({ controls: body.controls });
37
+ return () => set({ controls: previous });
38
+ }, [
39
+ makeDefault,
40
+ shouldConnect,
41
+ body,
42
+ set,
43
+ get
44
+ ]);
45
+ const invalidateAndRegress = useEffectEvent(() => {
46
+ invalidate();
47
+ if (regress) performance.regress();
48
+ });
49
+ const handleControlStart = useEffectEvent((e) => {
50
+ invalidateAndRegress();
51
+ onControlStart?.(e);
52
+ });
53
+ const handleControl = useEffectEvent((e) => {
54
+ invalidateAndRegress();
55
+ onControl?.(e);
56
+ });
57
+ const handleControlEnd = useEffectEvent((e) => onControlEnd?.(e));
58
+ const handleTransitionStart = useEffectEvent((e) => {
59
+ invalidateAndRegress();
60
+ onTransitionStart?.(e);
61
+ });
62
+ const handleUpdate = useEffectEvent((e) => {
63
+ invalidateAndRegress();
64
+ onUpdate?.(e);
65
+ });
66
+ const handleWake = useEffectEvent((e) => {
67
+ invalidateAndRegress();
68
+ onWake?.(e);
69
+ });
70
+ const handleRest = useEffectEvent((e) => onRest?.(e));
71
+ const handleSleep = useEffectEvent((e) => onSleep?.(e));
72
+ useEffect(() => {
73
+ if (!shouldConnect) return;
74
+ body.controls.connect(domElement);
75
+ body.controls.addEventListener("controlstart", handleControlStart);
76
+ body.controls.addEventListener("control", handleControl);
77
+ body.controls.addEventListener("controlend", handleControlEnd);
78
+ body.controls.addEventListener("transitionstart", handleTransitionStart);
79
+ body.controls.addEventListener("update", handleUpdate);
80
+ body.controls.addEventListener("wake", handleWake);
81
+ body.controls.addEventListener("rest", handleRest);
82
+ body.controls.addEventListener("sleep", handleSleep);
83
+ if (domElement.ownerDocument.pointerLockElement === domElement) body.controls.lockPointer();
84
+ return () => {
85
+ body.controls.disconnect();
86
+ body.controls.removeEventListener("controlstart", handleControlStart);
87
+ body.controls.removeEventListener("control", handleControl);
88
+ body.controls.removeEventListener("controlend", handleControlEnd);
89
+ body.controls.removeEventListener("transitionstart", handleTransitionStart);
90
+ body.controls.removeEventListener("update", handleUpdate);
91
+ body.controls.removeEventListener("wake", handleWake);
92
+ body.controls.removeEventListener("rest", handleRest);
93
+ body.controls.removeEventListener("sleep", handleSleep);
94
+ };
95
+ }, [
96
+ body,
97
+ domElement,
98
+ shouldConnect
99
+ ]);
100
+ return /* @__PURE__ */ jsx("primitive", {
101
+ object: body.controls,
102
+ ...controlsProps
103
+ });
104
+ }
105
+ //#endregion
106
+ export { CameraControls$1 as CameraControls };
@@ -0,0 +1,10 @@
1
+ import { type Ref } from 'react';
2
+ import { FollowBodyThree, type FollowThreeOptions } from '../../three/body/FollowBodyThree.js';
3
+ import type { Target } from '../../three/resolve/Target.js';
4
+ export type FollowProps = FollowThreeOptions & {
5
+ /** Target to follow. Unresolved targets are ignored. */
6
+ target?: Target;
7
+ ref?: Ref<FollowBodyThree>;
8
+ };
9
+ /** Follows a target with a configurable offset and rotation frame. */
10
+ export declare function Follow({ target, offset, ref, ...settings }: FollowProps): null;
@@ -0,0 +1,20 @@
1
+ import { createParams } from "../../core/body/follow.js";
2
+ import { resolveVec3 } from "../../three/resolve/resolveVector3.js";
3
+ import { FollowBodyThree } from "../../three/body/FollowBodyThree.js";
4
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
5
+ import { useEffect, useImperativeHandle, useState } from "react";
6
+ //#region src/react/body/Follow.tsx
7
+ /** Follows a target with a configurable offset and rotation frame. */
8
+ function Follow({ target, offset, ref, ...settings }) {
9
+ const camera = useVirtualCamera();
10
+ const { offset: defaultOffset, ...params } = createParams(settings);
11
+ const [body] = useState(() => new FollowBodyThree(target, params));
12
+ body.target = target;
13
+ Object.assign(body, params);
14
+ resolveVec3(body.offset, offset ?? defaultOffset);
15
+ useImperativeHandle(ref, () => body, [body]);
16
+ useEffect(() => camera.setBody(body), [camera, body]);
17
+ return null;
18
+ }
19
+ //#endregion
20
+ export { Follow };
@@ -0,0 +1,10 @@
1
+ import { type Ref } from 'react';
2
+ import { HardLockToTargetBodyThree, type HardLockToTargetOptions } from '../../three/body/HardLockToTargetBodyThree.js';
3
+ import type { Target } from '../../three/resolve/Target.js';
4
+ export type HardLockToTargetProps = HardLockToTargetOptions & {
5
+ /** Target position to follow. Unresolved targets are ignored. */
6
+ target?: Target;
7
+ ref?: Ref<HardLockToTargetBodyThree>;
8
+ };
9
+ /** Simple body that locks the camera to a target position, optionally with damping. */
10
+ export declare function HardLockToTarget({ target, ref, ...settings }: HardLockToTargetProps): null;
@@ -0,0 +1,18 @@
1
+ import { createParams } from "../../core/body/hardLockToTarget.js";
2
+ import { HardLockToTargetBodyThree } from "../../three/body/HardLockToTargetBodyThree.js";
3
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
4
+ import { useEffect, useImperativeHandle, useState } from "react";
5
+ //#region src/react/body/HardLockToTarget.tsx
6
+ /** Simple body that locks the camera to a target position, optionally with damping. */
7
+ function HardLockToTarget({ target, ref, ...settings }) {
8
+ const camera = useVirtualCamera();
9
+ const params = createParams(settings);
10
+ const [body] = useState(() => new HardLockToTargetBodyThree(target, params));
11
+ body.target = target;
12
+ Object.assign(body, params);
13
+ useImperativeHandle(ref, () => body, [body]);
14
+ useEffect(() => camera.setBody(body), [camera, body]);
15
+ return null;
16
+ }
17
+ //#endregion
18
+ export { HardLockToTarget };
@@ -0,0 +1,25 @@
1
+ import { type ReactNode, type Ref } from 'react';
2
+ import type { InputAxisParams } from '../../core/input/axis.js';
3
+ import { OrbitFollowBodyThree, type OrbitFollowThreeOptions } from '../../three/body/OrbitFollowBodyThree.js';
4
+ import type { Target } from '../../three/resolve/Target.js';
5
+ /** Settings of one orbit axis. It starts at `center`, then input drives its value. */
6
+ export type OrbitFollowAxisSettings = Partial<Omit<InputAxisParams, 'value'>>;
7
+ export type OrbitFollowProps = OrbitFollowThreeOptions & {
8
+ /** Target to orbit. Unresolved targets are ignored. */
9
+ target?: Target;
10
+ /** Angle around the target, in degrees. */
11
+ horizontal?: OrbitFollowAxisSettings;
12
+ /** Elevation above the target in degrees, or from the bottom to the top ring for `threeRing`. */
13
+ vertical?: OrbitFollowAxisSettings;
14
+ /** Natural log of the radius scale. */
15
+ radial?: OrbitFollowAxisSettings;
16
+ /** `horizontal.autoNormalize`: keeps it inside its range after each drag. */
17
+ autoNormalize?: boolean;
18
+ /** Draws the orbit in the scene. */
19
+ debug?: boolean;
20
+ ref?: Ref<OrbitFollowBodyThree>;
21
+ /** Nested `<InputController>` picks up `horizontal`/`vertical`/`radial` without an explicit `target`. */
22
+ children?: ReactNode;
23
+ };
24
+ /** Orbits a target, driven by the `horizontal`, `vertical` and `radial` axes. */
25
+ export declare function OrbitFollow({ target, targetOffset, horizontal, vertical, radial, autoNormalize, debug, ref, children, ...settings }: OrbitFollowProps): import("react").JSX.Element;
@@ -0,0 +1,67 @@
1
+ import { withDefaults } from "../../core/params.js";
2
+ import { createParams } from "../../core/input/axis.js";
3
+ import { createAxisSettings, createParams as createParams$1 } from "../../core/body/orbitFollow.js";
4
+ import { resolveVec3 } from "../../three/resolve/resolveVector3.js";
5
+ import { OrbitFollowBodyThree } from "../../three/body/OrbitFollowBodyThree.js";
6
+ import { OrbitFollowHelperThree } from "../../three/body/OrbitFollowHelperThree.js";
7
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
8
+ import { InputAxisOwnerContext } from "../input/InputAxisOwnerContext.js";
9
+ import { useFrame } from "@react-three/fiber";
10
+ import { useEffect, useImperativeHandle, useState } from "react";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ //#region src/react/body/OrbitFollow.tsx
13
+ function applyAxis(axis, defaults, settings) {
14
+ const params = withDefaults(createParams(defaults), settings);
15
+ params.value = axis.value;
16
+ Object.assign(axis, params);
17
+ }
18
+ function applyAxes(body, { horizontal, vertical, radial, autoNormalize }) {
19
+ const defaults = createAxisSettings();
20
+ defaults.horizontal.autoNormalize = autoNormalize;
21
+ applyAxis(body.horizontal, defaults.horizontal, horizontal);
22
+ applyAxis(body.vertical, defaults.vertical, vertical);
23
+ applyAxis(body.radial, defaults.radial, radial);
24
+ }
25
+ /** Orbits a target, driven by the `horizontal`, `vertical` and `radial` axes. */
26
+ function OrbitFollow({ target, targetOffset, horizontal, vertical, radial, autoNormalize = false, debug = false, ref, children, ...settings }) {
27
+ const camera = useVirtualCamera();
28
+ const { targetOffset: defaultTargetOffset, ...params } = createParams$1(settings);
29
+ const [body] = useState(() => {
30
+ const created = new OrbitFollowBodyThree(target, params);
31
+ applyAxes(created, {
32
+ horizontal,
33
+ vertical,
34
+ radial,
35
+ autoNormalize
36
+ });
37
+ for (const axis of [
38
+ created.horizontal,
39
+ created.vertical,
40
+ created.radial
41
+ ]) axis.setValue(axis.center);
42
+ return created;
43
+ });
44
+ body.target = target;
45
+ Object.assign(body, params);
46
+ resolveVec3(body.targetOffset, targetOffset ?? defaultTargetOffset);
47
+ applyAxes(body, {
48
+ horizontal,
49
+ vertical,
50
+ radial,
51
+ autoNormalize
52
+ });
53
+ useImperativeHandle(ref, () => body, [body]);
54
+ useEffect(() => camera.setBody(body), [camera, body]);
55
+ return /* @__PURE__ */ jsxs(InputAxisOwnerContext.Provider, {
56
+ value: body,
57
+ children: [children, debug && /* @__PURE__ */ jsx(OrbitDebug, { body })]
58
+ });
59
+ }
60
+ function OrbitDebug({ body }) {
61
+ const [helper] = useState(() => new OrbitFollowHelperThree());
62
+ useEffect(() => () => helper.dispose(), [helper]);
63
+ useFrame(() => helper.sync(body));
64
+ return /* @__PURE__ */ jsx("primitive", { object: helper });
65
+ }
66
+ //#endregion
67
+ export { OrbitFollow };
@@ -0,0 +1,12 @@
1
+ import { type Ref } from 'react';
2
+ import { PositionComposerBodyThree, type PositionComposerThreeOptions } from '../../three/body/PositionComposerBodyThree.js';
3
+ import type { Target } from '../../three/resolve/Target.js';
4
+ export type PositionComposerProps = Omit<PositionComposerThreeOptions, 'aspect'> & {
5
+ /** Target to compose around. Unresolved targets are ignored. */
6
+ target?: Target;
7
+ /** Draws the `deadZone` and `hardLimit` overlays. */
8
+ debug?: boolean;
9
+ ref?: Ref<PositionComposerBodyThree>;
10
+ };
11
+ /** Positions the camera around a target while maintaining screen composition. */
12
+ export declare function PositionComposer({ target, debug, ref, ...settings }: PositionComposerProps): import("react").JSX.Element | null;
@@ -0,0 +1,32 @@
1
+ import { createParams } from "../../core/body/positionComposer.js";
2
+ import { composer } from "../../core/debug/debugZones.js";
3
+ import { PositionComposerBodyThree } from "../../three/body/PositionComposerBodyThree.js";
4
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
5
+ import { DebugZoneOverlay } from "../DebugZoneOverlay.js";
6
+ import { useThree } from "@react-three/fiber";
7
+ import { useEffect, useImperativeHandle, useState } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/react/body/PositionComposer.tsx
10
+ /** Positions the camera around a target while maintaining screen composition. */
11
+ function PositionComposer({ target, debug = false, ref, ...settings }) {
12
+ const camera = useVirtualCamera();
13
+ const aspect = useThree((state) => state.viewport.aspect);
14
+ const params = createParams({
15
+ ...settings,
16
+ aspect
17
+ });
18
+ const [body] = useState(() => new PositionComposerBodyThree(target, params));
19
+ body.target = target;
20
+ Object.assign(body, params);
21
+ body.radius = settings.radius;
22
+ body.size = settings.size;
23
+ useImperativeHandle(ref, () => body, [body]);
24
+ useEffect(() => camera.setBody(body), [camera, body]);
25
+ if (!debug) return null;
26
+ return /* @__PURE__ */ jsx(DebugZoneOverlay, {
27
+ zones: composer(body.screenPosition, body.deadZone, body.hardLimit),
28
+ crosshair: body.screenPosition
29
+ });
30
+ }
31
+ //#endregion
32
+ export { PositionComposer };
@@ -0,0 +1,2 @@
1
+ export { CameraControls, type CameraControlsProps } from './CameraControls.js';
2
+ export { CameraControlsBodyThree } from '../../three/body/CameraControlsBodyThree.js';
@@ -0,0 +1,3 @@
1
+ import { CameraControlsBodyThree } from "../../three/body/CameraControlsBodyThree.js";
2
+ import { CameraControls } from "./CameraControls.js";
3
+ export { CameraControls, CameraControlsBodyThree };
@@ -0,0 +1,7 @@
1
+ import { GroupFraming } from './GroupFraming.js';
2
+ import { Lens } from './Lens.js';
3
+ /** Extensions run after Body/Aim and before Noise; multiple extensions can be registered. */
4
+ export declare const Extension: {
5
+ GroupFraming: typeof GroupFraming;
6
+ Lens: typeof Lens;
7
+ };
@@ -0,0 +1,10 @@
1
+ import { GroupFraming } from "./GroupFraming.js";
2
+ import { Lens } from "./Lens.js";
3
+ //#region src/react/extension/Extension.ts
4
+ /** Extensions run after Body/Aim and before Noise; multiple extensions can be registered. */
5
+ var Extension = {
6
+ GroupFraming,
7
+ Lens
8
+ };
9
+ //#endregion
10
+ export { Extension };
@@ -0,0 +1,14 @@
1
+ import { type Ref } from 'react';
2
+ import { GroupFramingExtensionThree, type GroupFramingOptions } from '../../three/extension/GroupFramingExtensionThree.js';
3
+ import { type TargetGroupMember, type TargetGroupPositionMode } from '../../three/extension/TargetGroup.js';
4
+ export type GroupFramingProps = Omit<GroupFramingOptions, 'viewportWidth' | 'viewportHeight'> & {
5
+ /** Targets to keep in frame. */
6
+ members: TargetGroupMember[];
7
+ /** Strategy used to compute the group's position. */
8
+ positionMode?: TargetGroupPositionMode;
9
+ /** Draws the padding boundary while this camera is live. */
10
+ debug?: boolean;
11
+ ref?: Ref<GroupFramingExtensionThree>;
12
+ };
13
+ /** Keeps a target group framed within the camera. */
14
+ export declare function GroupFraming({ members, positionMode, debug, ref, ...settings }: GroupFramingProps): import("react").JSX.Element | null;
@@ -0,0 +1,52 @@
1
+ import { createParams } from "../../core/extension/groupFraming.js";
2
+ import { groupFramingPaddingBox } from "../../core/debug/debugZones.js";
3
+ import { TargetGroup } from "../../three/extension/TargetGroup.js";
4
+ import { GroupFramingExtensionThree } from "../../three/extension/GroupFramingExtensionThree.js";
5
+ import { useVirtualCamera } from "../VirtualCameraContext.js";
6
+ import { DebugZoneOverlay } from "../DebugZoneOverlay.js";
7
+ import { Vector3 } from "three";
8
+ import { useFrame, useThree } from "@react-three/fiber";
9
+ import { useEffect, useImperativeHandle, useState } from "react";
10
+ import { jsx } from "react/jsx-runtime";
11
+ //#region src/react/extension/GroupFraming.tsx
12
+ var scratchGroupPosition = new Vector3();
13
+ var scratchCameraPosition = new Vector3();
14
+ /** Minimum visible change for the debug overlay. */
15
+ var DEBUG_BOX_EPSILON = .002;
16
+ /** Keeps a target group framed within the camera. */
17
+ function GroupFraming({ members, positionMode = "groupCenter", debug = false, ref, ...settings }) {
18
+ const camera = useVirtualCamera();
19
+ const cameraState = camera.state;
20
+ const size = useThree((state) => state.size);
21
+ const params = createParams({
22
+ ...settings,
23
+ viewportWidth: size.width,
24
+ viewportHeight: size.height
25
+ });
26
+ const [group] = useState(() => new TargetGroup(members, positionMode));
27
+ const [extension] = useState(() => new GroupFramingExtensionThree(group, params));
28
+ group.members = members;
29
+ group.positionMode = positionMode;
30
+ Object.assign(extension, params);
31
+ useImperativeHandle(ref, () => extension, [extension]);
32
+ useEffect(() => camera.addExtension(extension), [camera, extension]);
33
+ const [paddingBox, setPaddingBox] = useState(null);
34
+ useFrame(() => {
35
+ if (!debug) return;
36
+ if (group.computeBounds(scratchGroupPosition) <= 0) {
37
+ setPaddingBox((previous) => previous === null ? previous : null);
38
+ return;
39
+ }
40
+ const distance = scratchCameraPosition.fromArray(cameraState.position).distanceTo(scratchGroupPosition);
41
+ const next = groupFramingPaddingBox([0, 0], cameraState.fov, size.width / size.height, distance, extension.padding, extension.framingMode);
42
+ setPaddingBox((previous) => previous && Math.abs(previous[0] - next[0]) < DEBUG_BOX_EPSILON && Math.abs(previous[1] - next[1]) < DEBUG_BOX_EPSILON ? previous : next);
43
+ });
44
+ if (!debug || !paddingBox) return null;
45
+ return /* @__PURE__ */ jsx(DebugZoneOverlay, { zones: [{
46
+ screenPosition: extension.screenPosition,
47
+ size: paddingBox,
48
+ className: "klipp-debug-groupframing"
49
+ }] });
50
+ }
51
+ //#endregion
52
+ export { GroupFraming };
@@ -0,0 +1,7 @@
1
+ import { type Ref } from 'react';
2
+ import { LensExtension, type LensOptions } from '../../core/extension/LensExtension.js';
3
+ export type LensProps = LensOptions & {
4
+ ref?: Ref<LensExtension>;
5
+ };
6
+ /** Animates the camera lens without forcing a React re-render. */
7
+ export declare function Lens({ ref, ...settings }: LensProps): null;