@react-three/fiber 8.9.2 → 8.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/declarations/src/core/events.d.ts +70 -70
- package/dist/declarations/src/core/hooks.d.ts +28 -28
- package/dist/declarations/src/core/index.d.ts +55 -55
- package/dist/declarations/src/core/loop.d.ts +14 -14
- package/dist/declarations/src/core/renderer.d.ts +52 -52
- package/dist/declarations/src/core/store.d.ts +95 -95
- package/dist/declarations/src/core/utils.d.ts +83 -83
- package/dist/declarations/src/index.d.ts +12 -12
- package/dist/declarations/src/native/Canvas.d.ts +8 -8
- package/dist/declarations/src/native/events.d.ts +4 -4
- package/dist/declarations/src/native/polyfills.d.ts +1 -1
- package/dist/declarations/src/native.d.ts +12 -12
- package/dist/declarations/src/three-types.d.ts +335 -335
- package/dist/declarations/src/web/Canvas.d.ts +11 -11
- package/dist/declarations/src/web/events.d.ts +4 -4
- package/dist/{index-25dfa84d.cjs.prod.js → index-5d1efa67.cjs.prod.js} +425 -508
- package/dist/{index-79f9c7e9.esm.js → index-adfddf12.esm.js} +425 -508
- package/dist/{index-efc69a1d.cjs.dev.js → index-f2e97578.cjs.dev.js} +425 -508
- 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,102 @@ 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();
|
|
622
|
-
|
|
588
|
+
const rootState = store.getState();
|
|
589
|
+
// If anything has been found, forward it to the event listeners
|
|
623
590
|
if (intersections.length) {
|
|
624
591
|
const localState = {
|
|
625
592
|
stopped: false
|
|
626
593
|
};
|
|
627
|
-
|
|
628
594
|
for (const hit of intersections) {
|
|
629
595
|
const state = getRootState(hit.object) || rootState;
|
|
630
596
|
const {
|
|
@@ -634,19 +600,15 @@ function createEvents(store) {
|
|
|
634
600
|
internal
|
|
635
601
|
} = state;
|
|
636
602
|
const unprojectedPoint = new THREE__namespace.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
637
|
-
|
|
638
603
|
const hasPointerCapture = id => {
|
|
639
604
|
var _internal$capturedMap, _internal$capturedMap2;
|
|
640
|
-
|
|
641
605
|
return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
|
|
642
606
|
};
|
|
643
|
-
|
|
644
607
|
const setPointerCapture = id => {
|
|
645
608
|
const captureData = {
|
|
646
609
|
intersection: hit,
|
|
647
610
|
target: event.target
|
|
648
611
|
};
|
|
649
|
-
|
|
650
612
|
if (internal.capturedMap.has(id)) {
|
|
651
613
|
// if the pointerId was previously captured, we add the hit to the
|
|
652
614
|
// event capturedMap.
|
|
@@ -656,29 +618,27 @@ function createEvents(store) {
|
|
|
656
618
|
// containing the hitObject, and the hit. hitObject is used for
|
|
657
619
|
// faster access.
|
|
658
620
|
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
659
|
-
}
|
|
621
|
+
}
|
|
660
622
|
event.target.setPointerCapture(id);
|
|
661
623
|
};
|
|
662
|
-
|
|
663
624
|
const releasePointerCapture = id => {
|
|
664
625
|
const captures = internal.capturedMap.get(id);
|
|
665
|
-
|
|
666
626
|
if (captures) {
|
|
667
627
|
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
668
628
|
}
|
|
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.
|
|
629
|
+
};
|
|
673
630
|
|
|
631
|
+
// Add native event props
|
|
632
|
+
let extractEventProps = {};
|
|
633
|
+
// 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
634
|
for (let prop in event) {
|
|
675
|
-
let property = event[prop];
|
|
635
|
+
let property = event[prop];
|
|
636
|
+
// Only copy over atomics, leave functions alone as these should be
|
|
676
637
|
// called as event.nativeEvent.fn()
|
|
677
|
-
|
|
678
638
|
if (typeof property !== 'function') extractEventProps[prop] = property;
|
|
679
639
|
}
|
|
680
|
-
|
|
681
|
-
|
|
640
|
+
let raycastEvent = {
|
|
641
|
+
...hit,
|
|
682
642
|
...extractEventProps,
|
|
683
643
|
pointer,
|
|
684
644
|
intersections,
|
|
@@ -687,19 +647,21 @@ function createEvents(store) {
|
|
|
687
647
|
unprojectedPoint,
|
|
688
648
|
ray: raycaster.ray,
|
|
689
649
|
camera: camera,
|
|
690
|
-
|
|
691
650
|
// Hijack stopPropagation, which just sets a flag
|
|
692
651
|
stopPropagation() {
|
|
693
652
|
// https://github.com/pmndrs/react-three-fiber/issues/596
|
|
694
653
|
// Events are not allowed to stop propagation if the pointer has been captured
|
|
695
|
-
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
|
|
654
|
+
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
|
|
696
655
|
|
|
697
|
-
|
|
698
|
-
|
|
656
|
+
// We only authorize stopPropagation...
|
|
657
|
+
if (
|
|
658
|
+
// ...if this pointer hasn't been captured
|
|
659
|
+
!capturesForPointer ||
|
|
660
|
+
// ... or if the hit object is capturing the pointer
|
|
699
661
|
capturesForPointer.has(hit.eventObject)) {
|
|
700
|
-
raycastEvent.stopped = localState.stopped = true;
|
|
662
|
+
raycastEvent.stopped = localState.stopped = true;
|
|
663
|
+
// Propagation is stopped, remove all other hover records
|
|
701
664
|
// An event handler is only allowed to flush other handlers if it is hovered itself
|
|
702
|
-
|
|
703
665
|
if (internal.hovered.size && Array.from(internal.hovered.values()).find(i => i.eventObject === hit.eventObject)) {
|
|
704
666
|
// Objects cannot flush out higher up objects that have already caught the event
|
|
705
667
|
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
@@ -707,7 +669,6 @@ function createEvents(store) {
|
|
|
707
669
|
}
|
|
708
670
|
}
|
|
709
671
|
},
|
|
710
|
-
|
|
711
672
|
// there should be a distinction between target and currentTarget
|
|
712
673
|
target: {
|
|
713
674
|
hasPointerCapture,
|
|
@@ -720,22 +681,20 @@ function createEvents(store) {
|
|
|
720
681
|
releasePointerCapture
|
|
721
682
|
},
|
|
722
683
|
nativeEvent: event
|
|
723
|
-
};
|
|
724
|
-
|
|
725
|
-
callback(raycastEvent); // Event bubbling may be interrupted by stopPropagation
|
|
684
|
+
};
|
|
726
685
|
|
|
686
|
+
// Call subscribers
|
|
687
|
+
callback(raycastEvent);
|
|
688
|
+
// Event bubbling may be interrupted by stopPropagation
|
|
727
689
|
if (localState.stopped === true) break;
|
|
728
690
|
}
|
|
729
691
|
}
|
|
730
|
-
|
|
731
692
|
return intersections;
|
|
732
693
|
}
|
|
733
|
-
|
|
734
694
|
function cancelPointer(intersections) {
|
|
735
695
|
const {
|
|
736
696
|
internal
|
|
737
697
|
} = store.getState();
|
|
738
|
-
|
|
739
698
|
for (const hoveredObj of internal.hovered.values()) {
|
|
740
699
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
741
700
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
@@ -744,10 +703,10 @@ function createEvents(store) {
|
|
|
744
703
|
const instance = eventObject.__r3f;
|
|
745
704
|
const handlers = instance == null ? void 0 : instance.handlers;
|
|
746
705
|
internal.hovered.delete(makeId(hoveredObj));
|
|
747
|
-
|
|
748
706
|
if (instance != null && instance.eventCount) {
|
|
749
707
|
// Clear out intersects, they are outdated by now
|
|
750
|
-
const data = {
|
|
708
|
+
const data = {
|
|
709
|
+
...hoveredObj,
|
|
751
710
|
intersections
|
|
752
711
|
};
|
|
753
712
|
handlers.onPointerOut == null ? void 0 : handlers.onPointerOut(data);
|
|
@@ -756,27 +715,23 @@ function createEvents(store) {
|
|
|
756
715
|
}
|
|
757
716
|
}
|
|
758
717
|
}
|
|
759
|
-
|
|
760
718
|
function pointerMissed(event, objects) {
|
|
761
719
|
for (let i = 0; i < objects.length; i++) {
|
|
762
720
|
const instance = objects[i].__r3f;
|
|
763
721
|
instance == null ? void 0 : instance.handlers.onPointerMissed == null ? void 0 : instance.handlers.onPointerMissed(event);
|
|
764
722
|
}
|
|
765
723
|
}
|
|
766
|
-
|
|
767
724
|
function handlePointer(name) {
|
|
768
725
|
// Deal with cancelation
|
|
769
726
|
switch (name) {
|
|
770
727
|
case 'onPointerLeave':
|
|
771
728
|
case 'onPointerCancel':
|
|
772
729
|
return () => cancelPointer([]);
|
|
773
|
-
|
|
774
730
|
case 'onLostPointerCapture':
|
|
775
731
|
return event => {
|
|
776
732
|
const {
|
|
777
733
|
internal
|
|
778
734
|
} = store.getState();
|
|
779
|
-
|
|
780
735
|
if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
|
|
781
736
|
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
782
737
|
// object that's getting removed.
|
|
@@ -784,55 +739,54 @@ function createEvents(store) {
|
|
|
784
739
|
cancelPointer([]);
|
|
785
740
|
}
|
|
786
741
|
};
|
|
787
|
-
}
|
|
788
|
-
|
|
742
|
+
}
|
|
789
743
|
|
|
744
|
+
// Any other pointer goes here ...
|
|
790
745
|
return function handleEvent(event) {
|
|
791
746
|
const {
|
|
792
747
|
onPointerMissed,
|
|
793
748
|
internal
|
|
794
|
-
} = store.getState();
|
|
749
|
+
} = store.getState();
|
|
795
750
|
|
|
796
|
-
|
|
751
|
+
// prepareRay(event)
|
|
752
|
+
internal.lastEvent.current = event;
|
|
797
753
|
|
|
754
|
+
// Get fresh intersects
|
|
798
755
|
const isPointerMove = name === 'onPointerMove';
|
|
799
756
|
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
|
|
800
|
-
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
801
|
-
|
|
757
|
+
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
758
|
+
// const hits = patchIntersects(intersect(filter), event)
|
|
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;
|
|
826
|
-
|
|
781
|
+
const handlers = instance == null ? void 0 : instance.handlers;
|
|
782
|
+
// Check presence of handlers
|
|
827
783
|
if (!(instance != null && instance.eventCount)) return;
|
|
828
|
-
|
|
829
784
|
if (isPointerMove) {
|
|
830
785
|
// Move event ...
|
|
831
786
|
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
832
787
|
// When enter or out is present take care of hover-state
|
|
833
788
|
const id = makeId(data);
|
|
834
789
|
const hoveredItem = internal.hovered.get(id);
|
|
835
|
-
|
|
836
790
|
if (!hoveredItem) {
|
|
837
791
|
// If the object wasn't previously hovered, book it and call its handler
|
|
838
792
|
internal.hovered.set(id, data);
|
|
@@ -842,21 +796,19 @@ function createEvents(store) {
|
|
|
842
796
|
// If the object was previously hovered and stopped, we shouldn't allow other items to proceed
|
|
843
797
|
data.stopPropagation();
|
|
844
798
|
}
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
|
|
799
|
+
}
|
|
800
|
+
// Call mouse move
|
|
848
801
|
handlers.onPointerMove == null ? void 0 : handlers.onPointerMove(data);
|
|
849
802
|
} else {
|
|
850
803
|
// All other events ...
|
|
851
804
|
const handler = handlers[name];
|
|
852
|
-
|
|
853
805
|
if (handler) {
|
|
854
806
|
// Forward all events back to their respective handlers with the exception of click events,
|
|
855
807
|
// which must use the initial target
|
|
856
808
|
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
857
809
|
// Missed events have to come first
|
|
858
|
-
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
859
|
-
|
|
810
|
+
pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
|
|
811
|
+
// Now call the handler
|
|
860
812
|
handler(data);
|
|
861
813
|
}
|
|
862
814
|
} else {
|
|
@@ -867,22 +819,19 @@ function createEvents(store) {
|
|
|
867
819
|
}
|
|
868
820
|
}
|
|
869
821
|
}
|
|
870
|
-
|
|
871
822
|
handleIntersects(hits, event, delta, onIntersect);
|
|
872
823
|
};
|
|
873
824
|
}
|
|
874
|
-
|
|
875
825
|
return {
|
|
876
826
|
handlePointer
|
|
877
827
|
};
|
|
878
828
|
}
|
|
879
829
|
|
|
880
830
|
let catalogue = {};
|
|
881
|
-
|
|
882
|
-
|
|
831
|
+
let extend = objects => void (catalogue = {
|
|
832
|
+
...catalogue,
|
|
883
833
|
...objects
|
|
884
834
|
});
|
|
885
|
-
|
|
886
835
|
function createRenderer(_roots, _getEventPriority) {
|
|
887
836
|
function createInstance(type, {
|
|
888
837
|
args = [],
|
|
@@ -891,7 +840,6 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
891
840
|
}, root) {
|
|
892
841
|
let name = `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
893
842
|
let instance;
|
|
894
|
-
|
|
895
843
|
if (type === 'primitive') {
|
|
896
844
|
if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
|
|
897
845
|
const object = props.object;
|
|
@@ -903,15 +851,15 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
903
851
|
});
|
|
904
852
|
} else {
|
|
905
853
|
const target = catalogue[name];
|
|
906
|
-
|
|
907
854
|
if (!target) {
|
|
908
855
|
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
|
-
}
|
|
856
|
+
}
|
|
910
857
|
|
|
858
|
+
// Throw if an object or literal was passed for args
|
|
859
|
+
if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!');
|
|
911
860
|
|
|
912
|
-
|
|
861
|
+
// Instanciate new object, link it to the root
|
|
913
862
|
// Append memoized props with args so it's not forgotten
|
|
914
|
-
|
|
915
863
|
instance = prepare(new target(...args), {
|
|
916
864
|
type,
|
|
917
865
|
root,
|
|
@@ -921,27 +869,24 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
921
869
|
args
|
|
922
870
|
}
|
|
923
871
|
});
|
|
924
|
-
}
|
|
925
|
-
|
|
872
|
+
}
|
|
926
873
|
|
|
874
|
+
// Auto-attach geometries and materials
|
|
927
875
|
if (instance.__r3f.attach === undefined) {
|
|
928
876
|
if (instance instanceof THREE__namespace.BufferGeometry) instance.__r3f.attach = 'geometry';else if (instance instanceof THREE__namespace.Material) instance.__r3f.attach = 'material';
|
|
929
|
-
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// It should NOT call onUpdate on object instanciation, because it hasn't been added to the
|
|
930
880
|
// view yet. If the callback relies on references for instance, they won't be ready yet, this is
|
|
931
881
|
// why it passes "true" here
|
|
932
882
|
// There is no reason to apply props to injects
|
|
933
|
-
|
|
934
|
-
|
|
935
883
|
if (name !== 'inject') applyProps$1(instance, props);
|
|
936
884
|
return instance;
|
|
937
885
|
}
|
|
938
|
-
|
|
939
886
|
function appendChild(parentInstance, child) {
|
|
940
887
|
let added = false;
|
|
941
|
-
|
|
942
888
|
if (child) {
|
|
943
889
|
var _child$__r3f, _parentInstance$__r3f;
|
|
944
|
-
|
|
945
890
|
// The attach attribute implies that the object attaches itself on the parent
|
|
946
891
|
if ((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) {
|
|
947
892
|
attach(parentInstance, child, child.__r3f.attach);
|
|
@@ -949,10 +894,9 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
949
894
|
// add in the usual parent-child way
|
|
950
895
|
parentInstance.add(child);
|
|
951
896
|
added = true;
|
|
952
|
-
}
|
|
897
|
+
}
|
|
898
|
+
// This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
|
|
953
899
|
// that is, anything that's a child in React but not a child in the scenegraph.
|
|
954
|
-
|
|
955
|
-
|
|
956
900
|
if (!added) (_parentInstance$__r3f = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f.objects.push(child);
|
|
957
901
|
if (!child.__r3f) prepare(child, {});
|
|
958
902
|
child.__r3f.parent = parentInstance;
|
|
@@ -960,13 +904,10 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
960
904
|
invalidateInstance(child);
|
|
961
905
|
}
|
|
962
906
|
}
|
|
963
|
-
|
|
964
907
|
function insertBefore(parentInstance, child, beforeChild) {
|
|
965
908
|
let added = false;
|
|
966
|
-
|
|
967
909
|
if (child) {
|
|
968
910
|
var _child$__r3f2, _parentInstance$__r3f2;
|
|
969
|
-
|
|
970
911
|
if ((_child$__r3f2 = child.__r3f) != null && _child$__r3f2.attach) {
|
|
971
912
|
attach(parentInstance, child, child.__r3f.attach);
|
|
972
913
|
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
@@ -979,7 +920,6 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
979
920
|
parentInstance.children = [...restSiblings.slice(0, index), child, ...restSiblings.slice(index)];
|
|
980
921
|
added = true;
|
|
981
922
|
}
|
|
982
|
-
|
|
983
923
|
if (!added) (_parentInstance$__r3f2 = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f2.objects.push(child);
|
|
984
924
|
if (!child.__r3f) prepare(child, {});
|
|
985
925
|
child.__r3f.parent = parentInstance;
|
|
@@ -987,31 +927,29 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
987
927
|
invalidateInstance(child);
|
|
988
928
|
}
|
|
989
929
|
}
|
|
990
|
-
|
|
991
930
|
function removeRecursive(array, parent, dispose = false) {
|
|
992
931
|
if (array) [...array].forEach(child => removeChild(parent, child, dispose));
|
|
993
932
|
}
|
|
994
|
-
|
|
995
933
|
function removeChild(parentInstance, child, dispose) {
|
|
996
934
|
if (child) {
|
|
997
935
|
var _parentInstance$__r3f3, _child$__r3f3, _child$__r3f5;
|
|
998
|
-
|
|
999
936
|
// 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
|
-
|
|
937
|
+
if (child.__r3f) child.__r3f.parent = null;
|
|
938
|
+
// Remove child from the parents objects
|
|
939
|
+
if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
|
|
940
|
+
// Remove attachment
|
|
1004
941
|
if ((_child$__r3f3 = child.__r3f) != null && _child$__r3f3.attach) {
|
|
1005
942
|
detach(parentInstance, child, child.__r3f.attach);
|
|
1006
943
|
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
1007
944
|
var _child$__r3f4;
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
945
|
+
parentInstance.remove(child);
|
|
946
|
+
// Remove interactivity
|
|
1011
947
|
if ((_child$__r3f4 = child.__r3f) != null && _child$__r3f4.root) {
|
|
1012
948
|
removeInteractivity(child.__r3f.root, child);
|
|
1013
949
|
}
|
|
1014
|
-
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// Allow objects to bail out of recursive dispose altogether by passing dispose={null}
|
|
1015
953
|
// Never dispose of primitives because their state may be kept outside of React!
|
|
1016
954
|
// In order for an object to be able to dispose it has to have
|
|
1017
955
|
// - a dispose method,
|
|
@@ -1020,29 +958,27 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1020
958
|
//
|
|
1021
959
|
// Since disposal is recursive, we can check the optional dispose arg, which will be undefined
|
|
1022
960
|
// when the reconciler calls it, but then carry our own check recursively
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
961
|
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 ...
|
|
962
|
+
const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose;
|
|
1028
963
|
|
|
964
|
+
// Remove nested child objects. Primitives should not have objects and children that are
|
|
965
|
+
// attached to them declaratively ...
|
|
1029
966
|
if (!isPrimitive) {
|
|
1030
967
|
var _child$__r3f6;
|
|
1031
|
-
|
|
1032
968
|
removeRecursive((_child$__r3f6 = child.__r3f) == null ? void 0 : _child$__r3f6.objects, child, shouldDispose);
|
|
1033
969
|
removeRecursive(child.children, child, shouldDispose);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
970
|
+
}
|
|
1036
971
|
|
|
972
|
+
// Remove references
|
|
1037
973
|
if (child.__r3f) {
|
|
1038
974
|
delete child.__r3f.root;
|
|
1039
975
|
delete child.__r3f.objects;
|
|
1040
976
|
delete child.__r3f.handlers;
|
|
1041
977
|
delete child.__r3f.memoizedProps;
|
|
1042
978
|
if (!isPrimitive) delete child.__r3f;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
979
|
+
}
|
|
1045
980
|
|
|
981
|
+
// Dispose item whenever the reconciler feels like it
|
|
1046
982
|
if (shouldDispose && child.dispose && child.type !== 'Scene') {
|
|
1047
983
|
scheduler.unstable_scheduleCallback(scheduler.unstable_IdlePriority, () => {
|
|
1048
984
|
try {
|
|
@@ -1052,61 +988,51 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1052
988
|
}
|
|
1053
989
|
});
|
|
1054
990
|
}
|
|
1055
|
-
|
|
1056
991
|
invalidateInstance(parentInstance);
|
|
1057
992
|
}
|
|
1058
993
|
}
|
|
1059
|
-
|
|
1060
994
|
function switchInstance(instance, type, newProps, fiber) {
|
|
1061
995
|
var _instance$__r3f;
|
|
1062
|
-
|
|
1063
996
|
const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
|
|
1064
997
|
if (!parent) return;
|
|
1065
|
-
const newInstance = createInstance(type, newProps, instance.__r3f.root);
|
|
998
|
+
const newInstance = createInstance(type, newProps, instance.__r3f.root);
|
|
999
|
+
|
|
1000
|
+
// https://github.com/pmndrs/react-three-fiber/issues/1348
|
|
1066
1001
|
// When args change the instance has to be re-constructed, which then
|
|
1067
1002
|
// forces r3f to re-parent the children and non-scene objects
|
|
1068
|
-
|
|
1069
1003
|
if (instance.children) {
|
|
1070
1004
|
for (const child of instance.children) {
|
|
1071
1005
|
if (child.__r3f) appendChild(newInstance, child);
|
|
1072
1006
|
}
|
|
1073
|
-
|
|
1074
1007
|
instance.children = instance.children.filter(child => !child.__r3f);
|
|
1075
1008
|
}
|
|
1076
|
-
|
|
1077
1009
|
instance.__r3f.objects.forEach(child => appendChild(newInstance, child));
|
|
1078
|
-
|
|
1079
1010
|
instance.__r3f.objects = [];
|
|
1080
|
-
|
|
1081
1011
|
if (!instance.__r3f.autoRemovedBeforeAppend) {
|
|
1082
1012
|
removeChild(parent, instance);
|
|
1083
1013
|
}
|
|
1084
|
-
|
|
1085
1014
|
if (newInstance.parent) {
|
|
1086
1015
|
newInstance.__r3f.autoRemovedBeforeAppend = true;
|
|
1087
1016
|
}
|
|
1017
|
+
appendChild(parent, newInstance);
|
|
1088
1018
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1019
|
+
// Re-bind event handlers
|
|
1091
1020
|
if (newInstance.raycast && newInstance.__r3f.eventCount) {
|
|
1092
1021
|
const rootState = newInstance.__r3f.root.getState();
|
|
1093
|
-
|
|
1094
1022
|
rootState.internal.interaction.push(newInstance);
|
|
1095
|
-
}
|
|
1023
|
+
}
|
|
1096
1024
|
[fiber, fiber.alternate].forEach(fiber => {
|
|
1097
1025
|
if (fiber !== null) {
|
|
1098
1026
|
fiber.stateNode = newInstance;
|
|
1099
|
-
|
|
1100
1027
|
if (fiber.ref) {
|
|
1101
1028
|
if (typeof fiber.ref === 'function') fiber.ref(newInstance);else fiber.ref.current = newInstance;
|
|
1102
1029
|
}
|
|
1103
1030
|
}
|
|
1104
1031
|
});
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1032
|
+
}
|
|
1107
1033
|
|
|
1034
|
+
// Don't handle text instances, warn on undefined behavior
|
|
1108
1035
|
const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
|
|
1109
|
-
|
|
1110
1036
|
const reconciler = Reconciler__default["default"]({
|
|
1111
1037
|
createInstance,
|
|
1112
1038
|
removeChild,
|
|
@@ -1119,11 +1045,13 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1119
1045
|
supportsHydration: false,
|
|
1120
1046
|
noTimeout: -1,
|
|
1121
1047
|
appendChildToContainer: (container, child) => {
|
|
1122
|
-
if (!child) return;
|
|
1048
|
+
if (!child) return;
|
|
1123
1049
|
|
|
1050
|
+
// Don't append to unmounted container
|
|
1124
1051
|
const scene = container.getState().scene;
|
|
1125
|
-
if (!scene.__r3f) return;
|
|
1052
|
+
if (!scene.__r3f) return;
|
|
1126
1053
|
|
|
1054
|
+
// Link current root to the default scene
|
|
1127
1055
|
scene.__r3f.root = container;
|
|
1128
1056
|
appendChild(scene, child);
|
|
1129
1057
|
},
|
|
@@ -1132,24 +1060,22 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1132
1060
|
removeChild(container.getState().scene, child);
|
|
1133
1061
|
},
|
|
1134
1062
|
insertInContainerBefore: (container, child, beforeChild) => {
|
|
1135
|
-
if (!child || !beforeChild) return;
|
|
1063
|
+
if (!child || !beforeChild) return;
|
|
1136
1064
|
|
|
1065
|
+
// Don't append to unmounted container
|
|
1137
1066
|
const scene = container.getState().scene;
|
|
1138
1067
|
if (!scene.__r3f) return;
|
|
1139
1068
|
insertBefore(scene, child, beforeChild);
|
|
1140
1069
|
},
|
|
1141
1070
|
getRootHostContext: () => null,
|
|
1142
1071
|
getChildHostContext: parentHostContext => parentHostContext,
|
|
1143
|
-
|
|
1144
1072
|
finalizeInitialChildren(instance) {
|
|
1145
1073
|
var _instance$__r3f2;
|
|
1146
|
-
|
|
1147
|
-
|
|
1074
|
+
const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
|
|
1075
|
+
// https://github.com/facebook/react/issues/20271
|
|
1148
1076
|
// Returning true will trigger commitMount
|
|
1149
|
-
|
|
1150
1077
|
return Boolean(localState.handlers);
|
|
1151
1078
|
},
|
|
1152
|
-
|
|
1153
1079
|
prepareUpdate(instance, _type, oldProps, newProps) {
|
|
1154
1080
|
// Create diff-sets
|
|
1155
1081
|
if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
|
|
@@ -1165,47 +1091,44 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1165
1091
|
args: argsOld = [],
|
|
1166
1092
|
children: cO,
|
|
1167
1093
|
...restOld
|
|
1168
|
-
} = oldProps;
|
|
1094
|
+
} = oldProps;
|
|
1169
1095
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
|
|
1096
|
+
// Throw if an object or literal was passed for args
|
|
1097
|
+
if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!');
|
|
1173
1098
|
|
|
1099
|
+
// If it has new props or arguments, then it needs to be re-instantiated
|
|
1100
|
+
if (argsNew.some((value, index) => value !== argsOld[index])) return [true];
|
|
1101
|
+
// Create a diff-set, flag if there are any changes
|
|
1174
1102
|
const diff = diffProps(instance, restNew, restOld, true);
|
|
1175
|
-
if (diff.changes.length) return [false, diff];
|
|
1103
|
+
if (diff.changes.length) return [false, diff];
|
|
1176
1104
|
|
|
1105
|
+
// Otherwise do not touch the instance
|
|
1177
1106
|
return null;
|
|
1178
1107
|
}
|
|
1179
1108
|
},
|
|
1180
|
-
|
|
1181
1109
|
commitUpdate(instance, [reconstruct, diff], type, _oldProps, newProps, fiber) {
|
|
1182
1110
|
// Reconstruct when args or <primitive object={...} have changes
|
|
1183
|
-
if (reconstruct) switchInstance(instance, type, newProps, fiber);
|
|
1111
|
+
if (reconstruct) switchInstance(instance, type, newProps, fiber);
|
|
1112
|
+
// Otherwise just overwrite props
|
|
1184
1113
|
else applyProps$1(instance, diff);
|
|
1185
1114
|
},
|
|
1186
|
-
|
|
1187
1115
|
commitMount(instance, _type, _props, _int) {
|
|
1188
1116
|
var _instance$__r3f3;
|
|
1189
|
-
|
|
1190
1117
|
// https://github.com/facebook/react/issues/20271
|
|
1191
1118
|
// This will make sure events are only added once to the central container
|
|
1192
1119
|
const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
1193
|
-
|
|
1194
1120
|
if (instance.raycast && localState.handlers && localState.eventCount) {
|
|
1195
1121
|
instance.__r3f.root.getState().internal.interaction.push(instance);
|
|
1196
1122
|
}
|
|
1197
1123
|
},
|
|
1198
|
-
|
|
1199
1124
|
getPublicInstance: instance => instance,
|
|
1200
1125
|
prepareForCommit: () => null,
|
|
1201
1126
|
preparePortalMount: container => prepare(container.getState().scene),
|
|
1202
1127
|
resetAfterCommit: () => {},
|
|
1203
1128
|
shouldSetTextContent: () => false,
|
|
1204
1129
|
clearContainer: () => false,
|
|
1205
|
-
|
|
1206
1130
|
hideInstance(instance) {
|
|
1207
1131
|
var _instance$__r3f4;
|
|
1208
|
-
|
|
1209
1132
|
// Detach while the instance is hidden
|
|
1210
1133
|
const {
|
|
1211
1134
|
attach: type,
|
|
@@ -1215,10 +1138,8 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1215
1138
|
if (instance.isObject3D) instance.visible = false;
|
|
1216
1139
|
invalidateInstance(instance);
|
|
1217
1140
|
},
|
|
1218
|
-
|
|
1219
1141
|
unhideInstance(instance, props) {
|
|
1220
1142
|
var _instance$__r3f5;
|
|
1221
|
-
|
|
1222
1143
|
// Re-attach when the instance is unhidden
|
|
1223
1144
|
const {
|
|
1224
1145
|
attach: type,
|
|
@@ -1228,7 +1149,6 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1228
1149
|
if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
|
|
1229
1150
|
invalidateInstance(instance);
|
|
1230
1151
|
},
|
|
1231
|
-
|
|
1232
1152
|
createTextInstance: handleTextInstance,
|
|
1233
1153
|
hideTextInstance: handleTextInstance,
|
|
1234
1154
|
unhideTextInstance: handleTextInstance,
|
|
@@ -1249,16 +1169,15 @@ function createRenderer(_roots, _getEventPriority) {
|
|
|
1249
1169
|
};
|
|
1250
1170
|
}
|
|
1251
1171
|
|
|
1172
|
+
// Keys that shouldn't be copied between R3F stores
|
|
1252
1173
|
const privateKeys = ['set', 'get', 'setSize', 'setFrameloop', 'setDpr', 'events', 'invalidate', 'advance', 'size', 'viewport'];
|
|
1253
1174
|
const isRenderer = def => !!(def != null && def.render);
|
|
1254
1175
|
const context = /*#__PURE__*/React__namespace.createContext(null);
|
|
1255
|
-
|
|
1256
1176
|
const createStore = (invalidate, advance) => {
|
|
1257
1177
|
const rootState = create__default["default"]((set, get) => {
|
|
1258
1178
|
const position = new THREE__namespace.Vector3();
|
|
1259
1179
|
const defaultTarget = new THREE__namespace.Vector3();
|
|
1260
1180
|
const tempTarget = new THREE__namespace.Vector3();
|
|
1261
|
-
|
|
1262
1181
|
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
1263
1182
|
const {
|
|
1264
1183
|
width,
|
|
@@ -1269,7 +1188,6 @@ const createStore = (invalidate, advance) => {
|
|
|
1269
1188
|
const aspect = width / height;
|
|
1270
1189
|
if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
1271
1190
|
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
1272
|
-
|
|
1273
1191
|
if (isOrthographicCamera(camera)) {
|
|
1274
1192
|
return {
|
|
1275
1193
|
width: width / camera.zoom,
|
|
@@ -1282,9 +1200,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1282
1200
|
};
|
|
1283
1201
|
} else {
|
|
1284
1202
|
const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
|
|
1285
|
-
|
|
1286
1203
|
const h = 2 * Math.tan(fov / 2) * distance; // visible height
|
|
1287
|
-
|
|
1288
1204
|
const w = h * (width / height);
|
|
1289
1205
|
return {
|
|
1290
1206
|
width: w,
|
|
@@ -1297,15 +1213,13 @@ const createStore = (invalidate, advance) => {
|
|
|
1297
1213
|
};
|
|
1298
1214
|
}
|
|
1299
1215
|
}
|
|
1300
|
-
|
|
1301
1216
|
let performanceTimeout = undefined;
|
|
1302
|
-
|
|
1303
1217
|
const setPerformanceCurrent = current => set(state => ({
|
|
1304
|
-
performance: {
|
|
1218
|
+
performance: {
|
|
1219
|
+
...state.performance,
|
|
1305
1220
|
current
|
|
1306
1221
|
}
|
|
1307
1222
|
}));
|
|
1308
|
-
|
|
1309
1223
|
const pointer = new THREE__namespace.Vector2();
|
|
1310
1224
|
const rootState = {
|
|
1311
1225
|
set,
|
|
@@ -1338,12 +1252,12 @@ const createStore = (invalidate, advance) => {
|
|
|
1338
1252
|
max: 1,
|
|
1339
1253
|
debounce: 200,
|
|
1340
1254
|
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
|
-
|
|
1255
|
+
const state = get();
|
|
1256
|
+
// Clear timeout
|
|
1257
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1258
|
+
// Set lower bound performance
|
|
1259
|
+
if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min);
|
|
1260
|
+
// Go back to upper bound performance after a while unless something regresses meanwhile
|
|
1347
1261
|
performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
|
|
1348
1262
|
}
|
|
1349
1263
|
},
|
|
@@ -1366,8 +1280,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1366
1280
|
factor: 0,
|
|
1367
1281
|
getCurrentViewport
|
|
1368
1282
|
},
|
|
1369
|
-
setEvents: events => set(state => ({
|
|
1370
|
-
|
|
1283
|
+
setEvents: events => set(state => ({
|
|
1284
|
+
...state,
|
|
1285
|
+
events: {
|
|
1286
|
+
...state.events,
|
|
1371
1287
|
...events
|
|
1372
1288
|
}
|
|
1373
1289
|
})),
|
|
@@ -1382,7 +1298,8 @@ const createStore = (invalidate, advance) => {
|
|
|
1382
1298
|
};
|
|
1383
1299
|
set(state => ({
|
|
1384
1300
|
size,
|
|
1385
|
-
viewport: {
|
|
1301
|
+
viewport: {
|
|
1302
|
+
...state.viewport,
|
|
1386
1303
|
...getCurrentViewport(camera, defaultTarget, size)
|
|
1387
1304
|
}
|
|
1388
1305
|
}));
|
|
@@ -1390,23 +1307,23 @@ const createStore = (invalidate, advance) => {
|
|
|
1390
1307
|
setDpr: dpr => set(state => {
|
|
1391
1308
|
const resolved = calculateDpr(dpr);
|
|
1392
1309
|
return {
|
|
1393
|
-
viewport: {
|
|
1310
|
+
viewport: {
|
|
1311
|
+
...state.viewport,
|
|
1394
1312
|
dpr: resolved,
|
|
1395
1313
|
initialDpr: state.viewport.initialDpr || resolved
|
|
1396
1314
|
}
|
|
1397
1315
|
};
|
|
1398
1316
|
}),
|
|
1399
1317
|
setFrameloop: (frameloop = 'always') => {
|
|
1400
|
-
const clock = get().clock;
|
|
1318
|
+
const clock = get().clock;
|
|
1401
1319
|
|
|
1320
|
+
// if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
|
|
1402
1321
|
clock.stop();
|
|
1403
1322
|
clock.elapsedTime = 0;
|
|
1404
|
-
|
|
1405
1323
|
if (frameloop !== 'never') {
|
|
1406
1324
|
clock.start();
|
|
1407
1325
|
clock.elapsedTime = 0;
|
|
1408
1326
|
}
|
|
1409
|
-
|
|
1410
1327
|
set(() => ({
|
|
1411
1328
|
frameloop
|
|
1412
1329
|
}));
|
|
@@ -1424,27 +1341,26 @@ const createStore = (invalidate, advance) => {
|
|
|
1424
1341
|
initialHits: [],
|
|
1425
1342
|
capturedMap: new Map(),
|
|
1426
1343
|
subscribe: (ref, priority, store) => {
|
|
1427
|
-
const internal = get().internal;
|
|
1344
|
+
const internal = get().internal;
|
|
1345
|
+
// If this subscription was given a priority, it takes rendering into its own hands
|
|
1428
1346
|
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1429
1347
|
// As long as this flag is positive there can be no internal rendering at all
|
|
1430
1348
|
// because there could be multiple render subscriptions
|
|
1431
|
-
|
|
1432
1349
|
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1433
1350
|
internal.subscribers.push({
|
|
1434
1351
|
ref,
|
|
1435
1352
|
priority,
|
|
1436
1353
|
store
|
|
1437
|
-
});
|
|
1354
|
+
});
|
|
1355
|
+
// Register subscriber and sort layers from lowest to highest, meaning,
|
|
1438
1356
|
// highest priority renders last (on top of the other frames)
|
|
1439
|
-
|
|
1440
1357
|
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1441
1358
|
return () => {
|
|
1442
1359
|
const internal = get().internal;
|
|
1443
|
-
|
|
1444
1360
|
if (internal != null && internal.subscribers) {
|
|
1445
1361
|
// Decrease manual flag if this subscription had a priority
|
|
1446
|
-
internal.priority = internal.priority - (priority > 0 ? 1 : 0);
|
|
1447
|
-
|
|
1362
|
+
internal.priority = internal.priority - (priority > 0 ? 1 : 0);
|
|
1363
|
+
// Remove subscriber from list
|
|
1448
1364
|
internal.subscribers = internal.subscribers.filter(s => s.ref !== ref);
|
|
1449
1365
|
}
|
|
1450
1366
|
};
|
|
@@ -1464,31 +1380,35 @@ const createStore = (invalidate, advance) => {
|
|
|
1464
1380
|
viewport,
|
|
1465
1381
|
gl,
|
|
1466
1382
|
set
|
|
1467
|
-
} = rootState.getState();
|
|
1383
|
+
} = rootState.getState();
|
|
1468
1384
|
|
|
1385
|
+
// Resize camera and renderer on changes to size and pixelratio
|
|
1469
1386
|
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1470
1387
|
oldSize = size;
|
|
1471
|
-
oldDpr = viewport.dpr;
|
|
1472
|
-
|
|
1388
|
+
oldDpr = viewport.dpr;
|
|
1389
|
+
// Update camera & renderer
|
|
1473
1390
|
updateCamera(camera, size);
|
|
1474
1391
|
gl.setPixelRatio(viewport.dpr);
|
|
1475
1392
|
gl.setSize(size.width, size.height, size.updateStyle);
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1393
|
+
}
|
|
1478
1394
|
|
|
1395
|
+
// Update viewport once the camera changes
|
|
1479
1396
|
if (camera !== oldCamera) {
|
|
1480
|
-
oldCamera = camera;
|
|
1481
|
-
|
|
1397
|
+
oldCamera = camera;
|
|
1398
|
+
// Update viewport
|
|
1482
1399
|
set(state => ({
|
|
1483
|
-
viewport: {
|
|
1400
|
+
viewport: {
|
|
1401
|
+
...state.viewport,
|
|
1484
1402
|
...state.viewport.getCurrentViewport(camera)
|
|
1485
1403
|
}
|
|
1486
1404
|
}));
|
|
1487
1405
|
}
|
|
1488
|
-
});
|
|
1406
|
+
});
|
|
1489
1407
|
|
|
1490
|
-
|
|
1408
|
+
// Invalidate on any change
|
|
1409
|
+
rootState.subscribe(state => invalidate(state));
|
|
1491
1410
|
|
|
1411
|
+
// Return root state
|
|
1492
1412
|
return rootState;
|
|
1493
1413
|
};
|
|
1494
1414
|
|
|
@@ -1499,144 +1419,129 @@ function createSubs(callback, subs) {
|
|
|
1499
1419
|
subs.add(sub);
|
|
1500
1420
|
return () => void subs.delete(sub);
|
|
1501
1421
|
}
|
|
1502
|
-
|
|
1503
1422
|
let i;
|
|
1504
1423
|
let globalEffects = new Set();
|
|
1505
1424
|
let globalAfterEffects = new Set();
|
|
1506
1425
|
let globalTailEffects = new Set();
|
|
1426
|
+
|
|
1507
1427
|
/**
|
|
1508
1428
|
* Adds a global render callback which is called each frame.
|
|
1509
1429
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
|
|
1510
1430
|
*/
|
|
1511
|
-
|
|
1512
1431
|
const addEffect = callback => createSubs(callback, globalEffects);
|
|
1432
|
+
|
|
1513
1433
|
/**
|
|
1514
1434
|
* Adds a global after-render callback which is called each frame.
|
|
1515
1435
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
|
|
1516
1436
|
*/
|
|
1517
|
-
|
|
1518
1437
|
const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
|
|
1438
|
+
|
|
1519
1439
|
/**
|
|
1520
1440
|
* Adds a global callback which is called when rendering stops.
|
|
1521
1441
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
|
|
1522
1442
|
*/
|
|
1523
|
-
|
|
1524
1443
|
const addTail = callback => createSubs(callback, globalTailEffects);
|
|
1525
|
-
|
|
1526
1444
|
function run(effects, timestamp) {
|
|
1527
1445
|
if (!effects.size) return;
|
|
1528
|
-
|
|
1529
1446
|
for (const {
|
|
1530
1447
|
callback
|
|
1531
1448
|
} of effects.values()) {
|
|
1532
1449
|
callback(timestamp);
|
|
1533
1450
|
}
|
|
1534
1451
|
}
|
|
1535
|
-
|
|
1536
1452
|
function flushGlobalEffects(type, timestamp) {
|
|
1537
1453
|
switch (type) {
|
|
1538
1454
|
case 'before':
|
|
1539
1455
|
return run(globalEffects, timestamp);
|
|
1540
|
-
|
|
1541
1456
|
case 'after':
|
|
1542
1457
|
return run(globalAfterEffects, timestamp);
|
|
1543
|
-
|
|
1544
1458
|
case 'tail':
|
|
1545
1459
|
return run(globalTailEffects, timestamp);
|
|
1546
1460
|
}
|
|
1547
1461
|
}
|
|
1548
1462
|
let subscribers;
|
|
1549
1463
|
let subscription;
|
|
1550
|
-
|
|
1551
1464
|
function render$1(timestamp, state, frame) {
|
|
1552
1465
|
// Run local effects
|
|
1553
|
-
let delta = state.clock.getDelta();
|
|
1554
|
-
|
|
1466
|
+
let delta = state.clock.getDelta();
|
|
1467
|
+
// In frameloop='never' mode, clock times are updated using the provided timestamp
|
|
1555
1468
|
if (state.frameloop === 'never' && typeof timestamp === 'number') {
|
|
1556
1469
|
delta = timestamp - state.clock.elapsedTime;
|
|
1557
1470
|
state.clock.oldTime = state.clock.elapsedTime;
|
|
1558
1471
|
state.clock.elapsedTime = timestamp;
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
|
|
1472
|
+
}
|
|
1473
|
+
// Call subscribers (useFrame)
|
|
1562
1474
|
subscribers = state.internal.subscribers;
|
|
1563
|
-
|
|
1564
1475
|
for (i = 0; i < subscribers.length; i++) {
|
|
1565
1476
|
subscription = subscribers[i];
|
|
1566
1477
|
subscription.ref.current(subscription.store.getState(), delta, frame);
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1478
|
+
}
|
|
1479
|
+
// Render content
|
|
1480
|
+
if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera);
|
|
1481
|
+
// Decrease frame count
|
|
1572
1482
|
state.internal.frames = Math.max(0, state.internal.frames - 1);
|
|
1573
1483
|
return state.frameloop === 'always' ? 1 : state.internal.frames;
|
|
1574
1484
|
}
|
|
1575
|
-
|
|
1576
1485
|
function createLoop(roots) {
|
|
1577
1486
|
let running = false;
|
|
1578
1487
|
let repeat;
|
|
1579
1488
|
let frame;
|
|
1580
1489
|
let state;
|
|
1581
|
-
|
|
1582
1490
|
function loop(timestamp) {
|
|
1583
1491
|
frame = requestAnimationFrame(loop);
|
|
1584
1492
|
running = true;
|
|
1585
|
-
repeat = 0;
|
|
1493
|
+
repeat = 0;
|
|
1586
1494
|
|
|
1587
|
-
|
|
1495
|
+
// Run effects
|
|
1496
|
+
flushGlobalEffects('before', timestamp);
|
|
1588
1497
|
|
|
1498
|
+
// Render all roots
|
|
1589
1499
|
for (const root of roots.values()) {
|
|
1590
1500
|
var _state$gl$xr;
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1501
|
+
state = root.store.getState();
|
|
1502
|
+
// If the frameloop is invalidated, do not run another frame
|
|
1594
1503
|
if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
|
|
1595
1504
|
repeat += render$1(timestamp, state);
|
|
1596
1505
|
}
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1506
|
+
}
|
|
1599
1507
|
|
|
1600
|
-
|
|
1508
|
+
// Run after-effects
|
|
1509
|
+
flushGlobalEffects('after', timestamp);
|
|
1601
1510
|
|
|
1511
|
+
// Stop the loop if nothing invalidates it
|
|
1602
1512
|
if (repeat === 0) {
|
|
1603
1513
|
// Tail call effects, they are called when rendering stops
|
|
1604
|
-
flushGlobalEffects('tail', timestamp);
|
|
1514
|
+
flushGlobalEffects('tail', timestamp);
|
|
1605
1515
|
|
|
1516
|
+
// Flag end of operation
|
|
1606
1517
|
running = false;
|
|
1607
1518
|
return cancelAnimationFrame(frame);
|
|
1608
1519
|
}
|
|
1609
1520
|
}
|
|
1610
|
-
|
|
1611
1521
|
function invalidate(state, frames = 1) {
|
|
1612
1522
|
var _state$gl$xr2;
|
|
1613
|
-
|
|
1614
1523
|
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
|
-
|
|
1524
|
+
if ((_state$gl$xr2 = state.gl.xr) != null && _state$gl$xr2.isPresenting || !state.internal.active || state.frameloop === 'never') return;
|
|
1525
|
+
// Increase frames, do not go higher than 60
|
|
1526
|
+
state.internal.frames = Math.min(60, state.internal.frames + frames);
|
|
1527
|
+
// If the render-loop isn't active, start it
|
|
1619
1528
|
if (!running) {
|
|
1620
1529
|
running = true;
|
|
1621
1530
|
requestAnimationFrame(loop);
|
|
1622
1531
|
}
|
|
1623
1532
|
}
|
|
1624
|
-
|
|
1625
1533
|
function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
1626
1534
|
if (runGlobalEffects) flushGlobalEffects('before', timestamp);
|
|
1627
1535
|
if (!state) for (const root of roots.values()) render$1(timestamp, root.store.getState());else render$1(timestamp, state, frame);
|
|
1628
1536
|
if (runGlobalEffects) flushGlobalEffects('after', timestamp);
|
|
1629
1537
|
}
|
|
1630
|
-
|
|
1631
1538
|
return {
|
|
1632
1539
|
loop,
|
|
1633
|
-
|
|
1634
1540
|
/**
|
|
1635
1541
|
* Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
|
|
1636
1542
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
|
|
1637
1543
|
*/
|
|
1638
1544
|
invalidate,
|
|
1639
|
-
|
|
1640
1545
|
/**
|
|
1641
1546
|
* Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
|
|
1642
1547
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
@@ -1661,80 +1566,77 @@ function useStore() {
|
|
|
1661
1566
|
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1662
1567
|
return store;
|
|
1663
1568
|
}
|
|
1569
|
+
|
|
1664
1570
|
/**
|
|
1665
1571
|
* Accesses R3F's internal state, containing renderer, canvas, scene, etc.
|
|
1666
1572
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
|
|
1667
1573
|
*/
|
|
1668
|
-
|
|
1669
1574
|
function useThree(selector = state => state, equalityFn) {
|
|
1670
1575
|
return useStore()(selector, equalityFn);
|
|
1671
1576
|
}
|
|
1577
|
+
|
|
1672
1578
|
/**
|
|
1673
1579
|
* Executes a callback before render in a shared frame loop.
|
|
1674
1580
|
* Can order effects with render priority or manually render with a positive priority.
|
|
1675
1581
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
|
|
1676
1582
|
*/
|
|
1677
|
-
|
|
1678
1583
|
function useFrame(callback, renderPriority = 0) {
|
|
1679
1584
|
const store = useStore();
|
|
1680
|
-
const subscribe = store.getState().internal.subscribe;
|
|
1681
|
-
|
|
1682
|
-
const ref = useMutableCallback(callback);
|
|
1683
|
-
|
|
1585
|
+
const subscribe = store.getState().internal.subscribe;
|
|
1586
|
+
// Memoize ref
|
|
1587
|
+
const ref = useMutableCallback(callback);
|
|
1588
|
+
// Subscribe on mount, unsubscribe on unmount
|
|
1684
1589
|
useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
|
|
1685
1590
|
return null;
|
|
1686
1591
|
}
|
|
1592
|
+
|
|
1687
1593
|
/**
|
|
1688
1594
|
* Returns a node graph of an object with named nodes & materials.
|
|
1689
1595
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
|
|
1690
1596
|
*/
|
|
1691
|
-
|
|
1692
1597
|
function useGraph(object) {
|
|
1693
1598
|
return React__namespace.useMemo(() => buildGraph(object), [object]);
|
|
1694
1599
|
}
|
|
1695
|
-
|
|
1696
1600
|
function loadingFn(extensions, onProgress) {
|
|
1697
1601
|
return function (Proto, ...input) {
|
|
1698
1602
|
// Construct new loader and run extensions
|
|
1699
1603
|
const loader = new Proto();
|
|
1700
|
-
if (extensions) extensions(loader);
|
|
1701
|
-
|
|
1604
|
+
if (extensions) extensions(loader);
|
|
1605
|
+
// Go through the urls and load them
|
|
1702
1606
|
return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
|
|
1703
1607
|
if (data.scene) Object.assign(data, buildGraph(data.scene));
|
|
1704
1608
|
res(data);
|
|
1705
1609
|
}, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
|
|
1706
1610
|
};
|
|
1707
1611
|
}
|
|
1612
|
+
|
|
1708
1613
|
/**
|
|
1709
1614
|
* Synchronously loads and caches assets with a three loader.
|
|
1710
1615
|
*
|
|
1711
1616
|
* Note: this hook's caller must be wrapped with `React.Suspense`
|
|
1712
1617
|
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
|
|
1713
1618
|
*/
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
1619
|
function useLoader(Proto, input, extensions, onProgress) {
|
|
1717
1620
|
// Use suspense to load async assets
|
|
1718
1621
|
const keys = Array.isArray(input) ? input : [input];
|
|
1719
1622
|
const results = suspendReact.suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
|
|
1720
1623
|
equal: is.equ
|
|
1721
|
-
});
|
|
1722
|
-
|
|
1624
|
+
});
|
|
1625
|
+
// Return the object/s
|
|
1723
1626
|
return Array.isArray(input) ? results : results[0];
|
|
1724
1627
|
}
|
|
1628
|
+
|
|
1725
1629
|
/**
|
|
1726
1630
|
* Preloads an asset into cache as a side-effect.
|
|
1727
1631
|
*/
|
|
1728
|
-
|
|
1729
1632
|
useLoader.preload = function (Proto, input, extensions) {
|
|
1730
1633
|
const keys = Array.isArray(input) ? input : [input];
|
|
1731
1634
|
return suspendReact.preload(loadingFn(extensions), [Proto, ...keys]);
|
|
1732
1635
|
};
|
|
1636
|
+
|
|
1733
1637
|
/**
|
|
1734
1638
|
* Removes a loaded asset from cache.
|
|
1735
1639
|
*/
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
1640
|
useLoader.clear = function (Proto, input) {
|
|
1739
1641
|
const keys = Array.isArray(input) ? input : [input];
|
|
1740
1642
|
return suspendReact.clear([Proto, ...keys]);
|
|
@@ -1753,7 +1655,6 @@ const shallowLoose = {
|
|
|
1753
1655
|
objects: 'shallow',
|
|
1754
1656
|
strict: false
|
|
1755
1657
|
};
|
|
1756
|
-
|
|
1757
1658
|
const createRendererInstance = (gl, canvas) => {
|
|
1758
1659
|
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1759
1660
|
if (isRenderer(customRenderer)) return customRenderer;else return new THREE__namespace.WebGLRenderer({
|
|
@@ -1764,16 +1665,13 @@ const createRendererInstance = (gl, canvas) => {
|
|
|
1764
1665
|
...gl
|
|
1765
1666
|
});
|
|
1766
1667
|
};
|
|
1767
|
-
|
|
1768
1668
|
function isCanvas(maybeCanvas) {
|
|
1769
1669
|
return maybeCanvas instanceof HTMLCanvasElement;
|
|
1770
1670
|
}
|
|
1771
|
-
|
|
1772
1671
|
function computeInitialSize(canvas, defaultSize) {
|
|
1773
1672
|
if (defaultSize) {
|
|
1774
1673
|
return defaultSize;
|
|
1775
1674
|
}
|
|
1776
|
-
|
|
1777
1675
|
if (isCanvas(canvas) && canvas.parentElement) {
|
|
1778
1676
|
const {
|
|
1779
1677
|
width,
|
|
@@ -1788,7 +1686,6 @@ function computeInitialSize(canvas, defaultSize) {
|
|
|
1788
1686
|
left
|
|
1789
1687
|
};
|
|
1790
1688
|
}
|
|
1791
|
-
|
|
1792
1689
|
return {
|
|
1793
1690
|
width: 0,
|
|
1794
1691
|
height: 0,
|
|
@@ -1796,29 +1693,33 @@ function computeInitialSize(canvas, defaultSize) {
|
|
|
1796
1693
|
left: 0
|
|
1797
1694
|
};
|
|
1798
1695
|
}
|
|
1799
|
-
|
|
1800
1696
|
function createRoot(canvas) {
|
|
1801
1697
|
// Check against mistaken use of createRoot
|
|
1802
1698
|
const prevRoot = roots.get(canvas);
|
|
1803
1699
|
const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
|
|
1804
1700
|
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
|
|
1701
|
+
if (prevRoot) console.warn('R3F.createRoot should only be called once!');
|
|
1807
1702
|
|
|
1808
|
-
|
|
1703
|
+
// Report when an error was detected in a previous render
|
|
1704
|
+
// https://github.com/pmndrs/react-three-fiber/pull/2261
|
|
1705
|
+
const logRecoverableError = typeof reportError === 'function' ?
|
|
1706
|
+
// In modern browsers, reportError will dispatch an error event,
|
|
1809
1707
|
// emulating an uncaught JavaScript error.
|
|
1810
|
-
reportError :
|
|
1811
|
-
console.error
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
const
|
|
1816
|
-
|
|
1708
|
+
reportError :
|
|
1709
|
+
// In older browsers and test environments, fallback to console.error.
|
|
1710
|
+
console.error;
|
|
1711
|
+
|
|
1712
|
+
// Create store
|
|
1713
|
+
const store = prevStore || createStore(invalidate, advance);
|
|
1714
|
+
// Create renderer
|
|
1715
|
+
const fiber = prevFiber || reconciler.createContainer(store, constants.ConcurrentRoot, null, false, null, '', logRecoverableError, null);
|
|
1716
|
+
// Map it
|
|
1817
1717
|
if (!prevRoot) roots.set(canvas, {
|
|
1818
1718
|
fiber,
|
|
1819
1719
|
store
|
|
1820
|
-
});
|
|
1720
|
+
});
|
|
1821
1721
|
|
|
1722
|
+
// Locals
|
|
1822
1723
|
let onCreated;
|
|
1823
1724
|
let configured = false;
|
|
1824
1725
|
return {
|
|
@@ -1840,108 +1741,121 @@ function createRoot(canvas) {
|
|
|
1840
1741
|
camera: cameraOptions,
|
|
1841
1742
|
onPointerMissed
|
|
1842
1743
|
} = props;
|
|
1843
|
-
let state = store.getState();
|
|
1744
|
+
let state = store.getState();
|
|
1844
1745
|
|
|
1746
|
+
// Set up renderer (one time only!)
|
|
1845
1747
|
let gl = state.gl;
|
|
1846
1748
|
if (!state.gl) state.set({
|
|
1847
1749
|
gl: gl = createRendererInstance(glConfig, canvas)
|
|
1848
|
-
});
|
|
1750
|
+
});
|
|
1849
1751
|
|
|
1752
|
+
// Set up raycaster (one time only!)
|
|
1850
1753
|
let raycaster = state.raycaster;
|
|
1851
1754
|
if (!raycaster) state.set({
|
|
1852
1755
|
raycaster: raycaster = new THREE__namespace.Raycaster()
|
|
1853
|
-
});
|
|
1756
|
+
});
|
|
1854
1757
|
|
|
1758
|
+
// Set raycaster options
|
|
1855
1759
|
const {
|
|
1856
1760
|
params,
|
|
1857
1761
|
...options
|
|
1858
1762
|
} = raycastOptions || {};
|
|
1859
|
-
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
|
|
1763
|
+
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
|
|
1764
|
+
...options
|
|
1860
1765
|
});
|
|
1861
1766
|
if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
|
|
1862
|
-
params: {
|
|
1767
|
+
params: {
|
|
1768
|
+
...raycaster.params,
|
|
1863
1769
|
...params
|
|
1864
1770
|
}
|
|
1865
|
-
});
|
|
1771
|
+
});
|
|
1866
1772
|
|
|
1773
|
+
// Create default camera (one time only!)
|
|
1867
1774
|
if (!state.camera) {
|
|
1868
1775
|
const isCamera = cameraOptions instanceof THREE__namespace.Camera;
|
|
1869
1776
|
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
1777
|
if (!isCamera) {
|
|
1872
1778
|
camera.position.z = 5;
|
|
1873
|
-
if (cameraOptions) applyProps(camera, cameraOptions);
|
|
1874
|
-
|
|
1779
|
+
if (cameraOptions) applyProps(camera, cameraOptions);
|
|
1780
|
+
// Always look at center by default
|
|
1875
1781
|
if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1876
1782
|
}
|
|
1877
|
-
|
|
1878
1783
|
state.set({
|
|
1879
1784
|
camera
|
|
1880
1785
|
});
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1786
|
+
}
|
|
1883
1787
|
|
|
1788
|
+
// Set up XR (one time only!)
|
|
1884
1789
|
if (!state.xr) {
|
|
1885
1790
|
// Handle frame behavior in WebXR
|
|
1886
1791
|
const handleXRFrame = (timestamp, frame) => {
|
|
1887
1792
|
const state = store.getState();
|
|
1888
1793
|
if (state.frameloop === 'never') return;
|
|
1889
1794
|
advance(timestamp, true, state, frame);
|
|
1890
|
-
};
|
|
1891
|
-
|
|
1795
|
+
};
|
|
1892
1796
|
|
|
1797
|
+
// Toggle render switching on session
|
|
1893
1798
|
const handleSessionChange = () => {
|
|
1894
1799
|
const state = store.getState();
|
|
1895
1800
|
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
1896
1801
|
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
1897
1802
|
if (!state.gl.xr.isPresenting) invalidate(state);
|
|
1898
|
-
};
|
|
1899
|
-
|
|
1803
|
+
};
|
|
1900
1804
|
|
|
1805
|
+
// WebXR session manager
|
|
1901
1806
|
const xr = {
|
|
1902
1807
|
connect() {
|
|
1903
1808
|
const gl = store.getState().gl;
|
|
1904
1809
|
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
1905
1810
|
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
1906
1811
|
},
|
|
1907
|
-
|
|
1908
1812
|
disconnect() {
|
|
1909
1813
|
const gl = store.getState().gl;
|
|
1910
1814
|
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
1911
1815
|
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
1912
1816
|
}
|
|
1817
|
+
};
|
|
1913
1818
|
|
|
1914
|
-
|
|
1915
|
-
|
|
1819
|
+
// Subscribe to WebXR session events
|
|
1916
1820
|
if (gl.xr) xr.connect();
|
|
1917
1821
|
state.set({
|
|
1918
1822
|
xr
|
|
1919
1823
|
});
|
|
1920
|
-
}
|
|
1921
|
-
|
|
1824
|
+
}
|
|
1922
1825
|
|
|
1826
|
+
// Set shadowmap
|
|
1923
1827
|
if (gl.shadowMap) {
|
|
1924
|
-
const
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
gl.shadowMap.
|
|
1929
|
-
|
|
1930
|
-
|
|
1828
|
+
const oldEnabled = gl.shadowMap.enabled;
|
|
1829
|
+
const oldType = gl.shadowMap.type;
|
|
1830
|
+
gl.shadowMap.enabled = !!shadows;
|
|
1831
|
+
if (is.boo(shadows)) {
|
|
1832
|
+
gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
|
|
1833
|
+
} else if (is.str(shadows)) {
|
|
1834
|
+
var _types$shadows;
|
|
1835
|
+
const types = {
|
|
1836
|
+
basic: THREE__namespace.BasicShadowMap,
|
|
1837
|
+
percentage: THREE__namespace.PCFShadowMap,
|
|
1838
|
+
soft: THREE__namespace.PCFSoftShadowMap,
|
|
1839
|
+
variance: THREE__namespace.VSMShadowMap
|
|
1840
|
+
};
|
|
1841
|
+
gl.shadowMap.type = (_types$shadows = types[shadows]) != null ? _types$shadows : THREE__namespace.PCFSoftShadowMap;
|
|
1842
|
+
} else if (is.obj(shadows)) {
|
|
1843
|
+
Object.assign(gl.shadowMap, shadows);
|
|
1931
1844
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1845
|
+
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1846
|
+
}
|
|
1935
1847
|
|
|
1848
|
+
// Safely set color management if available.
|
|
1849
|
+
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1936
1850
|
if ('ColorManagement' in THREE__namespace) {
|
|
1937
1851
|
setDeep(THREE__namespace, legacy, ['ColorManagement', 'legacyMode']);
|
|
1938
1852
|
}
|
|
1939
|
-
|
|
1940
1853
|
const outputEncoding = linear ? THREE__namespace.LinearEncoding : THREE__namespace.sRGBEncoding;
|
|
1941
1854
|
const toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
1942
1855
|
if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
|
|
1943
|
-
if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping;
|
|
1856
|
+
if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping;
|
|
1944
1857
|
|
|
1858
|
+
// Update color management state
|
|
1945
1859
|
if (state.legacy !== legacy) state.set(() => ({
|
|
1946
1860
|
legacy
|
|
1947
1861
|
}));
|
|
@@ -1950,40 +1864,40 @@ function createRoot(canvas) {
|
|
|
1950
1864
|
}));
|
|
1951
1865
|
if (state.flat !== flat) state.set(() => ({
|
|
1952
1866
|
flat
|
|
1953
|
-
}));
|
|
1954
|
-
|
|
1955
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig); // Store events internally
|
|
1867
|
+
}));
|
|
1956
1868
|
|
|
1869
|
+
// Set gl props
|
|
1870
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
1871
|
+
// Store events internally
|
|
1957
1872
|
if (events && !state.events.handlers) state.set({
|
|
1958
1873
|
events: events(store)
|
|
1959
|
-
});
|
|
1960
|
-
|
|
1961
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1962
|
-
|
|
1874
|
+
});
|
|
1875
|
+
// Check pixelratio
|
|
1876
|
+
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1877
|
+
// Check size, allow it to take on container bounds initially
|
|
1963
1878
|
const size = computeInitialSize(canvas, propsSize);
|
|
1964
|
-
|
|
1965
1879
|
if (!is.equ(size, state.size, shallowLoose)) {
|
|
1966
1880
|
state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1881
|
+
}
|
|
1882
|
+
// Check frameloop
|
|
1883
|
+
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
1884
|
+
// Check pointer missed
|
|
1972
1885
|
if (!state.onPointerMissed) state.set({
|
|
1973
1886
|
onPointerMissed
|
|
1974
|
-
});
|
|
1975
|
-
|
|
1887
|
+
});
|
|
1888
|
+
// Check performance
|
|
1976
1889
|
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
1977
|
-
performance: {
|
|
1890
|
+
performance: {
|
|
1891
|
+
...state.performance,
|
|
1978
1892
|
...performance
|
|
1979
1893
|
}
|
|
1980
|
-
}));
|
|
1894
|
+
}));
|
|
1981
1895
|
|
|
1896
|
+
// Set locals
|
|
1982
1897
|
onCreated = onCreatedCallback;
|
|
1983
1898
|
configured = true;
|
|
1984
1899
|
return this;
|
|
1985
1900
|
},
|
|
1986
|
-
|
|
1987
1901
|
render(children) {
|
|
1988
1902
|
// The root has to be configured before it can be rendered
|
|
1989
1903
|
if (!configured) this.configure();
|
|
@@ -1995,21 +1909,17 @@ function createRoot(canvas) {
|
|
|
1995
1909
|
}), fiber, null, () => undefined);
|
|
1996
1910
|
return store;
|
|
1997
1911
|
},
|
|
1998
|
-
|
|
1999
1912
|
unmount() {
|
|
2000
1913
|
unmountComponentAtNode(canvas);
|
|
2001
1914
|
}
|
|
2002
|
-
|
|
2003
1915
|
};
|
|
2004
1916
|
}
|
|
2005
|
-
|
|
2006
1917
|
function render(children, canvas, config) {
|
|
2007
1918
|
console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
|
|
2008
1919
|
const root = createRoot(canvas);
|
|
2009
1920
|
root.configure(config);
|
|
2010
1921
|
return root.render(children);
|
|
2011
1922
|
}
|
|
2012
|
-
|
|
2013
1923
|
function Provider({
|
|
2014
1924
|
store,
|
|
2015
1925
|
children,
|
|
@@ -2017,28 +1927,28 @@ function Provider({
|
|
|
2017
1927
|
rootElement
|
|
2018
1928
|
}) {
|
|
2019
1929
|
useIsomorphicLayoutEffect(() => {
|
|
2020
|
-
const state = store.getState();
|
|
2021
|
-
|
|
1930
|
+
const state = store.getState();
|
|
1931
|
+
// Flag the canvas active, rendering will now begin
|
|
2022
1932
|
state.set(state => ({
|
|
2023
|
-
internal: {
|
|
1933
|
+
internal: {
|
|
1934
|
+
...state.internal,
|
|
2024
1935
|
active: true
|
|
2025
1936
|
}
|
|
2026
|
-
}));
|
|
2027
|
-
|
|
2028
|
-
if (onCreated) onCreated(state);
|
|
1937
|
+
}));
|
|
1938
|
+
// Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
|
|
1939
|
+
if (onCreated) onCreated(state);
|
|
1940
|
+
// Connect events to the targets parent, this is done to ensure events are registered on
|
|
2029
1941
|
// a shared target, and not on the canvas itself
|
|
2030
|
-
|
|
2031
|
-
|
|
1942
|
+
if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement);
|
|
1943
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2032
1944
|
}, []);
|
|
2033
1945
|
return /*#__PURE__*/React__namespace.createElement(context.Provider, {
|
|
2034
1946
|
value: store
|
|
2035
1947
|
}, children);
|
|
2036
1948
|
}
|
|
2037
|
-
|
|
2038
1949
|
function unmountComponentAtNode(canvas, callback) {
|
|
2039
1950
|
const root = roots.get(canvas);
|
|
2040
1951
|
const fiber = root == null ? void 0 : root.fiber;
|
|
2041
|
-
|
|
2042
1952
|
if (fiber) {
|
|
2043
1953
|
const state = root == null ? void 0 : root.store.getState();
|
|
2044
1954
|
if (state) state.internal.active = false;
|
|
@@ -2047,7 +1957,6 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
2047
1957
|
setTimeout(() => {
|
|
2048
1958
|
try {
|
|
2049
1959
|
var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
|
|
2050
|
-
|
|
2051
1960
|
state.events.disconnect == null ? void 0 : state.events.disconnect();
|
|
2052
1961
|
(_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();
|
|
2053
1962
|
(_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
|
|
@@ -2063,7 +1972,6 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
2063
1972
|
});
|
|
2064
1973
|
}
|
|
2065
1974
|
}
|
|
2066
|
-
|
|
2067
1975
|
function createPortal(children, container, state) {
|
|
2068
1976
|
return /*#__PURE__*/React__namespace.createElement(Portal, {
|
|
2069
1977
|
key: container.uuid,
|
|
@@ -2072,7 +1980,6 @@ function createPortal(children, container, state) {
|
|
|
2072
1980
|
state: state
|
|
2073
1981
|
});
|
|
2074
1982
|
}
|
|
2075
|
-
|
|
2076
1983
|
function Portal({
|
|
2077
1984
|
state = {},
|
|
2078
1985
|
children,
|
|
@@ -2083,6 +1990,7 @@ function Portal({
|
|
|
2083
1990
|
* the "R3F hooks can only be used within the Canvas component!" warning:
|
|
2084
1991
|
* <Canvas>
|
|
2085
1992
|
* {createPortal(...)} */
|
|
1993
|
+
|
|
2086
1994
|
const {
|
|
2087
1995
|
events,
|
|
2088
1996
|
size,
|
|
@@ -2092,30 +2000,32 @@ function Portal({
|
|
|
2092
2000
|
const [raycaster] = React__namespace.useState(() => new THREE__namespace.Raycaster());
|
|
2093
2001
|
const [pointer] = React__namespace.useState(() => new THREE__namespace.Vector2());
|
|
2094
2002
|
const inject = React__namespace.useCallback((rootState, injectState) => {
|
|
2095
|
-
const intersect = {
|
|
2003
|
+
const intersect = {
|
|
2004
|
+
...rootState
|
|
2096
2005
|
}; // all prev state props
|
|
2006
|
+
|
|
2097
2007
|
// Only the fields of "rootState" that do not differ from injectState
|
|
2098
2008
|
// Some props should be off-limits
|
|
2099
2009
|
// Otherwise filter out the props that are different and let the inject layer take precedence
|
|
2100
|
-
|
|
2101
2010
|
Object.keys(rootState).forEach(key => {
|
|
2102
|
-
if (
|
|
2103
|
-
|
|
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
|
|
2104
2015
|
rootState[key] !== injectState[key]) {
|
|
2105
2016
|
delete intersect[key];
|
|
2106
2017
|
}
|
|
2107
2018
|
});
|
|
2108
2019
|
let viewport = undefined;
|
|
2109
|
-
|
|
2110
2020
|
if (injectState && size) {
|
|
2111
|
-
const camera = injectState.camera;
|
|
2112
|
-
|
|
2113
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
|
|
2114
|
-
|
|
2021
|
+
const camera = injectState.camera;
|
|
2022
|
+
// Calculate the override viewport, if present
|
|
2023
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
|
|
2024
|
+
// Update the portal camera, if it differs from the previous layer
|
|
2115
2025
|
if (camera !== rootState.camera) updateCamera(camera, size);
|
|
2116
2026
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2027
|
+
return {
|
|
2028
|
+
// The intersect consists of the previous root state
|
|
2119
2029
|
...intersect,
|
|
2120
2030
|
// Portals have their own scene, which forms the root, a raycaster and a pointer
|
|
2121
2031
|
scene: container,
|
|
@@ -2125,14 +2035,17 @@ function Portal({
|
|
|
2125
2035
|
// Their previous root is the layer before it
|
|
2126
2036
|
previousRoot,
|
|
2127
2037
|
// Events, size and viewport can be overridden by the inject layer
|
|
2128
|
-
events: {
|
|
2038
|
+
events: {
|
|
2039
|
+
...rootState.events,
|
|
2129
2040
|
...(injectState == null ? void 0 : injectState.events),
|
|
2130
2041
|
...events
|
|
2131
2042
|
},
|
|
2132
|
-
size: {
|
|
2043
|
+
size: {
|
|
2044
|
+
...rootState.size,
|
|
2133
2045
|
...size
|
|
2134
2046
|
},
|
|
2135
|
-
viewport: {
|
|
2047
|
+
viewport: {
|
|
2048
|
+
...rootState.viewport,
|
|
2136
2049
|
...viewport
|
|
2137
2050
|
},
|
|
2138
2051
|
...rest
|
|
@@ -2141,16 +2054,19 @@ function Portal({
|
|
|
2141
2054
|
const [usePortalStore] = React__namespace.useState(() => {
|
|
2142
2055
|
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
2143
2056
|
const previousState = previousRoot.getState();
|
|
2144
|
-
const store = create__default["default"]((set, get) => ({
|
|
2057
|
+
const store = create__default["default"]((set, get) => ({
|
|
2058
|
+
...previousState,
|
|
2145
2059
|
scene: container,
|
|
2146
2060
|
raycaster,
|
|
2147
2061
|
pointer,
|
|
2148
2062
|
mouse: pointer,
|
|
2149
2063
|
previousRoot,
|
|
2150
|
-
events: {
|
|
2064
|
+
events: {
|
|
2065
|
+
...previousState.events,
|
|
2151
2066
|
...events
|
|
2152
2067
|
},
|
|
2153
|
-
size: {
|
|
2068
|
+
size: {
|
|
2069
|
+
...previousState.size,
|
|
2154
2070
|
...size
|
|
2155
2071
|
},
|
|
2156
2072
|
...rest,
|
|
@@ -2158,8 +2074,10 @@ function Portal({
|
|
|
2158
2074
|
set,
|
|
2159
2075
|
get,
|
|
2160
2076
|
// Layers are allowed to override events
|
|
2161
|
-
setEvents: events => set(state => ({
|
|
2162
|
-
|
|
2077
|
+
setEvents: events => set(state => ({
|
|
2078
|
+
...state,
|
|
2079
|
+
events: {
|
|
2080
|
+
...state.events,
|
|
2163
2081
|
...events
|
|
2164
2082
|
}
|
|
2165
2083
|
}))
|
|
@@ -2181,7 +2099,6 @@ function Portal({
|
|
|
2181
2099
|
value: usePortalStore
|
|
2182
2100
|
}, children), usePortalStore, null));
|
|
2183
2101
|
}
|
|
2184
|
-
|
|
2185
2102
|
reconciler.injectIntoDevTools({
|
|
2186
2103
|
bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
|
|
2187
2104
|
rendererPackageName: '@react-three/fiber',
|