@react-three/fiber 9.0.0-alpha.0 → 9.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -0
- package/dist/declarations/src/core/hooks.d.ts +5 -1
- package/dist/declarations/src/core/index.d.ts +8 -9
- package/dist/declarations/src/core/loop.d.ts +2 -0
- package/dist/declarations/src/core/renderer.d.ts +30 -41
- package/dist/declarations/src/core/store.d.ts +1 -2
- package/dist/declarations/src/core/utils.d.ts +29 -30
- package/dist/declarations/src/index.d.ts +1 -3
- package/dist/declarations/src/native/Canvas.d.ts +2 -2
- package/dist/declarations/src/native.d.ts +1 -3
- package/dist/declarations/src/three-types.d.ts +34 -318
- package/dist/declarations/src/web/Canvas.d.ts +4 -2
- package/dist/{index-e27d4a05.esm.js → index-47b7622a.esm.js} +831 -877
- package/dist/{index-b3be5a63.cjs.dev.js → index-5bd4d3cf.cjs.dev.js} +832 -877
- package/dist/{index-b12f488b.cjs.prod.js → index-8128f248.cjs.prod.js} +832 -877
- package/dist/react-three-fiber.cjs.dev.js +39 -11
- package/dist/react-three-fiber.cjs.prod.js +39 -11
- package/dist/react-three-fiber.esm.js +39 -11
- package/native/dist/react-three-fiber-native.cjs.dev.js +21 -11
- package/native/dist/react-three-fiber-native.cjs.prod.js +21 -11
- package/native/dist/react-three-fiber-native.esm.js +21 -11
- package/package.json +2 -1
- package/readme.md +1 -1
|
@@ -33,12 +33,9 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
33
33
|
var create__default = /*#__PURE__*/_interopDefault(create);
|
|
34
34
|
var Reconciler__default = /*#__PURE__*/_interopDefault(Reconciler);
|
|
35
35
|
|
|
36
|
-
var threeTypes = /*#__PURE__*/Object.freeze({
|
|
37
|
-
__proto__: null
|
|
38
|
-
});
|
|
39
|
-
|
|
40
36
|
var _window$document, _window$navigator;
|
|
41
37
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
38
|
+
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
42
39
|
/**
|
|
43
40
|
* An SSR-friendly useLayoutEffect.
|
|
44
41
|
*
|
|
@@ -72,8 +69,8 @@ class ErrorBoundary extends React__namespace.Component {
|
|
|
72
69
|
};
|
|
73
70
|
}
|
|
74
71
|
|
|
75
|
-
componentDidCatch(
|
|
76
|
-
this.props.set(
|
|
72
|
+
componentDidCatch(err) {
|
|
73
|
+
this.props.set(err);
|
|
77
74
|
}
|
|
78
75
|
|
|
79
76
|
render() {
|
|
@@ -86,10 +83,9 @@ ErrorBoundary.getDerivedStateFromError = () => ({
|
|
|
86
83
|
error: true
|
|
87
84
|
});
|
|
88
85
|
|
|
89
|
-
const DEFAULT = '__default';
|
|
90
|
-
const isDiffSet = def => def && !!def.memoized && !!def.changes;
|
|
91
86
|
function calculateDpr(dpr) {
|
|
92
|
-
|
|
87
|
+
const target = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
|
|
88
|
+
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
93
89
|
}
|
|
94
90
|
/**
|
|
95
91
|
* Returns instance root state
|
|
@@ -157,250 +153,225 @@ function buildGraph(object) {
|
|
|
157
153
|
}
|
|
158
154
|
|
|
159
155
|
return data;
|
|
160
|
-
}
|
|
161
|
-
|
|
156
|
+
}
|
|
157
|
+
// Disposes an object and all its properties
|
|
162
158
|
function dispose(obj) {
|
|
163
|
-
if (obj.
|
|
159
|
+
if (obj.type !== 'Scene') obj.dispose == null ? void 0 : obj.dispose();
|
|
164
160
|
|
|
165
161
|
for (const p in obj) {
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
const prop = obj[p];
|
|
163
|
+
if ((prop == null ? void 0 : prop.type) !== 'Scene') prop == null ? void 0 : prop.dispose == null ? void 0 : prop.dispose();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const REACT_INTERNAL_PROPS = ['children', 'key', 'ref']; // Gets only instance props from reconciler fibers
|
|
167
|
+
|
|
168
|
+
function getInstanceProps(queue) {
|
|
169
|
+
const props = {};
|
|
170
|
+
|
|
171
|
+
for (const key in queue) {
|
|
172
|
+
if (!REACT_INTERNAL_PROPS.includes(key)) props[key] = queue[key];
|
|
168
173
|
}
|
|
174
|
+
|
|
175
|
+
return props;
|
|
169
176
|
} // Each object in the scene carries a small LocalState descriptor
|
|
170
177
|
|
|
171
|
-
function prepare(
|
|
172
|
-
const
|
|
178
|
+
function prepare(target, root, type, props) {
|
|
179
|
+
const object = target; // Create instance descriptor
|
|
173
180
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
181
|
+
let instance = object.__r3f;
|
|
182
|
+
|
|
183
|
+
if (!instance) {
|
|
184
|
+
instance = {
|
|
185
|
+
root,
|
|
186
|
+
type,
|
|
187
|
+
parent: null,
|
|
188
|
+
children: [],
|
|
189
|
+
props: getInstanceProps(props),
|
|
190
|
+
object,
|
|
180
191
|
eventCount: 0,
|
|
181
192
|
handlers: {},
|
|
182
|
-
|
|
183
|
-
parent: null,
|
|
184
|
-
...state
|
|
193
|
+
isHidden: false
|
|
185
194
|
};
|
|
195
|
+
object.__r3f = instance;
|
|
186
196
|
}
|
|
187
197
|
|
|
188
|
-
return
|
|
198
|
+
return instance;
|
|
189
199
|
}
|
|
200
|
+
function resolve(root, key) {
|
|
201
|
+
var _target;
|
|
190
202
|
|
|
191
|
-
|
|
192
|
-
|
|
203
|
+
let target = root[key];
|
|
204
|
+
if (!key.includes('-')) return {
|
|
205
|
+
root,
|
|
206
|
+
key,
|
|
207
|
+
target
|
|
208
|
+
}; // Resolve pierced target
|
|
193
209
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
target,
|
|
204
|
-
key
|
|
210
|
+
const chain = key.split('-');
|
|
211
|
+
target = chain.reduce((acc, key) => acc[key], root);
|
|
212
|
+
key = chain.pop(); // Switch root if atomic
|
|
213
|
+
|
|
214
|
+
if (!((_target = target) != null && _target.set)) root = chain.reduce((acc, key) => acc[key], root);
|
|
215
|
+
return {
|
|
216
|
+
root,
|
|
217
|
+
key,
|
|
218
|
+
target
|
|
205
219
|
};
|
|
206
220
|
} // Checks if a dash-cased string ends with an integer
|
|
207
221
|
|
|
208
|
-
|
|
209
222
|
const INDEX_REGEX = /-\d+$/;
|
|
210
|
-
function attach(parent, child
|
|
211
|
-
if (is.str(
|
|
223
|
+
function attach(parent, child) {
|
|
224
|
+
if (is.str(child.props.attach)) {
|
|
212
225
|
// If attaching into an array (foo-0), create one
|
|
213
|
-
if (INDEX_REGEX.test(
|
|
214
|
-
const
|
|
226
|
+
if (INDEX_REGEX.test(child.props.attach)) {
|
|
227
|
+
const index = child.props.attach.replace(INDEX_REGEX, '');
|
|
215
228
|
const {
|
|
216
|
-
|
|
229
|
+
root,
|
|
217
230
|
key
|
|
218
|
-
} = resolve(parent,
|
|
219
|
-
if (!Array.isArray(
|
|
231
|
+
} = resolve(parent.object, index);
|
|
232
|
+
if (!Array.isArray(root[key])) root[key] = [];
|
|
220
233
|
}
|
|
221
234
|
|
|
222
235
|
const {
|
|
223
|
-
|
|
236
|
+
root,
|
|
224
237
|
key
|
|
225
|
-
} = resolve(parent,
|
|
226
|
-
child.
|
|
227
|
-
|
|
228
|
-
} else child.
|
|
238
|
+
} = resolve(parent.object, child.props.attach);
|
|
239
|
+
child.previousAttach = root[key];
|
|
240
|
+
root[key] = child.object;
|
|
241
|
+
} else if (is.fun(child.props.attach)) {
|
|
242
|
+
child.previousAttach = child.props.attach(parent.object, child.object);
|
|
243
|
+
}
|
|
229
244
|
}
|
|
230
|
-
function detach(parent, child
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (is.str(type)) {
|
|
245
|
+
function detach(parent, child) {
|
|
246
|
+
if (is.str(child.props.attach)) {
|
|
234
247
|
const {
|
|
235
|
-
|
|
248
|
+
root,
|
|
236
249
|
key
|
|
237
|
-
} = resolve(parent,
|
|
238
|
-
const previous = child.
|
|
239
|
-
|
|
240
|
-
if (previous === undefined) delete
|
|
241
|
-
else
|
|
242
|
-
} else
|
|
243
|
-
|
|
244
|
-
(_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
|
|
245
|
-
} // This function prepares a set of changes to be applied to the instance
|
|
246
|
-
|
|
247
|
-
function diffProps(instance, {
|
|
248
|
-
children: cN,
|
|
249
|
-
key: kN,
|
|
250
|
-
ref: rN,
|
|
251
|
-
...props
|
|
252
|
-
}, {
|
|
253
|
-
children: cP,
|
|
254
|
-
key: kP,
|
|
255
|
-
ref: rP,
|
|
256
|
-
...previous
|
|
257
|
-
} = {}, remove = false) {
|
|
258
|
-
var _instance$__r3f;
|
|
259
|
-
|
|
260
|
-
const localState = (_instance$__r3f = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f : {};
|
|
261
|
-
const entries = Object.entries(props);
|
|
262
|
-
const changes = []; // Catch removed props, prepend them so they can be reset or removed
|
|
263
|
-
|
|
264
|
-
if (remove) {
|
|
265
|
-
const previousKeys = Object.keys(previous);
|
|
266
|
-
|
|
267
|
-
for (let i = 0; i < previousKeys.length; i++) {
|
|
268
|
-
if (!props.hasOwnProperty(previousKeys[i])) entries.unshift([previousKeys[i], DEFAULT + 'remove']);
|
|
269
|
-
}
|
|
250
|
+
} = resolve(parent.object, child.props.attach);
|
|
251
|
+
const previous = child.previousAttach; // When the previous value was undefined, it means the value was never set to begin with
|
|
252
|
+
|
|
253
|
+
if (previous === undefined) delete root[key]; // Otherwise set the previous value
|
|
254
|
+
else root[key] = previous;
|
|
255
|
+
} else {
|
|
256
|
+
child.previousAttach == null ? void 0 : child.previousAttach(parent.object, child.object);
|
|
270
257
|
}
|
|
271
258
|
|
|
272
|
-
|
|
273
|
-
|
|
259
|
+
delete child.previousAttach;
|
|
260
|
+
}
|
|
261
|
+
const RESERVED_PROPS = [...REACT_INTERNAL_PROPS, // Instance props
|
|
262
|
+
'args', 'dispose', 'attach', 'object', // Behavior flags
|
|
263
|
+
'dispose']; // This function prepares a set of changes to be applied to the instance
|
|
274
264
|
|
|
275
|
-
|
|
276
|
-
|
|
265
|
+
function diffProps(instance, newProps, resetRemoved = false) {
|
|
266
|
+
const changedProps = {}; // Sort through props
|
|
277
267
|
|
|
278
|
-
|
|
268
|
+
for (const prop in newProps) {
|
|
269
|
+
// Skip reserved keys
|
|
270
|
+
if (RESERVED_PROPS.includes(prop)) continue; // Skip if props match
|
|
279
271
|
|
|
280
|
-
if (
|
|
272
|
+
if (is.equ(newProps[prop], instance.props[prop])) continue; // Props changed, add them
|
|
281
273
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
changes.push([key, value, false, entries]);
|
|
285
|
-
});
|
|
286
|
-
const memoized = { ...props
|
|
287
|
-
};
|
|
288
|
-
if (localState.memoizedProps && localState.memoizedProps.args) memoized.args = localState.memoizedProps.args;
|
|
289
|
-
if (localState.memoizedProps && localState.memoizedProps.attach) memoized.attach = localState.memoizedProps.attach;
|
|
290
|
-
return {
|
|
291
|
-
memoized,
|
|
292
|
-
changes
|
|
293
|
-
};
|
|
294
|
-
} // This function applies a set of changes to the instance
|
|
295
|
-
|
|
296
|
-
function applyProps$1(instance, data) {
|
|
297
|
-
var _instance$__r3f3, _root$getState;
|
|
298
|
-
|
|
299
|
-
// Filter equals, events and reserved props
|
|
300
|
-
const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
301
|
-
const root = localState.root;
|
|
302
|
-
const rootState = (_root$getState = root == null ? void 0 : root.getState == null ? void 0 : root.getState()) != null ? _root$getState : {};
|
|
303
|
-
const {
|
|
304
|
-
memoized,
|
|
305
|
-
changes
|
|
306
|
-
} = isDiffSet(data) ? data : diffProps(instance, data);
|
|
307
|
-
const prevHandlers = localState.eventCount; // Prepare memoized props
|
|
308
|
-
|
|
309
|
-
if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
|
|
310
|
-
changes.forEach(([key, value, isEvent, keys]) => {
|
|
311
|
-
let currentInstance = instance;
|
|
312
|
-
let targetProp = currentInstance[key]; // Revolve dashed props
|
|
313
|
-
|
|
314
|
-
if (keys.length) {
|
|
315
|
-
targetProp = keys.reduce((acc, key) => acc[key], instance); // If the target is atomic, it forces us to switch the root
|
|
316
|
-
|
|
317
|
-
if (!(targetProp && targetProp.set)) {
|
|
318
|
-
const [name, ...reverseEntries] = keys.reverse();
|
|
319
|
-
currentInstance = reverseEntries.reverse().reduce((acc, key) => acc[key], instance);
|
|
320
|
-
key = name;
|
|
321
|
-
}
|
|
322
|
-
} // https://github.com/mrdoob/three.js/issues/21209
|
|
323
|
-
// HMR/fast-refresh relies on the ability to cancel out props, but threejs
|
|
324
|
-
// has no means to do this. Hence we curate a small collection of value-classes
|
|
325
|
-
// with their respective constructor/set arguments
|
|
326
|
-
// For removed props, try to set default values, if possible
|
|
274
|
+
changedProps[prop] = newProps[prop];
|
|
275
|
+
} // Reset removed props for HMR
|
|
327
276
|
|
|
328
277
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
278
|
+
if (resetRemoved) {
|
|
279
|
+
for (const prop in instance.props) {
|
|
280
|
+
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
281
|
+
const {
|
|
282
|
+
root,
|
|
283
|
+
key
|
|
284
|
+
} = resolve(instance.object, prop); // https://github.com/mrdoob/three.js/issues/21209
|
|
285
|
+
// HMR/fast-refresh relies on the ability to cancel out props, but threejs
|
|
286
|
+
// has no means to do this. Hence we curate a small collection of value-classes
|
|
287
|
+
// with their respective constructor/set arguments
|
|
288
|
+
// For removed props, try to set default values, if possible
|
|
332
289
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
} else if (currentInstance.constructor) {
|
|
336
|
-
var _currentInstance$__r;
|
|
290
|
+
if (root.constructor) {
|
|
291
|
+
var _root$__r3f$props$arg, _root$__r3f;
|
|
337
292
|
|
|
338
293
|
// create a blank slate of the instance and copy the particular parameter.
|
|
339
294
|
// @ts-ignore
|
|
340
|
-
const defaultClassCall = new
|
|
341
|
-
|
|
295
|
+
const defaultClassCall = new root.constructor(...((_root$__r3f$props$arg = (_root$__r3f = root.__r3f) == null ? void 0 : _root$__r3f.props.args) != null ? _root$__r3f$props$arg : []));
|
|
296
|
+
changedProps[key] = defaultClassCall[key]; // destroy the instance
|
|
342
297
|
|
|
343
|
-
if (defaultClassCall.dispose) defaultClassCall.dispose();
|
|
298
|
+
if (defaultClassCall.dispose) defaultClassCall.dispose();
|
|
344
299
|
} else {
|
|
345
|
-
|
|
300
|
+
// instance does not have constructor, just set it to 0
|
|
301
|
+
changedProps[key] = 0;
|
|
346
302
|
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if (isEvent) {
|
|
351
|
-
if (value) localState.handlers[key] = value;else delete localState.handlers[key];
|
|
352
|
-
localState.eventCount = Object.keys(localState.handlers).length;
|
|
353
|
-
} // Special treatment for objects with support for set/copy, and layers
|
|
354
|
-
else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE__namespace.Layers)) {
|
|
355
|
-
// If value is an array
|
|
356
|
-
if (Array.isArray(value)) {
|
|
357
|
-
if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
|
|
358
|
-
} // Test again target.copy(class) next ...
|
|
359
|
-
else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) {
|
|
360
|
-
targetProp.copy(value);
|
|
361
|
-
} // If nothing else fits, just set the single value, ignore undefined
|
|
362
|
-
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
363
|
-
else if (value !== undefined) {
|
|
364
|
-
const isColor = targetProp instanceof THREE__namespace.Color; // Allow setting array scalars
|
|
365
|
-
|
|
366
|
-
if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
|
|
367
|
-
else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
|
|
368
|
-
else targetProp.set(value);
|
|
369
|
-
} // Else, just overwrite the value
|
|
303
|
+
}
|
|
304
|
+
}
|
|
370
305
|
|
|
371
|
-
|
|
372
|
-
|
|
306
|
+
return changedProps;
|
|
307
|
+
} // This function applies a set of changes to the instance
|
|
308
|
+
|
|
309
|
+
function applyProps(object, props) {
|
|
310
|
+
const instance = object.__r3f;
|
|
311
|
+
const rootState = instance == null ? void 0 : instance.root.getState();
|
|
312
|
+
const prevHandlers = instance == null ? void 0 : instance.eventCount;
|
|
313
|
+
|
|
314
|
+
for (const prop in props) {
|
|
315
|
+
let value = props[prop]; // Don't mutate reserved keys
|
|
316
|
+
|
|
317
|
+
if (RESERVED_PROPS.includes(prop)) continue; // Deal with pointer events ...
|
|
318
|
+
|
|
319
|
+
if (instance && /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(prop)) {
|
|
320
|
+
if (typeof value === 'function') instance.handlers[prop] = value;else delete instance.handlers[prop];
|
|
321
|
+
instance.eventCount = Object.keys(instance.handlers).length;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const {
|
|
325
|
+
root,
|
|
326
|
+
key,
|
|
327
|
+
target
|
|
328
|
+
} = resolve(object, prop); // Copy if properties match signatures
|
|
329
|
+
|
|
330
|
+
if (target != null && target.copy && (target == null ? void 0 : target.constructor) === (value == null ? void 0 : value.constructor)) {
|
|
331
|
+
target.copy(value);
|
|
332
|
+
} // Layers have no copy function, we must therefore copy the mask property
|
|
333
|
+
else if (target instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) {
|
|
334
|
+
target.mask = value.mask;
|
|
335
|
+
} // Set array types
|
|
336
|
+
else if (target != null && target.set && Array.isArray(value)) {
|
|
337
|
+
if (target.fromArray) target.fromArray(value);else target.set(...value);
|
|
338
|
+
} // Set literal types, ignore undefined
|
|
339
|
+
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
340
|
+
else if (target != null && target.set && typeof value !== 'object') {
|
|
341
|
+
const isColor = target instanceof THREE__namespace.Color; // Allow setting array scalars
|
|
342
|
+
|
|
343
|
+
if (!isColor && target.setScalar && typeof value === 'number') target.setScalar(value); // Otherwise just set ...
|
|
344
|
+
else if (value !== undefined) target.set(value);
|
|
345
|
+
} // Else, just overwrite the value
|
|
346
|
+
else {
|
|
347
|
+
root[key] = value; // Auto-convert sRGB textures, for now ...
|
|
373
348
|
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
374
349
|
|
|
375
|
-
if (!rootState.linear &&
|
|
376
|
-
|
|
350
|
+
if (!(rootState != null && rootState.linear) && root[key] instanceof THREE__namespace.Texture) {
|
|
351
|
+
root[key].encoding = THREE__namespace.sRGBEncoding;
|
|
377
352
|
}
|
|
378
353
|
}
|
|
354
|
+
}
|
|
379
355
|
|
|
380
|
-
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
|
|
356
|
+
if (instance != null && instance.parent && rootState != null && rootState.internal && instance.object instanceof THREE__namespace.Object3D && prevHandlers !== instance.eventCount) {
|
|
384
357
|
// Pre-emptively remove the instance from the interaction manager
|
|
385
|
-
const index = rootState.internal.interaction.indexOf(instance);
|
|
358
|
+
const index = rootState.internal.interaction.indexOf(instance.object);
|
|
386
359
|
if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
|
|
387
360
|
|
|
388
|
-
if (
|
|
389
|
-
|
|
390
|
-
|
|
361
|
+
if (instance.eventCount && instance.object.raycast !== null && instance.object instanceof THREE__namespace.Object3D) {
|
|
362
|
+
rootState.internal.interaction.push(instance.object);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
391
365
|
|
|
392
|
-
if (
|
|
393
|
-
return
|
|
366
|
+
if (instance) invalidateInstance(instance);
|
|
367
|
+
return object;
|
|
394
368
|
}
|
|
395
369
|
function invalidateInstance(instance) {
|
|
396
|
-
var _instance$
|
|
370
|
+
var _instance$root;
|
|
397
371
|
|
|
398
|
-
const state = (_instance$
|
|
372
|
+
const state = (_instance$root = instance.root) == null ? void 0 : _instance$root.getState == null ? void 0 : _instance$root.getState();
|
|
399
373
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
400
374
|
}
|
|
401
|
-
function updateInstance(instance) {
|
|
402
|
-
instance.onUpdate == null ? void 0 : instance.onUpdate(instance);
|
|
403
|
-
}
|
|
404
375
|
function updateCamera(camera, size) {
|
|
405
376
|
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
406
377
|
// Do not mess with the camera if it belongs to the user
|
|
@@ -421,6 +392,280 @@ function updateCamera(camera, size) {
|
|
|
421
392
|
}
|
|
422
393
|
}
|
|
423
394
|
|
|
395
|
+
// Keys that shouldn't be copied between R3F stores
|
|
396
|
+
const privateKeys = ['set', 'get', 'setSize', 'setFrameloop', 'setDpr', 'events', 'invalidate', 'advance', 'size', 'viewport'];
|
|
397
|
+
const isRenderer = def => !!(def != null && def.render);
|
|
398
|
+
const context = /*#__PURE__*/React__namespace.createContext(null);
|
|
399
|
+
|
|
400
|
+
const createStore = (invalidate, advance) => {
|
|
401
|
+
const rootStore = create__default["default"]((set, get) => {
|
|
402
|
+
const position = new THREE__namespace.Vector3();
|
|
403
|
+
const defaultTarget = new THREE__namespace.Vector3();
|
|
404
|
+
const tempTarget = new THREE__namespace.Vector3();
|
|
405
|
+
|
|
406
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
407
|
+
const {
|
|
408
|
+
width,
|
|
409
|
+
height,
|
|
410
|
+
top,
|
|
411
|
+
left
|
|
412
|
+
} = size;
|
|
413
|
+
const aspect = width / height;
|
|
414
|
+
if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
415
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
416
|
+
|
|
417
|
+
if (isOrthographicCamera(camera)) {
|
|
418
|
+
return {
|
|
419
|
+
width: width / camera.zoom,
|
|
420
|
+
height: height / camera.zoom,
|
|
421
|
+
top,
|
|
422
|
+
left,
|
|
423
|
+
factor: 1,
|
|
424
|
+
distance,
|
|
425
|
+
aspect
|
|
426
|
+
};
|
|
427
|
+
} else {
|
|
428
|
+
const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
|
|
429
|
+
|
|
430
|
+
const h = 2 * Math.tan(fov / 2) * distance; // visible height
|
|
431
|
+
|
|
432
|
+
const w = h * (width / height);
|
|
433
|
+
return {
|
|
434
|
+
width: w,
|
|
435
|
+
height: h,
|
|
436
|
+
top,
|
|
437
|
+
left,
|
|
438
|
+
factor: width / w,
|
|
439
|
+
distance,
|
|
440
|
+
aspect
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
let performanceTimeout = undefined;
|
|
446
|
+
|
|
447
|
+
const setPerformanceCurrent = current => set(state => ({
|
|
448
|
+
performance: { ...state.performance,
|
|
449
|
+
current
|
|
450
|
+
}
|
|
451
|
+
}));
|
|
452
|
+
|
|
453
|
+
const pointer = new THREE__namespace.Vector2();
|
|
454
|
+
const rootState = {
|
|
455
|
+
set,
|
|
456
|
+
get,
|
|
457
|
+
// Mock objects that have to be configured
|
|
458
|
+
gl: null,
|
|
459
|
+
camera: null,
|
|
460
|
+
raycaster: null,
|
|
461
|
+
events: {
|
|
462
|
+
priority: 1,
|
|
463
|
+
enabled: true,
|
|
464
|
+
connected: false
|
|
465
|
+
},
|
|
466
|
+
xr: null,
|
|
467
|
+
invalidate: (frames = 1) => invalidate(get(), frames),
|
|
468
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
469
|
+
legacy: false,
|
|
470
|
+
linear: false,
|
|
471
|
+
flat: false,
|
|
472
|
+
scene: new THREE__namespace.Scene(),
|
|
473
|
+
controls: null,
|
|
474
|
+
clock: new THREE__namespace.Clock(),
|
|
475
|
+
pointer,
|
|
476
|
+
mouse: pointer,
|
|
477
|
+
frameloop: 'always',
|
|
478
|
+
onPointerMissed: undefined,
|
|
479
|
+
performance: {
|
|
480
|
+
current: 1,
|
|
481
|
+
min: 0.5,
|
|
482
|
+
max: 1,
|
|
483
|
+
debounce: 200,
|
|
484
|
+
regress: () => {
|
|
485
|
+
const state = get(); // Clear timeout
|
|
486
|
+
|
|
487
|
+
if (performanceTimeout) clearTimeout(performanceTimeout); // Set lower bound performance
|
|
488
|
+
|
|
489
|
+
if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min); // Go back to upper bound performance after a while unless something regresses meanwhile
|
|
490
|
+
|
|
491
|
+
performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
size: {
|
|
495
|
+
width: 0,
|
|
496
|
+
height: 0,
|
|
497
|
+
top: 0,
|
|
498
|
+
left: 0
|
|
499
|
+
},
|
|
500
|
+
viewport: {
|
|
501
|
+
initialDpr: 0,
|
|
502
|
+
dpr: 0,
|
|
503
|
+
width: 0,
|
|
504
|
+
height: 0,
|
|
505
|
+
top: 0,
|
|
506
|
+
left: 0,
|
|
507
|
+
aspect: 0,
|
|
508
|
+
distance: 0,
|
|
509
|
+
factor: 0,
|
|
510
|
+
getCurrentViewport
|
|
511
|
+
},
|
|
512
|
+
setEvents: events => set(state => ({ ...state,
|
|
513
|
+
events: { ...state.events,
|
|
514
|
+
...events
|
|
515
|
+
}
|
|
516
|
+
})),
|
|
517
|
+
setSize: (width, height, top = 0, left = 0) => {
|
|
518
|
+
const camera = get().camera;
|
|
519
|
+
const size = {
|
|
520
|
+
width,
|
|
521
|
+
height,
|
|
522
|
+
top,
|
|
523
|
+
left
|
|
524
|
+
};
|
|
525
|
+
set(state => ({
|
|
526
|
+
size,
|
|
527
|
+
viewport: { ...state.viewport,
|
|
528
|
+
...getCurrentViewport(camera, defaultTarget, size)
|
|
529
|
+
}
|
|
530
|
+
}));
|
|
531
|
+
},
|
|
532
|
+
setDpr: dpr => set(state => {
|
|
533
|
+
const resolved = calculateDpr(dpr);
|
|
534
|
+
return {
|
|
535
|
+
viewport: { ...state.viewport,
|
|
536
|
+
dpr: resolved,
|
|
537
|
+
initialDpr: state.viewport.initialDpr || resolved
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}),
|
|
541
|
+
setFrameloop: frameloop => {
|
|
542
|
+
var _frameloop$mode, _frameloop$render, _frameloop$maxDelta;
|
|
543
|
+
|
|
544
|
+
const state = get();
|
|
545
|
+
const mode = typeof frameloop === 'string' ? frameloop : (frameloop == null ? void 0 : frameloop.mode) === 'auto' ? 'always' : (_frameloop$mode = frameloop == null ? void 0 : frameloop.mode) != null ? _frameloop$mode : state.frameloop;
|
|
546
|
+
const render = typeof frameloop === 'string' ? state.internal.render : (_frameloop$render = frameloop == null ? void 0 : frameloop.render) != null ? _frameloop$render : state.internal.render;
|
|
547
|
+
const maxDelta = typeof frameloop === 'string' ? state.internal.maxDelta : (_frameloop$maxDelta = frameloop == null ? void 0 : frameloop.maxDelta) != null ? _frameloop$maxDelta : state.internal.maxDelta;
|
|
548
|
+
const clock = state.clock; // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
|
|
549
|
+
|
|
550
|
+
clock.stop();
|
|
551
|
+
clock.elapsedTime = 0;
|
|
552
|
+
|
|
553
|
+
if (frameloop !== 'never') {
|
|
554
|
+
clock.start();
|
|
555
|
+
clock.elapsedTime = 0;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
set(() => ({
|
|
559
|
+
frameloop: mode,
|
|
560
|
+
internal: { ...state.internal,
|
|
561
|
+
render,
|
|
562
|
+
maxDelta
|
|
563
|
+
}
|
|
564
|
+
}));
|
|
565
|
+
},
|
|
566
|
+
previousRoot: undefined,
|
|
567
|
+
internal: {
|
|
568
|
+
// Events
|
|
569
|
+
interaction: [],
|
|
570
|
+
hovered: new Map(),
|
|
571
|
+
subscribers: [],
|
|
572
|
+
initialClick: [0, 0],
|
|
573
|
+
initialHits: [],
|
|
574
|
+
capturedMap: new Map(),
|
|
575
|
+
lastEvent: /*#__PURE__*/React__namespace.createRef(),
|
|
576
|
+
// Updates
|
|
577
|
+
active: false,
|
|
578
|
+
frames: 0,
|
|
579
|
+
stages: [],
|
|
580
|
+
render: 'auto',
|
|
581
|
+
maxDelta: 1 / 10,
|
|
582
|
+
priority: 0,
|
|
583
|
+
subscribe: (ref, priority, store) => {
|
|
584
|
+
const state = get();
|
|
585
|
+
const internal = state.internal; // If this subscription was given a priority, it takes rendering into its own hands
|
|
586
|
+
// For that reason we switch off automatic rendering and increase the manual flag
|
|
587
|
+
// As long as this flag is positive there can be no internal rendering at all
|
|
588
|
+
// because there could be multiple render subscriptions
|
|
589
|
+
|
|
590
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0); // We use the render flag and deprecate priority
|
|
591
|
+
|
|
592
|
+
if (internal.priority && state.internal.render === 'auto') set(() => ({
|
|
593
|
+
internal: { ...state.internal,
|
|
594
|
+
render: 'manual'
|
|
595
|
+
}
|
|
596
|
+
}));
|
|
597
|
+
internal.subscribers.push({
|
|
598
|
+
ref,
|
|
599
|
+
priority,
|
|
600
|
+
store
|
|
601
|
+
}); // Register subscriber and sort layers from lowest to highest, meaning,
|
|
602
|
+
// highest priority renders last (on top of the other frames)
|
|
603
|
+
|
|
604
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
605
|
+
return () => {
|
|
606
|
+
const state = get();
|
|
607
|
+
const internal = state.internal;
|
|
608
|
+
|
|
609
|
+
if (internal != null && internal.subscribers) {
|
|
610
|
+
// Decrease manual flag if this subscription had a priority
|
|
611
|
+
internal.priority = internal.priority - (priority > 0 ? 1 : 0); // We use the render flag and deprecate priority
|
|
612
|
+
|
|
613
|
+
if (!internal.priority && state.internal.render === 'manual') set(() => ({
|
|
614
|
+
internal: { ...state.internal,
|
|
615
|
+
render: 'auto'
|
|
616
|
+
}
|
|
617
|
+
})); // Remove subscriber from list
|
|
618
|
+
|
|
619
|
+
internal.subscribers = internal.subscribers.filter(s => s.ref !== ref);
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
return rootState;
|
|
626
|
+
});
|
|
627
|
+
const state = rootStore.getState();
|
|
628
|
+
prepare(state.scene, rootStore, '', {});
|
|
629
|
+
let oldSize = state.size;
|
|
630
|
+
let oldDpr = state.viewport.dpr;
|
|
631
|
+
let oldCamera = state.camera;
|
|
632
|
+
rootStore.subscribe(() => {
|
|
633
|
+
const {
|
|
634
|
+
camera,
|
|
635
|
+
size,
|
|
636
|
+
viewport,
|
|
637
|
+
gl,
|
|
638
|
+
set
|
|
639
|
+
} = rootStore.getState(); // Resize camera and renderer on changes to size and pixelratio
|
|
640
|
+
|
|
641
|
+
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
642
|
+
oldSize = size;
|
|
643
|
+
oldDpr = viewport.dpr; // Update camera & renderer
|
|
644
|
+
|
|
645
|
+
updateCamera(camera, size);
|
|
646
|
+
gl.setPixelRatio(viewport.dpr); // Play nice with offscreen canvas contexts
|
|
647
|
+
|
|
648
|
+
const updateStyle = gl.domElement instanceof HTMLCanvasElement;
|
|
649
|
+
gl.setSize(size.width, size.height, updateStyle);
|
|
650
|
+
} // Update viewport once the camera changes
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
if (camera !== oldCamera) {
|
|
654
|
+
oldCamera = camera; // Update viewport
|
|
655
|
+
|
|
656
|
+
set(state => ({
|
|
657
|
+
viewport: { ...state.viewport,
|
|
658
|
+
...state.viewport.getCurrentViewport(camera)
|
|
659
|
+
}
|
|
660
|
+
}));
|
|
661
|
+
}
|
|
662
|
+
}); // Invalidate on any change
|
|
663
|
+
|
|
664
|
+
rootStore.subscribe(state => invalidate(state)); // Return root state
|
|
665
|
+
|
|
666
|
+
return rootStore;
|
|
667
|
+
};
|
|
668
|
+
|
|
424
669
|
function makeId(event) {
|
|
425
670
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
426
671
|
} // https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
|
|
@@ -428,9 +673,13 @@ function makeId(event) {
|
|
|
428
673
|
|
|
429
674
|
|
|
430
675
|
function getEventPriority() {
|
|
431
|
-
var
|
|
676
|
+
var _globalScope$event;
|
|
432
677
|
|
|
433
|
-
|
|
678
|
+
// Get a handle to the current global scope in window and worker contexts if able
|
|
679
|
+
// https://github.com/pmndrs/react-three-fiber/pull/2493
|
|
680
|
+
const globalScope = typeof self !== 'undefined' && self || typeof window !== 'undefined' && window;
|
|
681
|
+
if (!globalScope) return constants.DefaultEventPriority;
|
|
682
|
+
const name = (_globalScope$event = globalScope.event) == null ? void 0 : _globalScope$event.type;
|
|
434
683
|
|
|
435
684
|
switch (name) {
|
|
436
685
|
case 'click':
|
|
@@ -489,9 +738,7 @@ function removeInteractivity(store, object) {
|
|
|
489
738
|
});
|
|
490
739
|
}
|
|
491
740
|
function createEvents(store) {
|
|
492
|
-
const temp = new THREE__namespace.Vector3();
|
|
493
741
|
/** Calculates delta */
|
|
494
|
-
|
|
495
742
|
function calculateDistance(event) {
|
|
496
743
|
const {
|
|
497
744
|
internal
|
|
@@ -591,108 +838,113 @@ function createEvents(store) {
|
|
|
591
838
|
|
|
592
839
|
|
|
593
840
|
function handleIntersects(intersections, event, delta, callback) {
|
|
594
|
-
|
|
595
|
-
raycaster,
|
|
596
|
-
pointer,
|
|
597
|
-
camera,
|
|
598
|
-
internal
|
|
599
|
-
} = store.getState(); // If anything has been found, forward it to the event listeners
|
|
600
|
-
|
|
841
|
+
// If anything has been found, forward it to the event listeners
|
|
601
842
|
if (intersections.length) {
|
|
602
|
-
const unprojectedPoint = temp.set(pointer.x, pointer.y, 0).unproject(camera);
|
|
603
843
|
const localState = {
|
|
604
844
|
stopped: false
|
|
605
845
|
};
|
|
606
846
|
|
|
607
847
|
for (const hit of intersections) {
|
|
608
|
-
const
|
|
609
|
-
var _internal$capturedMap, _internal$capturedMap2;
|
|
848
|
+
const state = getRootState(hit.object);
|
|
610
849
|
|
|
611
|
-
|
|
612
|
-
|
|
850
|
+
if (state) {
|
|
851
|
+
const {
|
|
852
|
+
raycaster,
|
|
853
|
+
pointer,
|
|
854
|
+
camera,
|
|
855
|
+
internal
|
|
856
|
+
} = state;
|
|
857
|
+
const unprojectedPoint = new THREE__namespace.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
613
858
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
859
|
+
const hasPointerCapture = id => {
|
|
860
|
+
var _internal$capturedMap, _internal$capturedMap2;
|
|
861
|
+
|
|
862
|
+
return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
|
|
618
863
|
};
|
|
619
864
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
865
|
+
const setPointerCapture = id => {
|
|
866
|
+
const captureData = {
|
|
867
|
+
intersection: hit,
|
|
868
|
+
target: event.target
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
if (internal.capturedMap.has(id)) {
|
|
872
|
+
// if the pointerId was previously captured, we add the hit to the
|
|
873
|
+
// event capturedMap.
|
|
874
|
+
internal.capturedMap.get(id).set(hit.eventObject, captureData);
|
|
875
|
+
} else {
|
|
876
|
+
// if the pointerId was not previously captured, we create a map
|
|
877
|
+
// containing the hitObject, and the hit. hitObject is used for
|
|
878
|
+
// faster access.
|
|
879
|
+
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
880
|
+
} // Call the original event now
|
|
881
|
+
event.target.setPointerCapture(id);
|
|
882
|
+
};
|
|
632
883
|
|
|
633
|
-
|
|
634
|
-
|
|
884
|
+
const releasePointerCapture = id => {
|
|
885
|
+
const captures = internal.capturedMap.get(id);
|
|
635
886
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
887
|
+
if (captures) {
|
|
888
|
+
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
889
|
+
}
|
|
890
|
+
}; // Add native event props
|
|
640
891
|
|
|
641
892
|
|
|
642
|
-
|
|
893
|
+
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.
|
|
643
894
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
895
|
+
for (let prop in event) {
|
|
896
|
+
let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
|
|
897
|
+
// called as event.nativeEvent.fn()
|
|
647
898
|
|
|
648
|
-
|
|
649
|
-
|
|
899
|
+
if (typeof property !== 'function') extractEventProps[prop] = property;
|
|
900
|
+
}
|
|
650
901
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
902
|
+
let raycastEvent = { ...hit,
|
|
903
|
+
...extractEventProps,
|
|
904
|
+
pointer,
|
|
905
|
+
intersections,
|
|
906
|
+
stopped: localState.stopped,
|
|
907
|
+
delta,
|
|
908
|
+
unprojectedPoint,
|
|
909
|
+
ray: raycaster.ray,
|
|
910
|
+
camera: camera,
|
|
911
|
+
// Hijack stopPropagation, which just sets a flag
|
|
912
|
+
stopPropagation: () => {
|
|
913
|
+
// https://github.com/pmndrs/react-three-fiber/issues/596
|
|
914
|
+
// Events are not allowed to stop propagation if the pointer has been captured
|
|
915
|
+
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId); // We only authorize stopPropagation...
|
|
916
|
+
|
|
917
|
+
if ( // ...if this pointer hasn't been captured
|
|
918
|
+
!capturesForPointer || // ... or if the hit object is capturing the pointer
|
|
919
|
+
capturesForPointer.has(hit.eventObject)) {
|
|
920
|
+
raycastEvent.stopped = localState.stopped = true; // Propagation is stopped, remove all other hover records
|
|
921
|
+
// An event handler is only allowed to flush other handlers if it is hovered itself
|
|
922
|
+
|
|
923
|
+
if (internal.hovered.size && Array.from(internal.hovered.values()).find(i => i.eventObject === hit.eventObject)) {
|
|
924
|
+
// Objects cannot flush out higher up objects that have already caught the event
|
|
925
|
+
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
926
|
+
cancelPointer([...higher, hit]);
|
|
927
|
+
}
|
|
676
928
|
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
929
|
+
},
|
|
930
|
+
// there should be a distinction between target and currentTarget
|
|
931
|
+
target: {
|
|
932
|
+
hasPointerCapture,
|
|
933
|
+
setPointerCapture,
|
|
934
|
+
releasePointerCapture
|
|
935
|
+
},
|
|
936
|
+
currentTarget: {
|
|
937
|
+
hasPointerCapture,
|
|
938
|
+
setPointerCapture,
|
|
939
|
+
releasePointerCapture
|
|
940
|
+
},
|
|
941
|
+
nativeEvent: event
|
|
942
|
+
}; // Call subscribers
|
|
943
|
+
|
|
944
|
+
callback(raycastEvent); // Event bubbling may be interrupted by stopPropagation
|
|
945
|
+
|
|
946
|
+
if (localState.stopped === true) break;
|
|
947
|
+
}
|
|
696
948
|
}
|
|
697
949
|
}
|
|
698
950
|
|
|
@@ -709,11 +961,11 @@ function createEvents(store) {
|
|
|
709
961
|
if (!intersections.length || !intersections.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
710
962
|
const eventObject = hoveredObj.eventObject;
|
|
711
963
|
const instance = eventObject.__r3f;
|
|
712
|
-
const handlers = instance == null ? void 0 : instance.handlers;
|
|
713
964
|
internal.hovered.delete(makeId(hoveredObj));
|
|
714
965
|
|
|
715
966
|
if (instance != null && instance.eventCount) {
|
|
716
|
-
// Clear out intersects, they are outdated by now
|
|
967
|
+
const handlers = instance.handlers; // Clear out intersects, they are outdated by now
|
|
968
|
+
|
|
717
969
|
const data = { ...hoveredObj,
|
|
718
970
|
intersections
|
|
719
971
|
};
|
|
@@ -780,10 +1032,10 @@ function createEvents(store) {
|
|
|
780
1032
|
if (isPointerMove) cancelPointer(hits);
|
|
781
1033
|
handleIntersects(hits, event, delta, data => {
|
|
782
1034
|
const eventObject = data.eventObject;
|
|
783
|
-
const instance = eventObject.__r3f;
|
|
784
|
-
const handlers = instance == null ? void 0 : instance.handlers; // Check presence of handlers
|
|
1035
|
+
const instance = eventObject.__r3f; // Check presence of handlers
|
|
785
1036
|
|
|
786
1037
|
if (!(instance != null && instance.eventCount)) return;
|
|
1038
|
+
const handlers = instance.handlers;
|
|
787
1039
|
|
|
788
1040
|
if (isPointerMove) {
|
|
789
1041
|
// Move event ...
|
|
@@ -842,634 +1094,296 @@ function createEvents(store) {
|
|
|
842
1094
|
};
|
|
843
1095
|
}
|
|
844
1096
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
let extend = objects => void (catalogue = { ...catalogue,
|
|
848
|
-
...objects
|
|
849
|
-
});
|
|
1097
|
+
const catalogue = {};
|
|
850
1098
|
|
|
851
|
-
|
|
852
|
-
function createInstance(type, {
|
|
853
|
-
args = [],
|
|
854
|
-
attach,
|
|
855
|
-
...props
|
|
856
|
-
}, root) {
|
|
857
|
-
let name = `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
858
|
-
let instance; // Auto-attach geometries and materials
|
|
859
|
-
|
|
860
|
-
if (attach === undefined) {
|
|
861
|
-
if (name.endsWith('Geometry')) attach = 'geometry';else if (name.endsWith('Material')) attach = 'material';
|
|
862
|
-
}
|
|
1099
|
+
const extend = objects => void Object.assign(catalogue, objects);
|
|
863
1100
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
const object = props.object;
|
|
867
|
-
instance = prepare(object, {
|
|
868
|
-
type,
|
|
869
|
-
root,
|
|
870
|
-
attach,
|
|
871
|
-
primitive: true
|
|
872
|
-
});
|
|
873
|
-
} else {
|
|
874
|
-
const target = catalogue[name];
|
|
1101
|
+
function createInstance(type, props, root) {
|
|
1102
|
+
var _props$object, _props$args;
|
|
875
1103
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1104
|
+
// Get target from catalogue
|
|
1105
|
+
const name = `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
1106
|
+
const target = catalogue[name]; // Validate element target
|
|
879
1107
|
|
|
1108
|
+
if (type !== 'primitive' && !target) 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`); // Validate primitives
|
|
880
1109
|
|
|
881
|
-
|
|
882
|
-
// Append memoized props with args so it's not forgotten
|
|
1110
|
+
if (type === 'primitive' && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`); // Throw if an object or literal was passed for args
|
|
883
1111
|
|
|
884
|
-
|
|
885
|
-
type,
|
|
886
|
-
root,
|
|
887
|
-
attach,
|
|
888
|
-
// Save args in case we need to reconstruct later for HMR
|
|
889
|
-
memoizedProps: {
|
|
890
|
-
args
|
|
891
|
-
}
|
|
892
|
-
});
|
|
893
|
-
} // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
|
|
894
|
-
// view yet. If the callback relies on references for instance, they won't be ready yet, this is
|
|
895
|
-
// why it passes "true" here
|
|
896
|
-
// There is no reason to apply props to injects
|
|
1112
|
+
if (props.args !== undefined && !Array.isArray(props.args)) throw new Error('R3F: The args prop must be an array!'); // Create instance
|
|
897
1113
|
|
|
1114
|
+
const object = (_props$object = props.object) != null ? _props$object : new target(...((_props$args = props.args) != null ? _props$args : []));
|
|
1115
|
+
const instance = prepare(object, root, type, props); // Auto-attach geometries and materials
|
|
898
1116
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
}
|
|
1117
|
+
if (instance.props.attach === undefined) {
|
|
1118
|
+
if (instance.object instanceof THREE__namespace.BufferGeometry) instance.props.attach = 'geometry';else if (instance.object instanceof THREE__namespace.Material) instance.props.attach = 'material';
|
|
1119
|
+
} // Set initial props
|
|
902
1120
|
|
|
903
|
-
function appendChild(parentInstance, child) {
|
|
904
|
-
let added = false;
|
|
905
1121
|
|
|
906
|
-
|
|
907
|
-
|
|
1122
|
+
applyProps(instance.object, props);
|
|
1123
|
+
return instance;
|
|
1124
|
+
} // https://github.com/facebook/react/issues/20271
|
|
1125
|
+
// This will make sure events and attach are only handled once when trees are complete
|
|
908
1126
|
|
|
909
|
-
// The attach attribute implies that the object attaches itself on the parent
|
|
910
|
-
if ((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) {
|
|
911
|
-
attach(parentInstance, child, child.__r3f.attach);
|
|
912
|
-
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
913
|
-
// add in the usual parent-child way
|
|
914
|
-
parentInstance.add(child);
|
|
915
|
-
added = true;
|
|
916
|
-
} // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
|
|
917
|
-
// that is, anything that's a child in React but not a child in the scenegraph.
|
|
918
1127
|
|
|
1128
|
+
function handleContainerEffects(parent, child) {
|
|
1129
|
+
// Bail if tree isn't mounted or parent is not a container.
|
|
1130
|
+
// This ensures that the tree is finalized and React won't discard results to Suspense
|
|
1131
|
+
const state = child.root.getState();
|
|
1132
|
+
if (!parent.parent && parent.object !== state.scene) return; // Handle interactivity
|
|
919
1133
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
updateInstance(child);
|
|
924
|
-
invalidateInstance(child);
|
|
925
|
-
}
|
|
926
|
-
}
|
|
1134
|
+
if (child.eventCount > 0 && child.object.raycast !== null && child.object instanceof THREE__namespace.Object3D) {
|
|
1135
|
+
state.internal.interaction.push(child.object);
|
|
1136
|
+
} // Handle attach
|
|
927
1137
|
|
|
928
|
-
function insertBefore(parentInstance, child, beforeChild) {
|
|
929
|
-
let added = false;
|
|
930
1138
|
|
|
931
|
-
|
|
932
|
-
var _child$__r3f2, _parentInstance$__r3f2;
|
|
1139
|
+
if (child.props.attach) attach(parent, child);
|
|
933
1140
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
937
|
-
child.parent = parentInstance;
|
|
938
|
-
child.dispatchEvent({
|
|
939
|
-
type: 'added'
|
|
940
|
-
});
|
|
941
|
-
const restSiblings = parentInstance.children.filter(sibling => sibling !== child);
|
|
942
|
-
const index = restSiblings.indexOf(beforeChild);
|
|
943
|
-
parentInstance.children = [...restSiblings.slice(0, index), child, ...restSiblings.slice(index)];
|
|
944
|
-
added = true;
|
|
945
|
-
}
|
|
1141
|
+
for (const childInstance of child.children) handleContainerEffects(child, childInstance);
|
|
1142
|
+
}
|
|
946
1143
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
child.__r3f.parent = parentInstance;
|
|
950
|
-
updateInstance(child);
|
|
951
|
-
invalidateInstance(child);
|
|
952
|
-
}
|
|
953
|
-
}
|
|
1144
|
+
function appendChild(parent, child) {
|
|
1145
|
+
if (!child) return; // Link instances
|
|
954
1146
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
}
|
|
1147
|
+
child.parent = parent;
|
|
1148
|
+
parent.children.push(child); // Add Object3Ds if able
|
|
958
1149
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1150
|
+
if (!child.props.attach && parent.object instanceof THREE__namespace.Object3D && child.object instanceof THREE__namespace.Object3D) {
|
|
1151
|
+
parent.object.add(child.object);
|
|
1152
|
+
} // Attach tree once complete
|
|
962
1153
|
|
|
963
|
-
// Clear the parent reference
|
|
964
|
-
if (child.__r3f) child.__r3f.parent = null; // Remove child from the parents objects
|
|
965
1154
|
|
|
966
|
-
|
|
1155
|
+
handleContainerEffects(parent, child); // Tree was updated, request a frame
|
|
967
1156
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
} else if (child.isObject3D && parentInstance.isObject3D) {
|
|
971
|
-
var _child$__r3f4;
|
|
1157
|
+
invalidateInstance(child);
|
|
1158
|
+
}
|
|
972
1159
|
|
|
973
|
-
|
|
1160
|
+
function insertBefore(parent, child, beforeChild, replace = false) {
|
|
1161
|
+
if (!child || !beforeChild) return; // Link instances
|
|
974
1162
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
// Never dispose of primitives because their state may be kept outside of React!
|
|
980
|
-
// In order for an object to be able to dispose it has to have
|
|
981
|
-
// - a dispose method,
|
|
982
|
-
// - it cannot be a <primitive object={...} />
|
|
983
|
-
// - it cannot be a THREE.Scene, because three has broken it's own api
|
|
984
|
-
//
|
|
985
|
-
// Since disposal is recursive, we can check the optional dispose arg, which will be undefined
|
|
986
|
-
// when the reconciler calls it, but then carry our own check recursively
|
|
1163
|
+
child.parent = parent;
|
|
1164
|
+
const childIndex = parent.children.indexOf(beforeChild);
|
|
1165
|
+
if (childIndex !== -1) parent.children.splice(childIndex, replace ? 1 : 0, child);
|
|
1166
|
+
if (replace) beforeChild.parent = null; // Manually splice Object3Ds
|
|
987
1167
|
|
|
1168
|
+
if (!child.props.attach && parent.object instanceof THREE__namespace.Object3D && child.object instanceof THREE__namespace.Object3D && beforeChild.object instanceof THREE__namespace.Object3D) {
|
|
1169
|
+
child.object.parent = parent.object;
|
|
1170
|
+
parent.object.children.splice(parent.object.children.indexOf(beforeChild.object), 0, child.object);
|
|
1171
|
+
child.object.dispatchEvent({
|
|
1172
|
+
type: 'added'
|
|
1173
|
+
});
|
|
1174
|
+
} // Attach tree once complete
|
|
988
1175
|
|
|
989
|
-
const isPrimitive = (_child$__r3f5 = child.__r3f) == null ? void 0 : _child$__r3f5.primitive;
|
|
990
|
-
const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose; // Remove nested child objects. Primitives should not have objects and children that are
|
|
991
|
-
// attached to them declaratively ...
|
|
992
1176
|
|
|
993
|
-
|
|
994
|
-
var _child$__r3f6;
|
|
1177
|
+
handleContainerEffects(parent, child); // Tree was updated, request a frame
|
|
995
1178
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
} // Remove references
|
|
1179
|
+
invalidateInstance(child);
|
|
1180
|
+
}
|
|
999
1181
|
|
|
1182
|
+
function removeChild(parent, child, dispose, recursive) {
|
|
1183
|
+
if (!child) return; // Unlink instances
|
|
1000
1184
|
|
|
1001
|
-
|
|
1002
|
-
delete child.__r3f.root;
|
|
1003
|
-
delete child.__r3f.objects;
|
|
1004
|
-
delete child.__r3f.handlers;
|
|
1005
|
-
delete child.__r3f.memoizedProps;
|
|
1006
|
-
if (!isPrimitive) delete child.__r3f;
|
|
1007
|
-
} // Dispose item whenever the reconciler feels like it
|
|
1185
|
+
child.parent = null;
|
|
1008
1186
|
|
|
1187
|
+
if (recursive === undefined) {
|
|
1188
|
+
const childIndex = parent.children.indexOf(child);
|
|
1189
|
+
if (childIndex !== -1) parent.children.splice(childIndex, 1);
|
|
1190
|
+
} // Eagerly tear down tree
|
|
1009
1191
|
|
|
1010
|
-
if (shouldDispose && child.dispose && child.type !== 'Scene') {
|
|
1011
|
-
scheduler.unstable_scheduleCallback(scheduler.unstable_IdlePriority, () => {
|
|
1012
|
-
try {
|
|
1013
|
-
child.dispose();
|
|
1014
|
-
} catch (e) {
|
|
1015
|
-
/* ... */
|
|
1016
|
-
}
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1019
1192
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
}
|
|
1193
|
+
if (child.props.attach) {
|
|
1194
|
+
detach(parent, child);
|
|
1195
|
+
} else if (child.object instanceof THREE__namespace.Object3D && parent.object instanceof THREE__namespace.Object3D) {
|
|
1196
|
+
parent.object.remove(child.object);
|
|
1197
|
+
removeInteractivity(child.root, child.object);
|
|
1198
|
+
} // Allow objects to bail out of unmount disposal with dispose={null}
|
|
1023
1199
|
|
|
1024
|
-
function switchInstance(instance, type, newProps, fiber) {
|
|
1025
|
-
var _instance$__r3f;
|
|
1026
1200
|
|
|
1027
|
-
|
|
1028
|
-
if (!parent) return;
|
|
1029
|
-
const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
|
|
1030
|
-
// When args change the instance has to be re-constructed, which then
|
|
1031
|
-
// forces r3f to re-parent the children and non-scene objects
|
|
1032
|
-
// This can not include primitives, which should not have declarative children
|
|
1201
|
+
const shouldDispose = child.props.dispose !== null && dispose !== false; // Recursively remove instance children
|
|
1033
1202
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
instance.children = [];
|
|
1037
|
-
}
|
|
1203
|
+
if (recursive !== false) {
|
|
1204
|
+
for (const node of child.children) removeChild(child, node, shouldDispose, true);
|
|
1038
1205
|
|
|
1039
|
-
|
|
1206
|
+
child.children = [];
|
|
1207
|
+
} // Unlink instance object
|
|
1040
1208
|
|
|
1041
|
-
instance.__r3f.objects = [];
|
|
1042
|
-
removeChild(parent, instance);
|
|
1043
|
-
appendChild(parent, newInstance); // Re-bind event handlers
|
|
1044
1209
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1210
|
+
delete child.object.__r3f; // Dispose object whenever the reconciler feels like it.
|
|
1211
|
+
// Never dispose of primitives because their state may be kept outside of React!
|
|
1212
|
+
// In order for an object to be able to dispose it
|
|
1213
|
+
// - has a dispose method
|
|
1214
|
+
// - cannot be a <primitive object={...} />
|
|
1215
|
+
// - cannot be a THREE.Scene, because three has broken its own API
|
|
1047
1216
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
[fiber, fiber.alternate].forEach(fiber => {
|
|
1051
|
-
if (fiber !== null) {
|
|
1052
|
-
fiber.stateNode = newInstance;
|
|
1217
|
+
if (shouldDispose && child.type !== 'primitive' && child.object.type !== 'Scene') {
|
|
1218
|
+
const dispose = child.object.dispose;
|
|
1053
1219
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1220
|
+
if (typeof dispose === 'function') {
|
|
1221
|
+
scheduler.unstable_scheduleCallback(scheduler.unstable_IdlePriority, () => {
|
|
1222
|
+
try {
|
|
1223
|
+
dispose();
|
|
1224
|
+
} catch (e) {
|
|
1225
|
+
/* ... */
|
|
1056
1226
|
}
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
} //
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
|
|
1063
|
-
|
|
1064
|
-
const reconciler = Reconciler__default["default"]({
|
|
1065
|
-
createInstance,
|
|
1066
|
-
removeChild,
|
|
1067
|
-
appendChild,
|
|
1068
|
-
appendInitialChild: appendChild,
|
|
1069
|
-
insertBefore,
|
|
1070
|
-
supportsMutation: true,
|
|
1071
|
-
isPrimaryRenderer: false,
|
|
1072
|
-
supportsPersistence: false,
|
|
1073
|
-
supportsHydration: false,
|
|
1074
|
-
noTimeout: -1,
|
|
1075
|
-
appendChildToContainer: (container, child) => {
|
|
1076
|
-
if (!child) return;
|
|
1077
|
-
const scene = container.getState().scene; // Link current root to the default scene
|
|
1078
|
-
|
|
1079
|
-
scene.__r3f.root = container;
|
|
1080
|
-
appendChild(scene, child);
|
|
1081
|
-
},
|
|
1082
|
-
removeChildFromContainer: (container, child) => {
|
|
1083
|
-
if (!child) return;
|
|
1084
|
-
removeChild(container.getState().scene, child);
|
|
1085
|
-
},
|
|
1086
|
-
insertInContainerBefore: (container, child, beforeChild) => {
|
|
1087
|
-
if (!child || !beforeChild) return;
|
|
1088
|
-
insertBefore(container.getState().scene, child, beforeChild);
|
|
1089
|
-
},
|
|
1090
|
-
getRootHostContext: () => null,
|
|
1091
|
-
getChildHostContext: parentHostContext => parentHostContext,
|
|
1092
|
-
|
|
1093
|
-
finalizeInitialChildren(instance) {
|
|
1094
|
-
var _instance$__r3f2;
|
|
1095
|
-
|
|
1096
|
-
const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {}; // https://github.com/facebook/react/issues/20271
|
|
1097
|
-
// Returning true will trigger commitMount
|
|
1098
|
-
|
|
1099
|
-
return Boolean(localState.handlers);
|
|
1100
|
-
},
|
|
1101
|
-
|
|
1102
|
-
prepareUpdate(instance, _type, oldProps, newProps) {
|
|
1103
|
-
// Create diff-sets
|
|
1104
|
-
if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
|
|
1105
|
-
return [true];
|
|
1106
|
-
} else {
|
|
1107
|
-
// This is a data object, let's extract critical information about it
|
|
1108
|
-
const {
|
|
1109
|
-
args: argsNew = [],
|
|
1110
|
-
children: cN,
|
|
1111
|
-
...restNew
|
|
1112
|
-
} = newProps;
|
|
1113
|
-
const {
|
|
1114
|
-
args: argsOld = [],
|
|
1115
|
-
children: cO,
|
|
1116
|
-
...restOld
|
|
1117
|
-
} = oldProps; // Throw if an object or literal was passed for args
|
|
1118
|
-
|
|
1119
|
-
if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instantiated
|
|
1120
|
-
|
|
1121
|
-
if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
|
|
1122
|
-
|
|
1123
|
-
const diff = diffProps(instance, restNew, restOld, true);
|
|
1124
|
-
if (diff.changes.length) return [false, diff]; // Otherwise do not touch the instance
|
|
1125
|
-
|
|
1126
|
-
return null;
|
|
1127
|
-
}
|
|
1128
|
-
},
|
|
1129
|
-
|
|
1130
|
-
commitUpdate(instance, [reconstruct, diff], type, _oldProps, newProps, fiber) {
|
|
1131
|
-
// Reconstruct when args or <primitive object={...} have changes
|
|
1132
|
-
if (reconstruct) switchInstance(instance, type, newProps, fiber); // Otherwise just overwrite props
|
|
1133
|
-
else applyProps$1(instance, diff);
|
|
1134
|
-
},
|
|
1135
|
-
|
|
1136
|
-
commitMount(instance, _type, _props, _int) {
|
|
1137
|
-
var _instance$__r3f3;
|
|
1138
|
-
|
|
1139
|
-
// https://github.com/facebook/react/issues/20271
|
|
1140
|
-
// This will make sure events are only added once to the central container
|
|
1141
|
-
const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
|
|
1142
|
-
|
|
1143
|
-
if (instance.raycast && localState.handlers && localState.eventCount) {
|
|
1144
|
-
instance.__r3f.root.getState().internal.interaction.push(instance);
|
|
1145
|
-
}
|
|
1146
|
-
},
|
|
1147
|
-
|
|
1148
|
-
getPublicInstance: instance => instance,
|
|
1149
|
-
prepareForCommit: () => null,
|
|
1150
|
-
preparePortalMount: container => prepare(container.getState().scene),
|
|
1151
|
-
resetAfterCommit: () => {},
|
|
1152
|
-
shouldSetTextContent: () => false,
|
|
1153
|
-
clearContainer: () => false,
|
|
1154
|
-
|
|
1155
|
-
hideInstance(instance) {
|
|
1156
|
-
var _instance$__r3f4;
|
|
1157
|
-
|
|
1158
|
-
// Deatch while the instance is hidden
|
|
1159
|
-
const {
|
|
1160
|
-
attach: type,
|
|
1161
|
-
parent
|
|
1162
|
-
} = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
|
|
1163
|
-
if (type && parent) detach(parent, instance, type);
|
|
1164
|
-
if (instance.isObject3D) instance.visible = false;
|
|
1165
|
-
invalidateInstance(instance);
|
|
1166
|
-
},
|
|
1167
|
-
|
|
1168
|
-
unhideInstance(instance, props) {
|
|
1169
|
-
var _instance$__r3f5;
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
} // Tree was updated, request a frame for top-level instance
|
|
1170
1230
|
|
|
1171
|
-
// Re-attach when the instance is unhidden
|
|
1172
|
-
const {
|
|
1173
|
-
attach: type,
|
|
1174
|
-
parent
|
|
1175
|
-
} = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
|
|
1176
|
-
if (type && parent) attach(parent, instance, type);
|
|
1177
|
-
if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
|
|
1178
|
-
invalidateInstance(instance);
|
|
1179
|
-
},
|
|
1180
1231
|
|
|
1181
|
-
|
|
1182
|
-
hideTextInstance: handleTextInstance,
|
|
1183
|
-
unhideTextInstance: handleTextInstance,
|
|
1184
|
-
// https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
|
|
1185
|
-
// @ts-ignore
|
|
1186
|
-
getCurrentEventPriority: () => _getEventPriority ? _getEventPriority() : constants.DefaultEventPriority,
|
|
1187
|
-
beforeActiveInstanceBlur: () => {},
|
|
1188
|
-
afterActiveInstanceBlur: () => {},
|
|
1189
|
-
detachDeletedInstance: () => {},
|
|
1190
|
-
now: typeof performance !== 'undefined' && is.fun(performance.now) ? performance.now : is.fun(Date.now) ? Date.now : () => 0,
|
|
1191
|
-
// https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r920883503
|
|
1192
|
-
scheduleTimeout: is.fun(setTimeout) ? setTimeout : undefined,
|
|
1193
|
-
cancelTimeout: is.fun(clearTimeout) ? clearTimeout : undefined
|
|
1194
|
-
});
|
|
1195
|
-
return {
|
|
1196
|
-
reconciler,
|
|
1197
|
-
applyProps: applyProps$1
|
|
1198
|
-
};
|
|
1232
|
+
if (dispose === undefined) invalidateInstance(child);
|
|
1199
1233
|
}
|
|
1200
1234
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
const
|
|
1204
|
-
const context = /*#__PURE__*/React__namespace.createContext(null);
|
|
1205
|
-
|
|
1206
|
-
const createStore = (invalidate, advance) => {
|
|
1207
|
-
const rootState = create__default["default"]((set, get) => {
|
|
1208
|
-
const position = new THREE__namespace.Vector3();
|
|
1209
|
-
const defaultTarget = new THREE__namespace.Vector3();
|
|
1210
|
-
const tempTarget = new THREE__namespace.Vector3();
|
|
1211
|
-
|
|
1212
|
-
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
1213
|
-
const {
|
|
1214
|
-
width,
|
|
1215
|
-
height,
|
|
1216
|
-
top,
|
|
1217
|
-
left
|
|
1218
|
-
} = size;
|
|
1219
|
-
const aspect = width / height;
|
|
1220
|
-
if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
1221
|
-
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
1222
|
-
|
|
1223
|
-
if (isOrthographicCamera(camera)) {
|
|
1224
|
-
return {
|
|
1225
|
-
width: width / camera.zoom,
|
|
1226
|
-
height: height / camera.zoom,
|
|
1227
|
-
top,
|
|
1228
|
-
left,
|
|
1229
|
-
factor: 1,
|
|
1230
|
-
distance,
|
|
1231
|
-
aspect
|
|
1232
|
-
};
|
|
1233
|
-
} else {
|
|
1234
|
-
const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
|
|
1235
|
+
function switchInstance(oldInstance, type, props, fiber) {
|
|
1236
|
+
// Create a new instance
|
|
1237
|
+
const newInstance = createInstance(type, props, oldInstance.root); // Move children to new instance
|
|
1235
1238
|
|
|
1236
|
-
|
|
1239
|
+
for (const child of oldInstance.children) {
|
|
1240
|
+
removeChild(oldInstance, child, false, false);
|
|
1241
|
+
appendChild(newInstance, child);
|
|
1242
|
+
}
|
|
1237
1243
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1244
|
+
oldInstance.children = []; // Link up new instance
|
|
1245
|
+
|
|
1246
|
+
const parent = oldInstance.parent;
|
|
1247
|
+
|
|
1248
|
+
if (parent) {
|
|
1249
|
+
insertBefore(parent, newInstance, oldInstance, true);
|
|
1250
|
+
} // This evil hack switches the react-internal fiber node
|
|
1251
|
+
[fiber, fiber.alternate].forEach(fiber => {
|
|
1252
|
+
if (fiber !== null) {
|
|
1253
|
+
fiber.stateNode = newInstance;
|
|
1254
|
+
|
|
1255
|
+
if (fiber.ref) {
|
|
1256
|
+
if (typeof fiber.ref === 'function') fiber.ref(newInstance.object);else fiber.ref.current = newInstance.object;
|
|
1248
1257
|
}
|
|
1249
1258
|
}
|
|
1259
|
+
}); // Tree was updated, request a frame
|
|
1250
1260
|
|
|
1251
|
-
|
|
1261
|
+
invalidateInstance(newInstance);
|
|
1262
|
+
return newInstance;
|
|
1263
|
+
} // Don't handle text instances, warn on undefined behavior
|
|
1252
1264
|
|
|
1253
|
-
const setPerformanceCurrent = current => set(state => ({
|
|
1254
|
-
performance: { ...state.performance,
|
|
1255
|
-
current
|
|
1256
|
-
}
|
|
1257
|
-
}));
|
|
1258
1265
|
|
|
1259
|
-
|
|
1260
|
-
const rootState = {
|
|
1261
|
-
set,
|
|
1262
|
-
get,
|
|
1263
|
-
// Mock objects that have to be configured
|
|
1264
|
-
gl: null,
|
|
1265
|
-
camera: null,
|
|
1266
|
-
raycaster: null,
|
|
1267
|
-
events: {
|
|
1268
|
-
priority: 1,
|
|
1269
|
-
enabled: true,
|
|
1270
|
-
connected: false
|
|
1271
|
-
},
|
|
1272
|
-
xr: null,
|
|
1273
|
-
invalidate: (frames = 1) => invalidate(get(), frames),
|
|
1274
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
1275
|
-
legacy: false,
|
|
1276
|
-
linear: false,
|
|
1277
|
-
flat: false,
|
|
1278
|
-
scene: prepare(new THREE__namespace.Scene()),
|
|
1279
|
-
controls: null,
|
|
1280
|
-
clock: new THREE__namespace.Clock(),
|
|
1281
|
-
pointer,
|
|
1282
|
-
mouse: pointer,
|
|
1283
|
-
frameloop: 'always',
|
|
1284
|
-
onPointerMissed: undefined,
|
|
1285
|
-
performance: {
|
|
1286
|
-
current: 1,
|
|
1287
|
-
min: 0.5,
|
|
1288
|
-
max: 1,
|
|
1289
|
-
debounce: 200,
|
|
1290
|
-
regress: () => {
|
|
1291
|
-
const state = get(); // Clear timeout
|
|
1266
|
+
const handleTextInstance = () => console.warn('R3F: Text is not allowed in JSX! This could be stray whitespace or characters.');
|
|
1292
1267
|
|
|
1293
|
-
|
|
1268
|
+
const reconciler = Reconciler__default["default"]({
|
|
1269
|
+
supportsMutation: true,
|
|
1270
|
+
isPrimaryRenderer: false,
|
|
1271
|
+
supportsPersistence: false,
|
|
1272
|
+
supportsHydration: false,
|
|
1273
|
+
noTimeout: -1,
|
|
1274
|
+
createInstance,
|
|
1275
|
+
removeChild,
|
|
1276
|
+
appendChild,
|
|
1277
|
+
appendInitialChild: appendChild,
|
|
1278
|
+
insertBefore,
|
|
1294
1279
|
|
|
1295
|
-
|
|
1280
|
+
appendChildToContainer(container, child) {
|
|
1281
|
+
const scene = container.getState().scene.__r3f;
|
|
1296
1282
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
size: {
|
|
1301
|
-
width: 0,
|
|
1302
|
-
height: 0,
|
|
1303
|
-
top: 0,
|
|
1304
|
-
left: 0,
|
|
1305
|
-
updateStyle: false
|
|
1306
|
-
},
|
|
1307
|
-
viewport: {
|
|
1308
|
-
initialDpr: 0,
|
|
1309
|
-
dpr: 0,
|
|
1310
|
-
width: 0,
|
|
1311
|
-
height: 0,
|
|
1312
|
-
top: 0,
|
|
1313
|
-
left: 0,
|
|
1314
|
-
aspect: 0,
|
|
1315
|
-
distance: 0,
|
|
1316
|
-
factor: 0,
|
|
1317
|
-
getCurrentViewport
|
|
1318
|
-
},
|
|
1319
|
-
setEvents: events => set(state => ({ ...state,
|
|
1320
|
-
events: { ...state.events,
|
|
1321
|
-
...events
|
|
1322
|
-
}
|
|
1323
|
-
})),
|
|
1324
|
-
setSize: (width, height, updateStyle, top, left) => {
|
|
1325
|
-
const camera = get().camera;
|
|
1326
|
-
const size = {
|
|
1327
|
-
width,
|
|
1328
|
-
height,
|
|
1329
|
-
top: top || 0,
|
|
1330
|
-
left: left || 0,
|
|
1331
|
-
updateStyle
|
|
1332
|
-
};
|
|
1333
|
-
set(state => ({
|
|
1334
|
-
size,
|
|
1335
|
-
viewport: { ...state.viewport,
|
|
1336
|
-
...getCurrentViewport(camera, defaultTarget, size)
|
|
1337
|
-
}
|
|
1338
|
-
}));
|
|
1339
|
-
},
|
|
1340
|
-
setDpr: dpr => set(state => {
|
|
1341
|
-
const resolved = calculateDpr(dpr);
|
|
1342
|
-
return {
|
|
1343
|
-
viewport: { ...state.viewport,
|
|
1344
|
-
dpr: resolved,
|
|
1345
|
-
initialDpr: state.viewport.initialDpr || resolved
|
|
1346
|
-
}
|
|
1347
|
-
};
|
|
1348
|
-
}),
|
|
1349
|
-
setFrameloop: frameloop => {
|
|
1350
|
-
var _frameloop$mode, _frameloop$render, _frameloop$maxDelta;
|
|
1283
|
+
if (!child || !scene) return;
|
|
1284
|
+
appendChild(scene, child);
|
|
1285
|
+
},
|
|
1351
1286
|
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
const render = typeof frameloop === 'string' ? state.internal.render : (_frameloop$render = frameloop == null ? void 0 : frameloop.render) != null ? _frameloop$render : state.internal.render;
|
|
1355
|
-
const maxDelta = typeof frameloop === 'string' ? state.internal.maxDelta : (_frameloop$maxDelta = frameloop == null ? void 0 : frameloop.maxDelta) != null ? _frameloop$maxDelta : state.internal.maxDelta;
|
|
1356
|
-
const clock = state.clock; // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
|
|
1287
|
+
removeChildFromContainer(container, child) {
|
|
1288
|
+
const scene = container.getState().scene.__r3f;
|
|
1357
1289
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1290
|
+
if (!child || !scene) return;
|
|
1291
|
+
removeChild(scene, child);
|
|
1292
|
+
},
|
|
1360
1293
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
clock.elapsedTime = 0;
|
|
1364
|
-
}
|
|
1294
|
+
insertInContainerBefore(container, child, beforeChild) {
|
|
1295
|
+
const scene = container.getState().scene.__r3f;
|
|
1365
1296
|
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
render,
|
|
1370
|
-
maxDelta
|
|
1371
|
-
}
|
|
1372
|
-
}));
|
|
1373
|
-
},
|
|
1374
|
-
previousRoot: undefined,
|
|
1375
|
-
internal: {
|
|
1376
|
-
// Events
|
|
1377
|
-
interaction: [],
|
|
1378
|
-
hovered: new Map(),
|
|
1379
|
-
subscribers: [],
|
|
1380
|
-
initialClick: [0, 0],
|
|
1381
|
-
initialHits: [],
|
|
1382
|
-
capturedMap: new Map(),
|
|
1383
|
-
lastEvent: /*#__PURE__*/React__namespace.createRef(),
|
|
1384
|
-
// Updates
|
|
1385
|
-
active: false,
|
|
1386
|
-
frames: 0,
|
|
1387
|
-
stages: [],
|
|
1388
|
-
render: 'auto',
|
|
1389
|
-
maxDelta: 1 / 10,
|
|
1390
|
-
priority: 0,
|
|
1391
|
-
subscribe: (ref, priority, store) => {
|
|
1392
|
-
const state = get();
|
|
1393
|
-
const internal = state.internal; // If this subscription was given a priority, it takes rendering into its own hands
|
|
1394
|
-
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1395
|
-
// As long as this flag is positive there can be no internal rendering at all
|
|
1396
|
-
// because there could be multiple render subscriptions
|
|
1297
|
+
if (!child || !beforeChild || !scene) return;
|
|
1298
|
+
insertBefore(scene, child, beforeChild);
|
|
1299
|
+
},
|
|
1397
1300
|
|
|
1398
|
-
|
|
1301
|
+
getRootHostContext: () => null,
|
|
1302
|
+
getChildHostContext: parentHostContext => parentHostContext,
|
|
1399
1303
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
render: 'manual'
|
|
1403
|
-
}
|
|
1404
|
-
}));
|
|
1405
|
-
internal.subscribers.push({
|
|
1406
|
-
ref,
|
|
1407
|
-
priority,
|
|
1408
|
-
store
|
|
1409
|
-
}); // Register subscriber and sort layers from lowest to highest, meaning,
|
|
1410
|
-
// highest priority renders last (on top of the other frames)
|
|
1304
|
+
prepareUpdate(instance, _type, oldProps, newProps) {
|
|
1305
|
+
var _newProps$args, _oldProps$args, _newProps$args2;
|
|
1411
1306
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
const state = get();
|
|
1415
|
-
const internal = state.internal;
|
|
1307
|
+
// Reconstruct primitives if object prop changes
|
|
1308
|
+
if (instance.type === 'primitive' && oldProps.object !== newProps.object) return [true]; // Throw if an object or literal was passed for args
|
|
1416
1309
|
|
|
1417
|
-
|
|
1418
|
-
// Decrease manual flag if this subscription had a priority
|
|
1419
|
-
internal.priority = internal.priority - (priority > 0 ? 1 : 0); // We use the render flag and deprecate priority
|
|
1310
|
+
if (newProps.args !== undefined && !Array.isArray(newProps.args)) throw new Error('R3F: The args prop must be an array!'); // Reconstruct instance if args change
|
|
1420
1311
|
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
}
|
|
1425
|
-
})); // Remove subscriber from list
|
|
1312
|
+
if (((_newProps$args = newProps.args) == null ? void 0 : _newProps$args.length) !== ((_oldProps$args = oldProps.args) == null ? void 0 : _oldProps$args.length)) return [true];
|
|
1313
|
+
if ((_newProps$args2 = newProps.args) != null && _newProps$args2.some((value, index) => {
|
|
1314
|
+
var _oldProps$args2;
|
|
1426
1315
|
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
};
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
};
|
|
1433
|
-
return rootState;
|
|
1434
|
-
});
|
|
1435
|
-
const state = rootState.getState();
|
|
1436
|
-
let oldSize = state.size;
|
|
1437
|
-
let oldDpr = state.viewport.dpr;
|
|
1438
|
-
let oldCamera = state.camera;
|
|
1439
|
-
rootState.subscribe(() => {
|
|
1440
|
-
const {
|
|
1441
|
-
camera,
|
|
1442
|
-
size,
|
|
1443
|
-
viewport,
|
|
1444
|
-
gl,
|
|
1445
|
-
set
|
|
1446
|
-
} = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
|
|
1316
|
+
return value !== ((_oldProps$args2 = oldProps.args) == null ? void 0 : _oldProps$args2[index]);
|
|
1317
|
+
})) return [true]; // Create a diff-set, flag if there are any changes
|
|
1447
1318
|
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
oldDpr = viewport.dpr; // Update camera & renderer
|
|
1319
|
+
const changedProps = diffProps(instance, newProps, true);
|
|
1320
|
+
if (Object.keys(changedProps).length) return [false, changedProps]; // Otherwise do not touch the instance
|
|
1451
1321
|
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
gl.setSize(size.width, size.height, size.updateStyle);
|
|
1455
|
-
} // Update viewport once the camera changes
|
|
1322
|
+
return null;
|
|
1323
|
+
},
|
|
1456
1324
|
|
|
1325
|
+
commitUpdate(instance, diff, type, _oldProps, newProps, fiber) {
|
|
1326
|
+
const [reconstruct, changedProps] = diff; // Reconstruct when args or <primitive object={...} have changes
|
|
1457
1327
|
|
|
1458
|
-
if (
|
|
1459
|
-
oldCamera = camera; // Update viewport
|
|
1328
|
+
if (reconstruct) return switchInstance(instance, type, newProps, fiber); // Otherwise just overwrite props
|
|
1460
1329
|
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1330
|
+
Object.assign(instance.props, changedProps);
|
|
1331
|
+
applyProps(instance.object, changedProps);
|
|
1332
|
+
},
|
|
1333
|
+
|
|
1334
|
+
finalizeInitialChildren: () => false,
|
|
1335
|
+
|
|
1336
|
+
commitMount() {},
|
|
1337
|
+
|
|
1338
|
+
getPublicInstance: instance => instance == null ? void 0 : instance.object,
|
|
1339
|
+
prepareForCommit: () => null,
|
|
1340
|
+
preparePortalMount: container => prepare(container.getState().scene, container, '', {}),
|
|
1341
|
+
resetAfterCommit: () => {},
|
|
1342
|
+
shouldSetTextContent: () => false,
|
|
1343
|
+
clearContainer: () => false,
|
|
1344
|
+
|
|
1345
|
+
hideInstance(instance) {
|
|
1346
|
+
var _instance$parent;
|
|
1347
|
+
|
|
1348
|
+
if (instance.props.attach && (_instance$parent = instance.parent) != null && _instance$parent.object) {
|
|
1349
|
+
detach(instance.parent, instance);
|
|
1350
|
+
} else if (instance.object instanceof THREE__namespace.Object3D) {
|
|
1351
|
+
instance.object.visible = false;
|
|
1466
1352
|
}
|
|
1467
|
-
}); // Invalidate on any change
|
|
1468
1353
|
|
|
1469
|
-
|
|
1354
|
+
instance.isHidden = true;
|
|
1355
|
+
invalidateInstance(instance);
|
|
1356
|
+
},
|
|
1357
|
+
|
|
1358
|
+
unhideInstance(instance) {
|
|
1359
|
+
if (instance.isHidden) {
|
|
1360
|
+
var _instance$parent2;
|
|
1470
1361
|
|
|
1471
|
-
|
|
1472
|
-
|
|
1362
|
+
if (instance.props.attach && (_instance$parent2 = instance.parent) != null && _instance$parent2.object) {
|
|
1363
|
+
attach(instance.parent, instance);
|
|
1364
|
+
} else if (instance.object instanceof THREE__namespace.Object3D && instance.props.visible !== false) {
|
|
1365
|
+
instance.object.visible = true;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
instance.isHidden = false;
|
|
1370
|
+
invalidateInstance(instance);
|
|
1371
|
+
},
|
|
1372
|
+
|
|
1373
|
+
createTextInstance: handleTextInstance,
|
|
1374
|
+
hideTextInstance: handleTextInstance,
|
|
1375
|
+
unhideTextInstance: handleTextInstance,
|
|
1376
|
+
// https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
|
|
1377
|
+
// @ts-ignore
|
|
1378
|
+
getCurrentEventPriority: () => getEventPriority(),
|
|
1379
|
+
beforeActiveInstanceBlur: () => {},
|
|
1380
|
+
afterActiveInstanceBlur: () => {},
|
|
1381
|
+
detachDeletedInstance: () => {},
|
|
1382
|
+
now: typeof performance !== 'undefined' && is.fun(performance.now) ? performance.now : is.fun(Date.now) ? Date.now : () => 0,
|
|
1383
|
+
// https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r920883503
|
|
1384
|
+
scheduleTimeout: is.fun(setTimeout) ? setTimeout : undefined,
|
|
1385
|
+
cancelTimeout: is.fun(clearTimeout) ? clearTimeout : undefined
|
|
1386
|
+
});
|
|
1473
1387
|
|
|
1474
1388
|
function createSubs(callback, subs) {
|
|
1475
1389
|
const sub = {
|
|
@@ -1501,11 +1415,25 @@ const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
|
|
|
1501
1415
|
const addTail = callback => createSubs(callback, globalTailEffects);
|
|
1502
1416
|
|
|
1503
1417
|
function run(effects, timestamp) {
|
|
1418
|
+
if (!effects.size) return;
|
|
1504
1419
|
effects.forEach(({
|
|
1505
1420
|
callback
|
|
1506
1421
|
}) => callback(timestamp));
|
|
1507
1422
|
}
|
|
1508
1423
|
|
|
1424
|
+
function flushGlobalEffects(type, timestamp) {
|
|
1425
|
+
switch (type) {
|
|
1426
|
+
case 'before':
|
|
1427
|
+
return run(globalEffects, timestamp);
|
|
1428
|
+
|
|
1429
|
+
case 'after':
|
|
1430
|
+
return run(globalAfterEffects, timestamp);
|
|
1431
|
+
|
|
1432
|
+
case 'tail':
|
|
1433
|
+
return run(globalTailEffects, timestamp);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1509
1437
|
function update(timestamp, state, frame) {
|
|
1510
1438
|
// Run local effects
|
|
1511
1439
|
let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
|
|
@@ -1538,7 +1466,7 @@ function createLoop(roots) {
|
|
|
1538
1466
|
running = true;
|
|
1539
1467
|
repeat = 0; // Run effects
|
|
1540
1468
|
|
|
1541
|
-
|
|
1469
|
+
flushGlobalEffects('before', timestamp); // Render all roots
|
|
1542
1470
|
|
|
1543
1471
|
roots.forEach(root => {
|
|
1544
1472
|
var _state$gl$xr;
|
|
@@ -1550,11 +1478,11 @@ function createLoop(roots) {
|
|
|
1550
1478
|
}
|
|
1551
1479
|
}); // Run after-effects
|
|
1552
1480
|
|
|
1553
|
-
|
|
1481
|
+
flushGlobalEffects('after', timestamp); // Stop the loop if nothing invalidates it
|
|
1554
1482
|
|
|
1555
1483
|
if (repeat === 0) {
|
|
1556
1484
|
// Tail call effects, they are called when rendering stops
|
|
1557
|
-
|
|
1485
|
+
flushGlobalEffects('tail', timestamp); // Flag end of operation
|
|
1558
1486
|
|
|
1559
1487
|
running = false;
|
|
1560
1488
|
return cancelAnimationFrame(frame);
|
|
@@ -1576,9 +1504,9 @@ function createLoop(roots) {
|
|
|
1576
1504
|
}
|
|
1577
1505
|
|
|
1578
1506
|
function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
1579
|
-
if (runGlobalEffects)
|
|
1507
|
+
if (runGlobalEffects) flushGlobalEffects('before', timestamp);
|
|
1580
1508
|
if (!state) roots.forEach(root => update(timestamp, root.store.getState()));else update(timestamp, state, frame);
|
|
1581
|
-
if (runGlobalEffects)
|
|
1509
|
+
if (runGlobalEffects) flushGlobalEffects('after', timestamp);
|
|
1582
1510
|
}
|
|
1583
1511
|
|
|
1584
1512
|
return {
|
|
@@ -1746,9 +1674,20 @@ const Stages = {
|
|
|
1746
1674
|
};
|
|
1747
1675
|
const Lifecycle = [Early, Fixed, Update, Late, Render, After];
|
|
1748
1676
|
|
|
1677
|
+
/**
|
|
1678
|
+
* Exposes an object's {@link Instance}.
|
|
1679
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
|
|
1680
|
+
*
|
|
1681
|
+
* **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
|
|
1682
|
+
*/
|
|
1683
|
+
function useInstanceHandle(ref) {
|
|
1684
|
+
const instance = React__namespace.useRef(null);
|
|
1685
|
+
useIsomorphicLayoutEffect(() => void (instance.current = ref.current.__r3f), [ref]);
|
|
1686
|
+
return instance;
|
|
1687
|
+
}
|
|
1749
1688
|
function useStore() {
|
|
1750
1689
|
const store = React__namespace.useContext(context);
|
|
1751
|
-
if (!store) throw
|
|
1690
|
+
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1752
1691
|
return store;
|
|
1753
1692
|
}
|
|
1754
1693
|
/**
|
|
@@ -1807,7 +1746,7 @@ function loadingFn(extensions, onProgress) {
|
|
|
1807
1746
|
return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
|
|
1808
1747
|
if (data.scene) Object.assign(data, buildGraph(data.scene));
|
|
1809
1748
|
res(data);
|
|
1810
|
-
}, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
|
|
1749
|
+
}, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
|
|
1811
1750
|
};
|
|
1812
1751
|
}
|
|
1813
1752
|
/**
|
|
@@ -1850,10 +1789,6 @@ const {
|
|
|
1850
1789
|
invalidate,
|
|
1851
1790
|
advance
|
|
1852
1791
|
} = createLoop(roots);
|
|
1853
|
-
const {
|
|
1854
|
-
reconciler,
|
|
1855
|
-
applyProps
|
|
1856
|
-
} = createRenderer(roots, getEventPriority);
|
|
1857
1792
|
const shallowLoose = {
|
|
1858
1793
|
objects: 'shallow',
|
|
1859
1794
|
strict: false
|
|
@@ -1871,19 +1806,19 @@ const createRendererInstance = (gl, canvas) => {
|
|
|
1871
1806
|
};
|
|
1872
1807
|
|
|
1873
1808
|
const createStages = (stages, store) => {
|
|
1874
|
-
var _stages;
|
|
1875
|
-
|
|
1876
1809
|
const state = store.getState();
|
|
1877
1810
|
let subscribers;
|
|
1878
1811
|
let subscription;
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1812
|
+
|
|
1813
|
+
const _stages = stages != null ? stages : Lifecycle;
|
|
1814
|
+
|
|
1815
|
+
if (!_stages.includes(Stages.Update)) throw 'The Stages.Update stage is required for R3F.';
|
|
1816
|
+
if (!_stages.includes(Stages.Render)) throw 'The Stages.Render stage is required for R3F.';
|
|
1882
1817
|
state.set(({
|
|
1883
1818
|
internal
|
|
1884
1819
|
}) => ({
|
|
1885
1820
|
internal: { ...internal,
|
|
1886
|
-
stages:
|
|
1821
|
+
stages: _stages
|
|
1887
1822
|
}
|
|
1888
1823
|
})); // Add useFrame loop to update stage
|
|
1889
1824
|
|
|
@@ -1907,11 +1842,36 @@ const createStages = (stages, store) => {
|
|
|
1907
1842
|
Stages.Render.add(renderCallback, store);
|
|
1908
1843
|
};
|
|
1909
1844
|
|
|
1845
|
+
function computeInitialSize(canvas, size) {
|
|
1846
|
+
if (!size && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1847
|
+
const {
|
|
1848
|
+
width,
|
|
1849
|
+
height,
|
|
1850
|
+
top,
|
|
1851
|
+
left
|
|
1852
|
+
} = canvas.parentElement.getBoundingClientRect();
|
|
1853
|
+
return {
|
|
1854
|
+
width,
|
|
1855
|
+
height,
|
|
1856
|
+
top,
|
|
1857
|
+
left
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
return {
|
|
1862
|
+
width: 0,
|
|
1863
|
+
height: 0,
|
|
1864
|
+
top: 0,
|
|
1865
|
+
left: 0,
|
|
1866
|
+
...size
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1910
1870
|
function createRoot(canvas) {
|
|
1911
1871
|
// Check against mistaken use of createRoot
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1872
|
+
const prevRoot = roots.get(canvas);
|
|
1873
|
+
const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
|
|
1874
|
+
const prevStore = prevRoot == null ? void 0 : prevRoot.store;
|
|
1915
1875
|
if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Report when an error was detected in a previous render
|
|
1916
1876
|
// https://github.com/pmndrs/react-three-fiber/pull/2261
|
|
1917
1877
|
|
|
@@ -1935,7 +1895,7 @@ function createRoot(canvas) {
|
|
|
1935
1895
|
configure(props = {}) {
|
|
1936
1896
|
let {
|
|
1937
1897
|
gl: glConfig,
|
|
1938
|
-
size,
|
|
1898
|
+
size: propsSize,
|
|
1939
1899
|
events,
|
|
1940
1900
|
onCreated: onCreatedCallback,
|
|
1941
1901
|
shadows = false,
|
|
@@ -2065,20 +2025,10 @@ function createRoot(canvas) {
|
|
|
2065
2025
|
|
|
2066
2026
|
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
|
|
2067
2027
|
|
|
2068
|
-
size =
|
|
2069
|
-
width: canvas.parentElement.clientWidth,
|
|
2070
|
-
height: canvas.parentElement.clientHeight,
|
|
2071
|
-
top: canvas.parentElement.clientTop,
|
|
2072
|
-
left: canvas.parentElement.clientLeft
|
|
2073
|
-
} : {
|
|
2074
|
-
width: 0,
|
|
2075
|
-
height: 0,
|
|
2076
|
-
top: 0,
|
|
2077
|
-
left: 0
|
|
2078
|
-
});
|
|
2028
|
+
const size = computeInitialSize(canvas, propsSize);
|
|
2079
2029
|
|
|
2080
2030
|
if (!is.equ(size, state.size, shallowLoose)) {
|
|
2081
|
-
state.setSize(size.width, size.height, size.
|
|
2031
|
+
state.setSize(size.width, size.height, size.top, size.left);
|
|
2082
2032
|
} // Check frameloop
|
|
2083
2033
|
|
|
2084
2034
|
|
|
@@ -2092,9 +2042,9 @@ function createRoot(canvas) {
|
|
|
2092
2042
|
performance: { ...state.performance,
|
|
2093
2043
|
...performance
|
|
2094
2044
|
}
|
|
2095
|
-
})); // Create update stages.
|
|
2045
|
+
})); // Create update stages. Only do this once on init
|
|
2096
2046
|
|
|
2097
|
-
if (
|
|
2047
|
+
if (state.internal.stages.length === 0) createStages(stages, store); // Set locals
|
|
2098
2048
|
|
|
2099
2049
|
onCreated = onCreatedCallback;
|
|
2100
2050
|
configured = true;
|
|
@@ -2169,7 +2119,7 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
2169
2119
|
(_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();
|
|
2170
2120
|
(_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
|
|
2171
2121
|
if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.xr.disconnect();
|
|
2172
|
-
dispose(state);
|
|
2122
|
+
dispose(state.scene);
|
|
2173
2123
|
roots.delete(canvas);
|
|
2174
2124
|
if (callback) callback(canvas);
|
|
2175
2125
|
} catch (e) {
|
|
@@ -2304,6 +2254,10 @@ reconciler.injectIntoDevTools({
|
|
|
2304
2254
|
rendererPackageName: '@react-three/fiber',
|
|
2305
2255
|
version: React__namespace.version
|
|
2306
2256
|
});
|
|
2257
|
+
|
|
2258
|
+
/**
|
|
2259
|
+
* Safely flush async effects when testing, simulating a legacy root.
|
|
2260
|
+
*/
|
|
2307
2261
|
const act = React__namespace.unstable_act;
|
|
2308
2262
|
|
|
2309
2263
|
exports.Block = Block;
|
|
@@ -2325,13 +2279,14 @@ exports.dispose = dispose;
|
|
|
2325
2279
|
exports.extend = extend;
|
|
2326
2280
|
exports.getRootState = getRootState;
|
|
2327
2281
|
exports.invalidate = invalidate;
|
|
2282
|
+
exports.isRef = isRef;
|
|
2328
2283
|
exports.reconciler = reconciler;
|
|
2329
2284
|
exports.render = render;
|
|
2330
2285
|
exports.roots = roots;
|
|
2331
|
-
exports.threeTypes = threeTypes;
|
|
2332
2286
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
2333
2287
|
exports.useFrame = useFrame;
|
|
2334
2288
|
exports.useGraph = useGraph;
|
|
2289
|
+
exports.useInstanceHandle = useInstanceHandle;
|
|
2335
2290
|
exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
|
|
2336
2291
|
exports.useLoader = useLoader;
|
|
2337
2292
|
exports.useMutableCallback = useMutableCallback;
|