@react-three/fiber 7.0.9 → 7.0.13
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 +25 -0
- package/dist/declarations/src/core/renderer.d.ts +2 -2
- package/dist/declarations/src/core/store.d.ts +1 -0
- package/dist/react-three-fiber.cjs.dev.js +89 -63
- package/dist/react-three-fiber.cjs.prod.js +89 -63
- package/dist/react-three-fiber.esm.js +89 -63
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @react-three/fiber
|
|
2
2
|
|
|
3
|
+
## 7.0.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f256558: fix(core): don't overwrite camera rotation
|
|
8
|
+
- 51e6fc9: fix(core): safely handle external instances
|
|
9
|
+
|
|
10
|
+
## 7.0.12
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 0df6073: fix: missed events
|
|
15
|
+
|
|
16
|
+
## 7.0.11
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 62b0a3a: fix: event order of missed pointers
|
|
21
|
+
|
|
22
|
+
## 7.0.10
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- e019dd4: fixes
|
|
27
|
+
|
|
3
28
|
## 7.0.9
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
|
@@ -10,6 +10,7 @@ export declare type Root = {
|
|
|
10
10
|
export declare type LocalState = {
|
|
11
11
|
root: UseStore<RootState>;
|
|
12
12
|
objects: Instance[];
|
|
13
|
+
parent: Instance | null;
|
|
13
14
|
primitive?: boolean;
|
|
14
15
|
handlers: {
|
|
15
16
|
count: number;
|
|
@@ -23,9 +24,8 @@ export declare type ClassConstructor = {
|
|
|
23
24
|
};
|
|
24
25
|
export declare type AttachFnType = (self: Instance, parent: Instance) => void;
|
|
25
26
|
export declare type AttachFnsType = [attach: string | AttachFnType, detach: string | AttachFnType];
|
|
26
|
-
export declare type BaseInstance = Omit<THREE.Object3D, '
|
|
27
|
+
export declare type BaseInstance = Omit<THREE.Object3D, 'children' | 'attach' | 'add' | 'remove' | 'raycast'> & {
|
|
27
28
|
__r3f: LocalState;
|
|
28
|
-
parent: Instance | null;
|
|
29
29
|
children: Instance[];
|
|
30
30
|
attach?: string;
|
|
31
31
|
attachFns?: AttachFnsType;
|
|
@@ -101,6 +101,7 @@ export declare type StoreProps = {
|
|
|
101
101
|
onPointerMissed?: (event: ThreeEvent<PointerEvent>) => void;
|
|
102
102
|
};
|
|
103
103
|
export declare type ApplyProps = (instance: Instance, newProps: InstanceProps) => void;
|
|
104
|
+
export declare function calculateDpr(dpr: Dpr): number;
|
|
104
105
|
declare const context: React.Context<UseStore<RootState>>;
|
|
105
106
|
declare const createStore: (applyProps: ApplyProps, invalidate: (state?: RootState | undefined) => void, advance: (timestamp: number, runGlobalEffects?: boolean | undefined, state?: RootState | undefined) => void, props: StoreProps) => UseStore<RootState>;
|
|
106
107
|
export { createStore, context };
|
|
@@ -58,7 +58,8 @@ const is = {
|
|
|
58
58
|
// Wrong type or one of the two undefined, doesn't match
|
|
59
59
|
if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
|
|
60
60
|
|
|
61
|
-
if (is.str(a) || is.num(a)
|
|
61
|
+
if (is.str(a) || is.num(a)) return a === b;
|
|
62
|
+
if (is.obj(a) && a === b) return true; // Array, shallow compare first to see if it's a match
|
|
62
63
|
|
|
63
64
|
if (is.arr(a) && a == b) return true; // Last resort, go through keys
|
|
64
65
|
|
|
@@ -132,7 +133,11 @@ function createEvents(store) {
|
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
function filterPointerEvents(objects) {
|
|
135
|
-
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name =>
|
|
136
|
+
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name => {
|
|
137
|
+
var _r3f;
|
|
138
|
+
|
|
139
|
+
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.handlers['onPointer' + name];
|
|
140
|
+
}));
|
|
136
141
|
}
|
|
137
142
|
|
|
138
143
|
function intersect(filter) {
|
|
@@ -162,7 +167,9 @@ function createEvents(store) {
|
|
|
162
167
|
let eventObject = intersect.object; // Bubble event up
|
|
163
168
|
|
|
164
169
|
while (eventObject) {
|
|
165
|
-
|
|
170
|
+
var _r3f2;
|
|
171
|
+
|
|
172
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.handlers.count) intersections.push({ ...intersect,
|
|
166
173
|
eventObject
|
|
167
174
|
});
|
|
168
175
|
eventObject = eventObject.parent;
|
|
@@ -189,7 +196,7 @@ function createEvents(store) {
|
|
|
189
196
|
/** Handles intersections by forwarding them to handlers */
|
|
190
197
|
|
|
191
198
|
|
|
192
|
-
function handleIntersects(intersections, event, callback) {
|
|
199
|
+
function handleIntersects(intersections, event, delta, callback) {
|
|
193
200
|
const {
|
|
194
201
|
raycaster,
|
|
195
202
|
mouse,
|
|
@@ -199,7 +206,6 @@ function createEvents(store) {
|
|
|
199
206
|
|
|
200
207
|
if (intersections.length) {
|
|
201
208
|
const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
|
|
202
|
-
const delta = event.type === 'click' ? calculateDistance(event) : 0;
|
|
203
209
|
|
|
204
210
|
const releasePointerCapture = id => event.target.releasePointerCapture(id);
|
|
205
211
|
|
|
@@ -300,11 +306,13 @@ function createEvents(store) {
|
|
|
300
306
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
301
307
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
302
308
|
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
309
|
+
var _r3f3;
|
|
310
|
+
|
|
303
311
|
const eventObject = hoveredObj.eventObject;
|
|
304
|
-
const handlers = eventObject.__r3f.handlers;
|
|
312
|
+
const handlers = (_r3f3 = eventObject.__r3f) == null ? void 0 : _r3f3.handlers;
|
|
305
313
|
internal.hovered.delete(makeId(hoveredObj));
|
|
306
314
|
|
|
307
|
-
if (handlers.count) {
|
|
315
|
+
if (handlers != null && handlers.count) {
|
|
308
316
|
// Clear out intersects, they are outdated by now
|
|
309
317
|
const data = { ...hoveredObj,
|
|
310
318
|
intersections: hits || []
|
|
@@ -345,15 +353,34 @@ function createEvents(store) {
|
|
|
345
353
|
prepareRay(event); // Get fresh intersects
|
|
346
354
|
|
|
347
355
|
const isPointerMove = name === 'onPointerMove';
|
|
356
|
+
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
348
357
|
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
349
|
-
const hits = patchIntersects(intersect(filter), event);
|
|
358
|
+
const hits = patchIntersects(intersect(filter), event);
|
|
359
|
+
const delta = isClickEvent ? calculateDistance(event) : 0; // Save initial coordinates on pointer-down
|
|
360
|
+
|
|
361
|
+
if (name === 'onPointerDown') {
|
|
362
|
+
internal.initialClick = [event.offsetX, event.offsetY];
|
|
363
|
+
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
364
|
+
} // If a click yields no results, pass it back to the user as a miss
|
|
365
|
+
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
if (isClickEvent && !hits.length) {
|
|
369
|
+
if (delta <= 2) {
|
|
370
|
+
pointerMissed(event, internal.interaction);
|
|
371
|
+
if (onPointerMissed) onPointerMissed(event);
|
|
372
|
+
}
|
|
373
|
+
} // Take care of unhover
|
|
374
|
+
|
|
350
375
|
|
|
351
376
|
if (isPointerMove) cancelPointer(hits);
|
|
352
|
-
handleIntersects(hits, event, data => {
|
|
377
|
+
handleIntersects(hits, event, delta, data => {
|
|
378
|
+
var _r3f4;
|
|
379
|
+
|
|
353
380
|
const eventObject = data.eventObject;
|
|
354
|
-
const handlers = eventObject.__r3f.handlers; // Check presence of handlers
|
|
381
|
+
const handlers = (_r3f4 = eventObject.__r3f) == null ? void 0 : _r3f4.handlers; // Check presence of handlers
|
|
355
382
|
|
|
356
|
-
if (!handlers.count) return;
|
|
383
|
+
if (!(handlers != null && handlers.count)) return;
|
|
357
384
|
|
|
358
385
|
if (isPointerMove) {
|
|
359
386
|
// Move event ...
|
|
@@ -383,33 +410,22 @@ function createEvents(store) {
|
|
|
383
410
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
384
411
|
// which must use the initial target
|
|
385
412
|
if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
|
|
413
|
+
// Missed events have to come first
|
|
414
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
|
|
415
|
+
|
|
386
416
|
handler(data);
|
|
387
|
-
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
388
417
|
}
|
|
389
418
|
}
|
|
390
419
|
}
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
if (name === 'onPointerDown') {
|
|
394
|
-
internal.initialClick = [event.offsetX, event.offsetY];
|
|
395
|
-
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
396
|
-
} // If a click yields no results, pass it back to the user as a miss
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if ((name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick') && !hits.length) {
|
|
400
|
-
if (calculateDistance(event) <= 2) {
|
|
401
|
-
pointerMissed(event, internal.interaction);
|
|
402
|
-
if (onPointerMissed) onPointerMissed(event);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
420
|
+
});
|
|
405
421
|
};
|
|
406
422
|
};
|
|
407
423
|
|
|
408
424
|
function pointerMissed(event, objects) {
|
|
409
425
|
objects.forEach(object => {
|
|
410
|
-
var
|
|
426
|
+
var _r3f5;
|
|
411
427
|
|
|
412
|
-
return (
|
|
428
|
+
return (_r3f5 = object.__r3f) == null ? void 0 : _r3f5.handlers.onPointerMissed == null ? void 0 : _r3f5.handlers.onPointerMissed(event);
|
|
413
429
|
});
|
|
414
430
|
}
|
|
415
431
|
|
|
@@ -464,6 +480,7 @@ function prepare(object, state) {
|
|
|
464
480
|
count: 0
|
|
465
481
|
},
|
|
466
482
|
objects: [],
|
|
483
|
+
parent: null,
|
|
467
484
|
...state
|
|
468
485
|
};
|
|
469
486
|
}
|
|
@@ -522,7 +539,7 @@ function createRenderer(roots) {
|
|
|
522
539
|
}
|
|
523
540
|
|
|
524
541
|
function applyProps(instance, data) {
|
|
525
|
-
var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2;
|
|
542
|
+
var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2, _instance$__r3f4;
|
|
526
543
|
|
|
527
544
|
// Filter equals, events and reserved props
|
|
528
545
|
const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
@@ -607,16 +624,16 @@ function createRenderer(roots) {
|
|
|
607
624
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
608
625
|
|
|
609
626
|
if (localState.handlers.count) rootState.internal.interaction.push(instance);
|
|
610
|
-
} // Call the update lifecycle when it is being updated
|
|
627
|
+
} // Call the update lifecycle when it is being updated
|
|
611
628
|
|
|
612
629
|
|
|
613
|
-
if (changes.length && instance.parent) updateInstance(instance);
|
|
630
|
+
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
614
631
|
}
|
|
615
632
|
|
|
616
633
|
function invalidateInstance(instance) {
|
|
617
|
-
var _instance$
|
|
634
|
+
var _instance$__r3f5, _instance$__r3f5$root;
|
|
618
635
|
|
|
619
|
-
const state = (_instance$
|
|
636
|
+
const state = (_instance$__r3f5 = instance.__r3f) == null ? void 0 : (_instance$__r3f5$root = _instance$__r3f5.root) == null ? void 0 : _instance$__r3f5$root.getState == null ? void 0 : _instance$__r3f5$root.getState();
|
|
620
637
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
621
638
|
}
|
|
622
639
|
|
|
@@ -708,7 +725,7 @@ function createRenderer(roots) {
|
|
|
708
725
|
} else if (is.fun(attachFn)) {
|
|
709
726
|
attachFn(child, parentInstance);
|
|
710
727
|
}
|
|
711
|
-
} else if (child.isObject3D) {
|
|
728
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
712
729
|
// add in the usual parent-child way
|
|
713
730
|
parentInstance.add(child);
|
|
714
731
|
addedAsChild = true;
|
|
@@ -718,10 +735,13 @@ function createRenderer(roots) {
|
|
|
718
735
|
// This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
|
|
719
736
|
// that is, anything that's a child in React but not a child in the scenegraph.
|
|
720
737
|
parentInstance.__r3f.objects.push(child);
|
|
738
|
+
}
|
|
721
739
|
|
|
722
|
-
|
|
740
|
+
if (!child.__r3f) {
|
|
741
|
+
prepare(child, {});
|
|
723
742
|
}
|
|
724
743
|
|
|
744
|
+
child.__r3f.parent = parentInstance;
|
|
725
745
|
updateInstance(child);
|
|
726
746
|
invalidateInstance(child);
|
|
727
747
|
}
|
|
@@ -738,7 +758,7 @@ function createRenderer(roots) {
|
|
|
738
758
|
} else if (child.attachObject || child.attach && !is.fun(child.attach)) {
|
|
739
759
|
// attach and attachObject don't have an order anyway, so just append
|
|
740
760
|
return appendChild(parentInstance, child);
|
|
741
|
-
} else if (child.isObject3D) {
|
|
761
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
742
762
|
child.parent = parentInstance;
|
|
743
763
|
child.dispatchEvent({
|
|
744
764
|
type: 'added'
|
|
@@ -751,10 +771,13 @@ function createRenderer(roots) {
|
|
|
751
771
|
|
|
752
772
|
if (!added) {
|
|
753
773
|
parentInstance.__r3f.objects.push(child);
|
|
774
|
+
}
|
|
754
775
|
|
|
755
|
-
|
|
776
|
+
if (!child.__r3f) {
|
|
777
|
+
prepare(child, {});
|
|
756
778
|
}
|
|
757
779
|
|
|
780
|
+
child.__r3f.parent = parentInstance;
|
|
758
781
|
updateInstance(child);
|
|
759
782
|
invalidateInstance(child);
|
|
760
783
|
}
|
|
@@ -766,17 +789,14 @@ function createRenderer(roots) {
|
|
|
766
789
|
|
|
767
790
|
function removeChild(parentInstance, child, dispose) {
|
|
768
791
|
if (child) {
|
|
769
|
-
var _child$__r3f2;
|
|
792
|
+
var _parentInstance$__r3f, _child$__r3f2;
|
|
770
793
|
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
const newLength = parentInstance.__r3f.objects.length; // was it in the list?
|
|
794
|
+
if (child.__r3f) {
|
|
795
|
+
child.__r3f.parent = null;
|
|
796
|
+
}
|
|
775
797
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
child.parent = null;
|
|
779
|
-
}
|
|
798
|
+
if ((_parentInstance$__r3f = parentInstance.__r3f) != null && _parentInstance$__r3f.objects) {
|
|
799
|
+
parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
|
|
780
800
|
} // Remove attachment
|
|
781
801
|
|
|
782
802
|
|
|
@@ -849,7 +869,9 @@ function createRenderer(roots) {
|
|
|
849
869
|
}
|
|
850
870
|
|
|
851
871
|
function switchInstance(instance, type, newProps, fiber) {
|
|
852
|
-
|
|
872
|
+
var _instance$__r3f6;
|
|
873
|
+
|
|
874
|
+
const parent = (_instance$__r3f6 = instance.__r3f) == null ? void 0 : _instance$__r3f6.parent;
|
|
853
875
|
if (!parent) return;
|
|
854
876
|
const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
|
|
855
877
|
// When args change the instance has to be re-constructed, which then
|
|
@@ -1012,6 +1034,9 @@ function createRenderer(roots) {
|
|
|
1012
1034
|
|
|
1013
1035
|
const isRenderer = def => def && !!def.render;
|
|
1014
1036
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
1037
|
+
function calculateDpr(dpr) {
|
|
1038
|
+
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
1039
|
+
}
|
|
1015
1040
|
const context = /*#__PURE__*/React__namespace.createContext(null);
|
|
1016
1041
|
|
|
1017
1042
|
const createStore = (applyProps, invalidate, advance, props) => {
|
|
@@ -1068,14 +1093,10 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1068
1093
|
camera.position.z = 5;
|
|
1069
1094
|
if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
|
|
1070
1095
|
|
|
1071
|
-
camera.lookAt(0, 0, 0);
|
|
1096
|
+
if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1072
1097
|
}
|
|
1073
1098
|
|
|
1074
|
-
|
|
1075
|
-
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
const initialDpr = setDpr(dpr);
|
|
1099
|
+
const initialDpr = calculateDpr(dpr);
|
|
1079
1100
|
const position = new THREE__namespace.Vector3();
|
|
1080
1101
|
const defaultTarget = new THREE__namespace.Vector3();
|
|
1081
1102
|
const tempTarget = new THREE__namespace.Vector3();
|
|
@@ -1182,7 +1203,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1182
1203
|
},
|
|
1183
1204
|
setDpr: dpr => set(state => ({
|
|
1184
1205
|
viewport: { ...state.viewport,
|
|
1185
|
-
dpr:
|
|
1206
|
+
dpr: calculateDpr(dpr)
|
|
1186
1207
|
}
|
|
1187
1208
|
})),
|
|
1188
1209
|
events: {
|
|
@@ -1473,7 +1494,10 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1473
1494
|
events,
|
|
1474
1495
|
...props
|
|
1475
1496
|
}, forwardedRef) {
|
|
1476
|
-
const [containerRef,
|
|
1497
|
+
const [containerRef, {
|
|
1498
|
+
width,
|
|
1499
|
+
height
|
|
1500
|
+
}] = useMeasure__default['default']({
|
|
1477
1501
|
scroll: true,
|
|
1478
1502
|
debounce: {
|
|
1479
1503
|
scroll: 50,
|
|
@@ -1490,7 +1514,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1490
1514
|
if (error) throw error; // Execute JSX in the reconciler as a layout-effect
|
|
1491
1515
|
|
|
1492
1516
|
useIsomorphicLayoutEffect(() => {
|
|
1493
|
-
if (
|
|
1517
|
+
if (width > 0 && height > 0) {
|
|
1494
1518
|
render( /*#__PURE__*/React__namespace.createElement(ErrorBoundary, {
|
|
1495
1519
|
set: setError
|
|
1496
1520
|
}, /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
|
|
@@ -1498,11 +1522,14 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1498
1522
|
set: setBlock
|
|
1499
1523
|
})
|
|
1500
1524
|
}, children)), canvasRef.current, { ...props,
|
|
1501
|
-
size
|
|
1525
|
+
size: {
|
|
1526
|
+
width,
|
|
1527
|
+
height
|
|
1528
|
+
},
|
|
1502
1529
|
events: events || createPointerEvents
|
|
1503
1530
|
});
|
|
1504
1531
|
}
|
|
1505
|
-
}, [
|
|
1532
|
+
}, [width, height, children]);
|
|
1506
1533
|
useIsomorphicLayoutEffect(() => {
|
|
1507
1534
|
const container = canvasRef.current;
|
|
1508
1535
|
return () => unmountComponentAtNode(container);
|
|
@@ -1646,15 +1673,14 @@ function render(element, canvas, {
|
|
|
1646
1673
|
let state = (_store = store) == null ? void 0 : _store.getState();
|
|
1647
1674
|
|
|
1648
1675
|
if (fiber && state) {
|
|
1649
|
-
|
|
1676
|
+
// When a root was found, see if any fundamental props must be changed or exchanged
|
|
1650
1677
|
// Check pixelratio
|
|
1678
|
+
if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
|
|
1651
1679
|
|
|
1652
|
-
if (
|
|
1653
|
-
|
|
1654
|
-
if (!is.equ(lastProps.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
|
|
1680
|
+
if (!is.equ(state.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
|
|
1655
1681
|
// Changes to the color-space
|
|
1656
1682
|
|
|
1657
|
-
const linearChanged = props.linear !== lastProps.linear;
|
|
1683
|
+
const linearChanged = props.linear !== state.internal.lastProps.linear;
|
|
1658
1684
|
|
|
1659
1685
|
if (linearChanged) {
|
|
1660
1686
|
unmountComponentAtNode(canvas);
|
|
@@ -58,7 +58,8 @@ const is = {
|
|
|
58
58
|
// Wrong type or one of the two undefined, doesn't match
|
|
59
59
|
if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
|
|
60
60
|
|
|
61
|
-
if (is.str(a) || is.num(a)
|
|
61
|
+
if (is.str(a) || is.num(a)) return a === b;
|
|
62
|
+
if (is.obj(a) && a === b) return true; // Array, shallow compare first to see if it's a match
|
|
62
63
|
|
|
63
64
|
if (is.arr(a) && a == b) return true; // Last resort, go through keys
|
|
64
65
|
|
|
@@ -132,7 +133,11 @@ function createEvents(store) {
|
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
function filterPointerEvents(objects) {
|
|
135
|
-
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name =>
|
|
136
|
+
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name => {
|
|
137
|
+
var _r3f;
|
|
138
|
+
|
|
139
|
+
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.handlers['onPointer' + name];
|
|
140
|
+
}));
|
|
136
141
|
}
|
|
137
142
|
|
|
138
143
|
function intersect(filter) {
|
|
@@ -162,7 +167,9 @@ function createEvents(store) {
|
|
|
162
167
|
let eventObject = intersect.object; // Bubble event up
|
|
163
168
|
|
|
164
169
|
while (eventObject) {
|
|
165
|
-
|
|
170
|
+
var _r3f2;
|
|
171
|
+
|
|
172
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.handlers.count) intersections.push({ ...intersect,
|
|
166
173
|
eventObject
|
|
167
174
|
});
|
|
168
175
|
eventObject = eventObject.parent;
|
|
@@ -189,7 +196,7 @@ function createEvents(store) {
|
|
|
189
196
|
/** Handles intersections by forwarding them to handlers */
|
|
190
197
|
|
|
191
198
|
|
|
192
|
-
function handleIntersects(intersections, event, callback) {
|
|
199
|
+
function handleIntersects(intersections, event, delta, callback) {
|
|
193
200
|
const {
|
|
194
201
|
raycaster,
|
|
195
202
|
mouse,
|
|
@@ -199,7 +206,6 @@ function createEvents(store) {
|
|
|
199
206
|
|
|
200
207
|
if (intersections.length) {
|
|
201
208
|
const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
|
|
202
|
-
const delta = event.type === 'click' ? calculateDistance(event) : 0;
|
|
203
209
|
|
|
204
210
|
const releasePointerCapture = id => event.target.releasePointerCapture(id);
|
|
205
211
|
|
|
@@ -300,11 +306,13 @@ function createEvents(store) {
|
|
|
300
306
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
301
307
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
302
308
|
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
309
|
+
var _r3f3;
|
|
310
|
+
|
|
303
311
|
const eventObject = hoveredObj.eventObject;
|
|
304
|
-
const handlers = eventObject.__r3f.handlers;
|
|
312
|
+
const handlers = (_r3f3 = eventObject.__r3f) == null ? void 0 : _r3f3.handlers;
|
|
305
313
|
internal.hovered.delete(makeId(hoveredObj));
|
|
306
314
|
|
|
307
|
-
if (handlers.count) {
|
|
315
|
+
if (handlers != null && handlers.count) {
|
|
308
316
|
// Clear out intersects, they are outdated by now
|
|
309
317
|
const data = { ...hoveredObj,
|
|
310
318
|
intersections: hits || []
|
|
@@ -345,15 +353,34 @@ function createEvents(store) {
|
|
|
345
353
|
prepareRay(event); // Get fresh intersects
|
|
346
354
|
|
|
347
355
|
const isPointerMove = name === 'onPointerMove';
|
|
356
|
+
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
348
357
|
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
349
|
-
const hits = patchIntersects(intersect(filter), event);
|
|
358
|
+
const hits = patchIntersects(intersect(filter), event);
|
|
359
|
+
const delta = isClickEvent ? calculateDistance(event) : 0; // Save initial coordinates on pointer-down
|
|
360
|
+
|
|
361
|
+
if (name === 'onPointerDown') {
|
|
362
|
+
internal.initialClick = [event.offsetX, event.offsetY];
|
|
363
|
+
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
364
|
+
} // If a click yields no results, pass it back to the user as a miss
|
|
365
|
+
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
if (isClickEvent && !hits.length) {
|
|
369
|
+
if (delta <= 2) {
|
|
370
|
+
pointerMissed(event, internal.interaction);
|
|
371
|
+
if (onPointerMissed) onPointerMissed(event);
|
|
372
|
+
}
|
|
373
|
+
} // Take care of unhover
|
|
374
|
+
|
|
350
375
|
|
|
351
376
|
if (isPointerMove) cancelPointer(hits);
|
|
352
|
-
handleIntersects(hits, event, data => {
|
|
377
|
+
handleIntersects(hits, event, delta, data => {
|
|
378
|
+
var _r3f4;
|
|
379
|
+
|
|
353
380
|
const eventObject = data.eventObject;
|
|
354
|
-
const handlers = eventObject.__r3f.handlers; // Check presence of handlers
|
|
381
|
+
const handlers = (_r3f4 = eventObject.__r3f) == null ? void 0 : _r3f4.handlers; // Check presence of handlers
|
|
355
382
|
|
|
356
|
-
if (!handlers.count) return;
|
|
383
|
+
if (!(handlers != null && handlers.count)) return;
|
|
357
384
|
|
|
358
385
|
if (isPointerMove) {
|
|
359
386
|
// Move event ...
|
|
@@ -383,33 +410,22 @@ function createEvents(store) {
|
|
|
383
410
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
384
411
|
// which must use the initial target
|
|
385
412
|
if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
|
|
413
|
+
// Missed events have to come first
|
|
414
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
|
|
415
|
+
|
|
386
416
|
handler(data);
|
|
387
|
-
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
388
417
|
}
|
|
389
418
|
}
|
|
390
419
|
}
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
if (name === 'onPointerDown') {
|
|
394
|
-
internal.initialClick = [event.offsetX, event.offsetY];
|
|
395
|
-
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
396
|
-
} // If a click yields no results, pass it back to the user as a miss
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if ((name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick') && !hits.length) {
|
|
400
|
-
if (calculateDistance(event) <= 2) {
|
|
401
|
-
pointerMissed(event, internal.interaction);
|
|
402
|
-
if (onPointerMissed) onPointerMissed(event);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
420
|
+
});
|
|
405
421
|
};
|
|
406
422
|
};
|
|
407
423
|
|
|
408
424
|
function pointerMissed(event, objects) {
|
|
409
425
|
objects.forEach(object => {
|
|
410
|
-
var
|
|
426
|
+
var _r3f5;
|
|
411
427
|
|
|
412
|
-
return (
|
|
428
|
+
return (_r3f5 = object.__r3f) == null ? void 0 : _r3f5.handlers.onPointerMissed == null ? void 0 : _r3f5.handlers.onPointerMissed(event);
|
|
413
429
|
});
|
|
414
430
|
}
|
|
415
431
|
|
|
@@ -464,6 +480,7 @@ function prepare(object, state) {
|
|
|
464
480
|
count: 0
|
|
465
481
|
},
|
|
466
482
|
objects: [],
|
|
483
|
+
parent: null,
|
|
467
484
|
...state
|
|
468
485
|
};
|
|
469
486
|
}
|
|
@@ -522,7 +539,7 @@ function createRenderer(roots) {
|
|
|
522
539
|
}
|
|
523
540
|
|
|
524
541
|
function applyProps(instance, data) {
|
|
525
|
-
var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2;
|
|
542
|
+
var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2, _instance$__r3f4;
|
|
526
543
|
|
|
527
544
|
// Filter equals, events and reserved props
|
|
528
545
|
const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
@@ -607,16 +624,16 @@ function createRenderer(roots) {
|
|
|
607
624
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
608
625
|
|
|
609
626
|
if (localState.handlers.count) rootState.internal.interaction.push(instance);
|
|
610
|
-
} // Call the update lifecycle when it is being updated
|
|
627
|
+
} // Call the update lifecycle when it is being updated
|
|
611
628
|
|
|
612
629
|
|
|
613
|
-
if (changes.length && instance.parent) updateInstance(instance);
|
|
630
|
+
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
614
631
|
}
|
|
615
632
|
|
|
616
633
|
function invalidateInstance(instance) {
|
|
617
|
-
var _instance$
|
|
634
|
+
var _instance$__r3f5, _instance$__r3f5$root;
|
|
618
635
|
|
|
619
|
-
const state = (_instance$
|
|
636
|
+
const state = (_instance$__r3f5 = instance.__r3f) == null ? void 0 : (_instance$__r3f5$root = _instance$__r3f5.root) == null ? void 0 : _instance$__r3f5$root.getState == null ? void 0 : _instance$__r3f5$root.getState();
|
|
620
637
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
621
638
|
}
|
|
622
639
|
|
|
@@ -708,7 +725,7 @@ function createRenderer(roots) {
|
|
|
708
725
|
} else if (is.fun(attachFn)) {
|
|
709
726
|
attachFn(child, parentInstance);
|
|
710
727
|
}
|
|
711
|
-
} else if (child.isObject3D) {
|
|
728
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
712
729
|
// add in the usual parent-child way
|
|
713
730
|
parentInstance.add(child);
|
|
714
731
|
addedAsChild = true;
|
|
@@ -718,10 +735,13 @@ function createRenderer(roots) {
|
|
|
718
735
|
// This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
|
|
719
736
|
// that is, anything that's a child in React but not a child in the scenegraph.
|
|
720
737
|
parentInstance.__r3f.objects.push(child);
|
|
738
|
+
}
|
|
721
739
|
|
|
722
|
-
|
|
740
|
+
if (!child.__r3f) {
|
|
741
|
+
prepare(child, {});
|
|
723
742
|
}
|
|
724
743
|
|
|
744
|
+
child.__r3f.parent = parentInstance;
|
|
725
745
|
updateInstance(child);
|
|
726
746
|
invalidateInstance(child);
|
|
727
747
|
}
|
|
@@ -738,7 +758,7 @@ function createRenderer(roots) {
|
|
|
738
758
|
} else if (child.attachObject || child.attach && !is.fun(child.attach)) {
|
|
739
759
|
// attach and attachObject don't have an order anyway, so just append
|
|
740
760
|
return appendChild(parentInstance, child);
|
|
741
|
-
} else if (child.isObject3D) {
|
|
761
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
742
762
|
child.parent = parentInstance;
|
|
743
763
|
child.dispatchEvent({
|
|
744
764
|
type: 'added'
|
|
@@ -751,10 +771,13 @@ function createRenderer(roots) {
|
|
|
751
771
|
|
|
752
772
|
if (!added) {
|
|
753
773
|
parentInstance.__r3f.objects.push(child);
|
|
774
|
+
}
|
|
754
775
|
|
|
755
|
-
|
|
776
|
+
if (!child.__r3f) {
|
|
777
|
+
prepare(child, {});
|
|
756
778
|
}
|
|
757
779
|
|
|
780
|
+
child.__r3f.parent = parentInstance;
|
|
758
781
|
updateInstance(child);
|
|
759
782
|
invalidateInstance(child);
|
|
760
783
|
}
|
|
@@ -766,17 +789,14 @@ function createRenderer(roots) {
|
|
|
766
789
|
|
|
767
790
|
function removeChild(parentInstance, child, dispose) {
|
|
768
791
|
if (child) {
|
|
769
|
-
var _child$__r3f2;
|
|
792
|
+
var _parentInstance$__r3f, _child$__r3f2;
|
|
770
793
|
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
const newLength = parentInstance.__r3f.objects.length; // was it in the list?
|
|
794
|
+
if (child.__r3f) {
|
|
795
|
+
child.__r3f.parent = null;
|
|
796
|
+
}
|
|
775
797
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
child.parent = null;
|
|
779
|
-
}
|
|
798
|
+
if ((_parentInstance$__r3f = parentInstance.__r3f) != null && _parentInstance$__r3f.objects) {
|
|
799
|
+
parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
|
|
780
800
|
} // Remove attachment
|
|
781
801
|
|
|
782
802
|
|
|
@@ -849,7 +869,9 @@ function createRenderer(roots) {
|
|
|
849
869
|
}
|
|
850
870
|
|
|
851
871
|
function switchInstance(instance, type, newProps, fiber) {
|
|
852
|
-
|
|
872
|
+
var _instance$__r3f6;
|
|
873
|
+
|
|
874
|
+
const parent = (_instance$__r3f6 = instance.__r3f) == null ? void 0 : _instance$__r3f6.parent;
|
|
853
875
|
if (!parent) return;
|
|
854
876
|
const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
|
|
855
877
|
// When args change the instance has to be re-constructed, which then
|
|
@@ -1012,6 +1034,9 @@ function createRenderer(roots) {
|
|
|
1012
1034
|
|
|
1013
1035
|
const isRenderer = def => def && !!def.render;
|
|
1014
1036
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
1037
|
+
function calculateDpr(dpr) {
|
|
1038
|
+
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
1039
|
+
}
|
|
1015
1040
|
const context = /*#__PURE__*/React__namespace.createContext(null);
|
|
1016
1041
|
|
|
1017
1042
|
const createStore = (applyProps, invalidate, advance, props) => {
|
|
@@ -1068,14 +1093,10 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1068
1093
|
camera.position.z = 5;
|
|
1069
1094
|
if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
|
|
1070
1095
|
|
|
1071
|
-
camera.lookAt(0, 0, 0);
|
|
1096
|
+
if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1072
1097
|
}
|
|
1073
1098
|
|
|
1074
|
-
|
|
1075
|
-
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
const initialDpr = setDpr(dpr);
|
|
1099
|
+
const initialDpr = calculateDpr(dpr);
|
|
1079
1100
|
const position = new THREE__namespace.Vector3();
|
|
1080
1101
|
const defaultTarget = new THREE__namespace.Vector3();
|
|
1081
1102
|
const tempTarget = new THREE__namespace.Vector3();
|
|
@@ -1182,7 +1203,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1182
1203
|
},
|
|
1183
1204
|
setDpr: dpr => set(state => ({
|
|
1184
1205
|
viewport: { ...state.viewport,
|
|
1185
|
-
dpr:
|
|
1206
|
+
dpr: calculateDpr(dpr)
|
|
1186
1207
|
}
|
|
1187
1208
|
})),
|
|
1188
1209
|
events: {
|
|
@@ -1473,7 +1494,10 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1473
1494
|
events,
|
|
1474
1495
|
...props
|
|
1475
1496
|
}, forwardedRef) {
|
|
1476
|
-
const [containerRef,
|
|
1497
|
+
const [containerRef, {
|
|
1498
|
+
width,
|
|
1499
|
+
height
|
|
1500
|
+
}] = useMeasure__default['default']({
|
|
1477
1501
|
scroll: true,
|
|
1478
1502
|
debounce: {
|
|
1479
1503
|
scroll: 50,
|
|
@@ -1490,7 +1514,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1490
1514
|
if (error) throw error; // Execute JSX in the reconciler as a layout-effect
|
|
1491
1515
|
|
|
1492
1516
|
useIsomorphicLayoutEffect(() => {
|
|
1493
|
-
if (
|
|
1517
|
+
if (width > 0 && height > 0) {
|
|
1494
1518
|
render( /*#__PURE__*/React__namespace.createElement(ErrorBoundary, {
|
|
1495
1519
|
set: setError
|
|
1496
1520
|
}, /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
|
|
@@ -1498,11 +1522,14 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1498
1522
|
set: setBlock
|
|
1499
1523
|
})
|
|
1500
1524
|
}, children)), canvasRef.current, { ...props,
|
|
1501
|
-
size
|
|
1525
|
+
size: {
|
|
1526
|
+
width,
|
|
1527
|
+
height
|
|
1528
|
+
},
|
|
1502
1529
|
events: events || createPointerEvents
|
|
1503
1530
|
});
|
|
1504
1531
|
}
|
|
1505
|
-
}, [
|
|
1532
|
+
}, [width, height, children]);
|
|
1506
1533
|
useIsomorphicLayoutEffect(() => {
|
|
1507
1534
|
const container = canvasRef.current;
|
|
1508
1535
|
return () => unmountComponentAtNode(container);
|
|
@@ -1646,15 +1673,14 @@ function render(element, canvas, {
|
|
|
1646
1673
|
let state = (_store = store) == null ? void 0 : _store.getState();
|
|
1647
1674
|
|
|
1648
1675
|
if (fiber && state) {
|
|
1649
|
-
|
|
1676
|
+
// When a root was found, see if any fundamental props must be changed or exchanged
|
|
1650
1677
|
// Check pixelratio
|
|
1678
|
+
if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
|
|
1651
1679
|
|
|
1652
|
-
if (
|
|
1653
|
-
|
|
1654
|
-
if (!is.equ(lastProps.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
|
|
1680
|
+
if (!is.equ(state.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
|
|
1655
1681
|
// Changes to the color-space
|
|
1656
1682
|
|
|
1657
|
-
const linearChanged = props.linear !== lastProps.linear;
|
|
1683
|
+
const linearChanged = props.linear !== state.internal.lastProps.linear;
|
|
1658
1684
|
|
|
1659
1685
|
if (linearChanged) {
|
|
1660
1686
|
unmountComponentAtNode(canvas);
|
|
@@ -24,7 +24,8 @@ const is = {
|
|
|
24
24
|
// Wrong type or one of the two undefined, doesn't match
|
|
25
25
|
if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
|
|
26
26
|
|
|
27
|
-
if (is.str(a) || is.num(a)
|
|
27
|
+
if (is.str(a) || is.num(a)) return a === b;
|
|
28
|
+
if (is.obj(a) && a === b) return true; // Array, shallow compare first to see if it's a match
|
|
28
29
|
|
|
29
30
|
if (is.arr(a) && a == b) return true; // Last resort, go through keys
|
|
30
31
|
|
|
@@ -98,7 +99,11 @@ function createEvents(store) {
|
|
|
98
99
|
|
|
99
100
|
|
|
100
101
|
function filterPointerEvents(objects) {
|
|
101
|
-
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name =>
|
|
102
|
+
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name => {
|
|
103
|
+
var _r3f;
|
|
104
|
+
|
|
105
|
+
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.handlers['onPointer' + name];
|
|
106
|
+
}));
|
|
102
107
|
}
|
|
103
108
|
|
|
104
109
|
function intersect(filter) {
|
|
@@ -128,7 +133,9 @@ function createEvents(store) {
|
|
|
128
133
|
let eventObject = intersect.object; // Bubble event up
|
|
129
134
|
|
|
130
135
|
while (eventObject) {
|
|
131
|
-
|
|
136
|
+
var _r3f2;
|
|
137
|
+
|
|
138
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.handlers.count) intersections.push({ ...intersect,
|
|
132
139
|
eventObject
|
|
133
140
|
});
|
|
134
141
|
eventObject = eventObject.parent;
|
|
@@ -155,7 +162,7 @@ function createEvents(store) {
|
|
|
155
162
|
/** Handles intersections by forwarding them to handlers */
|
|
156
163
|
|
|
157
164
|
|
|
158
|
-
function handleIntersects(intersections, event, callback) {
|
|
165
|
+
function handleIntersects(intersections, event, delta, callback) {
|
|
159
166
|
const {
|
|
160
167
|
raycaster,
|
|
161
168
|
mouse,
|
|
@@ -165,7 +172,6 @@ function createEvents(store) {
|
|
|
165
172
|
|
|
166
173
|
if (intersections.length) {
|
|
167
174
|
const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
|
|
168
|
-
const delta = event.type === 'click' ? calculateDistance(event) : 0;
|
|
169
175
|
|
|
170
176
|
const releasePointerCapture = id => event.target.releasePointerCapture(id);
|
|
171
177
|
|
|
@@ -266,11 +272,13 @@ function createEvents(store) {
|
|
|
266
272
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
267
273
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
268
274
|
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
275
|
+
var _r3f3;
|
|
276
|
+
|
|
269
277
|
const eventObject = hoveredObj.eventObject;
|
|
270
|
-
const handlers = eventObject.__r3f.handlers;
|
|
278
|
+
const handlers = (_r3f3 = eventObject.__r3f) == null ? void 0 : _r3f3.handlers;
|
|
271
279
|
internal.hovered.delete(makeId(hoveredObj));
|
|
272
280
|
|
|
273
|
-
if (handlers.count) {
|
|
281
|
+
if (handlers != null && handlers.count) {
|
|
274
282
|
// Clear out intersects, they are outdated by now
|
|
275
283
|
const data = { ...hoveredObj,
|
|
276
284
|
intersections: hits || []
|
|
@@ -311,15 +319,34 @@ function createEvents(store) {
|
|
|
311
319
|
prepareRay(event); // Get fresh intersects
|
|
312
320
|
|
|
313
321
|
const isPointerMove = name === 'onPointerMove';
|
|
322
|
+
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
314
323
|
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
315
|
-
const hits = patchIntersects(intersect(filter), event);
|
|
324
|
+
const hits = patchIntersects(intersect(filter), event);
|
|
325
|
+
const delta = isClickEvent ? calculateDistance(event) : 0; // Save initial coordinates on pointer-down
|
|
326
|
+
|
|
327
|
+
if (name === 'onPointerDown') {
|
|
328
|
+
internal.initialClick = [event.offsetX, event.offsetY];
|
|
329
|
+
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
330
|
+
} // If a click yields no results, pass it back to the user as a miss
|
|
331
|
+
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
if (isClickEvent && !hits.length) {
|
|
335
|
+
if (delta <= 2) {
|
|
336
|
+
pointerMissed(event, internal.interaction);
|
|
337
|
+
if (onPointerMissed) onPointerMissed(event);
|
|
338
|
+
}
|
|
339
|
+
} // Take care of unhover
|
|
340
|
+
|
|
316
341
|
|
|
317
342
|
if (isPointerMove) cancelPointer(hits);
|
|
318
|
-
handleIntersects(hits, event, data => {
|
|
343
|
+
handleIntersects(hits, event, delta, data => {
|
|
344
|
+
var _r3f4;
|
|
345
|
+
|
|
319
346
|
const eventObject = data.eventObject;
|
|
320
|
-
const handlers = eventObject.__r3f.handlers; // Check presence of handlers
|
|
347
|
+
const handlers = (_r3f4 = eventObject.__r3f) == null ? void 0 : _r3f4.handlers; // Check presence of handlers
|
|
321
348
|
|
|
322
|
-
if (!handlers.count) return;
|
|
349
|
+
if (!(handlers != null && handlers.count)) return;
|
|
323
350
|
|
|
324
351
|
if (isPointerMove) {
|
|
325
352
|
// Move event ...
|
|
@@ -349,33 +376,22 @@ function createEvents(store) {
|
|
|
349
376
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
350
377
|
// which must use the initial target
|
|
351
378
|
if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
|
|
379
|
+
// Missed events have to come first
|
|
380
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
|
|
381
|
+
|
|
352
382
|
handler(data);
|
|
353
|
-
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
354
383
|
}
|
|
355
384
|
}
|
|
356
385
|
}
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
if (name === 'onPointerDown') {
|
|
360
|
-
internal.initialClick = [event.offsetX, event.offsetY];
|
|
361
|
-
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
362
|
-
} // If a click yields no results, pass it back to the user as a miss
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if ((name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick') && !hits.length) {
|
|
366
|
-
if (calculateDistance(event) <= 2) {
|
|
367
|
-
pointerMissed(event, internal.interaction);
|
|
368
|
-
if (onPointerMissed) onPointerMissed(event);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
386
|
+
});
|
|
371
387
|
};
|
|
372
388
|
};
|
|
373
389
|
|
|
374
390
|
function pointerMissed(event, objects) {
|
|
375
391
|
objects.forEach(object => {
|
|
376
|
-
var
|
|
392
|
+
var _r3f5;
|
|
377
393
|
|
|
378
|
-
return (
|
|
394
|
+
return (_r3f5 = object.__r3f) == null ? void 0 : _r3f5.handlers.onPointerMissed == null ? void 0 : _r3f5.handlers.onPointerMissed(event);
|
|
379
395
|
});
|
|
380
396
|
}
|
|
381
397
|
|
|
@@ -430,6 +446,7 @@ function prepare(object, state) {
|
|
|
430
446
|
count: 0
|
|
431
447
|
},
|
|
432
448
|
objects: [],
|
|
449
|
+
parent: null,
|
|
433
450
|
...state
|
|
434
451
|
};
|
|
435
452
|
}
|
|
@@ -488,7 +505,7 @@ function createRenderer(roots) {
|
|
|
488
505
|
}
|
|
489
506
|
|
|
490
507
|
function applyProps(instance, data) {
|
|
491
|
-
var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2;
|
|
508
|
+
var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2, _instance$__r3f4;
|
|
492
509
|
|
|
493
510
|
// Filter equals, events and reserved props
|
|
494
511
|
const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
@@ -573,16 +590,16 @@ function createRenderer(roots) {
|
|
|
573
590
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
574
591
|
|
|
575
592
|
if (localState.handlers.count) rootState.internal.interaction.push(instance);
|
|
576
|
-
} // Call the update lifecycle when it is being updated
|
|
593
|
+
} // Call the update lifecycle when it is being updated
|
|
577
594
|
|
|
578
595
|
|
|
579
|
-
if (changes.length && instance.parent) updateInstance(instance);
|
|
596
|
+
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
580
597
|
}
|
|
581
598
|
|
|
582
599
|
function invalidateInstance(instance) {
|
|
583
|
-
var _instance$
|
|
600
|
+
var _instance$__r3f5, _instance$__r3f5$root;
|
|
584
601
|
|
|
585
|
-
const state = (_instance$
|
|
602
|
+
const state = (_instance$__r3f5 = instance.__r3f) == null ? void 0 : (_instance$__r3f5$root = _instance$__r3f5.root) == null ? void 0 : _instance$__r3f5$root.getState == null ? void 0 : _instance$__r3f5$root.getState();
|
|
586
603
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
587
604
|
}
|
|
588
605
|
|
|
@@ -674,7 +691,7 @@ function createRenderer(roots) {
|
|
|
674
691
|
} else if (is.fun(attachFn)) {
|
|
675
692
|
attachFn(child, parentInstance);
|
|
676
693
|
}
|
|
677
|
-
} else if (child.isObject3D) {
|
|
694
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
678
695
|
// add in the usual parent-child way
|
|
679
696
|
parentInstance.add(child);
|
|
680
697
|
addedAsChild = true;
|
|
@@ -684,10 +701,13 @@ function createRenderer(roots) {
|
|
|
684
701
|
// This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
|
|
685
702
|
// that is, anything that's a child in React but not a child in the scenegraph.
|
|
686
703
|
parentInstance.__r3f.objects.push(child);
|
|
704
|
+
}
|
|
687
705
|
|
|
688
|
-
|
|
706
|
+
if (!child.__r3f) {
|
|
707
|
+
prepare(child, {});
|
|
689
708
|
}
|
|
690
709
|
|
|
710
|
+
child.__r3f.parent = parentInstance;
|
|
691
711
|
updateInstance(child);
|
|
692
712
|
invalidateInstance(child);
|
|
693
713
|
}
|
|
@@ -704,7 +724,7 @@ function createRenderer(roots) {
|
|
|
704
724
|
} else if (child.attachObject || child.attach && !is.fun(child.attach)) {
|
|
705
725
|
// attach and attachObject don't have an order anyway, so just append
|
|
706
726
|
return appendChild(parentInstance, child);
|
|
707
|
-
} else if (child.isObject3D) {
|
|
727
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
708
728
|
child.parent = parentInstance;
|
|
709
729
|
child.dispatchEvent({
|
|
710
730
|
type: 'added'
|
|
@@ -717,10 +737,13 @@ function createRenderer(roots) {
|
|
|
717
737
|
|
|
718
738
|
if (!added) {
|
|
719
739
|
parentInstance.__r3f.objects.push(child);
|
|
740
|
+
}
|
|
720
741
|
|
|
721
|
-
|
|
742
|
+
if (!child.__r3f) {
|
|
743
|
+
prepare(child, {});
|
|
722
744
|
}
|
|
723
745
|
|
|
746
|
+
child.__r3f.parent = parentInstance;
|
|
724
747
|
updateInstance(child);
|
|
725
748
|
invalidateInstance(child);
|
|
726
749
|
}
|
|
@@ -732,17 +755,14 @@ function createRenderer(roots) {
|
|
|
732
755
|
|
|
733
756
|
function removeChild(parentInstance, child, dispose) {
|
|
734
757
|
if (child) {
|
|
735
|
-
var _child$__r3f2;
|
|
758
|
+
var _parentInstance$__r3f, _child$__r3f2;
|
|
736
759
|
|
|
737
|
-
if (
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
const newLength = parentInstance.__r3f.objects.length; // was it in the list?
|
|
760
|
+
if (child.__r3f) {
|
|
761
|
+
child.__r3f.parent = null;
|
|
762
|
+
}
|
|
741
763
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
child.parent = null;
|
|
745
|
-
}
|
|
764
|
+
if ((_parentInstance$__r3f = parentInstance.__r3f) != null && _parentInstance$__r3f.objects) {
|
|
765
|
+
parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
|
|
746
766
|
} // Remove attachment
|
|
747
767
|
|
|
748
768
|
|
|
@@ -815,7 +835,9 @@ function createRenderer(roots) {
|
|
|
815
835
|
}
|
|
816
836
|
|
|
817
837
|
function switchInstance(instance, type, newProps, fiber) {
|
|
818
|
-
|
|
838
|
+
var _instance$__r3f6;
|
|
839
|
+
|
|
840
|
+
const parent = (_instance$__r3f6 = instance.__r3f) == null ? void 0 : _instance$__r3f6.parent;
|
|
819
841
|
if (!parent) return;
|
|
820
842
|
const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
|
|
821
843
|
// When args change the instance has to be re-constructed, which then
|
|
@@ -978,6 +1000,9 @@ function createRenderer(roots) {
|
|
|
978
1000
|
|
|
979
1001
|
const isRenderer = def => def && !!def.render;
|
|
980
1002
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
1003
|
+
function calculateDpr(dpr) {
|
|
1004
|
+
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
1005
|
+
}
|
|
981
1006
|
const context = /*#__PURE__*/React.createContext(null);
|
|
982
1007
|
|
|
983
1008
|
const createStore = (applyProps, invalidate, advance, props) => {
|
|
@@ -1034,14 +1059,10 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1034
1059
|
camera.position.z = 5;
|
|
1035
1060
|
if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
|
|
1036
1061
|
|
|
1037
|
-
camera.lookAt(0, 0, 0);
|
|
1062
|
+
if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1038
1063
|
}
|
|
1039
1064
|
|
|
1040
|
-
|
|
1041
|
-
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
const initialDpr = setDpr(dpr);
|
|
1065
|
+
const initialDpr = calculateDpr(dpr);
|
|
1045
1066
|
const position = new THREE.Vector3();
|
|
1046
1067
|
const defaultTarget = new THREE.Vector3();
|
|
1047
1068
|
const tempTarget = new THREE.Vector3();
|
|
@@ -1148,7 +1169,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1148
1169
|
},
|
|
1149
1170
|
setDpr: dpr => set(state => ({
|
|
1150
1171
|
viewport: { ...state.viewport,
|
|
1151
|
-
dpr:
|
|
1172
|
+
dpr: calculateDpr(dpr)
|
|
1152
1173
|
}
|
|
1153
1174
|
})),
|
|
1154
1175
|
events: {
|
|
@@ -1439,7 +1460,10 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
|
|
|
1439
1460
|
events,
|
|
1440
1461
|
...props
|
|
1441
1462
|
}, forwardedRef) {
|
|
1442
|
-
const [containerRef,
|
|
1463
|
+
const [containerRef, {
|
|
1464
|
+
width,
|
|
1465
|
+
height
|
|
1466
|
+
}] = useMeasure({
|
|
1443
1467
|
scroll: true,
|
|
1444
1468
|
debounce: {
|
|
1445
1469
|
scroll: 50,
|
|
@@ -1456,7 +1480,7 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
|
|
|
1456
1480
|
if (error) throw error; // Execute JSX in the reconciler as a layout-effect
|
|
1457
1481
|
|
|
1458
1482
|
useIsomorphicLayoutEffect(() => {
|
|
1459
|
-
if (
|
|
1483
|
+
if (width > 0 && height > 0) {
|
|
1460
1484
|
render( /*#__PURE__*/React.createElement(ErrorBoundary, {
|
|
1461
1485
|
set: setError
|
|
1462
1486
|
}, /*#__PURE__*/React.createElement(React.Suspense, {
|
|
@@ -1464,11 +1488,14 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
|
|
|
1464
1488
|
set: setBlock
|
|
1465
1489
|
})
|
|
1466
1490
|
}, children)), canvasRef.current, { ...props,
|
|
1467
|
-
size
|
|
1491
|
+
size: {
|
|
1492
|
+
width,
|
|
1493
|
+
height
|
|
1494
|
+
},
|
|
1468
1495
|
events: events || createPointerEvents
|
|
1469
1496
|
});
|
|
1470
1497
|
}
|
|
1471
|
-
}, [
|
|
1498
|
+
}, [width, height, children]);
|
|
1472
1499
|
useIsomorphicLayoutEffect(() => {
|
|
1473
1500
|
const container = canvasRef.current;
|
|
1474
1501
|
return () => unmountComponentAtNode(container);
|
|
@@ -1612,15 +1639,14 @@ function render(element, canvas, {
|
|
|
1612
1639
|
let state = (_store = store) == null ? void 0 : _store.getState();
|
|
1613
1640
|
|
|
1614
1641
|
if (fiber && state) {
|
|
1615
|
-
|
|
1642
|
+
// When a root was found, see if any fundamental props must be changed or exchanged
|
|
1616
1643
|
// Check pixelratio
|
|
1644
|
+
if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
|
|
1617
1645
|
|
|
1618
|
-
if (
|
|
1619
|
-
|
|
1620
|
-
if (!is.equ(lastProps.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
|
|
1646
|
+
if (!is.equ(state.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
|
|
1621
1647
|
// Changes to the color-space
|
|
1622
1648
|
|
|
1623
|
-
const linearChanged = props.linear !== lastProps.linear;
|
|
1649
|
+
const linearChanged = props.linear !== state.internal.lastProps.linear;
|
|
1624
1650
|
|
|
1625
1651
|
if (linearChanged) {
|
|
1626
1652
|
unmountComponentAtNode(canvas);
|