@react-three/fiber 7.0.20 → 7.0.24
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/CHANGELOG.md +24 -0
- package/dist/declarations/src/core/events.d.ts +4 -4
- package/dist/declarations/src/core/store.d.ts +11 -5
- package/dist/declarations/src/three-types.d.ts +3 -1
- package/dist/react-three-fiber.cjs.dev.js +60 -17
- package/dist/react-three-fiber.cjs.prod.js +60 -17
- package/dist/react-three-fiber.esm.js +60 -17
- package/native/dist/react-three-fiber-native.cjs.dev.js +209 -411
- package/native/dist/react-three-fiber-native.cjs.prod.js +209 -411
- package/native/dist/react-three-fiber-native.esm.js +185 -387
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @react-three/fiber
|
|
2
2
|
|
|
3
|
+
## 7.0.24
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7f46ddf: cleanup captured pointers when released (#1914)
|
|
8
|
+
|
|
9
|
+
## 7.0.23
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 30d38b1: remove logs
|
|
14
|
+
|
|
15
|
+
## 7.0.22
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 259e1fa: add camera:manual
|
|
20
|
+
|
|
21
|
+
## 7.0.21
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 65e4147: up usemeasure, add last event to internals"
|
|
26
|
+
|
|
3
27
|
## 7.0.20
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -4,7 +4,7 @@ import type { RootState } from './store';
|
|
|
4
4
|
export interface Intersection extends THREE.Intersection {
|
|
5
5
|
eventObject: THREE.Object3D;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface IntersectionEvent<TSourceEvent> extends Intersection {
|
|
8
8
|
intersections: Intersection[];
|
|
9
9
|
stopped: boolean;
|
|
10
10
|
unprojectedPoint: THREE.Vector3;
|
|
@@ -18,8 +18,8 @@ export interface IntesectionEvent<TSourceEvent> extends Intersection {
|
|
|
18
18
|
spaceY: number;
|
|
19
19
|
}
|
|
20
20
|
export declare type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera;
|
|
21
|
-
export declare type ThreeEvent<TEvent> =
|
|
22
|
-
export declare type DomEvent =
|
|
21
|
+
export declare type ThreeEvent<TEvent> = IntersectionEvent<TEvent>;
|
|
22
|
+
export declare type DomEvent = PointerEvent | MouseEvent | WheelEvent;
|
|
23
23
|
export declare type Events = {
|
|
24
24
|
onClick: EventListener;
|
|
25
25
|
onContextMenu: EventListener;
|
|
@@ -43,7 +43,7 @@ export declare type EventHandlers = {
|
|
|
43
43
|
onPointerEnter?: (event: ThreeEvent<PointerEvent>) => void;
|
|
44
44
|
onPointerLeave?: (event: ThreeEvent<PointerEvent>) => void;
|
|
45
45
|
onPointerMove?: (event: ThreeEvent<PointerEvent>) => void;
|
|
46
|
-
onPointerMissed?: (event:
|
|
46
|
+
onPointerMissed?: (event: MouseEvent) => void;
|
|
47
47
|
onPointerCancel?: (event: ThreeEvent<PointerEvent>) => void;
|
|
48
48
|
onWheel?: (event: ThreeEvent<WheelEvent>) => void;
|
|
49
49
|
};
|
|
@@ -47,8 +47,9 @@ export declare type InternalState = {
|
|
|
47
47
|
priority: number;
|
|
48
48
|
frames: number;
|
|
49
49
|
lastProps: StoreProps;
|
|
50
|
+
lastEvent: React.MutableRefObject<DomEvent | null>;
|
|
50
51
|
interaction: THREE.Object3D[];
|
|
51
|
-
hovered: Map<string, DomEvent
|
|
52
|
+
hovered: Map<string, ThreeEvent<DomEvent>>;
|
|
52
53
|
subscribers: Subscription[];
|
|
53
54
|
capturedMap: Map<number, Map<THREE.Object3D, PointerCaptureTarget>>;
|
|
54
55
|
initialClick: [x: number, y: number];
|
|
@@ -58,7 +59,9 @@ export declare type InternalState = {
|
|
|
58
59
|
export declare type RootState = {
|
|
59
60
|
gl: THREE.WebGLRenderer;
|
|
60
61
|
scene: THREE.Scene;
|
|
61
|
-
camera: Camera
|
|
62
|
+
camera: Camera & {
|
|
63
|
+
manual?: boolean;
|
|
64
|
+
};
|
|
62
65
|
controls: THREE.EventDispatcher | null;
|
|
63
66
|
raycaster: Raycaster;
|
|
64
67
|
mouse: THREE.Vector2;
|
|
@@ -78,7 +81,8 @@ export declare type RootState = {
|
|
|
78
81
|
advance: (timestamp: number, runGlobalEffects?: boolean) => void;
|
|
79
82
|
setSize: (width: number, height: number) => void;
|
|
80
83
|
setDpr: (dpr: Dpr) => void;
|
|
81
|
-
|
|
84
|
+
setFrameloop: (frameloop?: 'always' | 'demand' | 'never') => void;
|
|
85
|
+
onPointerMissed?: (event: MouseEvent) => void;
|
|
82
86
|
events: EventManager<any>;
|
|
83
87
|
internal: InternalState;
|
|
84
88
|
};
|
|
@@ -100,8 +104,10 @@ export declare type StoreProps = {
|
|
|
100
104
|
dpr?: Dpr;
|
|
101
105
|
clock?: THREE.Clock;
|
|
102
106
|
raycaster?: Partial<Raycaster>;
|
|
103
|
-
camera?: Camera | Partial<ReactThreeFiber.Object3DNode<THREE.Camera, typeof THREE.Camera> & ReactThreeFiber.Object3DNode<THREE.PerspectiveCamera, typeof THREE.PerspectiveCamera> & ReactThreeFiber.Object3DNode<THREE.OrthographicCamera, typeof THREE.OrthographicCamera
|
|
104
|
-
|
|
107
|
+
camera?: (Camera | Partial<ReactThreeFiber.Object3DNode<THREE.Camera, typeof THREE.Camera> & ReactThreeFiber.Object3DNode<THREE.PerspectiveCamera, typeof THREE.PerspectiveCamera> & ReactThreeFiber.Object3DNode<THREE.OrthographicCamera, typeof THREE.OrthographicCamera>>) & {
|
|
108
|
+
manual?: boolean;
|
|
109
|
+
};
|
|
110
|
+
onPointerMissed?: (event: MouseEvent) => void;
|
|
105
111
|
};
|
|
106
112
|
export declare type ApplyProps = (instance: Instance, newProps: InstanceProps) => void;
|
|
107
113
|
export declare function calculateDpr(dpr: Dpr): number;
|
|
@@ -23,7 +23,7 @@ export interface NodeProps<T, P> {
|
|
|
23
23
|
attachFns?: [AttachCallback, AttachCallback];
|
|
24
24
|
args?: Args<P>;
|
|
25
25
|
children?: React.ReactNode;
|
|
26
|
-
ref?: React.
|
|
26
|
+
ref?: React.RefCallback<T> | React.RefObject<React.ReactNode> | null;
|
|
27
27
|
key?: React.Key;
|
|
28
28
|
onUpdate?: (self: T) => void;
|
|
29
29
|
}
|
|
@@ -174,6 +174,7 @@ export declare type Matrix3Props = Node<THREE.Matrix3, typeof THREE.Matrix3>;
|
|
|
174
174
|
export declare type Matrix4Props = Node<THREE.Matrix4, typeof THREE.Matrix4>;
|
|
175
175
|
export declare type QuaternionProps = Node<THREE.Quaternion, typeof THREE.Quaternion>;
|
|
176
176
|
export declare type BufferAttributeProps = Node<THREE.BufferAttribute, typeof THREE.BufferAttribute>;
|
|
177
|
+
export declare type Float32BufferAttributeProps = Node<THREE.Float32BufferAttribute, typeof THREE.Float32BufferAttribute>;
|
|
177
178
|
export declare type InstancedBufferAttributeProps = Node<THREE.InstancedBufferAttribute, typeof THREE.InstancedBufferAttribute>;
|
|
178
179
|
export declare type ColorProps = Node<THREE.Color, ColorArray>;
|
|
179
180
|
export declare type FogProps = Node<THREE.Fog, typeof THREE.Fog>;
|
|
@@ -307,6 +308,7 @@ declare global {
|
|
|
307
308
|
matrix4: Matrix4Props;
|
|
308
309
|
quaternion: QuaternionProps;
|
|
309
310
|
bufferAttribute: BufferAttributeProps;
|
|
311
|
+
float32BufferAttribute: Float32BufferAttributeProps;
|
|
310
312
|
instancedBufferAttribute: InstancedBufferAttributeProps;
|
|
311
313
|
color: ColorProps;
|
|
312
314
|
fog: FogProps;
|
|
@@ -74,7 +74,8 @@ const is = {
|
|
|
74
74
|
function makeId(event) {
|
|
75
75
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
76
76
|
}
|
|
77
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Release pointer captures.
|
|
78
79
|
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
79
80
|
*/
|
|
80
81
|
|
|
@@ -361,13 +362,16 @@ function createEvents(store) {
|
|
|
361
362
|
|
|
362
363
|
case 'onLostPointerCapture':
|
|
363
364
|
return event => {
|
|
364
|
-
|
|
365
|
+
const {
|
|
366
|
+
internal
|
|
367
|
+
} = store.getState();
|
|
368
|
+
|
|
369
|
+
if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
|
|
365
370
|
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
366
371
|
// object that's getting removed.
|
|
367
|
-
|
|
372
|
+
internal.capturedMap.delete(event.pointerId);
|
|
373
|
+
cancelPointer([]);
|
|
368
374
|
}
|
|
369
|
-
|
|
370
|
-
cancelPointer([]);
|
|
371
375
|
};
|
|
372
376
|
} // Any other pointer goes here ...
|
|
373
377
|
|
|
@@ -377,7 +381,8 @@ function createEvents(store) {
|
|
|
377
381
|
onPointerMissed,
|
|
378
382
|
internal
|
|
379
383
|
} = store.getState();
|
|
380
|
-
prepareRay(event);
|
|
384
|
+
prepareRay(event);
|
|
385
|
+
internal.lastEvent.current = event; // Get fresh intersects
|
|
381
386
|
|
|
382
387
|
const isPointerMove = name === 'onPointerMove';
|
|
383
388
|
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
@@ -435,12 +440,17 @@ function createEvents(store) {
|
|
|
435
440
|
if (handler) {
|
|
436
441
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
437
442
|
// which must use the initial target
|
|
438
|
-
if (
|
|
443
|
+
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
439
444
|
// Missed events have to come first
|
|
440
445
|
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
|
|
441
446
|
|
|
442
447
|
handler(data);
|
|
443
448
|
}
|
|
449
|
+
} else {
|
|
450
|
+
// Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
|
|
451
|
+
if (isClickEvent && internal.initialHits.includes(eventObject)) {
|
|
452
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
453
|
+
}
|
|
444
454
|
}
|
|
445
455
|
}
|
|
446
456
|
});
|
|
@@ -643,7 +653,7 @@ function createRenderer(roots) {
|
|
|
643
653
|
invalidateInstance(instance);
|
|
644
654
|
});
|
|
645
655
|
|
|
646
|
-
if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
656
|
+
if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
647
657
|
// Pre-emptively remove the instance from the interaction manager
|
|
648
658
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
649
659
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
@@ -696,7 +706,9 @@ function createRenderer(roots) {
|
|
|
696
706
|
});
|
|
697
707
|
} else {
|
|
698
708
|
const target = catalogue[name] || THREE__namespace[name];
|
|
699
|
-
if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; //
|
|
709
|
+
if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Throw if an object or literal was passed for args
|
|
710
|
+
|
|
711
|
+
if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
|
|
700
712
|
// Append memoized props with args so it's not forgotten
|
|
701
713
|
|
|
702
714
|
instance = prepare(new target(...args), {
|
|
@@ -829,7 +841,7 @@ function createRenderer(roots) {
|
|
|
829
841
|
parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
|
|
830
842
|
} else if (child.attachObject) {
|
|
831
843
|
delete parentInstance[child.attachObject[0]][child.attachObject[1]];
|
|
832
|
-
} else if (child.attach && !is.fun(child.attach)) {
|
|
844
|
+
} else if (child.attach && !is.fun(child.attach) && parentInstance[child.attach] === child) {
|
|
833
845
|
parentInstance[child.attach] = null;
|
|
834
846
|
} else if (is.arr(child.attachFns)) {
|
|
835
847
|
const [, detachFn] = child.attachFns;
|
|
@@ -970,12 +982,24 @@ function createRenderer(roots) {
|
|
|
970
982
|
args: argsOld = [],
|
|
971
983
|
children: cO,
|
|
972
984
|
...restOld
|
|
973
|
-
} = oldProps; //
|
|
985
|
+
} = oldProps; // Throw if an object or literal was passed for args
|
|
986
|
+
|
|
987
|
+
if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
|
|
974
988
|
|
|
975
989
|
if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
|
|
976
990
|
|
|
977
991
|
const diff = diffProps(instance, restNew, restOld, true);
|
|
978
|
-
if (diff.changes.length) return [false, diff]; //
|
|
992
|
+
if (diff.changes.length) return [false, diff]; // If instance was never attached, attach it
|
|
993
|
+
|
|
994
|
+
if (instance.attach && typeof instance.attach !== 'function') {
|
|
995
|
+
const localState = instance.__r3f;
|
|
996
|
+
const parent = localState.parent;
|
|
997
|
+
|
|
998
|
+
if (parent && parent[instance.attach] !== instance) {
|
|
999
|
+
appendChild(parent, instance);
|
|
1000
|
+
}
|
|
1001
|
+
} // Otherwise do not touch the instance
|
|
1002
|
+
|
|
979
1003
|
|
|
980
1004
|
return null;
|
|
981
1005
|
}
|
|
@@ -1020,11 +1044,24 @@ function createRenderer(roots) {
|
|
|
1020
1044
|
|
|
1021
1045
|
createTextInstance() {},
|
|
1022
1046
|
|
|
1023
|
-
finalizeInitialChildren() {
|
|
1024
|
-
|
|
1047
|
+
finalizeInitialChildren(instance) {
|
|
1048
|
+
var _instance$__r3f7;
|
|
1049
|
+
|
|
1050
|
+
// https://github.com/facebook/react/issues/20271
|
|
1051
|
+
// Returning true will trigger commitMount
|
|
1052
|
+
const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
|
|
1053
|
+
return !!localState.handlers;
|
|
1025
1054
|
},
|
|
1026
1055
|
|
|
1027
|
-
commitMount()
|
|
1056
|
+
commitMount(instance)
|
|
1057
|
+
/*, type, props*/
|
|
1058
|
+
{
|
|
1059
|
+
var _instance$__r3f8;
|
|
1060
|
+
|
|
1061
|
+
// https://github.com/facebook/react/issues/20271
|
|
1062
|
+
// This will make sure events are only added once to the central container
|
|
1063
|
+
const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
|
|
1064
|
+
if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
|
|
1028
1065
|
},
|
|
1029
1066
|
|
|
1030
1067
|
shouldDeprioritizeSubtree() {
|
|
@@ -1231,6 +1268,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1231
1268
|
dpr: calculateDpr(dpr)
|
|
1232
1269
|
}
|
|
1233
1270
|
})),
|
|
1271
|
+
setFrameloop: (frameloop = 'always') => set(() => ({
|
|
1272
|
+
frameloop
|
|
1273
|
+
})),
|
|
1234
1274
|
events: {
|
|
1235
1275
|
connected: false
|
|
1236
1276
|
},
|
|
@@ -1239,6 +1279,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1239
1279
|
priority: 0,
|
|
1240
1280
|
frames: 0,
|
|
1241
1281
|
lastProps: props,
|
|
1282
|
+
lastEvent: /*#__PURE__*/React__namespace.createRef(),
|
|
1242
1283
|
interaction: [],
|
|
1243
1284
|
hovered: new Map(),
|
|
1244
1285
|
subscribers: [],
|
|
@@ -1294,7 +1335,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1294
1335
|
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1295
1336
|
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
1296
1337
|
// Do not mess with the camera if it belongs to the user
|
|
1297
|
-
if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
|
|
1338
|
+
if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
|
|
1298
1339
|
if (isOrthographicCamera(camera)) {
|
|
1299
1340
|
camera.left = size.width / -2;
|
|
1300
1341
|
camera.right = size.width / 2;
|
|
@@ -1719,7 +1760,9 @@ function render(element, canvas, {
|
|
|
1719
1760
|
// Check pixelratio
|
|
1720
1761
|
if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
|
|
1721
1762
|
|
|
1722
|
-
if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); //
|
|
1763
|
+
if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
|
|
1764
|
+
|
|
1765
|
+
if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
|
|
1723
1766
|
// Changes to the color-space
|
|
1724
1767
|
|
|
1725
1768
|
const linearChanged = props.linear !== state.internal.lastProps.linear;
|
|
@@ -74,7 +74,8 @@ const is = {
|
|
|
74
74
|
function makeId(event) {
|
|
75
75
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
76
76
|
}
|
|
77
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Release pointer captures.
|
|
78
79
|
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
79
80
|
*/
|
|
80
81
|
|
|
@@ -361,13 +362,16 @@ function createEvents(store) {
|
|
|
361
362
|
|
|
362
363
|
case 'onLostPointerCapture':
|
|
363
364
|
return event => {
|
|
364
|
-
|
|
365
|
+
const {
|
|
366
|
+
internal
|
|
367
|
+
} = store.getState();
|
|
368
|
+
|
|
369
|
+
if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
|
|
365
370
|
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
366
371
|
// object that's getting removed.
|
|
367
|
-
|
|
372
|
+
internal.capturedMap.delete(event.pointerId);
|
|
373
|
+
cancelPointer([]);
|
|
368
374
|
}
|
|
369
|
-
|
|
370
|
-
cancelPointer([]);
|
|
371
375
|
};
|
|
372
376
|
} // Any other pointer goes here ...
|
|
373
377
|
|
|
@@ -377,7 +381,8 @@ function createEvents(store) {
|
|
|
377
381
|
onPointerMissed,
|
|
378
382
|
internal
|
|
379
383
|
} = store.getState();
|
|
380
|
-
prepareRay(event);
|
|
384
|
+
prepareRay(event);
|
|
385
|
+
internal.lastEvent.current = event; // Get fresh intersects
|
|
381
386
|
|
|
382
387
|
const isPointerMove = name === 'onPointerMove';
|
|
383
388
|
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
@@ -435,12 +440,17 @@ function createEvents(store) {
|
|
|
435
440
|
if (handler) {
|
|
436
441
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
437
442
|
// which must use the initial target
|
|
438
|
-
if (
|
|
443
|
+
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
439
444
|
// Missed events have to come first
|
|
440
445
|
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
|
|
441
446
|
|
|
442
447
|
handler(data);
|
|
443
448
|
}
|
|
449
|
+
} else {
|
|
450
|
+
// Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
|
|
451
|
+
if (isClickEvent && internal.initialHits.includes(eventObject)) {
|
|
452
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
453
|
+
}
|
|
444
454
|
}
|
|
445
455
|
}
|
|
446
456
|
});
|
|
@@ -643,7 +653,7 @@ function createRenderer(roots) {
|
|
|
643
653
|
invalidateInstance(instance);
|
|
644
654
|
});
|
|
645
655
|
|
|
646
|
-
if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
656
|
+
if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
647
657
|
// Pre-emptively remove the instance from the interaction manager
|
|
648
658
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
649
659
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
@@ -696,7 +706,9 @@ function createRenderer(roots) {
|
|
|
696
706
|
});
|
|
697
707
|
} else {
|
|
698
708
|
const target = catalogue[name] || THREE__namespace[name];
|
|
699
|
-
if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; //
|
|
709
|
+
if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Throw if an object or literal was passed for args
|
|
710
|
+
|
|
711
|
+
if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
|
|
700
712
|
// Append memoized props with args so it's not forgotten
|
|
701
713
|
|
|
702
714
|
instance = prepare(new target(...args), {
|
|
@@ -829,7 +841,7 @@ function createRenderer(roots) {
|
|
|
829
841
|
parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
|
|
830
842
|
} else if (child.attachObject) {
|
|
831
843
|
delete parentInstance[child.attachObject[0]][child.attachObject[1]];
|
|
832
|
-
} else if (child.attach && !is.fun(child.attach)) {
|
|
844
|
+
} else if (child.attach && !is.fun(child.attach) && parentInstance[child.attach] === child) {
|
|
833
845
|
parentInstance[child.attach] = null;
|
|
834
846
|
} else if (is.arr(child.attachFns)) {
|
|
835
847
|
const [, detachFn] = child.attachFns;
|
|
@@ -970,12 +982,24 @@ function createRenderer(roots) {
|
|
|
970
982
|
args: argsOld = [],
|
|
971
983
|
children: cO,
|
|
972
984
|
...restOld
|
|
973
|
-
} = oldProps; //
|
|
985
|
+
} = oldProps; // Throw if an object or literal was passed for args
|
|
986
|
+
|
|
987
|
+
if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
|
|
974
988
|
|
|
975
989
|
if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
|
|
976
990
|
|
|
977
991
|
const diff = diffProps(instance, restNew, restOld, true);
|
|
978
|
-
if (diff.changes.length) return [false, diff]; //
|
|
992
|
+
if (diff.changes.length) return [false, diff]; // If instance was never attached, attach it
|
|
993
|
+
|
|
994
|
+
if (instance.attach && typeof instance.attach !== 'function') {
|
|
995
|
+
const localState = instance.__r3f;
|
|
996
|
+
const parent = localState.parent;
|
|
997
|
+
|
|
998
|
+
if (parent && parent[instance.attach] !== instance) {
|
|
999
|
+
appendChild(parent, instance);
|
|
1000
|
+
}
|
|
1001
|
+
} // Otherwise do not touch the instance
|
|
1002
|
+
|
|
979
1003
|
|
|
980
1004
|
return null;
|
|
981
1005
|
}
|
|
@@ -1020,11 +1044,24 @@ function createRenderer(roots) {
|
|
|
1020
1044
|
|
|
1021
1045
|
createTextInstance() {},
|
|
1022
1046
|
|
|
1023
|
-
finalizeInitialChildren() {
|
|
1024
|
-
|
|
1047
|
+
finalizeInitialChildren(instance) {
|
|
1048
|
+
var _instance$__r3f7;
|
|
1049
|
+
|
|
1050
|
+
// https://github.com/facebook/react/issues/20271
|
|
1051
|
+
// Returning true will trigger commitMount
|
|
1052
|
+
const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
|
|
1053
|
+
return !!localState.handlers;
|
|
1025
1054
|
},
|
|
1026
1055
|
|
|
1027
|
-
commitMount()
|
|
1056
|
+
commitMount(instance)
|
|
1057
|
+
/*, type, props*/
|
|
1058
|
+
{
|
|
1059
|
+
var _instance$__r3f8;
|
|
1060
|
+
|
|
1061
|
+
// https://github.com/facebook/react/issues/20271
|
|
1062
|
+
// This will make sure events are only added once to the central container
|
|
1063
|
+
const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
|
|
1064
|
+
if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
|
|
1028
1065
|
},
|
|
1029
1066
|
|
|
1030
1067
|
shouldDeprioritizeSubtree() {
|
|
@@ -1231,6 +1268,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1231
1268
|
dpr: calculateDpr(dpr)
|
|
1232
1269
|
}
|
|
1233
1270
|
})),
|
|
1271
|
+
setFrameloop: (frameloop = 'always') => set(() => ({
|
|
1272
|
+
frameloop
|
|
1273
|
+
})),
|
|
1234
1274
|
events: {
|
|
1235
1275
|
connected: false
|
|
1236
1276
|
},
|
|
@@ -1239,6 +1279,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1239
1279
|
priority: 0,
|
|
1240
1280
|
frames: 0,
|
|
1241
1281
|
lastProps: props,
|
|
1282
|
+
lastEvent: /*#__PURE__*/React__namespace.createRef(),
|
|
1242
1283
|
interaction: [],
|
|
1243
1284
|
hovered: new Map(),
|
|
1244
1285
|
subscribers: [],
|
|
@@ -1294,7 +1335,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1294
1335
|
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1295
1336
|
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
1296
1337
|
// Do not mess with the camera if it belongs to the user
|
|
1297
|
-
if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
|
|
1338
|
+
if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
|
|
1298
1339
|
if (isOrthographicCamera(camera)) {
|
|
1299
1340
|
camera.left = size.width / -2;
|
|
1300
1341
|
camera.right = size.width / 2;
|
|
@@ -1719,7 +1760,9 @@ function render(element, canvas, {
|
|
|
1719
1760
|
// Check pixelratio
|
|
1720
1761
|
if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
|
|
1721
1762
|
|
|
1722
|
-
if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); //
|
|
1763
|
+
if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
|
|
1764
|
+
|
|
1765
|
+
if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
|
|
1723
1766
|
// Changes to the color-space
|
|
1724
1767
|
|
|
1725
1768
|
const linearChanged = props.linear !== state.internal.lastProps.linear;
|
|
@@ -41,7 +41,8 @@ const is = {
|
|
|
41
41
|
function makeId(event) {
|
|
42
42
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
43
43
|
}
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Release pointer captures.
|
|
45
46
|
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
46
47
|
*/
|
|
47
48
|
|
|
@@ -328,13 +329,16 @@ function createEvents(store) {
|
|
|
328
329
|
|
|
329
330
|
case 'onLostPointerCapture':
|
|
330
331
|
return event => {
|
|
331
|
-
|
|
332
|
+
const {
|
|
333
|
+
internal
|
|
334
|
+
} = store.getState();
|
|
335
|
+
|
|
336
|
+
if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
|
|
332
337
|
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
333
338
|
// object that's getting removed.
|
|
334
|
-
|
|
339
|
+
internal.capturedMap.delete(event.pointerId);
|
|
340
|
+
cancelPointer([]);
|
|
335
341
|
}
|
|
336
|
-
|
|
337
|
-
cancelPointer([]);
|
|
338
342
|
};
|
|
339
343
|
} // Any other pointer goes here ...
|
|
340
344
|
|
|
@@ -344,7 +348,8 @@ function createEvents(store) {
|
|
|
344
348
|
onPointerMissed,
|
|
345
349
|
internal
|
|
346
350
|
} = store.getState();
|
|
347
|
-
prepareRay(event);
|
|
351
|
+
prepareRay(event);
|
|
352
|
+
internal.lastEvent.current = event; // Get fresh intersects
|
|
348
353
|
|
|
349
354
|
const isPointerMove = name === 'onPointerMove';
|
|
350
355
|
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
@@ -402,12 +407,17 @@ function createEvents(store) {
|
|
|
402
407
|
if (handler) {
|
|
403
408
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
404
409
|
// which must use the initial target
|
|
405
|
-
if (
|
|
410
|
+
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
406
411
|
// Missed events have to come first
|
|
407
412
|
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
|
|
408
413
|
|
|
409
414
|
handler(data);
|
|
410
415
|
}
|
|
416
|
+
} else {
|
|
417
|
+
// Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
|
|
418
|
+
if (isClickEvent && internal.initialHits.includes(eventObject)) {
|
|
419
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
420
|
+
}
|
|
411
421
|
}
|
|
412
422
|
}
|
|
413
423
|
});
|
|
@@ -610,7 +620,7 @@ function createRenderer(roots) {
|
|
|
610
620
|
invalidateInstance(instance);
|
|
611
621
|
});
|
|
612
622
|
|
|
613
|
-
if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
623
|
+
if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
614
624
|
// Pre-emptively remove the instance from the interaction manager
|
|
615
625
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
616
626
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
@@ -663,7 +673,9 @@ function createRenderer(roots) {
|
|
|
663
673
|
});
|
|
664
674
|
} else {
|
|
665
675
|
const target = catalogue[name] || THREE[name];
|
|
666
|
-
if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; //
|
|
676
|
+
if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Throw if an object or literal was passed for args
|
|
677
|
+
|
|
678
|
+
if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
|
|
667
679
|
// Append memoized props with args so it's not forgotten
|
|
668
680
|
|
|
669
681
|
instance = prepare(new target(...args), {
|
|
@@ -796,7 +808,7 @@ function createRenderer(roots) {
|
|
|
796
808
|
parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
|
|
797
809
|
} else if (child.attachObject) {
|
|
798
810
|
delete parentInstance[child.attachObject[0]][child.attachObject[1]];
|
|
799
|
-
} else if (child.attach && !is.fun(child.attach)) {
|
|
811
|
+
} else if (child.attach && !is.fun(child.attach) && parentInstance[child.attach] === child) {
|
|
800
812
|
parentInstance[child.attach] = null;
|
|
801
813
|
} else if (is.arr(child.attachFns)) {
|
|
802
814
|
const [, detachFn] = child.attachFns;
|
|
@@ -937,12 +949,24 @@ function createRenderer(roots) {
|
|
|
937
949
|
args: argsOld = [],
|
|
938
950
|
children: cO,
|
|
939
951
|
...restOld
|
|
940
|
-
} = oldProps; //
|
|
952
|
+
} = oldProps; // Throw if an object or literal was passed for args
|
|
953
|
+
|
|
954
|
+
if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
|
|
941
955
|
|
|
942
956
|
if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
|
|
943
957
|
|
|
944
958
|
const diff = diffProps(instance, restNew, restOld, true);
|
|
945
|
-
if (diff.changes.length) return [false, diff]; //
|
|
959
|
+
if (diff.changes.length) return [false, diff]; // If instance was never attached, attach it
|
|
960
|
+
|
|
961
|
+
if (instance.attach && typeof instance.attach !== 'function') {
|
|
962
|
+
const localState = instance.__r3f;
|
|
963
|
+
const parent = localState.parent;
|
|
964
|
+
|
|
965
|
+
if (parent && parent[instance.attach] !== instance) {
|
|
966
|
+
appendChild(parent, instance);
|
|
967
|
+
}
|
|
968
|
+
} // Otherwise do not touch the instance
|
|
969
|
+
|
|
946
970
|
|
|
947
971
|
return null;
|
|
948
972
|
}
|
|
@@ -987,11 +1011,24 @@ function createRenderer(roots) {
|
|
|
987
1011
|
|
|
988
1012
|
createTextInstance() {},
|
|
989
1013
|
|
|
990
|
-
finalizeInitialChildren() {
|
|
991
|
-
|
|
1014
|
+
finalizeInitialChildren(instance) {
|
|
1015
|
+
var _instance$__r3f7;
|
|
1016
|
+
|
|
1017
|
+
// https://github.com/facebook/react/issues/20271
|
|
1018
|
+
// Returning true will trigger commitMount
|
|
1019
|
+
const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
|
|
1020
|
+
return !!localState.handlers;
|
|
992
1021
|
},
|
|
993
1022
|
|
|
994
|
-
commitMount()
|
|
1023
|
+
commitMount(instance)
|
|
1024
|
+
/*, type, props*/
|
|
1025
|
+
{
|
|
1026
|
+
var _instance$__r3f8;
|
|
1027
|
+
|
|
1028
|
+
// https://github.com/facebook/react/issues/20271
|
|
1029
|
+
// This will make sure events are only added once to the central container
|
|
1030
|
+
const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
|
|
1031
|
+
if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
|
|
995
1032
|
},
|
|
996
1033
|
|
|
997
1034
|
shouldDeprioritizeSubtree() {
|
|
@@ -1198,6 +1235,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1198
1235
|
dpr: calculateDpr(dpr)
|
|
1199
1236
|
}
|
|
1200
1237
|
})),
|
|
1238
|
+
setFrameloop: (frameloop = 'always') => set(() => ({
|
|
1239
|
+
frameloop
|
|
1240
|
+
})),
|
|
1201
1241
|
events: {
|
|
1202
1242
|
connected: false
|
|
1203
1243
|
},
|
|
@@ -1206,6 +1246,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1206
1246
|
priority: 0,
|
|
1207
1247
|
frames: 0,
|
|
1208
1248
|
lastProps: props,
|
|
1249
|
+
lastEvent: /*#__PURE__*/React.createRef(),
|
|
1209
1250
|
interaction: [],
|
|
1210
1251
|
hovered: new Map(),
|
|
1211
1252
|
subscribers: [],
|
|
@@ -1261,7 +1302,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1261
1302
|
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1262
1303
|
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
1263
1304
|
// Do not mess with the camera if it belongs to the user
|
|
1264
|
-
if (!(internal.lastProps.camera instanceof THREE.Camera)) {
|
|
1305
|
+
if (!camera.manual && !(internal.lastProps.camera instanceof THREE.Camera)) {
|
|
1265
1306
|
if (isOrthographicCamera(camera)) {
|
|
1266
1307
|
camera.left = size.width / -2;
|
|
1267
1308
|
camera.right = size.width / 2;
|
|
@@ -1686,7 +1727,9 @@ function render(element, canvas, {
|
|
|
1686
1727
|
// Check pixelratio
|
|
1687
1728
|
if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
|
|
1688
1729
|
|
|
1689
|
-
if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); //
|
|
1730
|
+
if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
|
|
1731
|
+
|
|
1732
|
+
if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
|
|
1690
1733
|
// Changes to the color-space
|
|
1691
1734
|
|
|
1692
1735
|
const linearChanged = props.linear !== state.internal.lastProps.linear;
|