@react-three/fiber 7.0.15 → 7.0.19
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 -0
- package/dist/declarations/src/core/renderer.d.ts +3 -4
- package/dist/declarations/src/core/store.d.ts +6 -3
- package/dist/declarations/src/web/index.d.ts +7 -3
- package/dist/react-three-fiber.cjs.dev.js +109 -65
- package/dist/react-three-fiber.cjs.prod.js +109 -65
- package/dist/react-three-fiber.esm.js +109 -64
- package/native/dist/react-three-fiber-native.cjs.d.ts +11 -0
- package/native/dist/react-three-fiber-native.cjs.js +16 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @react-three/fiber
|
|
2
2
|
|
|
3
|
+
## 7.0.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7aa2eab: fix: remove zustand subcribe selector
|
|
8
|
+
|
|
9
|
+
## 7.0.18
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 6780f58: fix unmount pointer capture
|
|
14
|
+
|
|
15
|
+
## 7.0.17
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 894c550: fix: event count
|
|
20
|
+
|
|
21
|
+
## 7.0.16
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- c7a4220: patch: applyprops returns the same instance
|
|
26
|
+
|
|
3
27
|
## 7.0.15
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -53,6 +53,10 @@ export interface EventManager<TTarget> {
|
|
|
53
53
|
connect?: (target: TTarget) => void;
|
|
54
54
|
disconnect?: () => void;
|
|
55
55
|
}
|
|
56
|
+
export interface PointerCaptureTarget {
|
|
57
|
+
intersection: Intersection;
|
|
58
|
+
target: Element;
|
|
59
|
+
}
|
|
56
60
|
export declare function removeInteractivity(store: UseStore<RootState>, object: THREE.Object3D): void;
|
|
57
61
|
export declare function createEvents(store: UseStore<RootState>): {
|
|
58
62
|
handlePointer: (name: string) => (event: DomEvent) => void;
|
|
@@ -12,9 +12,8 @@ export declare type LocalState = {
|
|
|
12
12
|
objects: Instance[];
|
|
13
13
|
parent: Instance | null;
|
|
14
14
|
primitive?: boolean;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} & Partial<EventHandlers>;
|
|
15
|
+
eventCount: number;
|
|
16
|
+
handlers: Partial<EventHandlers>;
|
|
18
17
|
memoizedProps: {
|
|
19
18
|
[key: string]: any;
|
|
20
19
|
};
|
|
@@ -57,6 +56,6 @@ declare let extend: (objects: object) => void;
|
|
|
57
56
|
declare function prepare<T = THREE.Object3D>(object: T, state?: Partial<LocalState>): T;
|
|
58
57
|
declare function createRenderer<TCanvas>(roots: Map<TCanvas, Root>): {
|
|
59
58
|
reconciler: Reconciler.Reconciler<unknown, unknown, unknown, unknown, unknown>;
|
|
60
|
-
applyProps: (instance: Instance, data: InstanceProps | DiffSet) =>
|
|
59
|
+
applyProps: (instance: Instance, data: InstanceProps | DiffSet) => Instance;
|
|
61
60
|
};
|
|
62
61
|
export { prepare, createRenderer, extend };
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import * as ReactThreeFiber from '../three-types';
|
|
4
4
|
import { GetState, SetState, UseStore } from 'zustand';
|
|
5
5
|
import { Instance, InstanceProps } from './renderer';
|
|
6
|
-
import { DomEvent, EventManager, ThreeEvent } from './events';
|
|
6
|
+
import { DomEvent, EventManager, PointerCaptureTarget, ThreeEvent } from './events';
|
|
7
7
|
export interface Intersection extends THREE.Intersection {
|
|
8
8
|
eventObject: THREE.Object3D;
|
|
9
9
|
}
|
|
@@ -37,7 +37,10 @@ export declare type Performance = {
|
|
|
37
37
|
debounce: number;
|
|
38
38
|
regress: () => void;
|
|
39
39
|
};
|
|
40
|
-
export declare
|
|
40
|
+
export declare type Renderer = {
|
|
41
|
+
render: (scene: THREE.Scene, camera: THREE.Camera) => any;
|
|
42
|
+
};
|
|
43
|
+
export declare const isRenderer: (def: Renderer) => boolean;
|
|
41
44
|
export declare const isOrthographicCamera: (def: THREE.Camera) => def is THREE.OrthographicCamera;
|
|
42
45
|
export declare type InternalState = {
|
|
43
46
|
active: boolean;
|
|
@@ -47,7 +50,7 @@ export declare type InternalState = {
|
|
|
47
50
|
interaction: THREE.Object3D[];
|
|
48
51
|
hovered: Map<string, DomEvent>;
|
|
49
52
|
subscribers: Subscription[];
|
|
50
|
-
capturedMap: Map<number, Map<THREE.Object3D,
|
|
53
|
+
capturedMap: Map<number, Map<THREE.Object3D, PointerCaptureTarget>>;
|
|
51
54
|
initialClick: [x: number, y: number];
|
|
52
55
|
initialHits: THREE.Object3D[];
|
|
53
56
|
subscribe: (callback: React.MutableRefObject<RenderCallback>, priority?: number) => () => void;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { UseStore } from 'zustand';
|
|
5
|
-
import { StoreProps, context, RootState, Size } from '../core/store';
|
|
5
|
+
import { Renderer, StoreProps, context, RootState, Size } from '../core/store';
|
|
6
6
|
import { extend, Root } from '../core/renderer';
|
|
7
7
|
import { addEffect, addAfterEffect, addTail } from '../core/loop';
|
|
8
8
|
import { createPointerEvents as events } from './events';
|
|
@@ -11,9 +11,13 @@ import { EventManager } from '../core/events';
|
|
|
11
11
|
declare const roots: Map<Element, Root>;
|
|
12
12
|
declare const modes: readonly ["legacy", "blocking", "concurrent"];
|
|
13
13
|
declare const invalidate: (state?: RootState | undefined) => void, advance: (timestamp: number, runGlobalEffects?: boolean, state?: RootState | undefined) => void;
|
|
14
|
-
declare const reconciler: import("react-reconciler").Reconciler<unknown, unknown, unknown, unknown, unknown>, applyProps: (instance: import("../core/renderer").Instance, data: import("../core/renderer").InstanceProps | import("../core/renderer").DiffSet) =>
|
|
14
|
+
declare const reconciler: import("react-reconciler").Reconciler<unknown, unknown, unknown, unknown, unknown>, applyProps: (instance: import("../core/renderer").Instance, data: import("../core/renderer").InstanceProps | import("../core/renderer").DiffSet) => import("../core/renderer").Instance;
|
|
15
|
+
declare type Properties<T> = Pick<T, {
|
|
16
|
+
[K in keyof T]: T[K] extends (_: any) => any ? never : K;
|
|
17
|
+
}[keyof T]>;
|
|
18
|
+
declare type GLProps = Renderer | ((canvas: HTMLCanvasElement) => Renderer) | Partial<Properties<THREE.WebGLRenderer> | THREE.WebGLRendererParameters> | undefined;
|
|
15
19
|
export declare type RenderProps<TCanvas extends Element> = Omit<StoreProps, 'gl' | 'events' | 'size'> & {
|
|
16
|
-
gl?:
|
|
20
|
+
gl?: GLProps;
|
|
17
21
|
events?: (store: UseStore<RootState>) => EventManager<TCanvas>;
|
|
18
22
|
size?: Size;
|
|
19
23
|
mode?: typeof modes[number];
|
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var THREE = require('three');
|
|
6
6
|
var React = require('react');
|
|
7
7
|
var create = require('zustand');
|
|
8
|
-
var shallow = require('zustand/shallow');
|
|
9
8
|
var Reconciler = require('react-reconciler');
|
|
10
9
|
var scheduler = require('scheduler');
|
|
11
10
|
var useAsset = require('use-asset');
|
|
@@ -37,7 +36,6 @@ function _interopNamespace(e) {
|
|
|
37
36
|
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
38
37
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
39
38
|
var create__default = /*#__PURE__*/_interopDefault(create);
|
|
40
|
-
var shallow__default = /*#__PURE__*/_interopDefault(shallow);
|
|
41
39
|
var Reconciler__default = /*#__PURE__*/_interopDefault(Reconciler);
|
|
42
40
|
var mergeRefs__default = /*#__PURE__*/_interopDefault(mergeRefs);
|
|
43
41
|
var useMeasure__default = /*#__PURE__*/_interopDefault(useMeasure);
|
|
@@ -76,6 +74,23 @@ const is = {
|
|
|
76
74
|
function makeId(event) {
|
|
77
75
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
78
76
|
}
|
|
77
|
+
/** Release pointer captures.
|
|
78
|
+
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
|
|
83
|
+
const captureData = captures.get(obj);
|
|
84
|
+
|
|
85
|
+
if (captureData) {
|
|
86
|
+
captures.delete(obj); // If this was the last capturing object for this pointer
|
|
87
|
+
|
|
88
|
+
if (captures.size === 0) {
|
|
89
|
+
capturedMap.delete(pointerId);
|
|
90
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
79
94
|
|
|
80
95
|
function removeInteractivity(store, object) {
|
|
81
96
|
const {
|
|
@@ -89,6 +104,9 @@ function removeInteractivity(store, object) {
|
|
|
89
104
|
internal.hovered.delete(key);
|
|
90
105
|
}
|
|
91
106
|
});
|
|
107
|
+
internal.capturedMap.forEach((captures, pointerId) => {
|
|
108
|
+
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
109
|
+
});
|
|
92
110
|
}
|
|
93
111
|
function createEvents(store) {
|
|
94
112
|
const temp = new THREE__namespace.Vector3();
|
|
@@ -168,7 +186,7 @@ function createEvents(store) {
|
|
|
168
186
|
while (eventObject) {
|
|
169
187
|
var _r3f2;
|
|
170
188
|
|
|
171
|
-
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.
|
|
189
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...intersect,
|
|
172
190
|
eventObject
|
|
173
191
|
});
|
|
174
192
|
eventObject = eventObject.parent;
|
|
@@ -187,7 +205,9 @@ function createEvents(store) {
|
|
|
187
205
|
// intersect.
|
|
188
206
|
|
|
189
207
|
if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
|
|
190
|
-
|
|
208
|
+
for (let captureData of internal.capturedMap.get(event.pointerId).values()) {
|
|
209
|
+
intersections.push(captureData.intersection);
|
|
210
|
+
}
|
|
191
211
|
}
|
|
192
212
|
|
|
193
213
|
return intersections;
|
|
@@ -205,9 +225,6 @@ function createEvents(store) {
|
|
|
205
225
|
|
|
206
226
|
if (intersections.length) {
|
|
207
227
|
const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
|
|
208
|
-
|
|
209
|
-
const releasePointerCapture = id => event.target.releasePointerCapture(id);
|
|
210
|
-
|
|
211
228
|
const localState = {
|
|
212
229
|
stopped: false
|
|
213
230
|
};
|
|
@@ -220,23 +237,36 @@ function createEvents(store) {
|
|
|
220
237
|
};
|
|
221
238
|
|
|
222
239
|
const setPointerCapture = id => {
|
|
240
|
+
const captureData = {
|
|
241
|
+
intersection: hit,
|
|
242
|
+
target: event.target
|
|
243
|
+
};
|
|
244
|
+
|
|
223
245
|
if (internal.capturedMap.has(id)) {
|
|
224
246
|
// if the pointerId was previously captured, we add the hit to the
|
|
225
247
|
// event capturedMap.
|
|
226
|
-
internal.capturedMap.get(id).set(hit.eventObject,
|
|
248
|
+
internal.capturedMap.get(id).set(hit.eventObject, captureData);
|
|
227
249
|
} else {
|
|
228
250
|
// if the pointerId was not previously captured, we create a map
|
|
229
251
|
// containing the hitObject, and the hit. hitObject is used for
|
|
230
252
|
// faster access.
|
|
231
|
-
internal.capturedMap.set(id, new Map([[hit.eventObject,
|
|
253
|
+
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
232
254
|
} // Call the original event now
|
|
233
255
|
event.target.setPointerCapture(id);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const releasePointerCapture = id => {
|
|
259
|
+
const captures = internal.capturedMap.get(id);
|
|
260
|
+
|
|
261
|
+
if (captures) {
|
|
262
|
+
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
263
|
+
}
|
|
234
264
|
}; // Add native event props
|
|
235
265
|
|
|
236
266
|
|
|
237
|
-
let extractEventProps = {};
|
|
267
|
+
let extractEventProps = {}; // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
|
|
238
268
|
|
|
239
|
-
for (let prop in
|
|
269
|
+
for (let prop in event) {
|
|
240
270
|
let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
|
|
241
271
|
// called as event.nativeEvent.fn()
|
|
242
272
|
|
|
@@ -305,13 +335,12 @@ function createEvents(store) {
|
|
|
305
335
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
306
336
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
307
337
|
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
308
|
-
var _r3f3;
|
|
309
|
-
|
|
310
338
|
const eventObject = hoveredObj.eventObject;
|
|
311
|
-
const
|
|
339
|
+
const instance = eventObject.__r3f;
|
|
340
|
+
const handlers = instance == null ? void 0 : instance.handlers;
|
|
312
341
|
internal.hovered.delete(makeId(hoveredObj));
|
|
313
342
|
|
|
314
|
-
if (
|
|
343
|
+
if (instance != null && instance.eventCount) {
|
|
315
344
|
// Clear out intersects, they are outdated by now
|
|
316
345
|
const data = { ...hoveredObj,
|
|
317
346
|
intersections: hits || []
|
|
@@ -333,9 +362,8 @@ function createEvents(store) {
|
|
|
333
362
|
case 'onLostPointerCapture':
|
|
334
363
|
return event => {
|
|
335
364
|
if ('pointerId' in event) {
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
// indifferently deletes all capturing references.
|
|
365
|
+
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
366
|
+
// object that's getting removed.
|
|
339
367
|
store.getState().internal.capturedMap.delete(event.pointerId);
|
|
340
368
|
}
|
|
341
369
|
|
|
@@ -374,12 +402,11 @@ function createEvents(store) {
|
|
|
374
402
|
|
|
375
403
|
if (isPointerMove) cancelPointer(hits);
|
|
376
404
|
handleIntersects(hits, event, delta, data => {
|
|
377
|
-
var _r3f4;
|
|
378
|
-
|
|
379
405
|
const eventObject = data.eventObject;
|
|
380
|
-
const
|
|
406
|
+
const instance = eventObject.__r3f;
|
|
407
|
+
const handlers = instance == null ? void 0 : instance.handlers; // Check presence of handlers
|
|
381
408
|
|
|
382
|
-
if (!(
|
|
409
|
+
if (!(instance != null && instance.eventCount)) return;
|
|
383
410
|
|
|
384
411
|
if (isPointerMove) {
|
|
385
412
|
// Move event ...
|
|
@@ -422,9 +449,9 @@ function createEvents(store) {
|
|
|
422
449
|
|
|
423
450
|
function pointerMissed(event, objects) {
|
|
424
451
|
objects.forEach(object => {
|
|
425
|
-
var
|
|
452
|
+
var _r3f3;
|
|
426
453
|
|
|
427
|
-
return (
|
|
454
|
+
return (_r3f3 = object.__r3f) == null ? void 0 : _r3f3.handlers.onPointerMissed == null ? void 0 : _r3f3.handlers.onPointerMissed(event);
|
|
428
455
|
});
|
|
429
456
|
}
|
|
430
457
|
|
|
@@ -475,9 +502,8 @@ function prepare(object, state) {
|
|
|
475
502
|
instance.__r3f = {
|
|
476
503
|
root: null,
|
|
477
504
|
memoizedProps: {},
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
},
|
|
505
|
+
eventCount: 0,
|
|
506
|
+
handlers: {},
|
|
481
507
|
objects: [],
|
|
482
508
|
parent: null,
|
|
483
509
|
...state
|
|
@@ -538,7 +564,7 @@ function createRenderer(roots) {
|
|
|
538
564
|
}
|
|
539
565
|
|
|
540
566
|
function applyProps(instance, data) {
|
|
541
|
-
var _instance$__r3f3, _root$getState,
|
|
567
|
+
var _instance$__r3f3, _root$getState, _instance$__r3f4;
|
|
542
568
|
|
|
543
569
|
// Filter equals, events and reserved props
|
|
544
570
|
const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
@@ -548,7 +574,7 @@ function createRenderer(roots) {
|
|
|
548
574
|
memoized,
|
|
549
575
|
changes
|
|
550
576
|
} = isDiffSet(data) ? data : diffProps(instance, data);
|
|
551
|
-
const prevHandlers =
|
|
577
|
+
const prevHandlers = localState.eventCount; // Prepare memoized props
|
|
552
578
|
|
|
553
579
|
if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
|
|
554
580
|
changes.forEach(([key, value, isEvent, keys]) => {
|
|
@@ -587,7 +613,7 @@ function createRenderer(roots) {
|
|
|
587
613
|
|
|
588
614
|
if (isEvent) {
|
|
589
615
|
if (value) localState.handlers[key] = value;else delete localState.handlers[key];
|
|
590
|
-
localState.
|
|
616
|
+
localState.eventCount = Object.keys(localState.handlers).length;
|
|
591
617
|
} // Special treatment for objects with support for set/copy, and layers
|
|
592
618
|
else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE__namespace.Layers)) {
|
|
593
619
|
// If value is an array
|
|
@@ -617,16 +643,17 @@ function createRenderer(roots) {
|
|
|
617
643
|
invalidateInstance(instance);
|
|
618
644
|
});
|
|
619
645
|
|
|
620
|
-
if (rootState.internal && instance.raycast && prevHandlers !==
|
|
646
|
+
if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
621
647
|
// Pre-emptively remove the instance from the interaction manager
|
|
622
648
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
623
649
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
624
650
|
|
|
625
|
-
if (localState.
|
|
651
|
+
if (localState.eventCount) rootState.internal.interaction.push(instance);
|
|
626
652
|
} // Call the update lifecycle when it is being updated
|
|
627
653
|
|
|
628
654
|
|
|
629
655
|
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
656
|
+
return instance;
|
|
630
657
|
}
|
|
631
658
|
|
|
632
659
|
function invalidateInstance(instance) {
|
|
@@ -812,7 +839,7 @@ function createRenderer(roots) {
|
|
|
812
839
|
} else if (is.fun(detachFn)) {
|
|
813
840
|
detachFn(child, parentInstance);
|
|
814
841
|
}
|
|
815
|
-
} else if (child.isObject3D) {
|
|
842
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
816
843
|
var _child$__r3f;
|
|
817
844
|
|
|
818
845
|
parentInstance.remove(child); // Remove interactivity
|
|
@@ -1030,7 +1057,7 @@ function createRenderer(roots) {
|
|
|
1030
1057
|
};
|
|
1031
1058
|
}
|
|
1032
1059
|
|
|
1033
|
-
const isRenderer = def => def &&
|
|
1060
|
+
const isRenderer = def => !!(def != null && def.render);
|
|
1034
1061
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
1035
1062
|
function calculateDpr(dpr) {
|
|
1036
1063
|
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
@@ -1058,11 +1085,11 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1058
1085
|
if (shadows) {
|
|
1059
1086
|
gl.shadowMap.enabled = true;
|
|
1060
1087
|
if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
|
|
1061
|
-
} // Set color
|
|
1088
|
+
} // Set color preferences
|
|
1062
1089
|
|
|
1063
1090
|
|
|
1064
|
-
if (
|
|
1065
|
-
if (
|
|
1091
|
+
if (linear) gl.outputEncoding = THREE__namespace.LinearEncoding;
|
|
1092
|
+
if (flat) gl.toneMapping = THREE__namespace.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
|
|
1066
1093
|
|
|
1067
1094
|
if (frameloop === 'never') {
|
|
1068
1095
|
clock.stop();
|
|
@@ -1251,38 +1278,45 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1251
1278
|
}
|
|
1252
1279
|
}
|
|
1253
1280
|
};
|
|
1254
|
-
});
|
|
1281
|
+
});
|
|
1282
|
+
const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
|
|
1255
1283
|
|
|
1284
|
+
let oldSize = state.size;
|
|
1285
|
+
let oldDpr = state.viewport.dpr;
|
|
1256
1286
|
rootState.subscribe(() => {
|
|
1257
1287
|
const {
|
|
1258
1288
|
camera,
|
|
1259
1289
|
size,
|
|
1260
1290
|
viewport,
|
|
1261
1291
|
internal
|
|
1262
|
-
} = rootState.getState();
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
camera
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1292
|
+
} = rootState.getState();
|
|
1293
|
+
|
|
1294
|
+
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1295
|
+
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
1296
|
+
// Do not mess with the camera if it belongs to the user
|
|
1297
|
+
if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
|
|
1298
|
+
if (isOrthographicCamera(camera)) {
|
|
1299
|
+
camera.left = size.width / -2;
|
|
1300
|
+
camera.right = size.width / 2;
|
|
1301
|
+
camera.top = size.height / 2;
|
|
1302
|
+
camera.bottom = size.height / -2;
|
|
1303
|
+
} else {
|
|
1304
|
+
camera.aspect = size.width / size.height;
|
|
1305
|
+
}
|
|
1274
1306
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1307
|
+
camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
|
|
1308
|
+
// Update matrix world since the renderer is a frame late
|
|
1277
1309
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1310
|
+
camera.updateMatrixWorld();
|
|
1311
|
+
} // Update renderer
|
|
1280
1312
|
|
|
1281
1313
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1314
|
+
gl.setPixelRatio(viewport.dpr);
|
|
1315
|
+
gl.setSize(size.width, size.height);
|
|
1316
|
+
oldSize = size;
|
|
1317
|
+
oldDpr = viewport.dpr;
|
|
1318
|
+
}
|
|
1319
|
+
}); // Update size
|
|
1286
1320
|
|
|
1287
1321
|
if (size) state.setSize(size.width, size.height); // Invalidate on any change
|
|
1288
1322
|
|
|
@@ -1637,13 +1671,23 @@ const {
|
|
|
1637
1671
|
applyProps
|
|
1638
1672
|
} = createRenderer();
|
|
1639
1673
|
|
|
1640
|
-
const createRendererInstance = (gl, canvas) =>
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1674
|
+
const createRendererInstance = (gl, canvas) => {
|
|
1675
|
+
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1676
|
+
if (isRenderer(customRenderer)) return customRenderer;
|
|
1677
|
+
const renderer = new THREE__namespace.WebGLRenderer({
|
|
1678
|
+
powerPreference: 'high-performance',
|
|
1679
|
+
canvas: canvas,
|
|
1680
|
+
antialias: true,
|
|
1681
|
+
alpha: true,
|
|
1682
|
+
...gl
|
|
1683
|
+
}); // Set color management
|
|
1684
|
+
|
|
1685
|
+
renderer.outputEncoding = THREE__namespace.sRGBEncoding;
|
|
1686
|
+
renderer.toneMapping = THREE__namespace.ACESFilmicToneMapping; // Set gl props
|
|
1687
|
+
|
|
1688
|
+
if (gl) applyProps(renderer, gl);
|
|
1689
|
+
return renderer;
|
|
1690
|
+
};
|
|
1647
1691
|
|
|
1648
1692
|
function render(element, canvas, {
|
|
1649
1693
|
gl,
|
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var THREE = require('three');
|
|
6
6
|
var React = require('react');
|
|
7
7
|
var create = require('zustand');
|
|
8
|
-
var shallow = require('zustand/shallow');
|
|
9
8
|
var Reconciler = require('react-reconciler');
|
|
10
9
|
var scheduler = require('scheduler');
|
|
11
10
|
var useAsset = require('use-asset');
|
|
@@ -37,7 +36,6 @@ function _interopNamespace(e) {
|
|
|
37
36
|
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
38
37
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
39
38
|
var create__default = /*#__PURE__*/_interopDefault(create);
|
|
40
|
-
var shallow__default = /*#__PURE__*/_interopDefault(shallow);
|
|
41
39
|
var Reconciler__default = /*#__PURE__*/_interopDefault(Reconciler);
|
|
42
40
|
var mergeRefs__default = /*#__PURE__*/_interopDefault(mergeRefs);
|
|
43
41
|
var useMeasure__default = /*#__PURE__*/_interopDefault(useMeasure);
|
|
@@ -76,6 +74,23 @@ const is = {
|
|
|
76
74
|
function makeId(event) {
|
|
77
75
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
78
76
|
}
|
|
77
|
+
/** Release pointer captures.
|
|
78
|
+
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
|
|
83
|
+
const captureData = captures.get(obj);
|
|
84
|
+
|
|
85
|
+
if (captureData) {
|
|
86
|
+
captures.delete(obj); // If this was the last capturing object for this pointer
|
|
87
|
+
|
|
88
|
+
if (captures.size === 0) {
|
|
89
|
+
capturedMap.delete(pointerId);
|
|
90
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
79
94
|
|
|
80
95
|
function removeInteractivity(store, object) {
|
|
81
96
|
const {
|
|
@@ -89,6 +104,9 @@ function removeInteractivity(store, object) {
|
|
|
89
104
|
internal.hovered.delete(key);
|
|
90
105
|
}
|
|
91
106
|
});
|
|
107
|
+
internal.capturedMap.forEach((captures, pointerId) => {
|
|
108
|
+
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
109
|
+
});
|
|
92
110
|
}
|
|
93
111
|
function createEvents(store) {
|
|
94
112
|
const temp = new THREE__namespace.Vector3();
|
|
@@ -168,7 +186,7 @@ function createEvents(store) {
|
|
|
168
186
|
while (eventObject) {
|
|
169
187
|
var _r3f2;
|
|
170
188
|
|
|
171
|
-
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.
|
|
189
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...intersect,
|
|
172
190
|
eventObject
|
|
173
191
|
});
|
|
174
192
|
eventObject = eventObject.parent;
|
|
@@ -187,7 +205,9 @@ function createEvents(store) {
|
|
|
187
205
|
// intersect.
|
|
188
206
|
|
|
189
207
|
if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
|
|
190
|
-
|
|
208
|
+
for (let captureData of internal.capturedMap.get(event.pointerId).values()) {
|
|
209
|
+
intersections.push(captureData.intersection);
|
|
210
|
+
}
|
|
191
211
|
}
|
|
192
212
|
|
|
193
213
|
return intersections;
|
|
@@ -205,9 +225,6 @@ function createEvents(store) {
|
|
|
205
225
|
|
|
206
226
|
if (intersections.length) {
|
|
207
227
|
const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
|
|
208
|
-
|
|
209
|
-
const releasePointerCapture = id => event.target.releasePointerCapture(id);
|
|
210
|
-
|
|
211
228
|
const localState = {
|
|
212
229
|
stopped: false
|
|
213
230
|
};
|
|
@@ -220,23 +237,36 @@ function createEvents(store) {
|
|
|
220
237
|
};
|
|
221
238
|
|
|
222
239
|
const setPointerCapture = id => {
|
|
240
|
+
const captureData = {
|
|
241
|
+
intersection: hit,
|
|
242
|
+
target: event.target
|
|
243
|
+
};
|
|
244
|
+
|
|
223
245
|
if (internal.capturedMap.has(id)) {
|
|
224
246
|
// if the pointerId was previously captured, we add the hit to the
|
|
225
247
|
// event capturedMap.
|
|
226
|
-
internal.capturedMap.get(id).set(hit.eventObject,
|
|
248
|
+
internal.capturedMap.get(id).set(hit.eventObject, captureData);
|
|
227
249
|
} else {
|
|
228
250
|
// if the pointerId was not previously captured, we create a map
|
|
229
251
|
// containing the hitObject, and the hit. hitObject is used for
|
|
230
252
|
// faster access.
|
|
231
|
-
internal.capturedMap.set(id, new Map([[hit.eventObject,
|
|
253
|
+
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
232
254
|
} // Call the original event now
|
|
233
255
|
event.target.setPointerCapture(id);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const releasePointerCapture = id => {
|
|
259
|
+
const captures = internal.capturedMap.get(id);
|
|
260
|
+
|
|
261
|
+
if (captures) {
|
|
262
|
+
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
263
|
+
}
|
|
234
264
|
}; // Add native event props
|
|
235
265
|
|
|
236
266
|
|
|
237
|
-
let extractEventProps = {};
|
|
267
|
+
let extractEventProps = {}; // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
|
|
238
268
|
|
|
239
|
-
for (let prop in
|
|
269
|
+
for (let prop in event) {
|
|
240
270
|
let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
|
|
241
271
|
// called as event.nativeEvent.fn()
|
|
242
272
|
|
|
@@ -305,13 +335,12 @@ function createEvents(store) {
|
|
|
305
335
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
306
336
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
307
337
|
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
308
|
-
var _r3f3;
|
|
309
|
-
|
|
310
338
|
const eventObject = hoveredObj.eventObject;
|
|
311
|
-
const
|
|
339
|
+
const instance = eventObject.__r3f;
|
|
340
|
+
const handlers = instance == null ? void 0 : instance.handlers;
|
|
312
341
|
internal.hovered.delete(makeId(hoveredObj));
|
|
313
342
|
|
|
314
|
-
if (
|
|
343
|
+
if (instance != null && instance.eventCount) {
|
|
315
344
|
// Clear out intersects, they are outdated by now
|
|
316
345
|
const data = { ...hoveredObj,
|
|
317
346
|
intersections: hits || []
|
|
@@ -333,9 +362,8 @@ function createEvents(store) {
|
|
|
333
362
|
case 'onLostPointerCapture':
|
|
334
363
|
return event => {
|
|
335
364
|
if ('pointerId' in event) {
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
// indifferently deletes all capturing references.
|
|
365
|
+
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
366
|
+
// object that's getting removed.
|
|
339
367
|
store.getState().internal.capturedMap.delete(event.pointerId);
|
|
340
368
|
}
|
|
341
369
|
|
|
@@ -374,12 +402,11 @@ function createEvents(store) {
|
|
|
374
402
|
|
|
375
403
|
if (isPointerMove) cancelPointer(hits);
|
|
376
404
|
handleIntersects(hits, event, delta, data => {
|
|
377
|
-
var _r3f4;
|
|
378
|
-
|
|
379
405
|
const eventObject = data.eventObject;
|
|
380
|
-
const
|
|
406
|
+
const instance = eventObject.__r3f;
|
|
407
|
+
const handlers = instance == null ? void 0 : instance.handlers; // Check presence of handlers
|
|
381
408
|
|
|
382
|
-
if (!(
|
|
409
|
+
if (!(instance != null && instance.eventCount)) return;
|
|
383
410
|
|
|
384
411
|
if (isPointerMove) {
|
|
385
412
|
// Move event ...
|
|
@@ -422,9 +449,9 @@ function createEvents(store) {
|
|
|
422
449
|
|
|
423
450
|
function pointerMissed(event, objects) {
|
|
424
451
|
objects.forEach(object => {
|
|
425
|
-
var
|
|
452
|
+
var _r3f3;
|
|
426
453
|
|
|
427
|
-
return (
|
|
454
|
+
return (_r3f3 = object.__r3f) == null ? void 0 : _r3f3.handlers.onPointerMissed == null ? void 0 : _r3f3.handlers.onPointerMissed(event);
|
|
428
455
|
});
|
|
429
456
|
}
|
|
430
457
|
|
|
@@ -475,9 +502,8 @@ function prepare(object, state) {
|
|
|
475
502
|
instance.__r3f = {
|
|
476
503
|
root: null,
|
|
477
504
|
memoizedProps: {},
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
},
|
|
505
|
+
eventCount: 0,
|
|
506
|
+
handlers: {},
|
|
481
507
|
objects: [],
|
|
482
508
|
parent: null,
|
|
483
509
|
...state
|
|
@@ -538,7 +564,7 @@ function createRenderer(roots) {
|
|
|
538
564
|
}
|
|
539
565
|
|
|
540
566
|
function applyProps(instance, data) {
|
|
541
|
-
var _instance$__r3f3, _root$getState,
|
|
567
|
+
var _instance$__r3f3, _root$getState, _instance$__r3f4;
|
|
542
568
|
|
|
543
569
|
// Filter equals, events and reserved props
|
|
544
570
|
const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
@@ -548,7 +574,7 @@ function createRenderer(roots) {
|
|
|
548
574
|
memoized,
|
|
549
575
|
changes
|
|
550
576
|
} = isDiffSet(data) ? data : diffProps(instance, data);
|
|
551
|
-
const prevHandlers =
|
|
577
|
+
const prevHandlers = localState.eventCount; // Prepare memoized props
|
|
552
578
|
|
|
553
579
|
if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
|
|
554
580
|
changes.forEach(([key, value, isEvent, keys]) => {
|
|
@@ -587,7 +613,7 @@ function createRenderer(roots) {
|
|
|
587
613
|
|
|
588
614
|
if (isEvent) {
|
|
589
615
|
if (value) localState.handlers[key] = value;else delete localState.handlers[key];
|
|
590
|
-
localState.
|
|
616
|
+
localState.eventCount = Object.keys(localState.handlers).length;
|
|
591
617
|
} // Special treatment for objects with support for set/copy, and layers
|
|
592
618
|
else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE__namespace.Layers)) {
|
|
593
619
|
// If value is an array
|
|
@@ -617,16 +643,17 @@ function createRenderer(roots) {
|
|
|
617
643
|
invalidateInstance(instance);
|
|
618
644
|
});
|
|
619
645
|
|
|
620
|
-
if (rootState.internal && instance.raycast && prevHandlers !==
|
|
646
|
+
if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
621
647
|
// Pre-emptively remove the instance from the interaction manager
|
|
622
648
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
623
649
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
624
650
|
|
|
625
|
-
if (localState.
|
|
651
|
+
if (localState.eventCount) rootState.internal.interaction.push(instance);
|
|
626
652
|
} // Call the update lifecycle when it is being updated
|
|
627
653
|
|
|
628
654
|
|
|
629
655
|
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
656
|
+
return instance;
|
|
630
657
|
}
|
|
631
658
|
|
|
632
659
|
function invalidateInstance(instance) {
|
|
@@ -812,7 +839,7 @@ function createRenderer(roots) {
|
|
|
812
839
|
} else if (is.fun(detachFn)) {
|
|
813
840
|
detachFn(child, parentInstance);
|
|
814
841
|
}
|
|
815
|
-
} else if (child.isObject3D) {
|
|
842
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
816
843
|
var _child$__r3f;
|
|
817
844
|
|
|
818
845
|
parentInstance.remove(child); // Remove interactivity
|
|
@@ -1030,7 +1057,7 @@ function createRenderer(roots) {
|
|
|
1030
1057
|
};
|
|
1031
1058
|
}
|
|
1032
1059
|
|
|
1033
|
-
const isRenderer = def => def &&
|
|
1060
|
+
const isRenderer = def => !!(def != null && def.render);
|
|
1034
1061
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
1035
1062
|
function calculateDpr(dpr) {
|
|
1036
1063
|
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
@@ -1058,11 +1085,11 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1058
1085
|
if (shadows) {
|
|
1059
1086
|
gl.shadowMap.enabled = true;
|
|
1060
1087
|
if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
|
|
1061
|
-
} // Set color
|
|
1088
|
+
} // Set color preferences
|
|
1062
1089
|
|
|
1063
1090
|
|
|
1064
|
-
if (
|
|
1065
|
-
if (
|
|
1091
|
+
if (linear) gl.outputEncoding = THREE__namespace.LinearEncoding;
|
|
1092
|
+
if (flat) gl.toneMapping = THREE__namespace.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
|
|
1066
1093
|
|
|
1067
1094
|
if (frameloop === 'never') {
|
|
1068
1095
|
clock.stop();
|
|
@@ -1251,38 +1278,45 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1251
1278
|
}
|
|
1252
1279
|
}
|
|
1253
1280
|
};
|
|
1254
|
-
});
|
|
1281
|
+
});
|
|
1282
|
+
const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
|
|
1255
1283
|
|
|
1284
|
+
let oldSize = state.size;
|
|
1285
|
+
let oldDpr = state.viewport.dpr;
|
|
1256
1286
|
rootState.subscribe(() => {
|
|
1257
1287
|
const {
|
|
1258
1288
|
camera,
|
|
1259
1289
|
size,
|
|
1260
1290
|
viewport,
|
|
1261
1291
|
internal
|
|
1262
|
-
} = rootState.getState();
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
camera
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1292
|
+
} = rootState.getState();
|
|
1293
|
+
|
|
1294
|
+
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1295
|
+
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
1296
|
+
// Do not mess with the camera if it belongs to the user
|
|
1297
|
+
if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
|
|
1298
|
+
if (isOrthographicCamera(camera)) {
|
|
1299
|
+
camera.left = size.width / -2;
|
|
1300
|
+
camera.right = size.width / 2;
|
|
1301
|
+
camera.top = size.height / 2;
|
|
1302
|
+
camera.bottom = size.height / -2;
|
|
1303
|
+
} else {
|
|
1304
|
+
camera.aspect = size.width / size.height;
|
|
1305
|
+
}
|
|
1274
1306
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1307
|
+
camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
|
|
1308
|
+
// Update matrix world since the renderer is a frame late
|
|
1277
1309
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1310
|
+
camera.updateMatrixWorld();
|
|
1311
|
+
} // Update renderer
|
|
1280
1312
|
|
|
1281
1313
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1314
|
+
gl.setPixelRatio(viewport.dpr);
|
|
1315
|
+
gl.setSize(size.width, size.height);
|
|
1316
|
+
oldSize = size;
|
|
1317
|
+
oldDpr = viewport.dpr;
|
|
1318
|
+
}
|
|
1319
|
+
}); // Update size
|
|
1286
1320
|
|
|
1287
1321
|
if (size) state.setSize(size.width, size.height); // Invalidate on any change
|
|
1288
1322
|
|
|
@@ -1637,13 +1671,23 @@ const {
|
|
|
1637
1671
|
applyProps
|
|
1638
1672
|
} = createRenderer();
|
|
1639
1673
|
|
|
1640
|
-
const createRendererInstance = (gl, canvas) =>
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1674
|
+
const createRendererInstance = (gl, canvas) => {
|
|
1675
|
+
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1676
|
+
if (isRenderer(customRenderer)) return customRenderer;
|
|
1677
|
+
const renderer = new THREE__namespace.WebGLRenderer({
|
|
1678
|
+
powerPreference: 'high-performance',
|
|
1679
|
+
canvas: canvas,
|
|
1680
|
+
antialias: true,
|
|
1681
|
+
alpha: true,
|
|
1682
|
+
...gl
|
|
1683
|
+
}); // Set color management
|
|
1684
|
+
|
|
1685
|
+
renderer.outputEncoding = THREE__namespace.sRGBEncoding;
|
|
1686
|
+
renderer.toneMapping = THREE__namespace.ACESFilmicToneMapping; // Set gl props
|
|
1687
|
+
|
|
1688
|
+
if (gl) applyProps(renderer, gl);
|
|
1689
|
+
return renderer;
|
|
1690
|
+
};
|
|
1647
1691
|
|
|
1648
1692
|
function render(element, canvas, {
|
|
1649
1693
|
gl,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import create from 'zustand';
|
|
4
|
-
import shallow from 'zustand/shallow';
|
|
5
4
|
import Reconciler from 'react-reconciler';
|
|
6
5
|
import { unstable_now, unstable_runWithPriority, unstable_IdlePriority } from 'scheduler';
|
|
7
6
|
import { useAsset } from 'use-asset';
|
|
@@ -42,6 +41,23 @@ const is = {
|
|
|
42
41
|
function makeId(event) {
|
|
43
42
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
44
43
|
}
|
|
44
|
+
/** Release pointer captures.
|
|
45
|
+
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
|
|
50
|
+
const captureData = captures.get(obj);
|
|
51
|
+
|
|
52
|
+
if (captureData) {
|
|
53
|
+
captures.delete(obj); // If this was the last capturing object for this pointer
|
|
54
|
+
|
|
55
|
+
if (captures.size === 0) {
|
|
56
|
+
capturedMap.delete(pointerId);
|
|
57
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
45
61
|
|
|
46
62
|
function removeInteractivity(store, object) {
|
|
47
63
|
const {
|
|
@@ -55,6 +71,9 @@ function removeInteractivity(store, object) {
|
|
|
55
71
|
internal.hovered.delete(key);
|
|
56
72
|
}
|
|
57
73
|
});
|
|
74
|
+
internal.capturedMap.forEach((captures, pointerId) => {
|
|
75
|
+
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
76
|
+
});
|
|
58
77
|
}
|
|
59
78
|
function createEvents(store) {
|
|
60
79
|
const temp = new THREE.Vector3();
|
|
@@ -134,7 +153,7 @@ function createEvents(store) {
|
|
|
134
153
|
while (eventObject) {
|
|
135
154
|
var _r3f2;
|
|
136
155
|
|
|
137
|
-
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.
|
|
156
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...intersect,
|
|
138
157
|
eventObject
|
|
139
158
|
});
|
|
140
159
|
eventObject = eventObject.parent;
|
|
@@ -153,7 +172,9 @@ function createEvents(store) {
|
|
|
153
172
|
// intersect.
|
|
154
173
|
|
|
155
174
|
if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
|
|
156
|
-
|
|
175
|
+
for (let captureData of internal.capturedMap.get(event.pointerId).values()) {
|
|
176
|
+
intersections.push(captureData.intersection);
|
|
177
|
+
}
|
|
157
178
|
}
|
|
158
179
|
|
|
159
180
|
return intersections;
|
|
@@ -171,9 +192,6 @@ function createEvents(store) {
|
|
|
171
192
|
|
|
172
193
|
if (intersections.length) {
|
|
173
194
|
const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
|
|
174
|
-
|
|
175
|
-
const releasePointerCapture = id => event.target.releasePointerCapture(id);
|
|
176
|
-
|
|
177
195
|
const localState = {
|
|
178
196
|
stopped: false
|
|
179
197
|
};
|
|
@@ -186,23 +204,36 @@ function createEvents(store) {
|
|
|
186
204
|
};
|
|
187
205
|
|
|
188
206
|
const setPointerCapture = id => {
|
|
207
|
+
const captureData = {
|
|
208
|
+
intersection: hit,
|
|
209
|
+
target: event.target
|
|
210
|
+
};
|
|
211
|
+
|
|
189
212
|
if (internal.capturedMap.has(id)) {
|
|
190
213
|
// if the pointerId was previously captured, we add the hit to the
|
|
191
214
|
// event capturedMap.
|
|
192
|
-
internal.capturedMap.get(id).set(hit.eventObject,
|
|
215
|
+
internal.capturedMap.get(id).set(hit.eventObject, captureData);
|
|
193
216
|
} else {
|
|
194
217
|
// if the pointerId was not previously captured, we create a map
|
|
195
218
|
// containing the hitObject, and the hit. hitObject is used for
|
|
196
219
|
// faster access.
|
|
197
|
-
internal.capturedMap.set(id, new Map([[hit.eventObject,
|
|
220
|
+
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
198
221
|
} // Call the original event now
|
|
199
222
|
event.target.setPointerCapture(id);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const releasePointerCapture = id => {
|
|
226
|
+
const captures = internal.capturedMap.get(id);
|
|
227
|
+
|
|
228
|
+
if (captures) {
|
|
229
|
+
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
230
|
+
}
|
|
200
231
|
}; // Add native event props
|
|
201
232
|
|
|
202
233
|
|
|
203
|
-
let extractEventProps = {};
|
|
234
|
+
let extractEventProps = {}; // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
|
|
204
235
|
|
|
205
|
-
for (let prop in
|
|
236
|
+
for (let prop in event) {
|
|
206
237
|
let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
|
|
207
238
|
// called as event.nativeEvent.fn()
|
|
208
239
|
|
|
@@ -271,13 +302,12 @@ function createEvents(store) {
|
|
|
271
302
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
272
303
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
273
304
|
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
274
|
-
var _r3f3;
|
|
275
|
-
|
|
276
305
|
const eventObject = hoveredObj.eventObject;
|
|
277
|
-
const
|
|
306
|
+
const instance = eventObject.__r3f;
|
|
307
|
+
const handlers = instance == null ? void 0 : instance.handlers;
|
|
278
308
|
internal.hovered.delete(makeId(hoveredObj));
|
|
279
309
|
|
|
280
|
-
if (
|
|
310
|
+
if (instance != null && instance.eventCount) {
|
|
281
311
|
// Clear out intersects, they are outdated by now
|
|
282
312
|
const data = { ...hoveredObj,
|
|
283
313
|
intersections: hits || []
|
|
@@ -299,9 +329,8 @@ function createEvents(store) {
|
|
|
299
329
|
case 'onLostPointerCapture':
|
|
300
330
|
return event => {
|
|
301
331
|
if ('pointerId' in event) {
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
// indifferently deletes all capturing references.
|
|
332
|
+
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
333
|
+
// object that's getting removed.
|
|
305
334
|
store.getState().internal.capturedMap.delete(event.pointerId);
|
|
306
335
|
}
|
|
307
336
|
|
|
@@ -340,12 +369,11 @@ function createEvents(store) {
|
|
|
340
369
|
|
|
341
370
|
if (isPointerMove) cancelPointer(hits);
|
|
342
371
|
handleIntersects(hits, event, delta, data => {
|
|
343
|
-
var _r3f4;
|
|
344
|
-
|
|
345
372
|
const eventObject = data.eventObject;
|
|
346
|
-
const
|
|
373
|
+
const instance = eventObject.__r3f;
|
|
374
|
+
const handlers = instance == null ? void 0 : instance.handlers; // Check presence of handlers
|
|
347
375
|
|
|
348
|
-
if (!(
|
|
376
|
+
if (!(instance != null && instance.eventCount)) return;
|
|
349
377
|
|
|
350
378
|
if (isPointerMove) {
|
|
351
379
|
// Move event ...
|
|
@@ -388,9 +416,9 @@ function createEvents(store) {
|
|
|
388
416
|
|
|
389
417
|
function pointerMissed(event, objects) {
|
|
390
418
|
objects.forEach(object => {
|
|
391
|
-
var
|
|
419
|
+
var _r3f3;
|
|
392
420
|
|
|
393
|
-
return (
|
|
421
|
+
return (_r3f3 = object.__r3f) == null ? void 0 : _r3f3.handlers.onPointerMissed == null ? void 0 : _r3f3.handlers.onPointerMissed(event);
|
|
394
422
|
});
|
|
395
423
|
}
|
|
396
424
|
|
|
@@ -441,9 +469,8 @@ function prepare(object, state) {
|
|
|
441
469
|
instance.__r3f = {
|
|
442
470
|
root: null,
|
|
443
471
|
memoizedProps: {},
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
},
|
|
472
|
+
eventCount: 0,
|
|
473
|
+
handlers: {},
|
|
447
474
|
objects: [],
|
|
448
475
|
parent: null,
|
|
449
476
|
...state
|
|
@@ -504,7 +531,7 @@ function createRenderer(roots) {
|
|
|
504
531
|
}
|
|
505
532
|
|
|
506
533
|
function applyProps(instance, data) {
|
|
507
|
-
var _instance$__r3f3, _root$getState,
|
|
534
|
+
var _instance$__r3f3, _root$getState, _instance$__r3f4;
|
|
508
535
|
|
|
509
536
|
// Filter equals, events and reserved props
|
|
510
537
|
const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
@@ -514,7 +541,7 @@ function createRenderer(roots) {
|
|
|
514
541
|
memoized,
|
|
515
542
|
changes
|
|
516
543
|
} = isDiffSet(data) ? data : diffProps(instance, data);
|
|
517
|
-
const prevHandlers =
|
|
544
|
+
const prevHandlers = localState.eventCount; // Prepare memoized props
|
|
518
545
|
|
|
519
546
|
if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
|
|
520
547
|
changes.forEach(([key, value, isEvent, keys]) => {
|
|
@@ -553,7 +580,7 @@ function createRenderer(roots) {
|
|
|
553
580
|
|
|
554
581
|
if (isEvent) {
|
|
555
582
|
if (value) localState.handlers[key] = value;else delete localState.handlers[key];
|
|
556
|
-
localState.
|
|
583
|
+
localState.eventCount = Object.keys(localState.handlers).length;
|
|
557
584
|
} // Special treatment for objects with support for set/copy, and layers
|
|
558
585
|
else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE.Layers)) {
|
|
559
586
|
// If value is an array
|
|
@@ -583,16 +610,17 @@ function createRenderer(roots) {
|
|
|
583
610
|
invalidateInstance(instance);
|
|
584
611
|
});
|
|
585
612
|
|
|
586
|
-
if (rootState.internal && instance.raycast && prevHandlers !==
|
|
613
|
+
if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
587
614
|
// Pre-emptively remove the instance from the interaction manager
|
|
588
615
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
589
616
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
590
617
|
|
|
591
|
-
if (localState.
|
|
618
|
+
if (localState.eventCount) rootState.internal.interaction.push(instance);
|
|
592
619
|
} // Call the update lifecycle when it is being updated
|
|
593
620
|
|
|
594
621
|
|
|
595
622
|
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
623
|
+
return instance;
|
|
596
624
|
}
|
|
597
625
|
|
|
598
626
|
function invalidateInstance(instance) {
|
|
@@ -778,7 +806,7 @@ function createRenderer(roots) {
|
|
|
778
806
|
} else if (is.fun(detachFn)) {
|
|
779
807
|
detachFn(child, parentInstance);
|
|
780
808
|
}
|
|
781
|
-
} else if (child.isObject3D) {
|
|
809
|
+
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
782
810
|
var _child$__r3f;
|
|
783
811
|
|
|
784
812
|
parentInstance.remove(child); // Remove interactivity
|
|
@@ -996,7 +1024,7 @@ function createRenderer(roots) {
|
|
|
996
1024
|
};
|
|
997
1025
|
}
|
|
998
1026
|
|
|
999
|
-
const isRenderer = def => def &&
|
|
1027
|
+
const isRenderer = def => !!(def != null && def.render);
|
|
1000
1028
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
1001
1029
|
function calculateDpr(dpr) {
|
|
1002
1030
|
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
|
|
@@ -1024,11 +1052,11 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1024
1052
|
if (shadows) {
|
|
1025
1053
|
gl.shadowMap.enabled = true;
|
|
1026
1054
|
if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
1027
|
-
} // Set color
|
|
1055
|
+
} // Set color preferences
|
|
1028
1056
|
|
|
1029
1057
|
|
|
1030
|
-
if (
|
|
1031
|
-
if (
|
|
1058
|
+
if (linear) gl.outputEncoding = THREE.LinearEncoding;
|
|
1059
|
+
if (flat) gl.toneMapping = THREE.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
|
|
1032
1060
|
|
|
1033
1061
|
if (frameloop === 'never') {
|
|
1034
1062
|
clock.stop();
|
|
@@ -1217,38 +1245,45 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1217
1245
|
}
|
|
1218
1246
|
}
|
|
1219
1247
|
};
|
|
1220
|
-
});
|
|
1248
|
+
});
|
|
1249
|
+
const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
|
|
1221
1250
|
|
|
1251
|
+
let oldSize = state.size;
|
|
1252
|
+
let oldDpr = state.viewport.dpr;
|
|
1222
1253
|
rootState.subscribe(() => {
|
|
1223
1254
|
const {
|
|
1224
1255
|
camera,
|
|
1225
1256
|
size,
|
|
1226
1257
|
viewport,
|
|
1227
1258
|
internal
|
|
1228
|
-
} = rootState.getState();
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
camera
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1259
|
+
} = rootState.getState();
|
|
1260
|
+
|
|
1261
|
+
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1262
|
+
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
1263
|
+
// Do not mess with the camera if it belongs to the user
|
|
1264
|
+
if (!(internal.lastProps.camera instanceof THREE.Camera)) {
|
|
1265
|
+
if (isOrthographicCamera(camera)) {
|
|
1266
|
+
camera.left = size.width / -2;
|
|
1267
|
+
camera.right = size.width / 2;
|
|
1268
|
+
camera.top = size.height / 2;
|
|
1269
|
+
camera.bottom = size.height / -2;
|
|
1270
|
+
} else {
|
|
1271
|
+
camera.aspect = size.width / size.height;
|
|
1272
|
+
}
|
|
1240
1273
|
|
|
1241
|
-
|
|
1242
|
-
|
|
1274
|
+
camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
|
|
1275
|
+
// Update matrix world since the renderer is a frame late
|
|
1243
1276
|
|
|
1244
|
-
|
|
1245
|
-
|
|
1277
|
+
camera.updateMatrixWorld();
|
|
1278
|
+
} // Update renderer
|
|
1246
1279
|
|
|
1247
1280
|
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1281
|
+
gl.setPixelRatio(viewport.dpr);
|
|
1282
|
+
gl.setSize(size.width, size.height);
|
|
1283
|
+
oldSize = size;
|
|
1284
|
+
oldDpr = viewport.dpr;
|
|
1285
|
+
}
|
|
1286
|
+
}); // Update size
|
|
1252
1287
|
|
|
1253
1288
|
if (size) state.setSize(size.width, size.height); // Invalidate on any change
|
|
1254
1289
|
|
|
@@ -1603,13 +1638,23 @@ const {
|
|
|
1603
1638
|
applyProps
|
|
1604
1639
|
} = createRenderer();
|
|
1605
1640
|
|
|
1606
|
-
const createRendererInstance = (gl, canvas) =>
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1641
|
+
const createRendererInstance = (gl, canvas) => {
|
|
1642
|
+
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1643
|
+
if (isRenderer(customRenderer)) return customRenderer;
|
|
1644
|
+
const renderer = new THREE.WebGLRenderer({
|
|
1645
|
+
powerPreference: 'high-performance',
|
|
1646
|
+
canvas: canvas,
|
|
1647
|
+
antialias: true,
|
|
1648
|
+
alpha: true,
|
|
1649
|
+
...gl
|
|
1650
|
+
}); // Set color management
|
|
1651
|
+
|
|
1652
|
+
renderer.outputEncoding = THREE.sRGBEncoding;
|
|
1653
|
+
renderer.toneMapping = THREE.ACESFilmicToneMapping; // Set gl props
|
|
1654
|
+
|
|
1655
|
+
if (gl) applyProps(renderer, gl);
|
|
1656
|
+
return renderer;
|
|
1657
|
+
};
|
|
1613
1658
|
|
|
1614
1659
|
function render(element, canvas, {
|
|
1615
1660
|
gl,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// are you seeing an error that a default export doesn't exist but your source file has a default export?
|
|
2
|
+
// you should run `yarn` or `yarn preconstruct dev` if preconstruct dev isn't in your postinstall hook
|
|
3
|
+
|
|
4
|
+
// curious why you need to?
|
|
5
|
+
// this file exists so that you can import from the entrypoint normally
|
|
6
|
+
// except that it points to your source file and you don't need to run build constantly
|
|
7
|
+
// which means we need to re-export all of the modules from your source file
|
|
8
|
+
// and since export * doesn't include default exports, we need to read your source file
|
|
9
|
+
// to check for a default export and re-export it if it exists
|
|
10
|
+
// it's not ideal, but it works pretty well ¯\_(ツ)_/¯
|
|
11
|
+
export * from "../../src/native";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// this file might look strange and you might be wondering what it's for
|
|
3
|
+
// it's lets you import your source files by importing this entrypoint
|
|
4
|
+
// as you would import it if it was built with preconstruct build
|
|
5
|
+
// this file is slightly different to some others though
|
|
6
|
+
// it has a require hook which compiles your code with Babel
|
|
7
|
+
// this means that you don't have to set up @babel/register or anything like that
|
|
8
|
+
// but you can still require this module and it'll be compiled
|
|
9
|
+
|
|
10
|
+
// this bit of code imports the require hook and registers it
|
|
11
|
+
let unregister = require("../../../../node_modules/@preconstruct/hook").___internalHook(typeof __dirname === 'undefined' ? undefined : __dirname, "../../../..", "../..");
|
|
12
|
+
|
|
13
|
+
// this re-exports the source file
|
|
14
|
+
module.exports = require("../../src/native.tsx");
|
|
15
|
+
|
|
16
|
+
unregister();
|