@react-three/fiber 8.10.0 → 8.10.2
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 +12 -0
- package/dist/{index-d957aeb6.cjs.prod.js → index-661b9d11.cjs.prod.js} +408 -503
- package/dist/{index-4ea38fa1.cjs.dev.js → index-bf8a2906.cjs.dev.js} +408 -503
- package/dist/{index-27a1523b.esm.js → index-fb77d67d.esm.js} +408 -503
- package/dist/react-three-fiber.cjs.dev.js +20 -23
- package/dist/react-three-fiber.cjs.prod.js +20 -23
- package/dist/react-three-fiber.esm.js +21 -24
- package/native/dist/react-three-fiber-native.cjs.dev.js +36 -44
- package/native/dist/react-three-fiber-native.cjs.prod.js +36 -44
- package/native/dist/react-three-fiber-native.esm.js +37 -45
- package/package.json +1 -1
|
@@ -40,6 +40,7 @@ var threeTypes = /*#__PURE__*/Object.freeze({
|
|
|
40
40
|
var _window$document, _window$navigator;
|
|
41
41
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
42
42
|
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
43
|
+
|
|
43
44
|
/**
|
|
44
45
|
* An SSR-friendly useLayoutEffect.
|
|
45
46
|
*
|
|
@@ -49,7 +50,6 @@ const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
|
49
50
|
*
|
|
50
51
|
* @see https://github.com/facebook/react/issues/14927
|
|
51
52
|
*/
|
|
52
|
-
|
|
53
53
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' && ((_window$document = window.document) != null && _window$document.createElement || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === 'ReactNative') ? React__namespace.useLayoutEffect : React__namespace.useEffect;
|
|
54
54
|
function useMutableCallback(fn) {
|
|
55
55
|
const ref = React__namespace.useRef(fn);
|
|
@@ -66,40 +66,31 @@ function Block({
|
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
68
|
class ErrorBoundary extends React__namespace.Component {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
69
|
+
state = {
|
|
70
|
+
error: false
|
|
71
|
+
};
|
|
72
|
+
static getDerivedStateFromError = () => ({
|
|
73
|
+
error: true
|
|
74
|
+
});
|
|
76
75
|
componentDidCatch(err) {
|
|
77
76
|
this.props.set(err);
|
|
78
77
|
}
|
|
79
|
-
|
|
80
78
|
render() {
|
|
81
79
|
return this.state.error ? null : this.props.children;
|
|
82
80
|
}
|
|
83
|
-
|
|
84
81
|
}
|
|
85
|
-
|
|
86
|
-
ErrorBoundary.getDerivedStateFromError = () => ({
|
|
87
|
-
error: true
|
|
88
|
-
});
|
|
89
|
-
|
|
90
82
|
const DEFAULT = '__default';
|
|
91
83
|
const isDiffSet = def => def && !!def.memoized && !!def.changes;
|
|
92
84
|
function calculateDpr(dpr) {
|
|
93
85
|
const target = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
|
|
94
86
|
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
95
87
|
}
|
|
88
|
+
|
|
96
89
|
/**
|
|
97
90
|
* Returns instance root state
|
|
98
91
|
*/
|
|
99
|
-
|
|
100
92
|
const getRootState = obj => {
|
|
101
93
|
var _r3f;
|
|
102
|
-
|
|
103
94
|
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
|
|
104
95
|
};
|
|
105
96
|
// A collection of compare functions
|
|
@@ -111,68 +102,61 @@ const is = {
|
|
|
111
102
|
boo: a => typeof a === 'boolean',
|
|
112
103
|
und: a => a === void 0,
|
|
113
104
|
arr: a => Array.isArray(a),
|
|
114
|
-
|
|
115
105
|
equ(a, b, {
|
|
116
106
|
arrays = 'shallow',
|
|
117
107
|
objects = 'reference',
|
|
118
108
|
strict = true
|
|
119
109
|
} = {}) {
|
|
120
110
|
// Wrong type or one of the two undefined, doesn't match
|
|
121
|
-
if (typeof a !== typeof b || !!a !== !!b) return false;
|
|
122
|
-
|
|
111
|
+
if (typeof a !== typeof b || !!a !== !!b) return false;
|
|
112
|
+
// Atomic, just compare a against b
|
|
123
113
|
if (is.str(a) || is.num(a)) return a === b;
|
|
124
114
|
const isObj = is.obj(a);
|
|
125
115
|
if (isObj && objects === 'reference') return a === b;
|
|
126
116
|
const isArr = is.arr(a);
|
|
127
|
-
if (isArr && arrays === 'reference') return a === b;
|
|
128
|
-
|
|
129
|
-
if ((isArr || isObj) && a === b) return true;
|
|
130
|
-
|
|
117
|
+
if (isArr && arrays === 'reference') return a === b;
|
|
118
|
+
// Array or Object, shallow compare first to see if it's a match
|
|
119
|
+
if ((isArr || isObj) && a === b) return true;
|
|
120
|
+
// Last resort, go through keys
|
|
131
121
|
let i;
|
|
132
|
-
|
|
133
122
|
for (i in a) if (!(i in b)) return false;
|
|
134
|
-
|
|
135
123
|
for (i in strict ? b : a) if (a[i] !== b[i]) return false;
|
|
136
|
-
|
|
137
124
|
if (is.und(i)) {
|
|
138
125
|
if (isArr && a.length === 0 && b.length === 0) return true;
|
|
139
126
|
if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
|
|
140
127
|
if (a !== b) return false;
|
|
141
128
|
}
|
|
142
|
-
|
|
143
129
|
return true;
|
|
144
130
|
}
|
|
131
|
+
};
|
|
145
132
|
|
|
146
|
-
|
|
147
|
-
|
|
133
|
+
// Collects nodes and materials from a THREE.Object3D
|
|
148
134
|
function buildGraph(object) {
|
|
149
135
|
const data = {
|
|
150
136
|
nodes: {},
|
|
151
137
|
materials: {}
|
|
152
138
|
};
|
|
153
|
-
|
|
154
139
|
if (object) {
|
|
155
140
|
object.traverse(obj => {
|
|
156
141
|
if (obj.name) data.nodes[obj.name] = obj;
|
|
157
142
|
if (obj.material && !data.materials[obj.material.name]) data.materials[obj.material.name] = obj.material;
|
|
158
143
|
});
|
|
159
144
|
}
|
|
160
|
-
|
|
161
145
|
return data;
|
|
162
|
-
}
|
|
146
|
+
}
|
|
163
147
|
|
|
148
|
+
// Disposes an object and all its properties
|
|
164
149
|
function dispose(obj) {
|
|
165
150
|
if (obj.dispose && obj.type !== 'Scene') obj.dispose();
|
|
166
|
-
|
|
167
151
|
for (const p in obj) {
|
|
168
152
|
p.dispose == null ? void 0 : p.dispose();
|
|
169
153
|
delete obj[p];
|
|
170
154
|
}
|
|
171
|
-
}
|
|
155
|
+
}
|
|
172
156
|
|
|
157
|
+
// Each object in the scene carries a small LocalState descriptor
|
|
173
158
|
function prepare(object, state) {
|
|
174
159
|
const instance = object;
|
|
175
|
-
|
|
176
160
|
if (state != null && state.primitive || !instance.__r3f) {
|
|
177
161
|
instance.__r3f = {
|
|
178
162
|
type: '',
|
|
@@ -186,13 +170,10 @@ function prepare(object, state) {
|
|
|
186
170
|
...state
|
|
187
171
|
};
|
|
188
172
|
}
|
|
189
|
-
|
|
190
173
|
return object;
|
|
191
174
|
}
|
|
192
|
-
|
|
193
175
|
function resolve(instance, key) {
|
|
194
176
|
let target = instance;
|
|
195
|
-
|
|
196
177
|
if (key.includes('-')) {
|
|
197
178
|
const entries = key.split('-');
|
|
198
179
|
const last = entries.pop();
|
|
@@ -205,9 +186,9 @@ function resolve(instance, key) {
|
|
|
205
186
|
target,
|
|
206
187
|
key
|
|
207
188
|
};
|
|
208
|
-
}
|
|
209
|
-
|
|
189
|
+
}
|
|
210
190
|
|
|
191
|
+
// Checks if a dash-cased string ends with an integer
|
|
211
192
|
const INDEX_REGEX = /-\d+$/;
|
|
212
193
|
function attach(parent, child, type) {
|
|
213
194
|
if (is.str(type)) {
|
|
@@ -220,7 +201,6 @@ function attach(parent, child, type) {
|
|
|
220
201
|
} = resolve(parent, root);
|
|
221
202
|
if (!Array.isArray(target[key])) target[key] = [];
|
|
222
203
|
}
|
|
223
|
-
|
|
224
204
|
const {
|
|
225
205
|
target,
|
|
226
206
|
key
|
|
@@ -231,21 +211,21 @@ function attach(parent, child, type) {
|
|
|
231
211
|
}
|
|
232
212
|
function detach(parent, child, type) {
|
|
233
213
|
var _child$__r3f, _child$__r3f2;
|
|
234
|
-
|
|
235
214
|
if (is.str(type)) {
|
|
236
215
|
const {
|
|
237
216
|
target,
|
|
238
217
|
key
|
|
239
218
|
} = resolve(parent, type);
|
|
240
|
-
const previous = child.__r3f.previousAttach;
|
|
241
|
-
|
|
242
|
-
if (previous === undefined) delete target[key];
|
|
219
|
+
const previous = child.__r3f.previousAttach;
|
|
220
|
+
// When the previous value was undefined, it means the value was never set to begin with
|
|
221
|
+
if (previous === undefined) delete target[key];
|
|
222
|
+
// Otherwise set the previous value
|
|
243
223
|
else target[key] = previous;
|
|
244
224
|
} else (_child$__r3f = child.__r3f) == null ? void 0 : _child$__r3f.previousAttach == null ? void 0 : _child$__r3f.previousAttach(parent, child);
|
|
245
|
-
|
|
246
225
|
(_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
|
|
247
|
-
}
|
|
226
|
+
}
|
|
248
227
|
|
|
228
|
+
// This function prepares a set of changes to be applied to the instance
|
|
249
229
|
function diffProps(instance, {
|
|
250
230
|
children: cN,
|
|
251
231
|
key: kN,
|
|
@@ -258,39 +238,38 @@ function diffProps(instance, {
|
|
|
258
238
|
...previous
|
|
259
239
|
} = {}, remove = false) {
|
|
260
240
|
var _instance$__r3f;
|
|
261
|
-
|
|
262
241
|
const localState = (_instance$__r3f = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f : {};
|
|
263
242
|
const entries = Object.entries(props);
|
|
264
|
-
const changes = [];
|
|
243
|
+
const changes = [];
|
|
265
244
|
|
|
245
|
+
// Catch removed props, prepend them so they can be reset or removed
|
|
266
246
|
if (remove) {
|
|
267
247
|
const previousKeys = Object.keys(previous);
|
|
268
|
-
|
|
269
248
|
for (let i = 0; i < previousKeys.length; i++) {
|
|
270
249
|
if (!props.hasOwnProperty(previousKeys[i])) entries.unshift([previousKeys[i], DEFAULT + 'remove']);
|
|
271
250
|
}
|
|
272
251
|
}
|
|
273
|
-
|
|
274
252
|
entries.forEach(([key, value]) => {
|
|
275
253
|
var _instance$__r3f2;
|
|
276
|
-
|
|
277
254
|
// Bail out on primitive object
|
|
278
|
-
if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return;
|
|
279
|
-
|
|
280
|
-
if (is.equ(value, previous[key])) return;
|
|
281
|
-
|
|
282
|
-
if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, []]);
|
|
283
|
-
|
|
255
|
+
if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return;
|
|
256
|
+
// When props match bail out
|
|
257
|
+
if (is.equ(value, previous[key])) return;
|
|
258
|
+
// Collect handlers and bail out
|
|
259
|
+
if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, []]);
|
|
260
|
+
// Split dashed props
|
|
284
261
|
let entries = [];
|
|
285
262
|
if (key.includes('-')) entries = key.split('-');
|
|
286
|
-
changes.push([key, value, false, entries]);
|
|
263
|
+
changes.push([key, value, false, entries]);
|
|
287
264
|
|
|
265
|
+
// Reset pierced props
|
|
288
266
|
for (const prop in props) {
|
|
289
267
|
const value = props[prop];
|
|
290
268
|
if (prop.startsWith(`${key}-`)) changes.push([prop, value, false, prop.split('-')]);
|
|
291
269
|
}
|
|
292
270
|
});
|
|
293
|
-
const memoized = {
|
|
271
|
+
const memoized = {
|
|
272
|
+
...props
|
|
294
273
|
};
|
|
295
274
|
if (localState.memoizedProps && localState.memoizedProps.args) memoized.args = localState.memoizedProps.args;
|
|
296
275
|
if (localState.memoizedProps && localState.memoizedProps.attach) memoized.attach = localState.memoizedProps.attach;
|
|
@@ -298,11 +277,11 @@ function diffProps(instance, {
|
|
|
298
277
|
memoized,
|
|
299
278
|
changes
|
|
300
279
|
};
|
|
301
|
-
}
|
|
280
|
+
}
|
|
302
281
|
|
|
282
|
+
// This function applies a set of changes to the instance
|
|
303
283
|
function applyProps$1(instance, data) {
|
|
304
284
|
var _instance$__r3f3, _root$getState, _instance$__r3f4;
|
|
305
|
-
|
|
306
285
|
// Filter equals, events and reserved props
|
|
307
286
|
const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
308
287
|
const root = localState.root;
|
|
@@ -311,104 +290,102 @@ function applyProps$1(instance, data) {
|
|
|
311
290
|
memoized,
|
|
312
291
|
changes
|
|
313
292
|
} = isDiffSet(data) ? data : diffProps(instance, data);
|
|
314
|
-
const prevHandlers = localState.eventCount;
|
|
293
|
+
const prevHandlers = localState.eventCount;
|
|
315
294
|
|
|
295
|
+
// Prepare memoized props
|
|
316
296
|
if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
|
|
317
|
-
|
|
318
297
|
for (let i = 0; i < changes.length; i++) {
|
|
319
298
|
let [key, value, isEvent, keys] = changes[i];
|
|
320
299
|
let currentInstance = instance;
|
|
321
|
-
let targetProp = currentInstance[key];
|
|
300
|
+
let targetProp = currentInstance[key];
|
|
322
301
|
|
|
302
|
+
// Revolve dashed props
|
|
323
303
|
if (keys.length) {
|
|
324
|
-
targetProp = keys.reduce((acc, key) => acc[key], instance);
|
|
325
|
-
|
|
304
|
+
targetProp = keys.reduce((acc, key) => acc[key], instance);
|
|
305
|
+
// If the target is atomic, it forces us to switch the root
|
|
326
306
|
if (!(targetProp && targetProp.set)) {
|
|
327
307
|
const [name, ...reverseEntries] = keys.reverse();
|
|
328
308
|
currentInstance = reverseEntries.reverse().reduce((acc, key) => acc[key], instance);
|
|
329
309
|
key = name;
|
|
330
310
|
}
|
|
331
|
-
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// https://github.com/mrdoob/three.js/issues/21209
|
|
332
314
|
// HMR/fast-refresh relies on the ability to cancel out props, but threejs
|
|
333
315
|
// has no means to do this. Hence we curate a small collection of value-classes
|
|
334
316
|
// with their respective constructor/set arguments
|
|
335
317
|
// For removed props, try to set default values, if possible
|
|
336
|
-
|
|
337
|
-
|
|
338
318
|
if (value === DEFAULT + 'remove') {
|
|
339
|
-
if (
|
|
340
|
-
var _memoized$args;
|
|
341
|
-
|
|
342
|
-
// use the prop constructor to find the default it should be
|
|
343
|
-
value = new targetProp.constructor(...((_memoized$args = memoized.args) != null ? _memoized$args : []));
|
|
344
|
-
} else if (currentInstance.constructor) {
|
|
319
|
+
if (currentInstance.constructor) {
|
|
345
320
|
var _currentInstance$__r;
|
|
346
|
-
|
|
347
321
|
// create a blank slate of the instance and copy the particular parameter.
|
|
348
322
|
// @ts-ignore
|
|
349
323
|
const defaultClassCall = new currentInstance.constructor(...((_currentInstance$__r = currentInstance.__r3f.memoizedProps.args) != null ? _currentInstance$__r : []));
|
|
350
|
-
value = defaultClassCall[
|
|
351
|
-
|
|
352
|
-
if (defaultClassCall.dispose) defaultClassCall.dispose();
|
|
324
|
+
value = defaultClassCall[key];
|
|
325
|
+
// destroy the instance
|
|
326
|
+
if (defaultClassCall.dispose) defaultClassCall.dispose();
|
|
353
327
|
} else {
|
|
328
|
+
// instance does not have constructor, just set it to 0
|
|
354
329
|
value = 0;
|
|
355
330
|
}
|
|
356
|
-
}
|
|
357
|
-
|
|
331
|
+
}
|
|
358
332
|
|
|
333
|
+
// Deal with pointer events ...
|
|
359
334
|
if (isEvent) {
|
|
360
335
|
if (value) localState.handlers[key] = value;else delete localState.handlers[key];
|
|
361
336
|
localState.eventCount = Object.keys(localState.handlers).length;
|
|
362
|
-
}
|
|
337
|
+
}
|
|
338
|
+
// Special treatment for objects with support for set/copy, and layers
|
|
363
339
|
else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE__namespace.Layers)) {
|
|
364
340
|
// If value is an array
|
|
365
341
|
if (Array.isArray(value)) {
|
|
366
342
|
if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
|
|
367
|
-
}
|
|
343
|
+
}
|
|
344
|
+
// Test again target.copy(class) next ...
|
|
368
345
|
else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) {
|
|
369
346
|
targetProp.copy(value);
|
|
370
|
-
}
|
|
347
|
+
}
|
|
348
|
+
// If nothing else fits, just set the single value, ignore undefined
|
|
371
349
|
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
372
350
|
else if (value !== undefined) {
|
|
373
|
-
const isColor = targetProp instanceof THREE__namespace.Color;
|
|
374
|
-
|
|
375
|
-
if (!isColor && targetProp.setScalar) targetProp.setScalar(value);
|
|
376
|
-
|
|
377
|
-
else targetProp
|
|
351
|
+
const isColor = targetProp instanceof THREE__namespace.Color;
|
|
352
|
+
// Allow setting array scalars
|
|
353
|
+
if (!isColor && targetProp.setScalar) targetProp.setScalar(value);
|
|
354
|
+
// Layers have no copy function, we must therefore copy the mask property
|
|
355
|
+
else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask;
|
|
356
|
+
// Otherwise just set ...
|
|
357
|
+
else targetProp.set(value);
|
|
358
|
+
// For versions of three which don't support THREE.ColorManagement,
|
|
378
359
|
// Auto-convert sRGB colors
|
|
379
360
|
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
380
|
-
|
|
381
361
|
const supportsColorManagement = ('ColorManagement' in THREE__namespace);
|
|
382
362
|
if (!supportsColorManagement && !rootState.linear && isColor) targetProp.convertSRGBToLinear();
|
|
383
|
-
}
|
|
384
|
-
|
|
363
|
+
}
|
|
364
|
+
// Else, just overwrite the value
|
|
385
365
|
} else {
|
|
386
|
-
currentInstance[key] = value;
|
|
366
|
+
currentInstance[key] = value;
|
|
367
|
+
// Auto-convert sRGB textures, for now ...
|
|
387
368
|
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
388
|
-
|
|
389
369
|
if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) {
|
|
390
370
|
currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
|
|
391
371
|
}
|
|
392
372
|
}
|
|
393
|
-
|
|
394
373
|
invalidateInstance(instance);
|
|
395
374
|
}
|
|
396
|
-
|
|
397
375
|
if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
398
376
|
// Pre-emptively remove the instance from the interaction manager
|
|
399
377
|
const index = rootState.internal.interaction.indexOf(instance);
|
|
400
|
-
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
401
|
-
|
|
378
|
+
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
379
|
+
// Add the instance to the interaction manager only when it has handlers
|
|
402
380
|
if (localState.eventCount) rootState.internal.interaction.push(instance);
|
|
403
|
-
}
|
|
404
|
-
|
|
381
|
+
}
|
|
405
382
|
|
|
383
|
+
// Call the update lifecycle when it is being updated, but only when it is part of the scene
|
|
406
384
|
if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
|
|
407
385
|
return instance;
|
|
408
386
|
}
|
|
409
387
|
function invalidateInstance(instance) {
|
|
410
388
|
var _instance$__r3f5, _instance$__r3f5$root;
|
|
411
|
-
|
|
412
389
|
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();
|
|
413
390
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
414
391
|
}
|
|
@@ -427,17 +404,16 @@ function updateCamera(camera, size) {
|
|
|
427
404
|
} else {
|
|
428
405
|
camera.aspect = size.width / size.height;
|
|
429
406
|
}
|
|
430
|
-
|
|
431
|
-
|
|
407
|
+
camera.updateProjectionMatrix();
|
|
408
|
+
// https://github.com/pmndrs/react-three-fiber/issues/178
|
|
432
409
|
// Update matrix world since the renderer is a frame late
|
|
433
|
-
|
|
434
410
|
camera.updateMatrixWorld();
|
|
435
411
|
}
|
|
436
412
|
}
|
|
413
|
+
|
|
437
414
|
/**
|
|
438
415
|
* Safely sets a deeply-nested value on an object.
|
|
439
416
|
*/
|
|
440
|
-
|
|
441
417
|
function setDeep(obj, value, keys) {
|
|
442
418
|
const key = keys.pop();
|
|
443
419
|
const target = keys.reduce((acc, key) => acc[key], obj);
|
|
@@ -446,19 +422,17 @@ function setDeep(obj, value, keys) {
|
|
|
446
422
|
|
|
447
423
|
function makeId(event) {
|
|
448
424
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
449
|
-
}
|
|
450
|
-
// Gives React a clue as to how import the current interaction is
|
|
451
|
-
|
|
425
|
+
}
|
|
452
426
|
|
|
427
|
+
// https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
|
|
428
|
+
// Gives React a clue as to how import the current interaction is
|
|
453
429
|
function getEventPriority() {
|
|
454
430
|
var _globalScope$event;
|
|
455
|
-
|
|
456
431
|
// Get a handle to the current global scope in window and worker contexts if able
|
|
457
432
|
// https://github.com/pmndrs/react-three-fiber/pull/2493
|
|
458
433
|
const globalScope = typeof self !== 'undefined' && self || typeof window !== 'undefined' && window;
|
|
459
434
|
if (!globalScope) return constants.DefaultEventPriority;
|
|
460
435
|
const name = (_globalScope$event = globalScope.event) == null ? void 0 : _globalScope$event.type;
|
|
461
|
-
|
|
462
436
|
switch (name) {
|
|
463
437
|
case 'click':
|
|
464
438
|
case 'contextmenu':
|
|
@@ -467,7 +441,6 @@ function getEventPriority() {
|
|
|
467
441
|
case 'pointerdown':
|
|
468
442
|
case 'pointerup':
|
|
469
443
|
return constants.DiscreteEventPriority;
|
|
470
|
-
|
|
471
444
|
case 'pointermove':
|
|
472
445
|
case 'pointerout':
|
|
473
446
|
case 'pointerover':
|
|
@@ -475,34 +448,31 @@ function getEventPriority() {
|
|
|
475
448
|
case 'pointerleave':
|
|
476
449
|
case 'wheel':
|
|
477
450
|
return constants.ContinuousEventPriority;
|
|
478
|
-
|
|
479
451
|
default:
|
|
480
452
|
return constants.DefaultEventPriority;
|
|
481
453
|
}
|
|
482
454
|
}
|
|
455
|
+
|
|
483
456
|
/**
|
|
484
457
|
* Release pointer captures.
|
|
485
458
|
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
486
459
|
*/
|
|
487
|
-
|
|
488
460
|
function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
|
|
489
461
|
const captureData = captures.get(obj);
|
|
490
|
-
|
|
491
462
|
if (captureData) {
|
|
492
|
-
captures.delete(obj);
|
|
493
|
-
|
|
463
|
+
captures.delete(obj);
|
|
464
|
+
// If this was the last capturing object for this pointer
|
|
494
465
|
if (captures.size === 0) {
|
|
495
466
|
capturedMap.delete(pointerId);
|
|
496
467
|
captureData.target.releasePointerCapture(pointerId);
|
|
497
468
|
}
|
|
498
469
|
}
|
|
499
470
|
}
|
|
500
|
-
|
|
501
471
|
function removeInteractivity(store, object) {
|
|
502
472
|
const {
|
|
503
473
|
internal
|
|
504
|
-
} = store.getState();
|
|
505
|
-
|
|
474
|
+
} = store.getState();
|
|
475
|
+
// Removes every trace of an object from the data store
|
|
506
476
|
internal.interaction = internal.interaction.filter(o => o !== object);
|
|
507
477
|
internal.initialHits = internal.initialHits.filter(o => o !== object);
|
|
508
478
|
internal.hovered.forEach((value, key) => {
|
|
@@ -525,106 +495,103 @@ function createEvents(store) {
|
|
|
525
495
|
const dy = event.offsetY - internal.initialClick[1];
|
|
526
496
|
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
527
497
|
}
|
|
528
|
-
/** Returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc */
|
|
529
|
-
|
|
530
498
|
|
|
499
|
+
/** Returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc */
|
|
531
500
|
function filterPointerEvents(objects) {
|
|
532
501
|
return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name => {
|
|
533
502
|
var _r3f;
|
|
534
|
-
|
|
535
503
|
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.handlers['onPointer' + name];
|
|
536
504
|
}));
|
|
537
505
|
}
|
|
538
|
-
|
|
539
506
|
function intersect(event, filter) {
|
|
540
507
|
const state = store.getState();
|
|
541
508
|
const duplicates = new Set();
|
|
542
|
-
const intersections = [];
|
|
543
|
-
|
|
544
|
-
const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction;
|
|
545
|
-
|
|
509
|
+
const intersections = [];
|
|
510
|
+
// Allow callers to eliminate event objects
|
|
511
|
+
const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction;
|
|
512
|
+
// Reset all raycaster cameras to undefined
|
|
546
513
|
for (let i = 0; i < eventsObjects.length; i++) {
|
|
547
514
|
const state = getRootState(eventsObjects[i]);
|
|
548
|
-
|
|
549
515
|
if (state) {
|
|
550
516
|
state.raycaster.camera = undefined;
|
|
551
517
|
}
|
|
552
518
|
}
|
|
553
|
-
|
|
554
519
|
if (!state.previousRoot) {
|
|
555
520
|
// Make sure root-level pointer and ray are set up
|
|
556
521
|
state.events.compute == null ? void 0 : state.events.compute(event, state);
|
|
557
522
|
}
|
|
558
|
-
|
|
559
523
|
function handleRaycast(obj) {
|
|
560
|
-
const state = getRootState(obj);
|
|
561
|
-
|
|
562
|
-
if (!state || !state.events.enabled || state.raycaster.camera === null) return [];
|
|
524
|
+
const state = getRootState(obj);
|
|
525
|
+
// Skip event handling when noEvents is set, or when the raycasters camera is null
|
|
526
|
+
if (!state || !state.events.enabled || state.raycaster.camera === null) return [];
|
|
563
527
|
|
|
528
|
+
// When the camera is undefined we have to call the event layers update function
|
|
564
529
|
if (state.raycaster.camera === undefined) {
|
|
565
530
|
var _state$previousRoot;
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
531
|
+
state.events.compute == null ? void 0 : state.events.compute(event, state, (_state$previousRoot = state.previousRoot) == null ? void 0 : _state$previousRoot.getState());
|
|
532
|
+
// If the camera is still undefined we have to skip this layer entirely
|
|
569
533
|
if (state.raycaster.camera === undefined) state.raycaster.camera = null;
|
|
570
|
-
}
|
|
571
|
-
|
|
534
|
+
}
|
|
572
535
|
|
|
536
|
+
// Intersect object by object
|
|
573
537
|
return state.raycaster.camera ? state.raycaster.intersectObject(obj, true) : [];
|
|
574
|
-
}
|
|
575
|
-
|
|
538
|
+
}
|
|
576
539
|
|
|
577
|
-
|
|
578
|
-
|
|
540
|
+
// Collect events
|
|
541
|
+
let hits = eventsObjects
|
|
542
|
+
// Intersect objects
|
|
543
|
+
.flatMap(handleRaycast)
|
|
544
|
+
// Sort by event priority and distance
|
|
579
545
|
.sort((a, b) => {
|
|
580
546
|
const aState = getRootState(a.object);
|
|
581
547
|
const bState = getRootState(b.object);
|
|
582
548
|
if (!aState || !bState) return a.distance - b.distance;
|
|
583
549
|
return bState.events.priority - aState.events.priority || a.distance - b.distance;
|
|
584
|
-
})
|
|
550
|
+
})
|
|
551
|
+
// Filter out duplicates
|
|
585
552
|
.filter(item => {
|
|
586
553
|
const id = makeId(item);
|
|
587
554
|
if (duplicates.has(id)) return false;
|
|
588
555
|
duplicates.add(id);
|
|
589
556
|
return true;
|
|
590
|
-
});
|
|
591
|
-
// Allow custom userland intersect sort order, this likely only makes sense on the root filter
|
|
557
|
+
});
|
|
592
558
|
|
|
593
|
-
|
|
559
|
+
// https://github.com/mrdoob/three.js/issues/16031
|
|
560
|
+
// Allow custom userland intersect sort order, this likely only makes sense on the root filter
|
|
561
|
+
if (state.events.filter) hits = state.events.filter(hits, state);
|
|
594
562
|
|
|
563
|
+
// Bubble up the events, find the event source (eventObject)
|
|
595
564
|
for (const hit of hits) {
|
|
596
|
-
let eventObject = hit.object;
|
|
597
|
-
|
|
565
|
+
let eventObject = hit.object;
|
|
566
|
+
// Bubble event up
|
|
598
567
|
while (eventObject) {
|
|
599
568
|
var _r3f2;
|
|
600
|
-
|
|
601
|
-
|
|
569
|
+
if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({
|
|
570
|
+
...hit,
|
|
602
571
|
eventObject
|
|
603
572
|
});
|
|
604
573
|
eventObject = eventObject.parent;
|
|
605
574
|
}
|
|
606
|
-
}
|
|
607
|
-
|
|
575
|
+
}
|
|
608
576
|
|
|
577
|
+
// If the interaction is captured, make all capturing targets part of the intersect.
|
|
609
578
|
if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
|
|
610
579
|
for (let captureData of state.internal.capturedMap.get(event.pointerId).values()) {
|
|
611
580
|
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
612
581
|
}
|
|
613
582
|
}
|
|
614
|
-
|
|
615
583
|
return intersections;
|
|
616
584
|
}
|
|
617
|
-
/** Handles intersections by forwarding them to handlers */
|
|
618
|
-
|
|
619
585
|
|
|
586
|
+
/** Handles intersections by forwarding them to handlers */
|
|
620
587
|
function handleIntersects(intersections, event, delta, callback) {
|
|
621
|
-
const rootState = store.getState();
|
|
588
|
+
const rootState = store.getState();
|
|
622
589
|
|
|
590
|
+
// If anything has been found, forward it to the event listeners
|
|
623
591
|
if (intersections.length) {
|
|
624
592
|
const localState = {
|
|
625
593
|
stopped: false
|
|
626
594
|
};
|
|
627
|
-
|
|
628
595
|
for (const hit of intersections) {
|
|
629
596
|
const state = getRootState(hit.object) || rootState;
|
|
630
597
|
const {
|
|
@@ -634,19 +601,15 @@ function createEvents(store) {
|
|
|
634
601
|
internal
|
|
635
602
|
} = state;
|
|
636
603
|
const unprojectedPoint = new THREE__namespace.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
637
|
-
|
|
638
604
|
const hasPointerCapture = id => {
|
|
639
605
|
var _internal$capturedMap, _internal$capturedMap2;
|
|
640
|
-
|
|
641
606
|
return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
|
|
642
607
|
};
|
|
643
|
-
|
|
644
608
|
const setPointerCapture = id => {
|
|
645
609
|
const captureData = {
|
|
646
610
|
intersection: hit,
|
|
647
611
|
target: event.target
|
|
648
612
|
};
|
|
649
|
-
|
|
650
613
|
if (internal.capturedMap.has(id)) {
|
|
651
614
|
// if the pointerId was previously captured, we add the hit to the
|
|
652
615
|
// event capturedMap.
|
|
@@ -656,29 +619,27 @@ function createEvents(store) {
|
|
|
656
619
|
// containing the hitObject, and the hit. hitObject is used for
|
|
657
620
|
// faster access.
|
|
658
621
|
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
659
|
-
}
|
|
622
|
+
}
|
|
660
623
|
event.target.setPointerCapture(id);
|
|
661
624
|
};
|
|
662
|
-
|
|
663
625
|
const releasePointerCapture = id => {
|
|
664
626
|
const captures = internal.capturedMap.get(id);
|
|
665
|
-
|
|
666
627
|
if (captures) {
|
|
667
628
|
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
668
629
|
}
|
|
669
|
-
};
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
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.
|
|
630
|
+
};
|
|
673
631
|
|
|
632
|
+
// Add native event props
|
|
633
|
+
let extractEventProps = {};
|
|
634
|
+
// 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.
|
|
674
635
|
for (let prop in event) {
|
|
675
|
-
let property = event[prop];
|
|
636
|
+
let property = event[prop];
|
|
637
|
+
// Only copy over atomics, leave functions alone as these should be
|
|
676
638
|
// called as event.nativeEvent.fn()
|
|
677
|
-
|
|
678
639
|
if (typeof property !== 'function') extractEventProps[prop] = property;
|
|
679
640
|
}
|
|
680
|
-
|
|
681
|
-
|
|
641
|
+
let raycastEvent = {
|
|
642
|
+
...hit,
|
|
682
643
|
...extractEventProps,
|
|
683
644
|
pointer,
|
|
684
645
|
intersections,
|
|
@@ -687,19 +648,21 @@ function createEvents(store) {
|
|
|
687
648
|
unprojectedPoint,
|
|
688
649
|
ray: raycaster.ray,
|
|
689
650
|
camera: camera,
|
|
690
|
-
|
|
691
651
|
// Hijack stopPropagation, which just sets a flag
|
|
692
652
|
stopPropagation() {
|
|
693
653
|
// https://github.com/pmndrs/react-three-fiber/issues/596
|
|
694
654
|
// Events are not allowed to stop propagation if the pointer has been captured
|
|
695
|
-
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
|
|
655
|
+
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
|
|
696
656
|
|
|
697
|
-
|
|
698
|
-
|
|
657
|
+
// We only authorize stopPropagation...
|
|
658
|
+
if (
|
|
659
|
+
// ...if this pointer hasn't been captured
|
|
660
|
+
!capturesForPointer ||
|
|
661
|
+
// ... or if the hit object is capturing the pointer
|
|
699
662
|
capturesForPointer.has(hit.eventObject)) {
|
|
700
|
-
raycastEvent.stopped = localState.stopped = true;
|
|
663
|
+
raycastEvent.stopped = localState.stopped = true;
|
|
664
|
+
// Propagation is stopped, remove all other hover records
|
|
701
665
|
// An event handler is only allowed to flush other handlers if it is hovered itself
|
|
702
|
-
|
|
703
666
|
if (internal.hovered.size && Array.from(internal.hovered.values()).find(i => i.eventObject === hit.eventObject)) {
|
|
704
667
|
// Objects cannot flush out higher up objects that have already caught the event
|
|
705
668
|
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
@@ -707,7 +670,6 @@ function createEvents(store) {
|
|
|
707
670
|
}
|
|
708
671
|
}
|
|
709
672
|
},
|
|
710
|
-
|
|
711
673
|
// there should be a distinction between target and currentTarget
|
|
712
674
|
target: {
|
|
713
675
|
hasPointerCapture,
|
|
@@ -720,22 +682,20 @@ function createEvents(store) {
|
|
|
720
682
|
releasePointerCapture
|
|
721
683
|
},
|
|
722
684
|
nativeEvent: event
|
|
723
|
-
};
|
|
724
|
-
|
|
725
|
-
callback(raycastEvent); // Event bubbling may be interrupted by stopPropagation
|
|
685
|
+
};
|
|
726
686
|
|
|
687
|
+
// Call subscribers
|
|
688
|
+
callback(raycastEvent);
|
|
689
|
+
// Event bubbling may be interrupted by stopPropagation
|
|
727
690
|
if (localState.stopped === true) break;
|
|
728
691
|
}
|
|
729
692
|
}
|
|
730
|
-
|
|
731
693
|
return intersections;
|
|
732
694
|
}
|
|
733
|
-
|
|
734
695
|
function cancelPointer(intersections) {
|
|
735
696
|
const {
|
|
736
697
|
internal
|
|
737
698
|
} = store.getState();
|
|
738
|
-
|
|
739
699
|
for (const hoveredObj of internal.hovered.values()) {
|
|
740
700
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
741
701
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
@@ -744,10 +704,10 @@ function createEvents(store) {
|
|
|
744
704
|
const instance = eventObject.__r3f;
|
|
745
705
|
const handlers = instance == null ? void 0 : instance.handlers;
|
|
746
706
|
internal.hovered.delete(makeId(hoveredObj));
|
|
747
|
-
|
|
748
707
|
if (instance != null && instance.eventCount) {
|
|
749
708
|
// Clear out intersects, they are outdated by now
|
|
750
|
-
const data = {
|
|
709
|
+
const data = {
|
|
710
|
+
...hoveredObj,
|
|
751
711
|
intersections
|
|
752
712
|
};
|
|
753
713
|
handlers.onPointerOut == null ? void 0 : handlers.onPointerOut(data);
|
|
@@ -756,27 +716,23 @@ function createEvents(store) {
|
|
|
756
716
|
}
|
|
757
717
|
}
|
|
758
718
|
}
|
|
759
|
-
|
|
760
719
|
function pointerMissed(event, objects) {
|
|
761
720
|
for (let i = 0; i < objects.length; i++) {
|
|
762
721
|
const instance = objects[i].__r3f;
|
|
763
722
|
instance == null ? void 0 : instance.handlers.onPointerMissed == null ? void 0 : instance.handlers.onPointerMissed(event);
|
|
764
723
|
}
|
|
765
724
|
}
|
|
766
|
-
|
|
767
725
|
function handlePointer(name) {
|
|
768
726
|
// Deal with cancelation
|
|
769
727
|
switch (name) {
|
|
770
728
|
case 'onPointerLeave':
|
|
771
729
|
case 'onPointerCancel':
|
|
772
730
|
return () => cancelPointer([]);
|
|
773
|
-
|
|
774
731
|
case 'onLostPointerCapture':
|
|
775
732
|
return event => {
|
|
776
733
|
const {
|
|
777
734
|
internal
|
|
778
735
|
} = store.getState();
|
|
779
|
-
|
|
780
736
|
if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
|
|
781
737
|
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
782
738
|
// object that's getting removed.
|
|
@@ -784,55 +740,54 @@ function createEvents(store) {
|
|
|
784
740
|
cancelPointer([]);
|
|
785
741
|
}
|
|
786
742
|
};
|
|
787
|
-
}
|
|
788
|
-
|
|
743
|
+
}
|
|
789
744
|
|
|
745
|
+
// Any other pointer goes here ...
|
|
790
746
|
return function handleEvent(event) {
|
|
791
747
|
const {
|
|
792
748
|
onPointerMissed,
|
|
793
749
|
internal
|
|
794
|
-
} = store.getState();
|
|
750
|
+
} = store.getState();
|
|
795
751
|
|
|
796
|
-
|
|
752
|
+
// prepareRay(event)
|
|
753
|
+
internal.lastEvent.current = event;
|
|
797
754
|
|
|
755
|
+
// Get fresh intersects
|
|
798
756
|
const isPointerMove = name === 'onPointerMove';
|
|
799
757
|
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
800
|
-
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
801
|
-
|
|
758
|
+
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
802
759
|
const hits = intersect(event, filter);
|
|
803
|
-
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
760
|
+
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
804
761
|
|
|
762
|
+
// Save initial coordinates on pointer-down
|
|
805
763
|
if (name === 'onPointerDown') {
|
|
806
764
|
internal.initialClick = [event.offsetX, event.offsetY];
|
|
807
765
|
internal.initialHits = hits.map(hit => hit.eventObject);
|
|
808
|
-
}
|
|
809
|
-
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
810
|
-
|
|
766
|
+
}
|
|
811
767
|
|
|
768
|
+
// If a click yields no results, pass it back to the user as a miss
|
|
769
|
+
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
812
770
|
if (isClickEvent && !hits.length) {
|
|
813
771
|
if (delta <= 2) {
|
|
814
772
|
pointerMissed(event, internal.interaction);
|
|
815
773
|
if (onPointerMissed) onPointerMissed(event);
|
|
816
774
|
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
|
|
775
|
+
}
|
|
776
|
+
// Take care of unhover
|
|
820
777
|
if (isPointerMove) cancelPointer(hits);
|
|
821
|
-
|
|
822
778
|
function onIntersect(data) {
|
|
823
779
|
const eventObject = data.eventObject;
|
|
824
780
|
const instance = eventObject.__r3f;
|
|
825
|
-
const handlers = instance == null ? void 0 : instance.handlers;
|
|
781
|
+
const handlers = instance == null ? void 0 : instance.handlers;
|
|
826
782
|
|
|
783
|
+
// Check presence of handlers
|
|
827
784
|
if (!(instance != null && instance.eventCount)) return;
|
|
828
|
-
|
|
829
785
|
if (isPointerMove) {
|
|
830
786
|
// Move event ...
|
|
831
787
|
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
832
788
|
// When enter or out is present take care of hover-state
|
|
833
789
|
const id = makeId(data);
|
|
834
790
|
const hoveredItem = internal.hovered.get(id);
|
|
835
|
-
|
|
836
791
|
if (!hoveredItem) {
|
|
837
792
|
// If the object wasn't previously hovered, book it and call its handler
|
|
838
793
|
internal.hovered.set(id, data);
|
|
@@ -842,21 +797,19 @@ function createEvents(store) {
|
|
|
842
797
|
// If the object was previously hovered and stopped, we shouldn't allow other items to proceed
|
|
843
798
|
data.stopPropagation();
|
|
844
799
|
}
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
|
|
800
|
+
}
|
|
801
|
+
// Call mouse move
|
|
848
802
|
handlers.onPointerMove == null ? void 0 : handlers.onPointerMove(data);
|
|
849
803
|
} else {
|
|
850
804
|
// All other events ...
|
|
851
805
|
const handler = handlers[name];
|
|
852
|
-
|
|
853
806
|
if (handler) {
|
|
854
807
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
855
808
|
// which must use the initial target
|
|
856
809
|
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
857
810
|
// Missed events have to come first
|
|
858
|
-
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
859
|
-
|
|
811
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
812
|
+
// Now call the handler
|
|
860
813
|
handler(data);
|
|
861
814
|
}
|
|
862
815
|
} else {
|
|
@@ -867,22 +820,19 @@ function createEvents(store) {
|
|
|
867
820
|
}
|
|
868
821
|
}
|
|
869
822
|
}
|
|
870
|
-
|
|
871
823
|
handleIntersects(hits, event, delta, onIntersect);
|
|
872
824
|
};
|
|
873
825
|
}
|
|
874
|
-
|
|
875
826
|
return {
|
|
876
827
|
handlePointer
|
|
877
828
|
};
|
|
878
829
|
}
|
|
879
830
|
|
|
880
831
|
let catalogue = {};
|
|
881
|
-
|
|
882
|
-
|
|
832
|
+
let extend = objects => void (catalogue = {
|
|
833
|
+
...catalogue,
|
|
883
834
|
...objects
|
|
884
835
|
});
|
|
885
|
-
|
|
886
836
|
function createRenderer(_roots, _getEventPriority) {
|
|
887
837
|
function createInstance(type, {
|
|
888
838
|
args = [],
|
|
@@ -891,7 +841,6 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
891
841
|
}, root) {
|
|
892
842
|
let name = `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
893
843
|
let instance;
|
|
894
|
-
|
|
895
844
|
if (type === 'primitive') {
|
|
896
845
|
if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
|
|
897
846
|
const object = props.object;
|
|
@@ -903,15 +852,15 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
903
852
|
});
|
|
904
853
|
} else {
|
|
905
854
|
const target = catalogue[name];
|
|
906
|
-
|
|
907
855
|
if (!target) {
|
|
908
856
|
throw new Error(`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`);
|
|
909
|
-
}
|
|
857
|
+
}
|
|
910
858
|
|
|
859
|
+
// Throw if an object or literal was passed for args
|
|
860
|
+
if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!');
|
|
911
861
|
|
|
912
|
-
|
|
862
|
+
// Instanciate new object, link it to the root
|
|
913
863
|
// Append memoized props with args so it's not forgotten
|
|
914
|
-
|
|
915
864
|
instance = prepare(new target(...args), {
|
|
916
865
|
type,
|
|
917
866
|
root,
|
|
@@ -921,27 +870,24 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
921
870
|
args
|
|
922
871
|
}
|
|
923
872
|
});
|
|
924
|
-
}
|
|
925
|
-
|
|
873
|
+
}
|
|
926
874
|
|
|
875
|
+
// Auto-attach geometries and materials
|
|
927
876
|
if (instance.__r3f.attach === undefined) {
|
|
928
877
|
if (instance instanceof THREE__namespace.BufferGeometry) instance.__r3f.attach = 'geometry';else if (instance instanceof THREE__namespace.Material) instance.__r3f.attach = 'material';
|
|
929
|
-
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// It should NOT call onUpdate on object instanciation, because it hasn't been added to the
|
|
930
881
|
// view yet. If the callback relies on references for instance, they won't be ready yet, this is
|
|
931
882
|
// why it passes "true" here
|
|
932
883
|
// There is no reason to apply props to injects
|
|
933
|
-
|
|
934
|
-
|
|
935
884
|
if (name !== 'inject') applyProps$1(instance, props);
|
|
936
885
|
return instance;
|
|
937
886
|
}
|
|
938
|
-
|
|
939
887
|
function appendChild(parentInstance, child) {
|
|
940
888
|
let added = false;
|
|
941
|
-
|
|
942
889
|
if (child) {
|
|
943
890
|
var _child$__r3f, _parentInstance$__r3f;
|
|
944
|
-
|
|
945
891
|
// The attach attribute implies that the object attaches itself on the parent
|
|
946
892
|
if ((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) {
|
|
947
893
|
attach(parentInstance, child, child.__r3f.attach);
|
|
@@ -949,10 +895,9 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
949
895
|
// add in the usual parent-child way
|
|
950
896
|
parentInstance.add(child);
|
|
951
897
|
added = true;
|
|
952
|
-
}
|
|
898
|
+
}
|
|
899
|
+
// This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
|
|
953
900
|
// that is, anything that's a child in React but not a child in the scenegraph.
|
|
954
|
-
|
|
955
|
-
|
|
956
901
|
if (!added) (_parentInstance$__r3f = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f.objects.push(child);
|
|
957
902
|
if (!child.__r3f) prepare(child, {});
|
|
958
903
|
child.__r3f.parent = parentInstance;
|
|
@@ -960,13 +905,10 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
960
905
|
invalidateInstance(child);
|
|
961
906
|
}
|
|
962
907
|
}
|
|
963
|
-
|
|
964
908
|
function insertBefore(parentInstance, child, beforeChild) {
|
|
965
909
|
let added = false;
|
|
966
|
-
|
|
967
910
|
if (child) {
|
|
968
911
|
var _child$__r3f2, _parentInstance$__r3f2;
|
|
969
|
-
|
|
970
912
|
if ((_child$__r3f2 = child.__r3f) != null && _child$__r3f2.attach) {
|
|
971
913
|
attach(parentInstance, child, child.__r3f.attach);
|
|
972
914
|
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
@@ -979,7 +921,6 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
979
921
|
parentInstance.children = [...restSiblings.slice(0, index), child, ...restSiblings.slice(index)];
|
|
980
922
|
added = true;
|
|
981
923
|
}
|
|
982
|
-
|
|
983
924
|
if (!added) (_parentInstance$__r3f2 = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f2.objects.push(child);
|
|
984
925
|
if (!child.__r3f) prepare(child, {});
|
|
985
926
|
child.__r3f.parent = parentInstance;
|
|
@@ -987,31 +928,29 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
987
928
|
invalidateInstance(child);
|
|
988
929
|
}
|
|
989
930
|
}
|
|
990
|
-
|
|
991
931
|
function removeRecursive(array, parent, dispose = false) {
|
|
992
932
|
if (array) [...array].forEach(child => removeChild(parent, child, dispose));
|
|
993
933
|
}
|
|
994
|
-
|
|
995
934
|
function removeChild(parentInstance, child, dispose) {
|
|
996
935
|
if (child) {
|
|
997
936
|
var _parentInstance$__r3f3, _child$__r3f3, _child$__r3f5;
|
|
998
|
-
|
|
999
937
|
// Clear the parent reference
|
|
1000
|
-
if (child.__r3f) child.__r3f.parent = null;
|
|
1001
|
-
|
|
1002
|
-
if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
|
|
1003
|
-
|
|
938
|
+
if (child.__r3f) child.__r3f.parent = null;
|
|
939
|
+
// Remove child from the parents objects
|
|
940
|
+
if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
|
|
941
|
+
// Remove attachment
|
|
1004
942
|
if ((_child$__r3f3 = child.__r3f) != null && _child$__r3f3.attach) {
|
|
1005
943
|
detach(parentInstance, child, child.__r3f.attach);
|
|
1006
944
|
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
1007
945
|
var _child$__r3f4;
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
946
|
+
parentInstance.remove(child);
|
|
947
|
+
// Remove interactivity
|
|
1011
948
|
if ((_child$__r3f4 = child.__r3f) != null && _child$__r3f4.root) {
|
|
1012
949
|
removeInteractivity(child.__r3f.root, child);
|
|
1013
950
|
}
|
|
1014
|
-
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// Allow objects to bail out of recursive dispose altogether by passing dispose={null}
|
|
1015
954
|
// Never dispose of primitives because their state may be kept outside of React!
|
|
1016
955
|
// In order for an object to be able to dispose it has to have
|
|
1017
956
|
// - a dispose method,
|
|
@@ -1020,29 +959,27 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1020
959
|
//
|
|
1021
960
|
// Since disposal is recursive, we can check the optional dispose arg, which will be undefined
|
|
1022
961
|
// when the reconciler calls it, but then carry our own check recursively
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
962
|
const isPrimitive = (_child$__r3f5 = child.__r3f) == null ? void 0 : _child$__r3f5.primitive;
|
|
1026
|
-
const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose;
|
|
1027
|
-
// attached to them declaratively ...
|
|
963
|
+
const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose;
|
|
1028
964
|
|
|
965
|
+
// Remove nested child objects. Primitives should not have objects and children that are
|
|
966
|
+
// attached to them declaratively ...
|
|
1029
967
|
if (!isPrimitive) {
|
|
1030
968
|
var _child$__r3f6;
|
|
1031
|
-
|
|
1032
969
|
removeRecursive((_child$__r3f6 = child.__r3f) == null ? void 0 : _child$__r3f6.objects, child, shouldDispose);
|
|
1033
970
|
removeRecursive(child.children, child, shouldDispose);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
971
|
+
}
|
|
1036
972
|
|
|
973
|
+
// Remove references
|
|
1037
974
|
if (child.__r3f) {
|
|
1038
975
|
delete child.__r3f.root;
|
|
1039
976
|
delete child.__r3f.objects;
|
|
1040
977
|
delete child.__r3f.handlers;
|
|
1041
978
|
delete child.__r3f.memoizedProps;
|
|
1042
979
|
if (!isPrimitive) delete child.__r3f;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
980
|
+
}
|
|
1045
981
|
|
|
982
|
+
// Dispose item whenever the reconciler feels like it
|
|
1046
983
|
if (shouldDispose && child.dispose && child.type !== 'Scene') {
|
|
1047
984
|
scheduler.unstable_scheduleCallback(scheduler.unstable_IdlePriority, () => {
|
|
1048
985
|
try {
|
|
@@ -1052,61 +989,51 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1052
989
|
}
|
|
1053
990
|
});
|
|
1054
991
|
}
|
|
1055
|
-
|
|
1056
992
|
invalidateInstance(parentInstance);
|
|
1057
993
|
}
|
|
1058
994
|
}
|
|
1059
|
-
|
|
1060
995
|
function switchInstance(instance, type, newProps, fiber) {
|
|
1061
996
|
var _instance$__r3f;
|
|
1062
|
-
|
|
1063
997
|
const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
|
|
1064
998
|
if (!parent) return;
|
|
1065
|
-
const newInstance = createInstance(type, newProps, instance.__r3f.root);
|
|
999
|
+
const newInstance = createInstance(type, newProps, instance.__r3f.root);
|
|
1000
|
+
|
|
1001
|
+
// https://github.com/pmndrs/react-three-fiber/issues/1348
|
|
1066
1002
|
// When args change the instance has to be re-constructed, which then
|
|
1067
1003
|
// forces r3f to re-parent the children and non-scene objects
|
|
1068
|
-
|
|
1069
1004
|
if (instance.children) {
|
|
1070
1005
|
for (const child of instance.children) {
|
|
1071
1006
|
if (child.__r3f) appendChild(newInstance, child);
|
|
1072
1007
|
}
|
|
1073
|
-
|
|
1074
1008
|
instance.children = instance.children.filter(child => !child.__r3f);
|
|
1075
1009
|
}
|
|
1076
|
-
|
|
1077
1010
|
instance.__r3f.objects.forEach(child => appendChild(newInstance, child));
|
|
1078
|
-
|
|
1079
1011
|
instance.__r3f.objects = [];
|
|
1080
|
-
|
|
1081
1012
|
if (!instance.__r3f.autoRemovedBeforeAppend) {
|
|
1082
1013
|
removeChild(parent, instance);
|
|
1083
1014
|
}
|
|
1084
|
-
|
|
1085
1015
|
if (newInstance.parent) {
|
|
1086
1016
|
newInstance.__r3f.autoRemovedBeforeAppend = true;
|
|
1087
1017
|
}
|
|
1018
|
+
appendChild(parent, newInstance);
|
|
1088
1019
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1020
|
+
// Re-bind event handlers
|
|
1091
1021
|
if (newInstance.raycast && newInstance.__r3f.eventCount) {
|
|
1092
1022
|
const rootState = newInstance.__r3f.root.getState();
|
|
1093
|
-
|
|
1094
1023
|
rootState.internal.interaction.push(newInstance);
|
|
1095
|
-
}
|
|
1024
|
+
}
|
|
1096
1025
|
[fiber, fiber.alternate].forEach(fiber => {
|
|
1097
1026
|
if (fiber !== null) {
|
|
1098
1027
|
fiber.stateNode = newInstance;
|
|
1099
|
-
|
|
1100
1028
|
if (fiber.ref) {
|
|
1101
1029
|
if (typeof fiber.ref === 'function') fiber.ref(newInstance);else fiber.ref.current = newInstance;
|
|
1102
1030
|
}
|
|
1103
1031
|
}
|
|
1104
1032
|
});
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1033
|
+
}
|
|
1107
1034
|
|
|
1035
|
+
// Don't handle text instances, warn on undefined behavior
|
|
1108
1036
|
const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
|
|
1109
|
-
|
|
1110
1037
|
const reconciler = Reconciler__default["default"]({
|
|
1111
1038
|
createInstance,
|
|
1112
1039
|
removeChild,
|
|
@@ -1119,11 +1046,13 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1119
1046
|
supportsHydration: false,
|
|
1120
1047
|
noTimeout: -1,
|
|
1121
1048
|
appendChildToContainer: (container, child) => {
|
|
1122
|
-
if (!child) return;
|
|
1049
|
+
if (!child) return;
|
|
1123
1050
|
|
|
1051
|
+
// Don't append to unmounted container
|
|
1124
1052
|
const scene = container.getState().scene;
|
|
1125
|
-
if (!scene.__r3f) return;
|
|
1053
|
+
if (!scene.__r3f) return;
|
|
1126
1054
|
|
|
1055
|
+
// Link current root to the default scene
|
|
1127
1056
|
scene.__r3f.root = container;
|
|
1128
1057
|
appendChild(scene, child);
|
|
1129
1058
|
},
|
|
@@ -1132,24 +1061,22 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1132
1061
|
removeChild(container.getState().scene, child);
|
|
1133
1062
|
},
|
|
1134
1063
|
insertInContainerBefore: (container, child, beforeChild) => {
|
|
1135
|
-
if (!child || !beforeChild) return;
|
|
1064
|
+
if (!child || !beforeChild) return;
|
|
1136
1065
|
|
|
1066
|
+
// Don't append to unmounted container
|
|
1137
1067
|
const scene = container.getState().scene;
|
|
1138
1068
|
if (!scene.__r3f) return;
|
|
1139
1069
|
insertBefore(scene, child, beforeChild);
|
|
1140
1070
|
},
|
|
1141
1071
|
getRootHostContext: () => null,
|
|
1142
1072
|
getChildHostContext: parentHostContext => parentHostContext,
|
|
1143
|
-
|
|
1144
1073
|
finalizeInitialChildren(instance) {
|
|
1145
1074
|
var _instance$__r3f2;
|
|
1146
|
-
|
|
1147
|
-
|
|
1075
|
+
const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
|
|
1076
|
+
// https://github.com/facebook/react/issues/20271
|
|
1148
1077
|
// Returning true will trigger commitMount
|
|
1149
|
-
|
|
1150
1078
|
return Boolean(localState.handlers);
|
|
1151
1079
|
},
|
|
1152
|
-
|
|
1153
1080
|
prepareUpdate(instance, _type, oldProps, newProps) {
|
|
1154
1081
|
// Create diff-sets
|
|
1155
1082
|
if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
|
|
@@ -1165,47 +1092,44 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1165
1092
|
args: argsOld = [],
|
|
1166
1093
|
children: cO,
|
|
1167
1094
|
...restOld
|
|
1168
|
-
} = oldProps;
|
|
1169
|
-
|
|
1170
|
-
if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!'); // If it has new props or arguments, then it needs to be re-instantiated
|
|
1095
|
+
} = oldProps;
|
|
1171
1096
|
|
|
1172
|
-
|
|
1097
|
+
// Throw if an object or literal was passed for args
|
|
1098
|
+
if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!');
|
|
1173
1099
|
|
|
1100
|
+
// If it has new props or arguments, then it needs to be re-instantiated
|
|
1101
|
+
if (argsNew.some((value, index) => value !== argsOld[index])) return [true];
|
|
1102
|
+
// Create a diff-set, flag if there are any changes
|
|
1174
1103
|
const diff = diffProps(instance, restNew, restOld, true);
|
|
1175
|
-
if (diff.changes.length) return [false, diff];
|
|
1104
|
+
if (diff.changes.length) return [false, diff];
|
|
1176
1105
|
|
|
1106
|
+
// Otherwise do not touch the instance
|
|
1177
1107
|
return null;
|
|
1178
1108
|
}
|
|
1179
1109
|
},
|
|
1180
|
-
|
|
1181
1110
|
commitUpdate(instance, [reconstruct, diff], type, _oldProps, newProps, fiber) {
|
|
1182
1111
|
// Reconstruct when args or <primitive object={...} have changes
|
|
1183
|
-
if (reconstruct) switchInstance(instance, type, newProps, fiber);
|
|
1112
|
+
if (reconstruct) switchInstance(instance, type, newProps, fiber);
|
|
1113
|
+
// Otherwise just overwrite props
|
|
1184
1114
|
else applyProps$1(instance, diff);
|
|
1185
1115
|
},
|
|
1186
|
-
|
|
1187
1116
|
commitMount(instance, _type, _props, _int) {
|
|
1188
1117
|
var _instance$__r3f3;
|
|
1189
|
-
|
|
1190
1118
|
// https://github.com/facebook/react/issues/20271
|
|
1191
1119
|
// This will make sure events are only added once to the central container
|
|
1192
1120
|
const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
1193
|
-
|
|
1194
1121
|
if (instance.raycast && localState.handlers && localState.eventCount) {
|
|
1195
1122
|
instance.__r3f.root.getState().internal.interaction.push(instance);
|
|
1196
1123
|
}
|
|
1197
1124
|
},
|
|
1198
|
-
|
|
1199
1125
|
getPublicInstance: instance => instance,
|
|
1200
1126
|
prepareForCommit: () => null,
|
|
1201
1127
|
preparePortalMount: container => prepare(container.getState().scene),
|
|
1202
1128
|
resetAfterCommit: () => {},
|
|
1203
1129
|
shouldSetTextContent: () => false,
|
|
1204
1130
|
clearContainer: () => false,
|
|
1205
|
-
|
|
1206
1131
|
hideInstance(instance) {
|
|
1207
1132
|
var _instance$__r3f4;
|
|
1208
|
-
|
|
1209
1133
|
// Detach while the instance is hidden
|
|
1210
1134
|
const {
|
|
1211
1135
|
attach: type,
|
|
@@ -1215,10 +1139,8 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1215
1139
|
if (instance.isObject3D) instance.visible = false;
|
|
1216
1140
|
invalidateInstance(instance);
|
|
1217
1141
|
},
|
|
1218
|
-
|
|
1219
1142
|
unhideInstance(instance, props) {
|
|
1220
1143
|
var _instance$__r3f5;
|
|
1221
|
-
|
|
1222
1144
|
// Re-attach when the instance is unhidden
|
|
1223
1145
|
const {
|
|
1224
1146
|
attach: type,
|
|
@@ -1228,7 +1150,6 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1228
1150
|
if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
|
|
1229
1151
|
invalidateInstance(instance);
|
|
1230
1152
|
},
|
|
1231
|
-
|
|
1232
1153
|
createTextInstance: handleTextInstance,
|
|
1233
1154
|
hideTextInstance: handleTextInstance,
|
|
1234
1155
|
unhideTextInstance: handleTextInstance,
|
|
@@ -1249,16 +1170,15 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1249
1170
|
};
|
|
1250
1171
|
}
|
|
1251
1172
|
|
|
1173
|
+
// Keys that shouldn't be copied between R3F stores
|
|
1252
1174
|
const privateKeys = ['set', 'get', 'setSize', 'setFrameloop', 'setDpr', 'events', 'invalidate', 'advance', 'size', 'viewport'];
|
|
1253
1175
|
const isRenderer = def => !!(def != null && def.render);
|
|
1254
1176
|
const context = /*#__PURE__*/React__namespace.createContext(null);
|
|
1255
|
-
|
|
1256
1177
|
const createStore = (invalidate, advance) => {
|
|
1257
1178
|
const rootState = create__default["default"]((set, get) => {
|
|
1258
1179
|
const position = new THREE__namespace.Vector3();
|
|
1259
1180
|
const defaultTarget = new THREE__namespace.Vector3();
|
|
1260
1181
|
const tempTarget = new THREE__namespace.Vector3();
|
|
1261
|
-
|
|
1262
1182
|
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
1263
1183
|
const {
|
|
1264
1184
|
width,
|
|
@@ -1269,7 +1189,6 @@ const createStore = (invalidate, advance) => {
|
|
|
1269
1189
|
const aspect = width / height;
|
|
1270
1190
|
if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
1271
1191
|
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
1272
|
-
|
|
1273
1192
|
if (isOrthographicCamera(camera)) {
|
|
1274
1193
|
return {
|
|
1275
1194
|
width: width / camera.zoom,
|
|
@@ -1282,9 +1201,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1282
1201
|
};
|
|
1283
1202
|
} else {
|
|
1284
1203
|
const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
|
|
1285
|
-
|
|
1286
1204
|
const h = 2 * Math.tan(fov / 2) * distance; // visible height
|
|
1287
|
-
|
|
1288
1205
|
const w = h * (width / height);
|
|
1289
1206
|
return {
|
|
1290
1207
|
width: w,
|
|
@@ -1297,15 +1214,13 @@ const createStore = (invalidate, advance) => {
|
|
|
1297
1214
|
};
|
|
1298
1215
|
}
|
|
1299
1216
|
}
|
|
1300
|
-
|
|
1301
1217
|
let performanceTimeout = undefined;
|
|
1302
|
-
|
|
1303
1218
|
const setPerformanceCurrent = current => set(state => ({
|
|
1304
|
-
performance: {
|
|
1219
|
+
performance: {
|
|
1220
|
+
...state.performance,
|
|
1305
1221
|
current
|
|
1306
1222
|
}
|
|
1307
1223
|
}));
|
|
1308
|
-
|
|
1309
1224
|
const pointer = new THREE__namespace.Vector2();
|
|
1310
1225
|
const rootState = {
|
|
1311
1226
|
set,
|
|
@@ -1338,12 +1253,12 @@ const createStore = (invalidate, advance) => {
|
|
|
1338
1253
|
max: 1,
|
|
1339
1254
|
debounce: 200,
|
|
1340
1255
|
regress: () => {
|
|
1341
|
-
const state = get();
|
|
1342
|
-
|
|
1343
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1344
|
-
|
|
1345
|
-
if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min);
|
|
1346
|
-
|
|
1256
|
+
const state = get();
|
|
1257
|
+
// Clear timeout
|
|
1258
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1259
|
+
// Set lower bound performance
|
|
1260
|
+
if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min);
|
|
1261
|
+
// Go back to upper bound performance after a while unless something regresses meanwhile
|
|
1347
1262
|
performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
|
|
1348
1263
|
}
|
|
1349
1264
|
},
|
|
@@ -1366,8 +1281,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1366
1281
|
factor: 0,
|
|
1367
1282
|
getCurrentViewport
|
|
1368
1283
|
},
|
|
1369
|
-
setEvents: events => set(state => ({
|
|
1370
|
-
|
|
1284
|
+
setEvents: events => set(state => ({
|
|
1285
|
+
...state,
|
|
1286
|
+
events: {
|
|
1287
|
+
...state.events,
|
|
1371
1288
|
...events
|
|
1372
1289
|
}
|
|
1373
1290
|
})),
|
|
@@ -1382,7 +1299,8 @@ const createStore = (invalidate, advance) => {
|
|
|
1382
1299
|
};
|
|
1383
1300
|
set(state => ({
|
|
1384
1301
|
size,
|
|
1385
|
-
viewport: {
|
|
1302
|
+
viewport: {
|
|
1303
|
+
...state.viewport,
|
|
1386
1304
|
...getCurrentViewport(camera, defaultTarget, size)
|
|
1387
1305
|
}
|
|
1388
1306
|
}));
|
|
@@ -1390,23 +1308,23 @@ const createStore = (invalidate, advance) => {
|
|
|
1390
1308
|
setDpr: dpr => set(state => {
|
|
1391
1309
|
const resolved = calculateDpr(dpr);
|
|
1392
1310
|
return {
|
|
1393
|
-
viewport: {
|
|
1311
|
+
viewport: {
|
|
1312
|
+
...state.viewport,
|
|
1394
1313
|
dpr: resolved,
|
|
1395
1314
|
initialDpr: state.viewport.initialDpr || resolved
|
|
1396
1315
|
}
|
|
1397
1316
|
};
|
|
1398
1317
|
}),
|
|
1399
1318
|
setFrameloop: (frameloop = 'always') => {
|
|
1400
|
-
const clock = get().clock;
|
|
1319
|
+
const clock = get().clock;
|
|
1401
1320
|
|
|
1321
|
+
// if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
|
|
1402
1322
|
clock.stop();
|
|
1403
1323
|
clock.elapsedTime = 0;
|
|
1404
|
-
|
|
1405
1324
|
if (frameloop !== 'never') {
|
|
1406
1325
|
clock.start();
|
|
1407
1326
|
clock.elapsedTime = 0;
|
|
1408
1327
|
}
|
|
1409
|
-
|
|
1410
1328
|
set(() => ({
|
|
1411
1329
|
frameloop
|
|
1412
1330
|
}));
|
|
@@ -1424,27 +1342,26 @@ const createStore = (invalidate, advance) => {
|
|
|
1424
1342
|
initialHits: [],
|
|
1425
1343
|
capturedMap: new Map(),
|
|
1426
1344
|
subscribe: (ref, priority, store) => {
|
|
1427
|
-
const internal = get().internal;
|
|
1345
|
+
const internal = get().internal;
|
|
1346
|
+
// If this subscription was given a priority, it takes rendering into its own hands
|
|
1428
1347
|
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1429
1348
|
// As long as this flag is positive there can be no internal rendering at all
|
|
1430
1349
|
// because there could be multiple render subscriptions
|
|
1431
|
-
|
|
1432
1350
|
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1433
1351
|
internal.subscribers.push({
|
|
1434
1352
|
ref,
|
|
1435
1353
|
priority,
|
|
1436
1354
|
store
|
|
1437
|
-
});
|
|
1355
|
+
});
|
|
1356
|
+
// Register subscriber and sort layers from lowest to highest, meaning,
|
|
1438
1357
|
// highest priority renders last (on top of the other frames)
|
|
1439
|
-
|
|
1440
1358
|
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1441
1359
|
return () => {
|
|
1442
1360
|
const internal = get().internal;
|
|
1443
|
-
|
|
1444
1361
|
if (internal != null && internal.subscribers) {
|
|
1445
1362
|
// Decrease manual flag if this subscription had a priority
|
|
1446
|
-
internal.priority = internal.priority - (priority > 0 ? 1 : 0);
|
|
1447
|
-
|
|
1363
|
+
internal.priority = internal.priority - (priority > 0 ? 1 : 0);
|
|
1364
|
+
// Remove subscriber from list
|
|
1448
1365
|
internal.subscribers = internal.subscribers.filter(s => s.ref !== ref);
|
|
1449
1366
|
}
|
|
1450
1367
|
};
|
|
@@ -1464,31 +1381,35 @@ const createStore = (invalidate, advance) => {
|
|
|
1464
1381
|
viewport,
|
|
1465
1382
|
gl,
|
|
1466
1383
|
set
|
|
1467
|
-
} = rootState.getState();
|
|
1384
|
+
} = rootState.getState();
|
|
1468
1385
|
|
|
1386
|
+
// Resize camera and renderer on changes to size and pixelratio
|
|
1469
1387
|
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1470
1388
|
oldSize = size;
|
|
1471
|
-
oldDpr = viewport.dpr;
|
|
1472
|
-
|
|
1389
|
+
oldDpr = viewport.dpr;
|
|
1390
|
+
// Update camera & renderer
|
|
1473
1391
|
updateCamera(camera, size);
|
|
1474
1392
|
gl.setPixelRatio(viewport.dpr);
|
|
1475
1393
|
gl.setSize(size.width, size.height, size.updateStyle);
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1394
|
+
}
|
|
1478
1395
|
|
|
1396
|
+
// Update viewport once the camera changes
|
|
1479
1397
|
if (camera !== oldCamera) {
|
|
1480
|
-
oldCamera = camera;
|
|
1481
|
-
|
|
1398
|
+
oldCamera = camera;
|
|
1399
|
+
// Update viewport
|
|
1482
1400
|
set(state => ({
|
|
1483
|
-
viewport: {
|
|
1401
|
+
viewport: {
|
|
1402
|
+
...state.viewport,
|
|
1484
1403
|
...state.viewport.getCurrentViewport(camera)
|
|
1485
1404
|
}
|
|
1486
1405
|
}));
|
|
1487
1406
|
}
|
|
1488
|
-
});
|
|
1407
|
+
});
|
|
1489
1408
|
|
|
1490
|
-
|
|
1409
|
+
// Invalidate on any change
|
|
1410
|
+
rootState.subscribe(state => invalidate(state));
|
|
1491
1411
|
|
|
1412
|
+
// Return root state
|
|
1492
1413
|
return rootState;
|
|
1493
1414
|
};
|
|
1494
1415
|
|
|
@@ -1499,144 +1420,129 @@ function createSubs(callback, subs) {
|
|
|
1499
1420
|
subs.add(sub);
|
|
1500
1421
|
return () => void subs.delete(sub);
|
|
1501
1422
|
}
|
|
1502
|
-
|
|
1503
1423
|
let i;
|
|
1504
1424
|
let globalEffects = new Set();
|
|
1505
1425
|
let globalAfterEffects = new Set();
|
|
1506
1426
|
let globalTailEffects = new Set();
|
|
1427
|
+
|
|
1507
1428
|
/**
|
|
1508
1429
|
* Adds a global render callback which is called each frame.
|
|
1509
1430
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
|
|
1510
1431
|
*/
|
|
1511
|
-
|
|
1512
1432
|
const addEffect = callback => createSubs(callback, globalEffects);
|
|
1433
|
+
|
|
1513
1434
|
/**
|
|
1514
1435
|
* Adds a global after-render callback which is called each frame.
|
|
1515
1436
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
|
|
1516
1437
|
*/
|
|
1517
|
-
|
|
1518
1438
|
const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
|
|
1439
|
+
|
|
1519
1440
|
/**
|
|
1520
1441
|
* Adds a global callback which is called when rendering stops.
|
|
1521
1442
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
|
|
1522
1443
|
*/
|
|
1523
|
-
|
|
1524
1444
|
const addTail = callback => createSubs(callback, globalTailEffects);
|
|
1525
|
-
|
|
1526
1445
|
function run(effects, timestamp) {
|
|
1527
1446
|
if (!effects.size) return;
|
|
1528
|
-
|
|
1529
1447
|
for (const {
|
|
1530
1448
|
callback
|
|
1531
1449
|
} of effects.values()) {
|
|
1532
1450
|
callback(timestamp);
|
|
1533
1451
|
}
|
|
1534
1452
|
}
|
|
1535
|
-
|
|
1536
1453
|
function flushGlobalEffects(type, timestamp) {
|
|
1537
1454
|
switch (type) {
|
|
1538
1455
|
case 'before':
|
|
1539
1456
|
return run(globalEffects, timestamp);
|
|
1540
|
-
|
|
1541
1457
|
case 'after':
|
|
1542
1458
|
return run(globalAfterEffects, timestamp);
|
|
1543
|
-
|
|
1544
1459
|
case 'tail':
|
|
1545
1460
|
return run(globalTailEffects, timestamp);
|
|
1546
1461
|
}
|
|
1547
1462
|
}
|
|
1548
1463
|
let subscribers;
|
|
1549
1464
|
let subscription;
|
|
1550
|
-
|
|
1551
1465
|
function render$1(timestamp, state, frame) {
|
|
1552
1466
|
// Run local effects
|
|
1553
|
-
let delta = state.clock.getDelta();
|
|
1554
|
-
|
|
1467
|
+
let delta = state.clock.getDelta();
|
|
1468
|
+
// In frameloop='never' mode, clock times are updated using the provided timestamp
|
|
1555
1469
|
if (state.frameloop === 'never' && typeof timestamp === 'number') {
|
|
1556
1470
|
delta = timestamp - state.clock.elapsedTime;
|
|
1557
1471
|
state.clock.oldTime = state.clock.elapsedTime;
|
|
1558
1472
|
state.clock.elapsedTime = timestamp;
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
|
|
1473
|
+
}
|
|
1474
|
+
// Call subscribers (useFrame)
|
|
1562
1475
|
subscribers = state.internal.subscribers;
|
|
1563
|
-
|
|
1564
1476
|
for (i = 0; i < subscribers.length; i++) {
|
|
1565
1477
|
subscription = subscribers[i];
|
|
1566
1478
|
subscription.ref.current(subscription.store.getState(), delta, frame);
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1479
|
+
}
|
|
1480
|
+
// Render content
|
|
1481
|
+
if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera);
|
|
1482
|
+
// Decrease frame count
|
|
1572
1483
|
state.internal.frames = Math.max(0, state.internal.frames - 1);
|
|
1573
1484
|
return state.frameloop === 'always' ? 1 : state.internal.frames;
|
|
1574
1485
|
}
|
|
1575
|
-
|
|
1576
1486
|
function createLoop(roots) {
|
|
1577
1487
|
let running = false;
|
|
1578
1488
|
let repeat;
|
|
1579
1489
|
let frame;
|
|
1580
1490
|
let state;
|
|
1581
|
-
|
|
1582
1491
|
function loop(timestamp) {
|
|
1583
1492
|
frame = requestAnimationFrame(loop);
|
|
1584
1493
|
running = true;
|
|
1585
|
-
repeat = 0;
|
|
1494
|
+
repeat = 0;
|
|
1586
1495
|
|
|
1587
|
-
|
|
1496
|
+
// Run effects
|
|
1497
|
+
flushGlobalEffects('before', timestamp);
|
|
1588
1498
|
|
|
1499
|
+
// Render all roots
|
|
1589
1500
|
for (const root of roots.values()) {
|
|
1590
1501
|
var _state$gl$xr;
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1502
|
+
state = root.store.getState();
|
|
1503
|
+
// If the frameloop is invalidated, do not run another frame
|
|
1594
1504
|
if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
|
|
1595
1505
|
repeat += render$1(timestamp, state);
|
|
1596
1506
|
}
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1507
|
+
}
|
|
1599
1508
|
|
|
1600
|
-
|
|
1509
|
+
// Run after-effects
|
|
1510
|
+
flushGlobalEffects('after', timestamp);
|
|
1601
1511
|
|
|
1512
|
+
// Stop the loop if nothing invalidates it
|
|
1602
1513
|
if (repeat === 0) {
|
|
1603
1514
|
// Tail call effects, they are called when rendering stops
|
|
1604
|
-
flushGlobalEffects('tail', timestamp);
|
|
1515
|
+
flushGlobalEffects('tail', timestamp);
|
|
1605
1516
|
|
|
1517
|
+
// Flag end of operation
|
|
1606
1518
|
running = false;
|
|
1607
1519
|
return cancelAnimationFrame(frame);
|
|
1608
1520
|
}
|
|
1609
1521
|
}
|
|
1610
|
-
|
|
1611
1522
|
function invalidate(state, frames = 1) {
|
|
1612
1523
|
var _state$gl$xr2;
|
|
1613
|
-
|
|
1614
1524
|
if (!state) return roots.forEach(root => invalidate(root.store.getState()), frames);
|
|
1615
|
-
if ((_state$gl$xr2 = state.gl.xr) != null && _state$gl$xr2.isPresenting || !state.internal.active || state.frameloop === 'never') return;
|
|
1616
|
-
|
|
1617
|
-
state.internal.frames = Math.min(60, state.internal.frames + frames);
|
|
1618
|
-
|
|
1525
|
+
if ((_state$gl$xr2 = state.gl.xr) != null && _state$gl$xr2.isPresenting || !state.internal.active || state.frameloop === 'never') return;
|
|
1526
|
+
// Increase frames, do not go higher than 60
|
|
1527
|
+
state.internal.frames = Math.min(60, state.internal.frames + frames);
|
|
1528
|
+
// If the render-loop isn't active, start it
|
|
1619
1529
|
if (!running) {
|
|
1620
1530
|
running = true;
|
|
1621
1531
|
requestAnimationFrame(loop);
|
|
1622
1532
|
}
|
|
1623
1533
|
}
|
|
1624
|
-
|
|
1625
1534
|
function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
1626
1535
|
if (runGlobalEffects) flushGlobalEffects('before', timestamp);
|
|
1627
1536
|
if (!state) for (const root of roots.values()) render$1(timestamp, root.store.getState());else render$1(timestamp, state, frame);
|
|
1628
1537
|
if (runGlobalEffects) flushGlobalEffects('after', timestamp);
|
|
1629
1538
|
}
|
|
1630
|
-
|
|
1631
1539
|
return {
|
|
1632
1540
|
loop,
|
|
1633
|
-
|
|
1634
1541
|
/**
|
|
1635
1542
|
* Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
|
|
1636
1543
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
|
|
1637
1544
|
*/
|
|
1638
1545
|
invalidate,
|
|
1639
|
-
|
|
1640
1546
|
/**
|
|
1641
1547
|
* Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
|
|
1642
1548
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
@@ -1661,80 +1567,77 @@ function useStore() {
|
|
|
1661
1567
|
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1662
1568
|
return store;
|
|
1663
1569
|
}
|
|
1570
|
+
|
|
1664
1571
|
/**
|
|
1665
1572
|
* Accesses R3F's internal state, containing renderer, canvas, scene, etc.
|
|
1666
1573
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
|
|
1667
1574
|
*/
|
|
1668
|
-
|
|
1669
1575
|
function useThree(selector = state => state, equalityFn) {
|
|
1670
1576
|
return useStore()(selector, equalityFn);
|
|
1671
1577
|
}
|
|
1578
|
+
|
|
1672
1579
|
/**
|
|
1673
1580
|
* Executes a callback before render in a shared frame loop.
|
|
1674
1581
|
* Can order effects with render priority or manually render with a positive priority.
|
|
1675
1582
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
|
|
1676
1583
|
*/
|
|
1677
|
-
|
|
1678
1584
|
function useFrame(callback, renderPriority = 0) {
|
|
1679
1585
|
const store = useStore();
|
|
1680
|
-
const subscribe = store.getState().internal.subscribe;
|
|
1681
|
-
|
|
1682
|
-
const ref = useMutableCallback(callback);
|
|
1683
|
-
|
|
1586
|
+
const subscribe = store.getState().internal.subscribe;
|
|
1587
|
+
// Memoize ref
|
|
1588
|
+
const ref = useMutableCallback(callback);
|
|
1589
|
+
// Subscribe on mount, unsubscribe on unmount
|
|
1684
1590
|
useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
|
|
1685
1591
|
return null;
|
|
1686
1592
|
}
|
|
1593
|
+
|
|
1687
1594
|
/**
|
|
1688
1595
|
* Returns a node graph of an object with named nodes & materials.
|
|
1689
1596
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
|
|
1690
1597
|
*/
|
|
1691
|
-
|
|
1692
1598
|
function useGraph(object) {
|
|
1693
1599
|
return React__namespace.useMemo(() => buildGraph(object), [object]);
|
|
1694
1600
|
}
|
|
1695
|
-
|
|
1696
1601
|
function loadingFn(extensions, onProgress) {
|
|
1697
1602
|
return function (Proto, ...input) {
|
|
1698
1603
|
// Construct new loader and run extensions
|
|
1699
1604
|
const loader = new Proto();
|
|
1700
|
-
if (extensions) extensions(loader);
|
|
1701
|
-
|
|
1605
|
+
if (extensions) extensions(loader);
|
|
1606
|
+
// Go through the urls and load them
|
|
1702
1607
|
return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
|
|
1703
1608
|
if (data.scene) Object.assign(data, buildGraph(data.scene));
|
|
1704
1609
|
res(data);
|
|
1705
1610
|
}, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
|
|
1706
1611
|
};
|
|
1707
1612
|
}
|
|
1613
|
+
|
|
1708
1614
|
/**
|
|
1709
1615
|
* Synchronously loads and caches assets with a three loader.
|
|
1710
1616
|
*
|
|
1711
1617
|
* Note: this hook's caller must be wrapped with `React.Suspense`
|
|
1712
1618
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
|
|
1713
1619
|
*/
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
1620
|
function useLoader(Proto, input, extensions, onProgress) {
|
|
1717
1621
|
// Use suspense to load async assets
|
|
1718
1622
|
const keys = Array.isArray(input) ? input : [input];
|
|
1719
1623
|
const results = suspendReact.suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
|
|
1720
1624
|
equal: is.equ
|
|
1721
|
-
});
|
|
1722
|
-
|
|
1625
|
+
});
|
|
1626
|
+
// Return the object/s
|
|
1723
1627
|
return Array.isArray(input) ? results : results[0];
|
|
1724
1628
|
}
|
|
1629
|
+
|
|
1725
1630
|
/**
|
|
1726
1631
|
* Preloads an asset into cache as a side-effect.
|
|
1727
1632
|
*/
|
|
1728
|
-
|
|
1729
1633
|
useLoader.preload = function (Proto, input, extensions) {
|
|
1730
1634
|
const keys = Array.isArray(input) ? input : [input];
|
|
1731
1635
|
return suspendReact.preload(loadingFn(extensions), [Proto, ...keys]);
|
|
1732
1636
|
};
|
|
1637
|
+
|
|
1733
1638
|
/**
|
|
1734
1639
|
* Removes a loaded asset from cache.
|
|
1735
1640
|
*/
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
1641
|
useLoader.clear = function (Proto, input) {
|
|
1739
1642
|
const keys = Array.isArray(input) ? input : [input];
|
|
1740
1643
|
return suspendReact.clear([Proto, ...keys]);
|
|
@@ -1753,7 +1656,6 @@ const shallowLoose = {
|
|
|
1753
1656
|
objects: 'shallow',
|
|
1754
1657
|
strict: false
|
|
1755
1658
|
};
|
|
1756
|
-
|
|
1757
1659
|
const createRendererInstance = (gl, canvas) => {
|
|
1758
1660
|
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1759
1661
|
if (isRenderer(customRenderer)) return customRenderer;else return new THREE__namespace.WebGLRenderer({
|
|
@@ -1764,16 +1666,13 @@ const createRendererInstance = (gl, canvas) => {
|
|
|
1764
1666
|
...gl
|
|
1765
1667
|
});
|
|
1766
1668
|
};
|
|
1767
|
-
|
|
1768
1669
|
function isCanvas(maybeCanvas) {
|
|
1769
1670
|
return maybeCanvas instanceof HTMLCanvasElement;
|
|
1770
1671
|
}
|
|
1771
|
-
|
|
1772
1672
|
function computeInitialSize(canvas, defaultSize) {
|
|
1773
1673
|
if (defaultSize) {
|
|
1774
1674
|
return defaultSize;
|
|
1775
1675
|
}
|
|
1776
|
-
|
|
1777
1676
|
if (isCanvas(canvas) && canvas.parentElement) {
|
|
1778
1677
|
const {
|
|
1779
1678
|
width,
|
|
@@ -1788,7 +1687,6 @@ function computeInitialSize(canvas, defaultSize) {
|
|
|
1788
1687
|
left
|
|
1789
1688
|
};
|
|
1790
1689
|
}
|
|
1791
|
-
|
|
1792
1690
|
return {
|
|
1793
1691
|
width: 0,
|
|
1794
1692
|
height: 0,
|
|
@@ -1796,29 +1694,33 @@ function computeInitialSize(canvas, defaultSize) {
|
|
|
1796
1694
|
left: 0
|
|
1797
1695
|
};
|
|
1798
1696
|
}
|
|
1799
|
-
|
|
1800
1697
|
function createRoot(canvas) {
|
|
1801
1698
|
// Check against mistaken use of createRoot
|
|
1802
1699
|
const prevRoot = roots.get(canvas);
|
|
1803
1700
|
const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
|
|
1804
1701
|
const prevStore = prevRoot == null ? void 0 : prevRoot.store;
|
|
1805
|
-
if (prevRoot) console.warn('R3F.createRoot should only be called once!');
|
|
1806
|
-
// https://github.com/pmndrs/react-three-fiber/pull/2261
|
|
1702
|
+
if (prevRoot) console.warn('R3F.createRoot should only be called once!');
|
|
1807
1703
|
|
|
1808
|
-
|
|
1704
|
+
// Report when an error was detected in a previous render
|
|
1705
|
+
// https://github.com/pmndrs/react-three-fiber/pull/2261
|
|
1706
|
+
const logRecoverableError = typeof reportError === 'function' ?
|
|
1707
|
+
// In modern browsers, reportError will dispatch an error event,
|
|
1809
1708
|
// emulating an uncaught JavaScript error.
|
|
1810
|
-
reportError :
|
|
1811
|
-
console.error
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
const
|
|
1816
|
-
|
|
1709
|
+
reportError :
|
|
1710
|
+
// In older browsers and test environments, fallback to console.error.
|
|
1711
|
+
console.error;
|
|
1712
|
+
|
|
1713
|
+
// Create store
|
|
1714
|
+
const store = prevStore || createStore(invalidate, advance);
|
|
1715
|
+
// Create renderer
|
|
1716
|
+
const fiber = prevFiber || reconciler.createContainer(store, constants.ConcurrentRoot, null, false, null, '', logRecoverableError, null);
|
|
1717
|
+
// Map it
|
|
1817
1718
|
if (!prevRoot) roots.set(canvas, {
|
|
1818
1719
|
fiber,
|
|
1819
1720
|
store
|
|
1820
|
-
});
|
|
1721
|
+
});
|
|
1821
1722
|
|
|
1723
|
+
// Locals
|
|
1822
1724
|
let onCreated;
|
|
1823
1725
|
let configured = false;
|
|
1824
1726
|
return {
|
|
@@ -1840,96 +1742,97 @@ function createRoot(canvas) {
|
|
|
1840
1742
|
camera: cameraOptions,
|
|
1841
1743
|
onPointerMissed
|
|
1842
1744
|
} = props;
|
|
1843
|
-
let state = store.getState();
|
|
1745
|
+
let state = store.getState();
|
|
1844
1746
|
|
|
1747
|
+
// Set up renderer (one time only!)
|
|
1845
1748
|
let gl = state.gl;
|
|
1846
1749
|
if (!state.gl) state.set({
|
|
1847
1750
|
gl: gl = createRendererInstance(glConfig, canvas)
|
|
1848
|
-
});
|
|
1751
|
+
});
|
|
1849
1752
|
|
|
1753
|
+
// Set up raycaster (one time only!)
|
|
1850
1754
|
let raycaster = state.raycaster;
|
|
1851
1755
|
if (!raycaster) state.set({
|
|
1852
1756
|
raycaster: raycaster = new THREE__namespace.Raycaster()
|
|
1853
|
-
});
|
|
1757
|
+
});
|
|
1854
1758
|
|
|
1759
|
+
// Set raycaster options
|
|
1855
1760
|
const {
|
|
1856
1761
|
params,
|
|
1857
1762
|
...options
|
|
1858
1763
|
} = raycastOptions || {};
|
|
1859
|
-
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
|
|
1764
|
+
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
|
|
1765
|
+
...options
|
|
1860
1766
|
});
|
|
1861
1767
|
if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
|
|
1862
|
-
params: {
|
|
1768
|
+
params: {
|
|
1769
|
+
...raycaster.params,
|
|
1863
1770
|
...params
|
|
1864
1771
|
}
|
|
1865
|
-
});
|
|
1772
|
+
});
|
|
1866
1773
|
|
|
1774
|
+
// Create default camera (one time only!)
|
|
1867
1775
|
if (!state.camera) {
|
|
1868
1776
|
const isCamera = cameraOptions instanceof THREE__namespace.Camera;
|
|
1869
1777
|
const camera = isCamera ? cameraOptions : orthographic ? new THREE__namespace.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE__namespace.PerspectiveCamera(75, 0, 0.1, 1000);
|
|
1870
|
-
|
|
1871
1778
|
if (!isCamera) {
|
|
1872
1779
|
camera.position.z = 5;
|
|
1873
|
-
if (cameraOptions) applyProps(camera, cameraOptions);
|
|
1874
|
-
|
|
1780
|
+
if (cameraOptions) applyProps(camera, cameraOptions);
|
|
1781
|
+
// Always look at center by default
|
|
1875
1782
|
if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1876
1783
|
}
|
|
1877
|
-
|
|
1878
1784
|
state.set({
|
|
1879
1785
|
camera
|
|
1880
1786
|
});
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1787
|
+
}
|
|
1883
1788
|
|
|
1789
|
+
// Set up XR (one time only!)
|
|
1884
1790
|
if (!state.xr) {
|
|
1885
1791
|
// Handle frame behavior in WebXR
|
|
1886
1792
|
const handleXRFrame = (timestamp, frame) => {
|
|
1887
1793
|
const state = store.getState();
|
|
1888
1794
|
if (state.frameloop === 'never') return;
|
|
1889
1795
|
advance(timestamp, true, state, frame);
|
|
1890
|
-
};
|
|
1891
|
-
|
|
1796
|
+
};
|
|
1892
1797
|
|
|
1798
|
+
// Toggle render switching on session
|
|
1893
1799
|
const handleSessionChange = () => {
|
|
1894
1800
|
const state = store.getState();
|
|
1895
1801
|
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
1896
1802
|
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
1897
1803
|
if (!state.gl.xr.isPresenting) invalidate(state);
|
|
1898
|
-
};
|
|
1899
|
-
|
|
1804
|
+
};
|
|
1900
1805
|
|
|
1806
|
+
// WebXR session manager
|
|
1901
1807
|
const xr = {
|
|
1902
1808
|
connect() {
|
|
1903
1809
|
const gl = store.getState().gl;
|
|
1904
1810
|
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
1905
1811
|
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
1906
1812
|
},
|
|
1907
|
-
|
|
1908
1813
|
disconnect() {
|
|
1909
1814
|
const gl = store.getState().gl;
|
|
1910
1815
|
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
1911
1816
|
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
1912
1817
|
}
|
|
1818
|
+
};
|
|
1913
1819
|
|
|
1914
|
-
|
|
1915
|
-
|
|
1820
|
+
// Subscribe to WebXR session events
|
|
1916
1821
|
if (gl.xr) xr.connect();
|
|
1917
1822
|
state.set({
|
|
1918
1823
|
xr
|
|
1919
1824
|
});
|
|
1920
|
-
}
|
|
1921
|
-
|
|
1825
|
+
}
|
|
1922
1826
|
|
|
1827
|
+
// Set shadowmap
|
|
1923
1828
|
if (gl.shadowMap) {
|
|
1924
1829
|
const oldEnabled = gl.shadowMap.enabled;
|
|
1925
1830
|
const oldType = gl.shadowMap.type;
|
|
1926
1831
|
gl.shadowMap.enabled = !!shadows;
|
|
1927
|
-
|
|
1928
1832
|
if (is.boo(shadows)) {
|
|
1929
1833
|
gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
|
|
1930
1834
|
} else if (is.str(shadows)) {
|
|
1931
1835
|
var _types$shadows;
|
|
1932
|
-
|
|
1933
1836
|
const types = {
|
|
1934
1837
|
basic: THREE__namespace.BasicShadowMap,
|
|
1935
1838
|
percentage: THREE__namespace.PCFShadowMap,
|
|
@@ -1940,21 +1843,20 @@ function createRoot(canvas) {
|
|
|
1940
1843
|
} else if (is.obj(shadows)) {
|
|
1941
1844
|
Object.assign(gl.shadowMap, shadows);
|
|
1942
1845
|
}
|
|
1943
|
-
|
|
1944
1846
|
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1945
|
-
}
|
|
1946
|
-
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1947
|
-
|
|
1847
|
+
}
|
|
1948
1848
|
|
|
1849
|
+
// Safely set color management if available.
|
|
1850
|
+
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1949
1851
|
if ('ColorManagement' in THREE__namespace) {
|
|
1950
1852
|
setDeep(THREE__namespace, legacy, ['ColorManagement', 'legacyMode']);
|
|
1951
1853
|
}
|
|
1952
|
-
|
|
1953
1854
|
const outputEncoding = linear ? THREE__namespace.LinearEncoding : THREE__namespace.sRGBEncoding;
|
|
1954
1855
|
const toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
1955
1856
|
if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
|
|
1956
|
-
if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping;
|
|
1857
|
+
if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping;
|
|
1957
1858
|
|
|
1859
|
+
// Update color management state
|
|
1958
1860
|
if (state.legacy !== legacy) state.set(() => ({
|
|
1959
1861
|
legacy
|
|
1960
1862
|
}));
|
|
@@ -1963,40 +1865,40 @@ function createRoot(canvas) {
|
|
|
1963
1865
|
}));
|
|
1964
1866
|
if (state.flat !== flat) state.set(() => ({
|
|
1965
1867
|
flat
|
|
1966
|
-
}));
|
|
1967
|
-
|
|
1968
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig); // Store events internally
|
|
1868
|
+
}));
|
|
1969
1869
|
|
|
1870
|
+
// Set gl props
|
|
1871
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
1872
|
+
// Store events internally
|
|
1970
1873
|
if (events && !state.events.handlers) state.set({
|
|
1971
1874
|
events: events(store)
|
|
1972
|
-
});
|
|
1973
|
-
|
|
1974
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1975
|
-
|
|
1875
|
+
});
|
|
1876
|
+
// Check pixelratio
|
|
1877
|
+
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1878
|
+
// Check size, allow it to take on container bounds initially
|
|
1976
1879
|
const size = computeInitialSize(canvas, propsSize);
|
|
1977
|
-
|
|
1978
1880
|
if (!is.equ(size, state.size, shallowLoose)) {
|
|
1979
1881
|
state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1882
|
+
}
|
|
1883
|
+
// Check frameloop
|
|
1884
|
+
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
1885
|
+
// Check pointer missed
|
|
1985
1886
|
if (!state.onPointerMissed) state.set({
|
|
1986
1887
|
onPointerMissed
|
|
1987
|
-
});
|
|
1988
|
-
|
|
1888
|
+
});
|
|
1889
|
+
// Check performance
|
|
1989
1890
|
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
1990
|
-
performance: {
|
|
1891
|
+
performance: {
|
|
1892
|
+
...state.performance,
|
|
1991
1893
|
...performance
|
|
1992
1894
|
}
|
|
1993
|
-
}));
|
|
1895
|
+
}));
|
|
1994
1896
|
|
|
1897
|
+
// Set locals
|
|
1995
1898
|
onCreated = onCreatedCallback;
|
|
1996
1899
|
configured = true;
|
|
1997
1900
|
return this;
|
|
1998
1901
|
},
|
|
1999
|
-
|
|
2000
1902
|
render(children) {
|
|
2001
1903
|
// The root has to be configured before it can be rendered
|
|
2002
1904
|
if (!configured) this.configure();
|
|
@@ -2008,21 +1910,17 @@ function createRoot(canvas) {
|
|
|
2008
1910
|
}), fiber, null, () => undefined);
|
|
2009
1911
|
return store;
|
|
2010
1912
|
},
|
|
2011
|
-
|
|
2012
1913
|
unmount() {
|
|
2013
1914
|
unmountComponentAtNode(canvas);
|
|
2014
1915
|
}
|
|
2015
|
-
|
|
2016
1916
|
};
|
|
2017
1917
|
}
|
|
2018
|
-
|
|
2019
1918
|
function render(children, canvas, config) {
|
|
2020
1919
|
console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
|
|
2021
1920
|
const root = createRoot(canvas);
|
|
2022
1921
|
root.configure(config);
|
|
2023
1922
|
return root.render(children);
|
|
2024
1923
|
}
|
|
2025
|
-
|
|
2026
1924
|
function Provider({
|
|
2027
1925
|
store,
|
|
2028
1926
|
children,
|
|
@@ -2030,28 +1928,28 @@ function Provider({
|
|
|
2030
1928
|
rootElement
|
|
2031
1929
|
}) {
|
|
2032
1930
|
useIsomorphicLayoutEffect(() => {
|
|
2033
|
-
const state = store.getState();
|
|
2034
|
-
|
|
1931
|
+
const state = store.getState();
|
|
1932
|
+
// Flag the canvas active, rendering will now begin
|
|
2035
1933
|
state.set(state => ({
|
|
2036
|
-
internal: {
|
|
1934
|
+
internal: {
|
|
1935
|
+
...state.internal,
|
|
2037
1936
|
active: true
|
|
2038
1937
|
}
|
|
2039
|
-
}));
|
|
2040
|
-
|
|
2041
|
-
if (onCreated) onCreated(state);
|
|
1938
|
+
}));
|
|
1939
|
+
// Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
|
|
1940
|
+
if (onCreated) onCreated(state);
|
|
1941
|
+
// Connect events to the targets parent, this is done to ensure events are registered on
|
|
2042
1942
|
// a shared target, and not on the canvas itself
|
|
2043
|
-
|
|
2044
|
-
|
|
1943
|
+
if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement);
|
|
1944
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2045
1945
|
}, []);
|
|
2046
1946
|
return /*#__PURE__*/React__namespace.createElement(context.Provider, {
|
|
2047
1947
|
value: store
|
|
2048
1948
|
}, children);
|
|
2049
1949
|
}
|
|
2050
|
-
|
|
2051
1950
|
function unmountComponentAtNode(canvas, callback) {
|
|
2052
1951
|
const root = roots.get(canvas);
|
|
2053
1952
|
const fiber = root == null ? void 0 : root.fiber;
|
|
2054
|
-
|
|
2055
1953
|
if (fiber) {
|
|
2056
1954
|
const state = root == null ? void 0 : root.store.getState();
|
|
2057
1955
|
if (state) state.internal.active = false;
|
|
@@ -2060,7 +1958,6 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
2060
1958
|
setTimeout(() => {
|
|
2061
1959
|
try {
|
|
2062
1960
|
var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
|
|
2063
|
-
|
|
2064
1961
|
state.events.disconnect == null ? void 0 : state.events.disconnect();
|
|
2065
1962
|
(_state$gl = state.gl) == null ? void 0 : (_state$gl$renderLists = _state$gl.renderLists) == null ? void 0 : _state$gl$renderLists.dispose == null ? void 0 : _state$gl$renderLists.dispose();
|
|
2066
1963
|
(_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
|
|
@@ -2076,7 +1973,6 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
2076
1973
|
});
|
|
2077
1974
|
}
|
|
2078
1975
|
}
|
|
2079
|
-
|
|
2080
1976
|
function createPortal(children, container, state) {
|
|
2081
1977
|
return /*#__PURE__*/React__namespace.createElement(Portal, {
|
|
2082
1978
|
key: container.uuid,
|
|
@@ -2085,7 +1981,6 @@ function createPortal(children, container, state) {
|
|
|
2085
1981
|
state: state
|
|
2086
1982
|
});
|
|
2087
1983
|
}
|
|
2088
|
-
|
|
2089
1984
|
function Portal({
|
|
2090
1985
|
state = {},
|
|
2091
1986
|
children,
|
|
@@ -2105,30 +2000,33 @@ function Portal({
|
|
|
2105
2000
|
const [raycaster] = React__namespace.useState(() => new THREE__namespace.Raycaster());
|
|
2106
2001
|
const [pointer] = React__namespace.useState(() => new THREE__namespace.Vector2());
|
|
2107
2002
|
const inject = React__namespace.useCallback((rootState, injectState) => {
|
|
2108
|
-
const intersect = {
|
|
2003
|
+
const intersect = {
|
|
2004
|
+
...rootState
|
|
2109
2005
|
}; // all prev state props
|
|
2006
|
+
|
|
2110
2007
|
// Only the fields of "rootState" that do not differ from injectState
|
|
2111
2008
|
// Some props should be off-limits
|
|
2112
2009
|
// Otherwise filter out the props that are different and let the inject layer take precedence
|
|
2113
|
-
|
|
2114
2010
|
Object.keys(rootState).forEach(key => {
|
|
2115
|
-
if (
|
|
2116
|
-
|
|
2117
|
-
|
|
2011
|
+
if (
|
|
2012
|
+
// Some props should be off-limits
|
|
2013
|
+
privateKeys.includes(key) ||
|
|
2014
|
+
// Otherwise filter out the props that are different and let the inject layer take precedence
|
|
2015
|
+
// Unless the inject layer props is undefined, then we keep the root layer
|
|
2016
|
+
rootState[key] !== injectState[key] && injectState[key]) {
|
|
2118
2017
|
delete intersect[key];
|
|
2119
2018
|
}
|
|
2120
2019
|
});
|
|
2121
2020
|
let viewport = undefined;
|
|
2122
|
-
|
|
2123
2021
|
if (injectState && size) {
|
|
2124
|
-
const camera = injectState.camera;
|
|
2125
|
-
|
|
2126
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
|
|
2127
|
-
|
|
2022
|
+
const camera = injectState.camera;
|
|
2023
|
+
// Calculate the override viewport, if present
|
|
2024
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
|
|
2025
|
+
// Update the portal camera, if it differs from the previous layer
|
|
2128
2026
|
if (camera !== rootState.camera) updateCamera(camera, size);
|
|
2129
2027
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2028
|
+
return {
|
|
2029
|
+
// The intersect consists of the previous root state
|
|
2132
2030
|
...intersect,
|
|
2133
2031
|
// Portals have their own scene, which forms the root, a raycaster and a pointer
|
|
2134
2032
|
scene: container,
|
|
@@ -2138,14 +2036,17 @@ function Portal({
|
|
|
2138
2036
|
// Their previous root is the layer before it
|
|
2139
2037
|
previousRoot,
|
|
2140
2038
|
// Events, size and viewport can be overridden by the inject layer
|
|
2141
|
-
events: {
|
|
2039
|
+
events: {
|
|
2040
|
+
...rootState.events,
|
|
2142
2041
|
...(injectState == null ? void 0 : injectState.events),
|
|
2143
2042
|
...events
|
|
2144
2043
|
},
|
|
2145
|
-
size: {
|
|
2044
|
+
size: {
|
|
2045
|
+
...rootState.size,
|
|
2146
2046
|
...size
|
|
2147
2047
|
},
|
|
2148
|
-
viewport: {
|
|
2048
|
+
viewport: {
|
|
2049
|
+
...rootState.viewport,
|
|
2149
2050
|
...viewport
|
|
2150
2051
|
},
|
|
2151
2052
|
...rest
|
|
@@ -2154,16 +2055,19 @@ function Portal({
|
|
|
2154
2055
|
const [usePortalStore] = React__namespace.useState(() => {
|
|
2155
2056
|
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
2156
2057
|
const previousState = previousRoot.getState();
|
|
2157
|
-
const store = create__default["default"]((set, get) => ({
|
|
2058
|
+
const store = create__default["default"]((set, get) => ({
|
|
2059
|
+
...previousState,
|
|
2158
2060
|
scene: container,
|
|
2159
2061
|
raycaster,
|
|
2160
2062
|
pointer,
|
|
2161
2063
|
mouse: pointer,
|
|
2162
2064
|
previousRoot,
|
|
2163
|
-
events: {
|
|
2065
|
+
events: {
|
|
2066
|
+
...previousState.events,
|
|
2164
2067
|
...events
|
|
2165
2068
|
},
|
|
2166
|
-
size: {
|
|
2069
|
+
size: {
|
|
2070
|
+
...previousState.size,
|
|
2167
2071
|
...size
|
|
2168
2072
|
},
|
|
2169
2073
|
...rest,
|
|
@@ -2171,8 +2075,10 @@ function Portal({
|
|
|
2171
2075
|
set,
|
|
2172
2076
|
get,
|
|
2173
2077
|
// Layers are allowed to override events
|
|
2174
|
-
setEvents: events => set(state => ({
|
|
2175
|
-
|
|
2078
|
+
setEvents: events => set(state => ({
|
|
2079
|
+
...state,
|
|
2080
|
+
events: {
|
|
2081
|
+
...state.events,
|
|
2176
2082
|
...events
|
|
2177
2083
|
}
|
|
2178
2084
|
}))
|
|
@@ -2194,7 +2100,6 @@ function Portal({
|
|
|
2194
2100
|
value: usePortalStore
|
|
2195
2101
|
}, children), usePortalStore, null));
|
|
2196
2102
|
}
|
|
2197
|
-
|
|
2198
2103
|
reconciler.injectIntoDevTools({
|
|
2199
2104
|
bundleType: 0 ,
|
|
2200
2105
|
rendererPackageName: '@react-three/fiber',
|