@react-three/drei 9.31.2 → 9.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,8 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
48
48
  <li><a href="#controls">PointerLockControls</a></li>
49
49
  <li><a href="#controls">FirstPersonControls</a></li>
50
50
  <li><a href="#scrollcontrols">ScrollControls</a></li>
51
- <li><a href="#presentationcontrols">PresentationControls</a></li>
51
+ <li><a href="#presentationcontrols">PresentationControls</a></li>
52
+ <li><a href="#keyboardcontrols">KeyboardControls</a></li>
52
53
  </ul>
53
54
  <li><a href="#gizmos">Gizmos</a></li>
54
55
  <ul>
@@ -385,6 +386,79 @@ Semi-OrbitControls with spring-physics, polar zoom and snap-back, for presentati
385
386
  </PresentationControls>
386
387
  ```
387
388
 
389
+ #### KeyboardControls
390
+
391
+ ![](https://img.shields.io/badge/-Dom only-red)
392
+
393
+ A rudimentary keyboard controller which distributes your defined data-model to the `useKeyboard` hook. It's a rather simple way to get started with keyboard input.
394
+
395
+ ```tsx
396
+ type KeyboardControlsState = { [key: string]: boolean }
397
+
398
+ type KeyboardControlsEntry = {
399
+ /** Name of the action */
400
+ name: string
401
+ /** The keys that define it, you can use either event.key, or event.code */
402
+ keys: string[]
403
+ /** If the event receives the keyup event, true by default */
404
+ up?: boolean
405
+ }
406
+
407
+ type KeyboardControlsProps = {
408
+ /** A map of named keys */
409
+ map: KeyboardControlsEntry[]
410
+ /** All children will be able to useKeyboardControls */
411
+ children: React.ReactNode
412
+ /** Optional onchange event */
413
+ onChange: (name: string, pressed: boolean, state: KeyboardControlsState) => void
414
+ /** Optional event source */
415
+ domElement?: HTMLElement
416
+ }
417
+ ```
418
+
419
+ You start by wrapping your app, or scene, into `<KeyboardControls>`.
420
+
421
+ ```jsx
422
+ function App() {
423
+ return (
424
+ <KeyboardControls
425
+ map={[
426
+ { name: 'forward', keys: ['ArrowUp', 'w', 'W'] },
427
+ { name: 'backward', keys: ['ArrowDown', 's', 'S'] },
428
+ { name: 'leftward', keys: ['ArrowLeft', 'a', 'A'] },
429
+ { name: 'rightward', keys: ['ArrowRight', 'd', 'D'] },
430
+ { name: 'jump', keys: ['Space'] },
431
+ ]}>
432
+ <App />
433
+ </KeyboardControls>
434
+ ```
435
+
436
+ You can either respond to input reactively, it uses zustand (width the `subscribeWithSelector` middleware) so all the rules apply:
437
+
438
+ ```jsx
439
+ function Foo() {
440
+ const pressed = useKeyboardControls(state => foward)
441
+ ```
442
+
443
+ Or transiently, either by `subscribe`, which is a function which returns a function to unsubscribe, so you can pair it with useEffect for cleanup, or `get`, which fetches fresh state non-reactively.
444
+
445
+ ```jsx
446
+ function Foo() {
447
+ const [sub, get] = useKeyboardControls()
448
+
449
+ useEffect(() => {
450
+ return sub(state => state.forward, pressed => {
451
+ console.log('forward', pressed)
452
+ })
453
+ }, [])
454
+
455
+ useFrame(() => {
456
+ // Fetch fresh data from store
457
+ const pressed = get().backward
458
+ })
459
+ }
460
+ ```
461
+
388
462
  # Gizmos
389
463
 
390
464
  #### GizmoHelper
@@ -2124,15 +2198,17 @@ function App() {
2124
2198
  <PerformanceMonitor onIncline={() => setDpr(2)} onDecline={() => setDpr(1)} >
2125
2199
  ```
2126
2200
 
2127
- You can also use the `onChange` callback to get notified when the average changes in whichever direction. This allows you to make gradual changes. It gives you a factor between 0 and 1, which is increased by incline and decreased by decline. The factor is initially 0.5 by default.
2201
+ You can also use the `onChange` callback to get notified when the average changes in whichever direction. This allows you to make gradual changes. It gives you a `factor` between 0 and 1, which is increased by incline and decreased by decline. The `factor` is initially 0.5 by default. If your app starts with lowest defaults and gradually increases quality set `factor` to 0. If it starts with highest defaults and decreases quality, set it to 1. If it starts in the middle and can either increase or decrease, set it to 0.5.
2202
+
2203
+ The following starts at the highest dpr (2) and clamps the gradual dpr between 0.5 at the lowest and 2 at the highest. If the app is in trouble it will reduce `factor` by `step` until it is either 0 or the app has found its sweet spot above that.
2128
2204
 
2129
2205
  ```jsx
2130
2206
  import round from 'lodash/round'
2131
2207
 
2132
- const [dpr, set] = useState(1)
2208
+ const [dpr, set] = useState(2)
2133
2209
  return (
2134
2210
  <Canvas dpr={dpr}>
2135
- <PerformanceMonitor onChange={({ factor }) => setDpr(round(0.5 + 1.5 * factor, 1))} >
2211
+ <PerformanceMonitor factor={1} onChange={({ factor }) => setDpr(round(0.5 + 1.5 * factor, 1))} >
2136
2212
  ```
2137
2213
 
2138
2214
  If you still experience flip flops despite the bounds you can define a limit of `flipflops`. If it is met `onFallback` will be triggered which typically sets a lowest possible baseline for the app. After the fallback has been called PerformanceMonitor will shut down.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("@react-three/fiber"),r=require("react"),n=require("three-stdlib");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function l(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=u(e),a=l(r);const i=a.forwardRef((({domElement:e,...r},u)=>{const{onChange:l,...i}=r,c=t.useThree((e=>e.invalidate)),s=t.useThree((e=>e.camera)),d=t.useThree((e=>e.gl)),f=t.useThree((e=>e.events)),v=e||f.connected||d.domElement,[b]=a.useState((()=>new n.FlyControls(s,v)));return a.useEffect((()=>{const e=e=>{c(),l&&l(e)};return null==b||null==b.addEventListener||b.addEventListener("change",e),()=>null==b||null==b.removeEventListener?void 0:b.removeEventListener("change",e)}),[l,b,c]),t.useFrame(((e,t)=>null==b?void 0:b.update(t))),b?a.createElement("primitive",o.default({ref:u,object:b},i)):null}));exports.FlyControls=i;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("@react-three/fiber"),r=require("react"),n=require("three-stdlib");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var s=u(e),c=o(r);const a=c.forwardRef((({domElement:e,...r},u)=>{const{onChange:o,...a}=r,i=t.useThree((e=>e.invalidate)),l=t.useThree((e=>e.camera)),f=t.useThree((e=>e.gl)),d=t.useThree((e=>e.events)),v=e||d.connected||f.domElement,b=c.useMemo((()=>new n.FlyControls(l)),[l]);return c.useEffect((()=>(b.connect(v),()=>{b.dispose()})),[v,b,i]),c.useEffect((()=>{const e=e=>{i(),o&&o(e)};return null==b.addEventListener||b.addEventListener("change",e),()=>null==b.removeEventListener?void 0:b.removeEventListener("change",e)}),[o,i]),t.useFrame(((e,t)=>b.update(t))),c.createElement("primitive",s.default({ref:u,object:b,args:[l,v]},a))}));exports.FlyControls=a;
@@ -6,4 +6,4 @@ export declare type FlyControlsProps = ReactThreeFiber.Object3DNode<FlyControlsI
6
6
  onChange?: (e?: THREE.Event) => void;
7
7
  domElement?: HTMLElement;
8
8
  };
9
- export declare const FlyControls: React.ForwardRefExoticComponent<Pick<FlyControlsProps, "object" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onChange" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "update" | "domElement" | "movementSpeed" | "rollSpeed" | "dragToLook" | "autoForward"> & React.RefAttributes<FlyControlsImpl>>;
9
+ export declare const FlyControls: React.ForwardRefExoticComponent<Pick<FlyControlsProps, "object" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onChange" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "connect" | "update" | "domElement" | "movementSpeed" | "rollSpeed" | "dragToLook" | "autoForward"> & React.RefAttributes<FlyControlsImpl>>;
@@ -6,7 +6,7 @@ import { FlyControls as FlyControls$1 } from 'three-stdlib';
6
6
  const FlyControls = /*#__PURE__*/React.forwardRef(({
7
7
  domElement,
8
8
  ...props
9
- }, ref) => {
9
+ }, fref) => {
10
10
  const {
11
11
  onChange,
12
12
  ...rest
@@ -16,21 +16,26 @@ const FlyControls = /*#__PURE__*/React.forwardRef(({
16
16
  const gl = useThree(state => state.gl);
17
17
  const events = useThree(state => state.events);
18
18
  const explDomElement = domElement || events.connected || gl.domElement;
19
- const [controls] = React.useState(() => new FlyControls$1(camera, explDomElement));
19
+ const controls = React.useMemo(() => new FlyControls$1(camera), [camera]);
20
+ React.useEffect(() => {
21
+ controls.connect(explDomElement);
22
+ return () => void controls.dispose();
23
+ }, [explDomElement, controls, invalidate]);
20
24
  React.useEffect(() => {
21
25
  const callback = e => {
22
26
  invalidate();
23
27
  if (onChange) onChange(e);
24
28
  };
25
29
 
26
- controls == null ? void 0 : controls.addEventListener == null ? void 0 : controls.addEventListener('change', callback);
27
- return () => controls == null ? void 0 : controls.removeEventListener == null ? void 0 : controls.removeEventListener('change', callback);
28
- }, [onChange, controls, invalidate]);
29
- useFrame((_, delta) => controls == null ? void 0 : controls.update(delta));
30
- return controls ? /*#__PURE__*/React.createElement("primitive", _extends({
31
- ref: ref,
32
- object: controls
33
- }, rest)) : null;
30
+ controls.addEventListener == null ? void 0 : controls.addEventListener('change', callback);
31
+ return () => controls.removeEventListener == null ? void 0 : controls.removeEventListener('change', callback);
32
+ }, [onChange, invalidate]);
33
+ useFrame((_, delta) => controls.update(delta));
34
+ return /*#__PURE__*/React.createElement("primitive", _extends({
35
+ ref: fref,
36
+ object: controls,
37
+ args: [camera, explDomElement]
38
+ }, rest));
34
39
  });
35
40
 
36
41
  export { FlyControls };
@@ -11,4 +11,4 @@ export declare type MapControlsProps = ReactThreeFiber.Overwrite<ReactThreeFiber
11
11
  onEnd?: (e?: THREE.Event) => void;
12
12
  domElement?: HTMLElement;
13
13
  }>;
14
- export declare const MapControls: React.ForwardRefExoticComponent<Pick<MapControlsProps, "object" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onChange" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "camera" | "reset" | "enabled" | "connect" | "update" | "target" | "onStart" | "keys" | "touches" | "makeDefault" | "domElement" | "minDistance" | "maxDistance" | "minZoom" | "maxZoom" | "minPolarAngle" | "maxPolarAngle" | "minAzimuthAngle" | "maxAzimuthAngle" | "enableDamping" | "dampingFactor" | "enableZoom" | "zoomSpeed" | "enableRotate" | "rotateSpeed" | "enablePan" | "panSpeed" | "screenSpacePanning" | "keyPanSpeed" | "autoRotate" | "autoRotateSpeed" | "reverseOrbit" | "mouseButtons" | "target0" | "position0" | "zoom0" | "_domElementKeyEvents" | "getPolarAngle" | "getAzimuthalAngle" | "setPolarAngle" | "setAzimuthalAngle" | "getDistance" | "listenToKeyEvents" | "saveState" | "onEnd"> & React.RefAttributes<MapControlsImpl>>;
14
+ export declare const MapControls: React.ForwardRefExoticComponent<Pick<MapControlsProps, "object" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onChange" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "camera" | "reset" | "enabled" | "connect" | "update" | "target" | "onStart" | "keys" | "touches" | "domElement" | "makeDefault" | "minDistance" | "maxDistance" | "minZoom" | "maxZoom" | "minPolarAngle" | "maxPolarAngle" | "minAzimuthAngle" | "maxAzimuthAngle" | "enableDamping" | "dampingFactor" | "enableZoom" | "zoomSpeed" | "enableRotate" | "rotateSpeed" | "enablePan" | "panSpeed" | "screenSpacePanning" | "keyPanSpeed" | "autoRotate" | "autoRotateSpeed" | "reverseOrbit" | "mouseButtons" | "target0" | "position0" | "zoom0" | "_domElementKeyEvents" | "getPolarAngle" | "getAzimuthalAngle" | "setPolarAngle" | "setAzimuthalAngle" | "getDistance" | "listenToKeyEvents" | "saveState" | "onEnd"> & React.RefAttributes<MapControlsImpl>>;
@@ -12,4 +12,4 @@ export declare type TrackballControlsProps = ReactThreeFiber.Overwrite<ReactThre
12
12
  onStart?: (e?: THREE.Event) => void;
13
13
  onEnd?: (e?: THREE.Event) => void;
14
14
  }>;
15
- export declare const TrackballControls: React.ForwardRefExoticComponent<Pick<TrackballControlsProps, "object" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onChange" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "camera" | "screen" | "reset" | "enabled" | "connect" | "update" | "target" | "onStart" | "keys" | "makeDefault" | "domElement" | "minDistance" | "maxDistance" | "zoomSpeed" | "rotateSpeed" | "panSpeed" | "mouseButtons" | "onEnd" | "regress" | "noRotate" | "noZoom" | "noPan" | "staticMoving" | "dynamicDampingFactor" | "cursorZoom" | "handleResize"> & React.RefAttributes<TrackballControlsImpl>>;
15
+ export declare const TrackballControls: React.ForwardRefExoticComponent<Pick<TrackballControlsProps, "object" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onChange" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "camera" | "screen" | "reset" | "enabled" | "connect" | "update" | "target" | "onStart" | "keys" | "domElement" | "makeDefault" | "minDistance" | "maxDistance" | "zoomSpeed" | "rotateSpeed" | "panSpeed" | "mouseButtons" | "onEnd" | "regress" | "noRotate" | "noZoom" | "noPan" | "staticMoving" | "dynamicDampingFactor" | "cursorZoom" | "handleResize"> & React.RefAttributes<TrackballControlsImpl>>;
package/core/useGLTF.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { GLTFLoader, GLTF } from 'three-stdlib';
2
- export declare function useGLTF<T extends string | string[]>(path: T, useDraco?: boolean | string, useMeshOpt?: boolean, extendLoader?: (loader: GLTFLoader) => void): T extends any[] ? GLTF[] : GLTF;
1
+ import { GLTFLoader } from 'three-stdlib';
2
+ export declare function useGLTF<T extends string | string[]>(path: T, useDraco?: boolean | string, useMeshOpt?: boolean, extendLoader?: (loader: GLTFLoader) => void): T extends any[] ? (import("three/examples/jsm/loaders/GLTFLoader").GLTF & import("@react-three/fiber").ObjectMap)[] : import("three/examples/jsm/loaders/GLTFLoader").GLTF & import("@react-three/fiber").ObjectMap;
3
3
  export declare namespace useGLTF {
4
4
  var preload: (path: string | string[], useDraco?: string | boolean, useMeshOpt?: boolean, extendLoader?: ((loader: GLTFLoader) => void) | undefined) => undefined;
5
5
  var clear: (input: string | string[]) => void;