@react-three/fiber 9.0.0-rc.1 → 9.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/declarations/src/core/events.d.ts +1 -0
- package/dist/declarations/src/core/hooks.d.ts +13 -12
- package/dist/declarations/src/core/index.d.ts +1 -1
- package/dist/declarations/src/core/reconciler.d.ts +0 -5
- package/dist/declarations/src/core/renderer.d.ts +5 -3
- package/dist/declarations/src/core/utils.d.ts +80 -31
- package/dist/declarations/src/native/Canvas.d.ts +2 -3
- package/dist/declarations/src/three-types.d.ts +5 -1
- package/dist/declarations/src/web/Canvas.d.ts +3 -4
- package/dist/{events-26d2636c.esm.js → events-aba3c3d1.esm.js} +973 -976
- package/dist/{events-cb1a9ea0.cjs.prod.js → events-b02714fc.cjs.dev.js} +971 -974
- package/dist/{events-df578889.cjs.dev.js → events-bd708dc8.cjs.prod.js} +971 -975
- package/dist/react-three-fiber.cjs.dev.js +60 -252
- package/dist/react-three-fiber.cjs.prod.js +60 -252
- package/dist/react-three-fiber.esm.js +59 -251
- package/native/dist/react-three-fiber-native.cjs.dev.js +63 -63
- package/native/dist/react-three-fiber-native.cjs.prod.js +63 -63
- package/native/dist/react-three-fiber-native.esm.js +64 -63
- package/package.json +11 -12
- package/dist/declarations/src/web/use-measure.d.ts +0 -34
|
@@ -4,11 +4,11 @@ var THREE = require('three');
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var constants = require('react-reconciler/constants');
|
|
6
6
|
var traditional = require('zustand/traditional');
|
|
7
|
+
var Reconciler = require('react-reconciler');
|
|
8
|
+
var scheduler = require('scheduler');
|
|
7
9
|
var suspendReact = require('suspend-react');
|
|
8
10
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
11
|
var itsFine = require('its-fine');
|
|
10
|
-
var Reconciler = require('react-reconciler');
|
|
11
|
-
var scheduler = require('scheduler');
|
|
12
12
|
|
|
13
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
14
14
|
|
|
@@ -38,851 +38,414 @@ var threeTypes = /*#__PURE__*/Object.freeze({
|
|
|
38
38
|
__proto__: null
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// https://github.com/microsoft/TypeScript/issues/37079
|
|
49
|
-
|
|
50
|
-
const catalogue = {};
|
|
51
|
-
let i = 0;
|
|
52
|
-
const isConstructor$1 = object => typeof object === 'function';
|
|
53
|
-
function extend(objects) {
|
|
54
|
-
if (isConstructor$1(objects)) {
|
|
55
|
-
const Component = `${i++}`;
|
|
56
|
-
catalogue[Component] = objects;
|
|
57
|
-
return Component;
|
|
58
|
-
} else {
|
|
59
|
-
Object.assign(catalogue, objects);
|
|
60
|
-
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns the instance's initial (outmost) root.
|
|
43
|
+
*/
|
|
44
|
+
function findInitialRoot(instance) {
|
|
45
|
+
let root = instance.root;
|
|
46
|
+
while (root.getState().previousRoot) root = root.getState().previousRoot;
|
|
47
|
+
return root;
|
|
61
48
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Safely flush async effects when testing, simulating a legacy root.
|
|
51
|
+
*/
|
|
52
|
+
const act = React__namespace.act;
|
|
53
|
+
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
54
|
+
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
55
|
+
const isColorRepresentation = value => value != null && (typeof value === 'string' || typeof value === 'number' || value.isColor);
|
|
69
56
|
|
|
70
|
-
|
|
71
|
-
|
|
57
|
+
/**
|
|
58
|
+
* An SSR-friendly useLayoutEffect.
|
|
59
|
+
*
|
|
60
|
+
* React currently throws a warning when using useLayoutEffect on the server.
|
|
61
|
+
* To get around it, we can conditionally useEffect on the server (no-op) and
|
|
62
|
+
* useLayoutEffect elsewhere.
|
|
63
|
+
*
|
|
64
|
+
* @see https://github.com/facebook/react/issues/14927
|
|
65
|
+
*/
|
|
66
|
+
const useIsomorphicLayoutEffect = /* @__PURE__ */((_window$document, _window$navigator) => typeof window !== 'undefined' && (((_window$document = window.document) == null ? void 0 : _window$document.createElement) || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === 'ReactNative'))() ? React__namespace.useLayoutEffect : React__namespace.useEffect;
|
|
67
|
+
function useMutableCallback(fn) {
|
|
68
|
+
const ref = React__namespace.useRef(fn);
|
|
69
|
+
useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
|
|
70
|
+
return ref;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Bridges renderer Context and StrictMode from a primary renderer.
|
|
74
|
+
*/
|
|
75
|
+
function useBridge() {
|
|
76
|
+
const fiber = itsFine.useFiber();
|
|
77
|
+
const ContextBridge = itsFine.useContextBridge();
|
|
78
|
+
return React__namespace.useMemo(() => ({
|
|
79
|
+
children
|
|
80
|
+
}) => {
|
|
81
|
+
const strict = !!itsFine.traverseFiber(fiber, true, node => node.type === React__namespace.StrictMode);
|
|
82
|
+
const Root = strict ? React__namespace.StrictMode : React__namespace.Fragment;
|
|
83
|
+
return /*#__PURE__*/jsxRuntime.jsx(Root, {
|
|
84
|
+
children: /*#__PURE__*/jsxRuntime.jsx(ContextBridge, {
|
|
85
|
+
children: children
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
}, [fiber, ContextBridge]);
|
|
89
|
+
}
|
|
90
|
+
function Block({
|
|
91
|
+
set
|
|
92
|
+
}) {
|
|
93
|
+
useIsomorphicLayoutEffect(() => {
|
|
94
|
+
set(new Promise(() => null));
|
|
95
|
+
return () => set(false);
|
|
96
|
+
}, [set]);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
72
99
|
|
|
73
|
-
|
|
74
|
-
|
|
100
|
+
// NOTE: static members get down-level transpiled to mutations which break tree-shaking
|
|
101
|
+
const ErrorBoundary = /* @__PURE__ */(_ErrorBoundary => (_ErrorBoundary = class ErrorBoundary extends React__namespace.Component {
|
|
102
|
+
constructor(...args) {
|
|
103
|
+
super(...args);
|
|
104
|
+
this.state = {
|
|
105
|
+
error: false
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
componentDidCatch(err) {
|
|
109
|
+
this.props.set(err);
|
|
110
|
+
}
|
|
111
|
+
render() {
|
|
112
|
+
return this.state.error ? null : this.props.children;
|
|
113
|
+
}
|
|
114
|
+
}, _ErrorBoundary.getDerivedStateFromError = () => ({
|
|
115
|
+
error: true
|
|
116
|
+
}), _ErrorBoundary))();
|
|
117
|
+
function calculateDpr(dpr) {
|
|
118
|
+
var _window$devicePixelRa;
|
|
119
|
+
// Err on the side of progress by assuming 2x dpr if we can't detect it
|
|
120
|
+
// This will happen in workers where window is defined but dpr isn't.
|
|
121
|
+
const target = typeof window !== 'undefined' ? (_window$devicePixelRa = window.devicePixelRatio) != null ? _window$devicePixelRa : 2 : 1;
|
|
122
|
+
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
75
123
|
}
|
|
76
|
-
function createInstance(type, props, root) {
|
|
77
|
-
var _props$object;
|
|
78
|
-
validateInstance(type, props);
|
|
79
124
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Returns instance root state
|
|
127
|
+
*/
|
|
128
|
+
function getRootState(obj) {
|
|
129
|
+
var _r3f;
|
|
130
|
+
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
|
|
83
131
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
132
|
+
// A collection of compare functions
|
|
133
|
+
const is = {
|
|
134
|
+
obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
|
|
135
|
+
fun: a => typeof a === 'function',
|
|
136
|
+
str: a => typeof a === 'string',
|
|
137
|
+
num: a => typeof a === 'number',
|
|
138
|
+
boo: a => typeof a === 'boolean',
|
|
139
|
+
und: a => a === void 0,
|
|
140
|
+
nul: a => a === null,
|
|
141
|
+
arr: a => Array.isArray(a),
|
|
142
|
+
equ(a, b, {
|
|
143
|
+
arrays = 'shallow',
|
|
144
|
+
objects = 'reference',
|
|
145
|
+
strict = true
|
|
146
|
+
} = {}) {
|
|
147
|
+
// Wrong type or one of the two undefined, doesn't match
|
|
148
|
+
if (typeof a !== typeof b || !!a !== !!b) return false;
|
|
149
|
+
// Atomic, just compare a against b
|
|
150
|
+
if (is.str(a) || is.num(a) || is.boo(a)) return a === b;
|
|
151
|
+
const isObj = is.obj(a);
|
|
152
|
+
if (isObj && objects === 'reference') return a === b;
|
|
153
|
+
const isArr = is.arr(a);
|
|
154
|
+
if (isArr && arrays === 'reference') return a === b;
|
|
155
|
+
// Array or Object, shallow compare first to see if it's a match
|
|
156
|
+
if ((isArr || isObj) && a === b) return true;
|
|
157
|
+
// Last resort, go through keys
|
|
158
|
+
let i;
|
|
159
|
+
// Check if a has all the keys of b
|
|
160
|
+
for (i in a) if (!(i in b)) return false;
|
|
161
|
+
// Check if values between keys match
|
|
162
|
+
if (isObj && arrays === 'shallow' && objects === 'shallow') {
|
|
163
|
+
for (i in strict ? b : a) if (!is.equ(a[i], b[i], {
|
|
164
|
+
strict,
|
|
165
|
+
objects: 'reference'
|
|
166
|
+
})) return false;
|
|
167
|
+
} else {
|
|
168
|
+
for (i in strict ? b : a) if (a[i] !== b[i]) return false;
|
|
91
169
|
}
|
|
92
|
-
|
|
93
|
-
|
|
170
|
+
// If i is undefined
|
|
171
|
+
if (is.und(i)) {
|
|
172
|
+
// If both arrays are empty we consider them equal
|
|
173
|
+
if (isArr && a.length === 0 && b.length === 0) return true;
|
|
174
|
+
// If both objects are empty we consider them equal
|
|
175
|
+
if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
|
|
176
|
+
// Otherwise match them by value
|
|
177
|
+
if (a !== b) return false;
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Collects nodes and materials from a THREE.Object3D
|
|
184
|
+
function buildGraph(object) {
|
|
185
|
+
const data = {
|
|
186
|
+
nodes: {},
|
|
187
|
+
materials: {}
|
|
188
|
+
};
|
|
189
|
+
if (object) {
|
|
190
|
+
object.traverse(obj => {
|
|
191
|
+
if (obj.name) data.nodes[obj.name] = obj;
|
|
192
|
+
if (obj.material && !data.materials[obj.material.name]) data.materials[obj.material.name] = obj.material;
|
|
193
|
+
});
|
|
94
194
|
}
|
|
195
|
+
return data;
|
|
95
196
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
instance.object.visible = true;
|
|
103
|
-
}
|
|
104
|
-
instance.isHidden = false;
|
|
105
|
-
invalidateInstance(instance);
|
|
197
|
+
// Disposes an object and all its properties
|
|
198
|
+
function dispose(obj) {
|
|
199
|
+
if (obj.type !== 'Scene') obj.dispose == null ? void 0 : obj.dispose();
|
|
200
|
+
for (const p in obj) {
|
|
201
|
+
const prop = obj[p];
|
|
202
|
+
if ((prop == null ? void 0 : prop.type) !== 'Scene') prop == null ? void 0 : prop.dispose == null ? void 0 : prop.dispose();
|
|
106
203
|
}
|
|
107
204
|
}
|
|
205
|
+
const REACT_INTERNAL_PROPS = ['children', 'key', 'ref'];
|
|
108
206
|
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// Create & link object on first run
|
|
118
|
-
if (!child.object) {
|
|
119
|
-
var _child$props$object, _child$props$args;
|
|
120
|
-
// Get target from catalogue
|
|
121
|
-
const name = `${child.type[0].toUpperCase()}${child.type.slice(1)}`;
|
|
122
|
-
const target = catalogue[name];
|
|
207
|
+
// Gets only instance props from reconciler fibers
|
|
208
|
+
function getInstanceProps(queue) {
|
|
209
|
+
const props = {};
|
|
210
|
+
for (const key in queue) {
|
|
211
|
+
if (!REACT_INTERNAL_PROPS.includes(key)) props[key] = queue[key];
|
|
212
|
+
}
|
|
213
|
+
return props;
|
|
214
|
+
}
|
|
123
215
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
216
|
+
// Each object in the scene carries a small LocalState descriptor
|
|
217
|
+
function prepare(target, root, type, props) {
|
|
218
|
+
const object = target;
|
|
127
219
|
|
|
128
|
-
|
|
129
|
-
|
|
220
|
+
// Create instance descriptor
|
|
221
|
+
let instance = object == null ? void 0 : object.__r3f;
|
|
222
|
+
if (!instance) {
|
|
223
|
+
instance = {
|
|
224
|
+
root,
|
|
225
|
+
type,
|
|
226
|
+
parent: null,
|
|
227
|
+
children: [],
|
|
228
|
+
props: getInstanceProps(props),
|
|
229
|
+
object,
|
|
230
|
+
eventCount: 0,
|
|
231
|
+
handlers: {},
|
|
232
|
+
isHidden: false
|
|
233
|
+
};
|
|
234
|
+
if (object) object.__r3f = instance;
|
|
130
235
|
}
|
|
236
|
+
return instance;
|
|
237
|
+
}
|
|
238
|
+
function resolve(root, key) {
|
|
239
|
+
var _target;
|
|
240
|
+
let target = root[key];
|
|
241
|
+
if (!key.includes('-')) return {
|
|
242
|
+
root,
|
|
243
|
+
key,
|
|
244
|
+
target
|
|
245
|
+
};
|
|
131
246
|
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const childIndex = parent.object.children.indexOf(beforeChild == null ? void 0 : beforeChild.object);
|
|
137
|
-
if (beforeChild && childIndex !== -1) {
|
|
138
|
-
child.object.parent = parent.object;
|
|
139
|
-
parent.object.children.splice(childIndex, 0, child.object);
|
|
140
|
-
child.object.dispatchEvent({
|
|
141
|
-
type: 'added'
|
|
142
|
-
});
|
|
143
|
-
parent.object.dispatchEvent({
|
|
144
|
-
type: 'childadded',
|
|
145
|
-
child: child.object
|
|
146
|
-
});
|
|
147
|
-
} else {
|
|
148
|
-
parent.object.add(child.object);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Link subtree
|
|
153
|
-
for (const childInstance of child.children) handleContainerEffects(child, childInstance);
|
|
247
|
+
// Resolve pierced target
|
|
248
|
+
const chain = key.split('-');
|
|
249
|
+
target = chain.reduce((acc, key) => acc[key], root);
|
|
250
|
+
key = chain.pop();
|
|
154
251
|
|
|
155
|
-
//
|
|
156
|
-
|
|
252
|
+
// Switch root if atomic
|
|
253
|
+
if (!((_target = target) != null && _target.set)) root = chain.reduce((acc, key) => acc[key], root);
|
|
254
|
+
return {
|
|
255
|
+
root,
|
|
256
|
+
key,
|
|
257
|
+
target
|
|
258
|
+
};
|
|
157
259
|
}
|
|
158
|
-
function appendChild(parent, child) {
|
|
159
|
-
if (!child) return;
|
|
160
|
-
|
|
161
|
-
// Link instances
|
|
162
|
-
child.parent = parent;
|
|
163
|
-
parent.children.push(child);
|
|
164
260
|
|
|
165
|
-
|
|
166
|
-
|
|
261
|
+
// Checks if a dash-cased string ends with an integer
|
|
262
|
+
const INDEX_REGEX = /-\d+$/;
|
|
263
|
+
function attach(parent, child) {
|
|
264
|
+
if (is.str(child.props.attach)) {
|
|
265
|
+
// If attaching into an array (foo-0), create one
|
|
266
|
+
if (INDEX_REGEX.test(child.props.attach)) {
|
|
267
|
+
const index = child.props.attach.replace(INDEX_REGEX, '');
|
|
268
|
+
const {
|
|
269
|
+
root,
|
|
270
|
+
key
|
|
271
|
+
} = resolve(parent.object, index);
|
|
272
|
+
if (!Array.isArray(root[key])) root[key] = [];
|
|
273
|
+
}
|
|
274
|
+
const {
|
|
275
|
+
root,
|
|
276
|
+
key
|
|
277
|
+
} = resolve(parent.object, child.props.attach);
|
|
278
|
+
child.previousAttach = root[key];
|
|
279
|
+
root[key] = child.object;
|
|
280
|
+
} else if (is.fun(child.props.attach)) {
|
|
281
|
+
child.previousAttach = child.props.attach(parent.object, child.object);
|
|
282
|
+
}
|
|
167
283
|
}
|
|
168
|
-
function
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
284
|
+
function detach(parent, child) {
|
|
285
|
+
if (is.str(child.props.attach)) {
|
|
286
|
+
const {
|
|
287
|
+
root,
|
|
288
|
+
key
|
|
289
|
+
} = resolve(parent.object, child.props.attach);
|
|
290
|
+
const previous = child.previousAttach;
|
|
291
|
+
// When the previous value was undefined, it means the value was never set to begin with
|
|
292
|
+
if (previous === undefined) delete root[key];
|
|
293
|
+
// Otherwise set the previous value
|
|
294
|
+
else root[key] = previous;
|
|
295
|
+
} else {
|
|
296
|
+
child.previousAttach == null ? void 0 : child.previousAttach(parent.object, child.object);
|
|
297
|
+
}
|
|
298
|
+
delete child.previousAttach;
|
|
178
299
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
300
|
+
const RESERVED_PROPS = [...REACT_INTERNAL_PROPS,
|
|
301
|
+
// Instance props
|
|
302
|
+
'args', 'dispose', 'attach', 'object', 'onUpdate',
|
|
303
|
+
// Behavior flags
|
|
304
|
+
'dispose'];
|
|
305
|
+
const MEMOIZED_PROTOTYPES = new Map();
|
|
306
|
+
function getMemoizedPrototype(root) {
|
|
307
|
+
let ctor = MEMOIZED_PROTOTYPES.get(root.constructor);
|
|
308
|
+
try {
|
|
309
|
+
if (!ctor) {
|
|
310
|
+
ctor = new root.constructor();
|
|
311
|
+
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
312
|
+
}
|
|
313
|
+
} catch (e) {
|
|
314
|
+
// ...
|
|
193
315
|
}
|
|
316
|
+
return ctor;
|
|
194
317
|
}
|
|
195
|
-
function removeChild(parent, child, dispose) {
|
|
196
|
-
if (!child) return;
|
|
197
318
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
if (childIndex !== -1) parent.children.splice(childIndex, 1);
|
|
319
|
+
// This function prepares a set of changes to be applied to the instance
|
|
320
|
+
function diffProps(instance, newProps) {
|
|
321
|
+
const changedProps = {};
|
|
202
322
|
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
323
|
+
// Sort through props
|
|
324
|
+
for (const prop in newProps) {
|
|
325
|
+
// Skip reserved keys
|
|
326
|
+
if (RESERVED_PROPS.includes(prop)) continue;
|
|
327
|
+
// Skip if props match
|
|
328
|
+
if (is.equ(newProps[prop], instance.props[prop])) continue;
|
|
210
329
|
|
|
211
|
-
|
|
212
|
-
|
|
330
|
+
// Props changed, add them
|
|
331
|
+
changedProps[prop] = newProps[prop];
|
|
213
332
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
333
|
+
// Reset pierced props
|
|
334
|
+
for (const other in newProps) {
|
|
335
|
+
if (other.startsWith(`${prop}-`)) changedProps[other] = newProps[other];
|
|
336
|
+
}
|
|
218
337
|
}
|
|
219
|
-
child.children.length = 0;
|
|
220
338
|
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// - cannot be a <primitive object={...} />
|
|
229
|
-
// - cannot be a THREE.Scene, because three has broken its own API
|
|
230
|
-
if (shouldDispose && child.type !== 'primitive' && child.object.type !== 'Scene') {
|
|
231
|
-
disposeOnIdle(child.object);
|
|
232
|
-
}
|
|
339
|
+
// Reset removed props for HMR
|
|
340
|
+
for (const prop in instance.props) {
|
|
341
|
+
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
342
|
+
const {
|
|
343
|
+
root,
|
|
344
|
+
key
|
|
345
|
+
} = resolve(instance.object, prop);
|
|
233
346
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
347
|
+
// https://github.com/mrdoob/three.js/issues/21209
|
|
348
|
+
// HMR/fast-refresh relies on the ability to cancel out props, but threejs
|
|
349
|
+
// has no means to do this. Hence we curate a small collection of value-classes
|
|
350
|
+
// with their respective constructor/set arguments
|
|
351
|
+
// For removed props, try to set default values, if possible
|
|
352
|
+
if (root.constructor && root.constructor.length === 0) {
|
|
353
|
+
// create a blank slate of the instance and copy the particular parameter.
|
|
354
|
+
const ctor = getMemoizedPrototype(root);
|
|
355
|
+
if (!is.und(ctor)) changedProps[key] = ctor[key];
|
|
356
|
+
} else {
|
|
357
|
+
// instance does not have constructor, just set it to 0
|
|
358
|
+
changedProps[key] = 0;
|
|
247
359
|
}
|
|
248
360
|
}
|
|
361
|
+
return changedProps;
|
|
249
362
|
}
|
|
250
|
-
const reconstructed = [];
|
|
251
|
-
function swapInstances() {
|
|
252
|
-
// Detach instance
|
|
253
|
-
for (const [instance] of reconstructed) {
|
|
254
|
-
const parent = instance.parent;
|
|
255
|
-
if (parent) {
|
|
256
|
-
if (instance.props.attach) {
|
|
257
|
-
detach(parent, instance);
|
|
258
|
-
} else if (isObject3D(instance.object) && isObject3D(parent.object)) {
|
|
259
|
-
parent.object.remove(instance.object);
|
|
260
|
-
}
|
|
261
|
-
for (const child of instance.children) {
|
|
262
|
-
if (child.props.attach) {
|
|
263
|
-
detach(instance, child);
|
|
264
|
-
} else if (isObject3D(child.object) && isObject3D(instance.object)) {
|
|
265
|
-
instance.object.remove(child.object);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
363
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
364
|
+
// https://github.com/mrdoob/three.js/pull/27042
|
|
365
|
+
// https://github.com/mrdoob/three.js/pull/22748
|
|
366
|
+
const colorMaps = ['map', 'emissiveMap', 'sheenColorMap', 'specularColorMap', 'envMap'];
|
|
367
|
+
const EVENT_REGEX = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/;
|
|
368
|
+
// This function applies a set of changes to the instance
|
|
369
|
+
function applyProps(object, props) {
|
|
370
|
+
var _instance$object;
|
|
371
|
+
const instance = object.__r3f;
|
|
372
|
+
const rootState = instance && findInitialRoot(instance).getState();
|
|
373
|
+
const prevHandlers = instance == null ? void 0 : instance.eventCount;
|
|
374
|
+
for (const prop in props) {
|
|
375
|
+
let value = props[prop];
|
|
275
376
|
|
|
276
|
-
//
|
|
277
|
-
if (
|
|
278
|
-
if (instance.type !== 'primitive') disposeOnIdle(instance.object);
|
|
279
|
-
}
|
|
377
|
+
// Don't mutate reserved keys
|
|
378
|
+
if (RESERVED_PROPS.includes(prop)) continue;
|
|
280
379
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
// Get target from catalogue
|
|
288
|
-
const name = `${instance.type[0].toUpperCase()}${instance.type.slice(1)}`;
|
|
289
|
-
const target = catalogue[name];
|
|
380
|
+
// Deal with pointer events, including removing them if undefined
|
|
381
|
+
if (instance && EVENT_REGEX.test(prop)) {
|
|
382
|
+
if (typeof value === 'function') instance.handlers[prop] = value;else delete instance.handlers[prop];
|
|
383
|
+
instance.eventCount = Object.keys(instance.handlers).length;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
290
386
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
387
|
+
// Ignore setting undefined props
|
|
388
|
+
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
389
|
+
if (value === undefined) continue;
|
|
390
|
+
let {
|
|
391
|
+
root,
|
|
392
|
+
key,
|
|
393
|
+
target
|
|
394
|
+
} = resolve(object, prop);
|
|
295
395
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
parent.object.add(instance.object);
|
|
302
|
-
}
|
|
303
|
-
for (const child of instance.children) {
|
|
304
|
-
if (child.props.attach) {
|
|
305
|
-
attach(instance, child);
|
|
306
|
-
} else if (isObject3D(child.object) && isObject3D(instance.object)) {
|
|
307
|
-
instance.object.add(child.object);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Tree was updated, request a frame
|
|
312
|
-
invalidateInstance(instance);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
reconstructed.length = 0;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Don't handle text instances, make it no-op
|
|
319
|
-
const handleTextInstance = () => {};
|
|
320
|
-
const NO_CONTEXT = {};
|
|
321
|
-
let currentUpdatePriority = constants.NoEventPriority;
|
|
322
|
-
|
|
323
|
-
// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberFlags.js
|
|
324
|
-
const NoFlags = 0;
|
|
325
|
-
const Update = 4;
|
|
326
|
-
const reconciler = createReconciler({
|
|
327
|
-
isPrimaryRenderer: false,
|
|
328
|
-
warnsIfNotActing: false,
|
|
329
|
-
supportsMutation: true,
|
|
330
|
-
supportsPersistence: false,
|
|
331
|
-
supportsHydration: false,
|
|
332
|
-
createInstance,
|
|
333
|
-
removeChild,
|
|
334
|
-
appendChild,
|
|
335
|
-
appendInitialChild: appendChild,
|
|
336
|
-
insertBefore,
|
|
337
|
-
appendChildToContainer(container, child) {
|
|
338
|
-
const scene = container.getState().scene.__r3f;
|
|
339
|
-
if (!child || !scene) return;
|
|
340
|
-
appendChild(scene, child);
|
|
341
|
-
},
|
|
342
|
-
removeChildFromContainer(container, child) {
|
|
343
|
-
const scene = container.getState().scene.__r3f;
|
|
344
|
-
if (!child || !scene) return;
|
|
345
|
-
removeChild(scene, child);
|
|
346
|
-
},
|
|
347
|
-
insertInContainerBefore(container, child, beforeChild) {
|
|
348
|
-
const scene = container.getState().scene.__r3f;
|
|
349
|
-
if (!child || !beforeChild || !scene) return;
|
|
350
|
-
insertBefore(scene, child, beforeChild);
|
|
351
|
-
},
|
|
352
|
-
getRootHostContext: () => NO_CONTEXT,
|
|
353
|
-
getChildHostContext: () => NO_CONTEXT,
|
|
354
|
-
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
355
|
-
var _newProps$args, _oldProps$args, _newProps$args2;
|
|
356
|
-
validateInstance(type, newProps);
|
|
357
|
-
let reconstruct = false;
|
|
358
|
-
|
|
359
|
-
// Reconstruct primitives if object prop changes
|
|
360
|
-
if (instance.type === 'primitive' && oldProps.object !== newProps.object) reconstruct = true;
|
|
361
|
-
// Reconstruct instance if args were added or removed
|
|
362
|
-
else if (((_newProps$args = newProps.args) == null ? void 0 : _newProps$args.length) !== ((_oldProps$args = oldProps.args) == null ? void 0 : _oldProps$args.length)) reconstruct = true;
|
|
363
|
-
// Reconstruct instance if args were changed
|
|
364
|
-
else if ((_newProps$args2 = newProps.args) != null && _newProps$args2.some((value, index) => {
|
|
365
|
-
var _oldProps$args2;
|
|
366
|
-
return value !== ((_oldProps$args2 = oldProps.args) == null ? void 0 : _oldProps$args2[index]);
|
|
367
|
-
})) reconstruct = true;
|
|
368
|
-
|
|
369
|
-
// Reconstruct when args or <primitive object={...} have changes
|
|
370
|
-
if (reconstruct) {
|
|
371
|
-
reconstructed.push([instance, {
|
|
372
|
-
...newProps
|
|
373
|
-
}, fiber]);
|
|
374
|
-
} else {
|
|
375
|
-
// Create a diff-set, flag if there are any changes
|
|
376
|
-
const changedProps = diffProps(instance, newProps);
|
|
377
|
-
if (Object.keys(changedProps).length) {
|
|
378
|
-
Object.assign(instance.props, changedProps);
|
|
379
|
-
applyProps(instance.object, changedProps);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Flush reconstructed siblings when we hit the last updated child in a sequence
|
|
384
|
-
const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
|
|
385
|
-
if (isTailSibling) swapInstances();
|
|
386
|
-
},
|
|
387
|
-
finalizeInitialChildren: () => false,
|
|
388
|
-
commitMount() {},
|
|
389
|
-
getPublicInstance: instance => instance == null ? void 0 : instance.object,
|
|
390
|
-
prepareForCommit: () => null,
|
|
391
|
-
preparePortalMount: container => prepare(container.getState().scene, container, '', {}),
|
|
392
|
-
resetAfterCommit: () => {},
|
|
393
|
-
shouldSetTextContent: () => false,
|
|
394
|
-
clearContainer: () => false,
|
|
395
|
-
hideInstance,
|
|
396
|
-
unhideInstance,
|
|
397
|
-
createTextInstance: handleTextInstance,
|
|
398
|
-
hideTextInstance: handleTextInstance,
|
|
399
|
-
unhideTextInstance: handleTextInstance,
|
|
400
|
-
scheduleTimeout: typeof setTimeout === 'function' ? setTimeout : undefined,
|
|
401
|
-
cancelTimeout: typeof clearTimeout === 'function' ? clearTimeout : undefined,
|
|
402
|
-
noTimeout: -1,
|
|
403
|
-
getInstanceFromNode: () => null,
|
|
404
|
-
beforeActiveInstanceBlur() {},
|
|
405
|
-
afterActiveInstanceBlur() {},
|
|
406
|
-
detachDeletedInstance() {},
|
|
407
|
-
prepareScopeUpdate() {},
|
|
408
|
-
getInstanceFromScope: () => null,
|
|
409
|
-
shouldAttemptEagerTransition: () => false,
|
|
410
|
-
trackSchedulerEvent: () => {},
|
|
411
|
-
resolveEventType: () => null,
|
|
412
|
-
resolveEventTimeStamp: () => -1.1,
|
|
413
|
-
requestPostPaintCallback() {},
|
|
414
|
-
maySuspendCommit: () => false,
|
|
415
|
-
preloadInstance: () => true,
|
|
416
|
-
// true indicates already loaded
|
|
417
|
-
startSuspendingCommit() {},
|
|
418
|
-
suspendInstance() {},
|
|
419
|
-
waitForCommitToBeReady: () => null,
|
|
420
|
-
NotPendingTransition: null,
|
|
421
|
-
setCurrentUpdatePriority(newPriority) {
|
|
422
|
-
currentUpdatePriority = newPriority;
|
|
423
|
-
},
|
|
424
|
-
getCurrentUpdatePriority() {
|
|
425
|
-
return currentUpdatePriority;
|
|
426
|
-
},
|
|
427
|
-
resolveUpdatePriority() {
|
|
428
|
-
var _window$event;
|
|
429
|
-
if (currentUpdatePriority !== constants.NoEventPriority) return currentUpdatePriority;
|
|
430
|
-
switch (typeof window !== 'undefined' && ((_window$event = window.event) == null ? void 0 : _window$event.type)) {
|
|
431
|
-
case 'click':
|
|
432
|
-
case 'contextmenu':
|
|
433
|
-
case 'dblclick':
|
|
434
|
-
case 'pointercancel':
|
|
435
|
-
case 'pointerdown':
|
|
436
|
-
case 'pointerup':
|
|
437
|
-
return constants.DiscreteEventPriority;
|
|
438
|
-
case 'pointermove':
|
|
439
|
-
case 'pointerout':
|
|
440
|
-
case 'pointerover':
|
|
441
|
-
case 'pointerenter':
|
|
442
|
-
case 'pointerleave':
|
|
443
|
-
case 'wheel':
|
|
444
|
-
return constants.ContinuousEventPriority;
|
|
445
|
-
default:
|
|
446
|
-
return constants.DefaultEventPriority;
|
|
447
|
-
}
|
|
448
|
-
},
|
|
449
|
-
resetFormInstance() {}
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
var _window$document, _window$navigator;
|
|
453
|
-
/**
|
|
454
|
-
* Returns the instance's initial (outmost) root.
|
|
455
|
-
*/
|
|
456
|
-
function findInitialRoot(instance) {
|
|
457
|
-
let root = instance.root;
|
|
458
|
-
while (root.getState().previousRoot) root = root.getState().previousRoot;
|
|
459
|
-
return root;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Returns `true` with correct TS type inference if an object has a configurable color space (since r152).
|
|
464
|
-
*/
|
|
465
|
-
const hasColorSpace = object => 'colorSpace' in object || 'outputColorSpace' in object;
|
|
466
|
-
/**
|
|
467
|
-
* The current THREE.ColorManagement instance, if present.
|
|
468
|
-
*/
|
|
469
|
-
const getColorManagement = () => {
|
|
470
|
-
var _ColorManagement;
|
|
471
|
-
return (_ColorManagement = catalogue.ColorManagement) != null ? _ColorManagement : null;
|
|
472
|
-
};
|
|
473
|
-
/**
|
|
474
|
-
* Safely flush async effects when testing, simulating a legacy root.
|
|
475
|
-
*/
|
|
476
|
-
const act = React__namespace.act;
|
|
477
|
-
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
478
|
-
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* An SSR-friendly useLayoutEffect.
|
|
482
|
-
*
|
|
483
|
-
* React currently throws a warning when using useLayoutEffect on the server.
|
|
484
|
-
* To get around it, we can conditionally useEffect on the server (no-op) and
|
|
485
|
-
* useLayoutEffect elsewhere.
|
|
486
|
-
*
|
|
487
|
-
* @see https://github.com/facebook/react/issues/14927
|
|
488
|
-
*/
|
|
489
|
-
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;
|
|
490
|
-
function useMutableCallback(fn) {
|
|
491
|
-
const ref = React__namespace.useRef(fn);
|
|
492
|
-
useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
|
|
493
|
-
return ref;
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* Bridges renderer Context and StrictMode from a primary renderer.
|
|
497
|
-
*/
|
|
498
|
-
function useBridge() {
|
|
499
|
-
const fiber = itsFine.useFiber();
|
|
500
|
-
const ContextBridge = itsFine.useContextBridge();
|
|
501
|
-
return React__namespace.useMemo(() => ({
|
|
502
|
-
children
|
|
503
|
-
}) => {
|
|
504
|
-
const strict = !!itsFine.traverseFiber(fiber, true, node => node.type === React__namespace.StrictMode);
|
|
505
|
-
const Root = strict ? React__namespace.StrictMode : React__namespace.Fragment;
|
|
506
|
-
return /*#__PURE__*/jsxRuntime.jsx(Root, {
|
|
507
|
-
children: /*#__PURE__*/jsxRuntime.jsx(ContextBridge, {
|
|
508
|
-
children: children
|
|
509
|
-
})
|
|
510
|
-
});
|
|
511
|
-
}, [fiber, ContextBridge]);
|
|
512
|
-
}
|
|
513
|
-
function Block({
|
|
514
|
-
set
|
|
515
|
-
}) {
|
|
516
|
-
useIsomorphicLayoutEffect(() => {
|
|
517
|
-
set(new Promise(() => null));
|
|
518
|
-
return () => set(false);
|
|
519
|
-
}, [set]);
|
|
520
|
-
return null;
|
|
521
|
-
}
|
|
522
|
-
class ErrorBoundary extends React__namespace.Component {
|
|
523
|
-
constructor(...args) {
|
|
524
|
-
super(...args);
|
|
525
|
-
this.state = {
|
|
526
|
-
error: false
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
componentDidCatch(err) {
|
|
530
|
-
this.props.set(err);
|
|
531
|
-
}
|
|
532
|
-
render() {
|
|
533
|
-
return this.state.error ? null : this.props.children;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
ErrorBoundary.getDerivedStateFromError = () => ({
|
|
537
|
-
error: true
|
|
538
|
-
});
|
|
539
|
-
function calculateDpr(dpr) {
|
|
540
|
-
var _window$devicePixelRa;
|
|
541
|
-
// Err on the side of progress by assuming 2x dpr if we can't detect it
|
|
542
|
-
// This will happen in workers where window is defined but dpr isn't.
|
|
543
|
-
const target = typeof window !== 'undefined' ? (_window$devicePixelRa = window.devicePixelRatio) != null ? _window$devicePixelRa : 2 : 1;
|
|
544
|
-
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
/**
|
|
548
|
-
* Returns instance root state
|
|
549
|
-
*/
|
|
550
|
-
function getRootState(obj) {
|
|
551
|
-
var _r3f;
|
|
552
|
-
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
|
|
553
|
-
}
|
|
554
|
-
// A collection of compare functions
|
|
555
|
-
const is = {
|
|
556
|
-
obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
|
|
557
|
-
fun: a => typeof a === 'function',
|
|
558
|
-
str: a => typeof a === 'string',
|
|
559
|
-
num: a => typeof a === 'number',
|
|
560
|
-
boo: a => typeof a === 'boolean',
|
|
561
|
-
und: a => a === void 0,
|
|
562
|
-
arr: a => Array.isArray(a),
|
|
563
|
-
equ(a, b, {
|
|
564
|
-
arrays = 'shallow',
|
|
565
|
-
objects = 'reference',
|
|
566
|
-
strict = true
|
|
567
|
-
} = {}) {
|
|
568
|
-
// Wrong type or one of the two undefined, doesn't match
|
|
569
|
-
if (typeof a !== typeof b || !!a !== !!b) return false;
|
|
570
|
-
// Atomic, just compare a against b
|
|
571
|
-
if (is.str(a) || is.num(a) || is.boo(a)) return a === b;
|
|
572
|
-
const isObj = is.obj(a);
|
|
573
|
-
if (isObj && objects === 'reference') return a === b;
|
|
574
|
-
const isArr = is.arr(a);
|
|
575
|
-
if (isArr && arrays === 'reference') return a === b;
|
|
576
|
-
// Array or Object, shallow compare first to see if it's a match
|
|
577
|
-
if ((isArr || isObj) && a === b) return true;
|
|
578
|
-
// Last resort, go through keys
|
|
579
|
-
let i;
|
|
580
|
-
// Check if a has all the keys of b
|
|
581
|
-
for (i in a) if (!(i in b)) return false;
|
|
582
|
-
// Check if values between keys match
|
|
583
|
-
if (isObj && arrays === 'shallow' && objects === 'shallow') {
|
|
584
|
-
for (i in strict ? b : a) if (!is.equ(a[i], b[i], {
|
|
585
|
-
strict,
|
|
586
|
-
objects: 'reference'
|
|
587
|
-
})) return false;
|
|
588
|
-
} else {
|
|
589
|
-
for (i in strict ? b : a) if (a[i] !== b[i]) return false;
|
|
590
|
-
}
|
|
591
|
-
// If i is undefined
|
|
592
|
-
if (is.und(i)) {
|
|
593
|
-
// If both arrays are empty we consider them equal
|
|
594
|
-
if (isArr && a.length === 0 && b.length === 0) return true;
|
|
595
|
-
// If both objects are empty we consider them equal
|
|
596
|
-
if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
|
|
597
|
-
// Otherwise match them by value
|
|
598
|
-
if (a !== b) return false;
|
|
599
|
-
}
|
|
600
|
-
return true;
|
|
601
|
-
}
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
// Collects nodes and materials from a THREE.Object3D
|
|
605
|
-
function buildGraph(object) {
|
|
606
|
-
const data = {
|
|
607
|
-
nodes: {},
|
|
608
|
-
materials: {}
|
|
609
|
-
};
|
|
610
|
-
if (object) {
|
|
611
|
-
object.traverse(obj => {
|
|
612
|
-
if (obj.name) data.nodes[obj.name] = obj;
|
|
613
|
-
if (obj.material && !data.materials[obj.material.name]) data.materials[obj.material.name] = obj.material;
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
return data;
|
|
617
|
-
}
|
|
618
|
-
// Disposes an object and all its properties
|
|
619
|
-
function dispose(obj) {
|
|
620
|
-
if (obj.type !== 'Scene') obj.dispose == null ? void 0 : obj.dispose();
|
|
621
|
-
for (const p in obj) {
|
|
622
|
-
const prop = obj[p];
|
|
623
|
-
if ((prop == null ? void 0 : prop.type) !== 'Scene') prop == null ? void 0 : prop.dispose == null ? void 0 : prop.dispose();
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
const REACT_INTERNAL_PROPS = ['children', 'key', 'ref'];
|
|
627
|
-
|
|
628
|
-
// Gets only instance props from reconciler fibers
|
|
629
|
-
function getInstanceProps(queue) {
|
|
630
|
-
const props = {};
|
|
631
|
-
for (const key in queue) {
|
|
632
|
-
if (!REACT_INTERNAL_PROPS.includes(key)) props[key] = queue[key];
|
|
633
|
-
}
|
|
634
|
-
return props;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// Each object in the scene carries a small LocalState descriptor
|
|
638
|
-
function prepare(target, root, type, props) {
|
|
639
|
-
const object = target;
|
|
640
|
-
|
|
641
|
-
// Create instance descriptor
|
|
642
|
-
let instance = object == null ? void 0 : object.__r3f;
|
|
643
|
-
if (!instance) {
|
|
644
|
-
instance = {
|
|
645
|
-
root,
|
|
646
|
-
type,
|
|
647
|
-
parent: null,
|
|
648
|
-
children: [],
|
|
649
|
-
props: getInstanceProps(props),
|
|
650
|
-
object,
|
|
651
|
-
eventCount: 0,
|
|
652
|
-
handlers: {},
|
|
653
|
-
isHidden: false
|
|
654
|
-
};
|
|
655
|
-
if (object) {
|
|
656
|
-
object.__r3f = instance;
|
|
657
|
-
if (type) applyProps(object, instance.props);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
return instance;
|
|
661
|
-
}
|
|
662
|
-
function resolve(root, key) {
|
|
663
|
-
var _target;
|
|
664
|
-
let target = root[key];
|
|
665
|
-
if (!key.includes('-')) return {
|
|
666
|
-
root,
|
|
667
|
-
key,
|
|
668
|
-
target
|
|
669
|
-
};
|
|
670
|
-
|
|
671
|
-
// Resolve pierced target
|
|
672
|
-
const chain = key.split('-');
|
|
673
|
-
target = chain.reduce((acc, key) => acc[key], root);
|
|
674
|
-
key = chain.pop();
|
|
675
|
-
|
|
676
|
-
// Switch root if atomic
|
|
677
|
-
if (!((_target = target) != null && _target.set)) root = chain.reduce((acc, key) => acc[key], root);
|
|
678
|
-
return {
|
|
679
|
-
root,
|
|
680
|
-
key,
|
|
681
|
-
target
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
// Checks if a dash-cased string ends with an integer
|
|
686
|
-
const INDEX_REGEX = /-\d+$/;
|
|
687
|
-
function attach(parent, child) {
|
|
688
|
-
if (is.str(child.props.attach)) {
|
|
689
|
-
// If attaching into an array (foo-0), create one
|
|
690
|
-
if (INDEX_REGEX.test(child.props.attach)) {
|
|
691
|
-
const index = child.props.attach.replace(INDEX_REGEX, '');
|
|
692
|
-
const {
|
|
693
|
-
root,
|
|
694
|
-
key
|
|
695
|
-
} = resolve(parent.object, index);
|
|
696
|
-
if (!Array.isArray(root[key])) root[key] = [];
|
|
697
|
-
}
|
|
698
|
-
const {
|
|
699
|
-
root,
|
|
700
|
-
key
|
|
701
|
-
} = resolve(parent.object, child.props.attach);
|
|
702
|
-
child.previousAttach = root[key];
|
|
703
|
-
root[key] = child.object;
|
|
704
|
-
} else if (is.fun(child.props.attach)) {
|
|
705
|
-
child.previousAttach = child.props.attach(parent.object, child.object);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
function detach(parent, child) {
|
|
709
|
-
if (is.str(child.props.attach)) {
|
|
710
|
-
const {
|
|
711
|
-
root,
|
|
712
|
-
key
|
|
713
|
-
} = resolve(parent.object, child.props.attach);
|
|
714
|
-
const previous = child.previousAttach;
|
|
715
|
-
// When the previous value was undefined, it means the value was never set to begin with
|
|
716
|
-
if (previous === undefined) delete root[key];
|
|
717
|
-
// Otherwise set the previous value
|
|
718
|
-
else root[key] = previous;
|
|
719
|
-
} else {
|
|
720
|
-
child.previousAttach == null ? void 0 : child.previousAttach(parent.object, child.object);
|
|
721
|
-
}
|
|
722
|
-
delete child.previousAttach;
|
|
723
|
-
}
|
|
724
|
-
const RESERVED_PROPS = [...REACT_INTERNAL_PROPS,
|
|
725
|
-
// Instance props
|
|
726
|
-
'args', 'dispose', 'attach', 'object', 'onUpdate',
|
|
727
|
-
// Behavior flags
|
|
728
|
-
'dispose'];
|
|
729
|
-
const MEMOIZED_PROTOTYPES = new Map();
|
|
730
|
-
|
|
731
|
-
// This function prepares a set of changes to be applied to the instance
|
|
732
|
-
function diffProps(instance, newProps) {
|
|
733
|
-
const changedProps = {};
|
|
734
|
-
|
|
735
|
-
// Sort through props
|
|
736
|
-
for (const prop in newProps) {
|
|
737
|
-
// Skip reserved keys
|
|
738
|
-
if (RESERVED_PROPS.includes(prop)) continue;
|
|
739
|
-
// Skip if props match
|
|
740
|
-
if (is.equ(newProps[prop], instance.props[prop])) continue;
|
|
741
|
-
|
|
742
|
-
// Props changed, add them
|
|
743
|
-
changedProps[prop] = newProps[prop];
|
|
744
|
-
|
|
745
|
-
// Reset pierced props
|
|
746
|
-
for (const other in newProps) {
|
|
747
|
-
if (other.startsWith(`${prop}-`)) changedProps[other] = newProps[other];
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// Reset removed props for HMR
|
|
752
|
-
for (const prop in instance.props) {
|
|
753
|
-
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
754
|
-
const {
|
|
755
|
-
root,
|
|
756
|
-
key
|
|
757
|
-
} = resolve(instance.object, prop);
|
|
758
|
-
|
|
759
|
-
// https://github.com/mrdoob/three.js/issues/21209
|
|
760
|
-
// HMR/fast-refresh relies on the ability to cancel out props, but threejs
|
|
761
|
-
// has no means to do this. Hence we curate a small collection of value-classes
|
|
762
|
-
// with their respective constructor/set arguments
|
|
763
|
-
// For removed props, try to set default values, if possible
|
|
764
|
-
if (root.constructor && root.constructor.length === 0) {
|
|
765
|
-
// create a blank slate of the instance and copy the particular parameter.
|
|
766
|
-
let ctor = MEMOIZED_PROTOTYPES.get(root.constructor);
|
|
767
|
-
if (!ctor) {
|
|
768
|
-
ctor = new root.constructor();
|
|
769
|
-
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
770
|
-
}
|
|
771
|
-
changedProps[key] = ctor[key];
|
|
772
|
-
} else {
|
|
773
|
-
// instance does not have constructor, just set it to 0
|
|
774
|
-
changedProps[key] = 0;
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
return changedProps;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// const LinearEncoding = 3000
|
|
781
|
-
const sRGBEncoding = 3001;
|
|
782
|
-
const SRGBColorSpace = 'srgb';
|
|
783
|
-
const LinearSRGBColorSpace = 'srgb-linear';
|
|
784
|
-
|
|
785
|
-
// https://github.com/mrdoob/three.js/pull/27042
|
|
786
|
-
// https://github.com/mrdoob/three.js/pull/22748
|
|
787
|
-
const colorMaps = ['map', 'emissiveMap', 'sheenTintMap',
|
|
788
|
-
// <r134
|
|
789
|
-
'sheenColorMap', 'specularTintMap',
|
|
790
|
-
// <r134
|
|
791
|
-
'specularColorMap', 'envMap'];
|
|
792
|
-
const EVENT_REGEX = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/;
|
|
793
|
-
|
|
794
|
-
// This function applies a set of changes to the instance
|
|
795
|
-
function applyProps(object, props) {
|
|
796
|
-
const instance = object.__r3f;
|
|
797
|
-
const rootState = instance && findInitialRoot(instance).getState();
|
|
798
|
-
const prevHandlers = instance == null ? void 0 : instance.eventCount;
|
|
799
|
-
for (const prop in props) {
|
|
800
|
-
let value = props[prop];
|
|
801
|
-
|
|
802
|
-
// Don't mutate reserved keys
|
|
803
|
-
if (RESERVED_PROPS.includes(prop)) continue;
|
|
804
|
-
|
|
805
|
-
// Deal with pointer events, including removing them if undefined
|
|
806
|
-
if (instance && EVENT_REGEX.test(prop)) {
|
|
807
|
-
if (typeof value === 'function') instance.handlers[prop] = value;else delete instance.handlers[prop];
|
|
808
|
-
instance.eventCount = Object.keys(instance.handlers).length;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
// Ignore setting undefined props
|
|
812
|
-
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
813
|
-
if (value === undefined) continue;
|
|
814
|
-
let {
|
|
815
|
-
root,
|
|
816
|
-
key,
|
|
817
|
-
target
|
|
818
|
-
} = resolve(object, prop);
|
|
819
|
-
|
|
820
|
-
// Alias (output)encoding => (output)colorSpace (since r152)
|
|
821
|
-
// https://github.com/pmndrs/react-three-fiber/pull/2829
|
|
822
|
-
if (hasColorSpace(root)) {
|
|
823
|
-
if (key === 'encoding') {
|
|
824
|
-
key = 'colorSpace';
|
|
825
|
-
value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
|
|
826
|
-
} else if (key === 'outputEncoding') {
|
|
827
|
-
key = 'outputColorSpace';
|
|
828
|
-
value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
|
|
829
|
-
}
|
|
396
|
+
// Layers must be written to the mask property
|
|
397
|
+
if (target instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) {
|
|
398
|
+
target.mask = value.mask;
|
|
399
|
+
} else if (target instanceof THREE__namespace.Color && isColorRepresentation(value)) {
|
|
400
|
+
target.set(value);
|
|
830
401
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
if (typeof (target == null ? void 0 : target.copy) === 'function' && target.copy === value.copy) {
|
|
402
|
+
// Copy if properties match signatures and implement math interface (likely read-only)
|
|
403
|
+
else if (target && typeof target.set === 'function' && typeof target.copy === 'function' && value != null && value.constructor && target.constructor === value.constructor) {
|
|
834
404
|
target.copy(value);
|
|
835
405
|
}
|
|
836
|
-
// Layers have no copy function, we must therefore copy the mask property
|
|
837
|
-
else if (target instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) {
|
|
838
|
-
target.mask = value.mask;
|
|
839
|
-
}
|
|
840
406
|
// Set array types
|
|
841
|
-
else if (target
|
|
842
|
-
if (target.fromArray) target.fromArray(value);else target.set(...value);
|
|
407
|
+
else if (target && typeof target.set === 'function' && Array.isArray(value)) {
|
|
408
|
+
if (typeof target.fromArray === 'function') target.fromArray(value);else target.set(...value);
|
|
843
409
|
}
|
|
844
410
|
// Set literal types
|
|
845
|
-
else if (target
|
|
846
|
-
const isColor = target instanceof THREE__namespace.Color;
|
|
411
|
+
else if (target && typeof target.set === 'function' && typeof value === 'number') {
|
|
847
412
|
// Allow setting array scalars
|
|
848
|
-
if (
|
|
413
|
+
if (typeof target.setScalar === 'function') target.setScalar(value);
|
|
849
414
|
// Otherwise just set single value
|
|
850
415
|
else target.set(value);
|
|
851
|
-
|
|
852
|
-
// Emulate THREE.ColorManagement for older three.js versions
|
|
853
|
-
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
854
|
-
if (!getColorManagement() && !(rootState != null && rootState.linear) && isColor) target.convertSRGBToLinear();
|
|
855
416
|
}
|
|
856
417
|
// Else, just overwrite the value
|
|
857
418
|
else {
|
|
419
|
+
var _root$key;
|
|
858
420
|
root[key] = value;
|
|
859
421
|
|
|
860
422
|
// Auto-convert sRGB texture parameters for built-in materials
|
|
861
423
|
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
862
424
|
// https://github.com/mrdoob/three.js/pull/25857
|
|
863
|
-
if (rootState && !rootState.linear && colorMaps.includes(key) && root[key]
|
|
425
|
+
if (rootState && !rootState.linear && colorMaps.includes(key) && (_root$key = root[key]) != null && _root$key.isTexture &&
|
|
864
426
|
// sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
865
427
|
root[key].format === THREE__namespace.RGBAFormat && root[key].type === THREE__namespace.UnsignedByteType) {
|
|
866
428
|
// NOTE: this cannot be set from the renderer (e.g. sRGB source textures rendered to P3)
|
|
867
|
-
|
|
429
|
+
root[key].colorSpace = THREE__namespace.SRGBColorSpace;
|
|
868
430
|
}
|
|
869
431
|
}
|
|
870
432
|
}
|
|
871
433
|
|
|
872
434
|
// Register event handlers
|
|
873
|
-
if (instance != null && instance.parent && rootState != null && rootState.internal && instance.object
|
|
435
|
+
if (instance != null && instance.parent && rootState != null && rootState.internal && (_instance$object = instance.object) != null && _instance$object.isObject3D && prevHandlers !== instance.eventCount) {
|
|
436
|
+
const object = instance.object;
|
|
874
437
|
// Pre-emptively remove the instance from the interaction manager
|
|
875
|
-
const index = rootState.internal.interaction.indexOf(
|
|
438
|
+
const index = rootState.internal.interaction.indexOf(object);
|
|
876
439
|
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
877
440
|
// Add the instance to the interaction manager only when it has handlers
|
|
878
|
-
if (instance.eventCount &&
|
|
879
|
-
rootState.internal.interaction.push(
|
|
441
|
+
if (instance.eventCount && object.raycast !== null) {
|
|
442
|
+
rootState.internal.interaction.push(object);
|
|
880
443
|
}
|
|
881
444
|
}
|
|
882
445
|
|
|
883
446
|
// Auto-attach geometries and materials
|
|
884
447
|
if (instance && instance.props.attach === undefined) {
|
|
885
|
-
if (instance.object
|
|
448
|
+
if (instance.object.isBufferGeometry) instance.props.attach = 'geometry';else if (instance.object.isMaterial) instance.props.attach = 'material';
|
|
886
449
|
}
|
|
887
450
|
|
|
888
451
|
// Instance was updated, request a frame
|
|
@@ -1054,7 +617,19 @@ function createEvents(store) {
|
|
|
1054
617
|
stopped: false
|
|
1055
618
|
};
|
|
1056
619
|
for (const hit of intersections) {
|
|
1057
|
-
|
|
620
|
+
let state = getRootState(hit.object);
|
|
621
|
+
|
|
622
|
+
// If the object is not managed by R3F, it might be parented to an element which is.
|
|
623
|
+
// Traverse upwards until we find a managed parent and use its state instead.
|
|
624
|
+
if (!state) {
|
|
625
|
+
hit.object.traverseAncestors(obj => {
|
|
626
|
+
const parentState = getRootState(obj);
|
|
627
|
+
if (parentState) {
|
|
628
|
+
state = parentState;
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
1058
633
|
if (state) {
|
|
1059
634
|
const {
|
|
1060
635
|
raycaster,
|
|
@@ -1315,7 +890,7 @@ function createEvents(store) {
|
|
|
1315
890
|
}
|
|
1316
891
|
|
|
1317
892
|
const isRenderer = def => !!(def != null && def.render);
|
|
1318
|
-
const context =
|
|
893
|
+
const context = /* @__PURE__ */React__namespace.createContext(null);
|
|
1319
894
|
const createStore = (invalidate, advance) => {
|
|
1320
895
|
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
1321
896
|
const position = new THREE__namespace.Vector3();
|
|
@@ -1329,7 +904,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1329
904
|
left
|
|
1330
905
|
} = size;
|
|
1331
906
|
const aspect = width / height;
|
|
1332
|
-
if (target
|
|
907
|
+
if (target.isVector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
1333
908
|
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
1334
909
|
if (isOrthographicCamera(camera)) {
|
|
1335
910
|
return {
|
|
@@ -1531,161 +1106,576 @@ const createStore = (invalidate, advance) => {
|
|
|
1531
1106
|
oldDpr = viewport.dpr;
|
|
1532
1107
|
// Update camera & renderer
|
|
1533
1108
|
updateCamera(camera, size);
|
|
1534
|
-
gl.setPixelRatio(viewport.dpr);
|
|
1109
|
+
if (viewport.dpr > 0) gl.setPixelRatio(viewport.dpr);
|
|
1535
1110
|
const updateStyle = typeof HTMLCanvasElement !== 'undefined' && gl.domElement instanceof HTMLCanvasElement;
|
|
1536
1111
|
gl.setSize(size.width, size.height, updateStyle);
|
|
1537
1112
|
}
|
|
1538
|
-
|
|
1539
|
-
// Update viewport once the camera changes
|
|
1540
|
-
if (camera !== oldCamera) {
|
|
1541
|
-
oldCamera = camera;
|
|
1542
|
-
// Update viewport
|
|
1543
|
-
set(state => ({
|
|
1544
|
-
viewport: {
|
|
1545
|
-
...state.viewport,
|
|
1546
|
-
...state.viewport.getCurrentViewport(camera)
|
|
1547
|
-
}
|
|
1548
|
-
}));
|
|
1113
|
+
|
|
1114
|
+
// Update viewport once the camera changes
|
|
1115
|
+
if (camera !== oldCamera) {
|
|
1116
|
+
oldCamera = camera;
|
|
1117
|
+
// Update viewport
|
|
1118
|
+
set(state => ({
|
|
1119
|
+
viewport: {
|
|
1120
|
+
...state.viewport,
|
|
1121
|
+
...state.viewport.getCurrentViewport(camera)
|
|
1122
|
+
}
|
|
1123
|
+
}));
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
// Invalidate on any change
|
|
1128
|
+
rootStore.subscribe(state => invalidate(state));
|
|
1129
|
+
|
|
1130
|
+
// Return root state
|
|
1131
|
+
return rootStore;
|
|
1132
|
+
};
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Exposes an object's {@link Instance}.
|
|
1136
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
|
|
1137
|
+
*
|
|
1138
|
+
* **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
|
|
1139
|
+
*/
|
|
1140
|
+
function useInstanceHandle(ref) {
|
|
1141
|
+
const instance = React__namespace.useRef(null);
|
|
1142
|
+
React__namespace.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
1143
|
+
return instance;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
/**
|
|
1147
|
+
* Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
|
|
1148
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
|
|
1149
|
+
*/
|
|
1150
|
+
function useStore() {
|
|
1151
|
+
const store = React__namespace.useContext(context);
|
|
1152
|
+
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1153
|
+
return store;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Accesses R3F's internal state, containing renderer, canvas, scene, etc.
|
|
1158
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
|
|
1159
|
+
*/
|
|
1160
|
+
function useThree(selector = state => state, equalityFn) {
|
|
1161
|
+
return useStore()(selector, equalityFn);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/**
|
|
1165
|
+
* Executes a callback before render in a shared frame loop.
|
|
1166
|
+
* Can order effects with render priority or manually render with a positive priority.
|
|
1167
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
|
|
1168
|
+
*/
|
|
1169
|
+
function useFrame(callback, renderPriority = 0) {
|
|
1170
|
+
const store = useStore();
|
|
1171
|
+
const subscribe = store.getState().internal.subscribe;
|
|
1172
|
+
// Memoize ref
|
|
1173
|
+
const ref = useMutableCallback(callback);
|
|
1174
|
+
// Subscribe on mount, unsubscribe on unmount
|
|
1175
|
+
useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
|
|
1176
|
+
return null;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Returns a node graph of an object with named nodes & materials.
|
|
1181
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
|
|
1182
|
+
*/
|
|
1183
|
+
function useGraph(object) {
|
|
1184
|
+
return React__namespace.useMemo(() => buildGraph(object), [object]);
|
|
1185
|
+
}
|
|
1186
|
+
const memoizedLoaders = new WeakMap();
|
|
1187
|
+
const isConstructor$1 = value => {
|
|
1188
|
+
var _value$prototype;
|
|
1189
|
+
return typeof value === 'function' && (value == null ? void 0 : (_value$prototype = value.prototype) == null ? void 0 : _value$prototype.constructor) === value;
|
|
1190
|
+
};
|
|
1191
|
+
function loadingFn(extensions, onProgress) {
|
|
1192
|
+
return function (Proto, ...input) {
|
|
1193
|
+
let loader;
|
|
1194
|
+
|
|
1195
|
+
// Construct and cache loader if constructor was passed
|
|
1196
|
+
if (isConstructor$1(Proto)) {
|
|
1197
|
+
loader = memoizedLoaders.get(Proto);
|
|
1198
|
+
if (!loader) {
|
|
1199
|
+
loader = new Proto();
|
|
1200
|
+
memoizedLoaders.set(Proto, loader);
|
|
1201
|
+
}
|
|
1202
|
+
} else {
|
|
1203
|
+
loader = Proto;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// Apply loader extensions
|
|
1207
|
+
if (extensions) extensions(loader);
|
|
1208
|
+
|
|
1209
|
+
// Go through the urls and load them
|
|
1210
|
+
return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
|
|
1211
|
+
if (isObject3D(data == null ? void 0 : data.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1212
|
+
res(data);
|
|
1213
|
+
}, onProgress, error => reject(new Error(`Could not load ${input}: ${error == null ? void 0 : error.message}`))))));
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Synchronously loads and caches assets with a three loader.
|
|
1219
|
+
*
|
|
1220
|
+
* Note: this hook's caller must be wrapped with `React.Suspense`
|
|
1221
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
|
|
1222
|
+
*/
|
|
1223
|
+
function useLoader(loader, input, extensions, onProgress) {
|
|
1224
|
+
// Use suspense to load async assets
|
|
1225
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
1226
|
+
const results = suspendReact.suspend(loadingFn(extensions, onProgress), [loader, ...keys], {
|
|
1227
|
+
equal: is.equ
|
|
1228
|
+
});
|
|
1229
|
+
// Return the object(s)
|
|
1230
|
+
return Array.isArray(input) ? results : results[0];
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
/**
|
|
1234
|
+
* Preloads an asset into cache as a side-effect.
|
|
1235
|
+
*/
|
|
1236
|
+
useLoader.preload = function (loader, input, extensions) {
|
|
1237
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
1238
|
+
return suspendReact.preload(loadingFn(extensions), [loader, ...keys]);
|
|
1239
|
+
};
|
|
1240
|
+
|
|
1241
|
+
/**
|
|
1242
|
+
* Removes a loaded asset from cache.
|
|
1243
|
+
*/
|
|
1244
|
+
useLoader.clear = function (loader, input) {
|
|
1245
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
1246
|
+
return suspendReact.clear([loader, ...keys]);
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
// TODO: upstream to DefinitelyTyped for React 19
|
|
1250
|
+
// https://github.com/facebook/react/issues/28956
|
|
1251
|
+
|
|
1252
|
+
function createReconciler(config) {
|
|
1253
|
+
const reconciler = Reconciler__default["default"](config);
|
|
1254
|
+
reconciler.injectIntoDevTools({
|
|
1255
|
+
bundleType: typeof process !== 'undefined' && process.env.NODE_ENV !== 'production' ? 1 : 0,
|
|
1256
|
+
rendererPackageName: '@react-three/fiber',
|
|
1257
|
+
version: React__namespace.version
|
|
1258
|
+
});
|
|
1259
|
+
return reconciler;
|
|
1260
|
+
}
|
|
1261
|
+
const NoEventPriority = 0;
|
|
1262
|
+
|
|
1263
|
+
// TODO: handle constructor overloads
|
|
1264
|
+
// https://github.com/pmndrs/react-three-fiber/pull/2931
|
|
1265
|
+
// https://github.com/microsoft/TypeScript/issues/37079
|
|
1266
|
+
|
|
1267
|
+
const catalogue = {};
|
|
1268
|
+
const PREFIX_REGEX = /^three(?=[A-Z])/;
|
|
1269
|
+
const toPascalCase = type => `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
1270
|
+
let i = 0;
|
|
1271
|
+
const isConstructor = object => typeof object === 'function';
|
|
1272
|
+
function extend(objects) {
|
|
1273
|
+
if (isConstructor(objects)) {
|
|
1274
|
+
const Component = `${i++}`;
|
|
1275
|
+
catalogue[Component] = objects;
|
|
1276
|
+
return Component;
|
|
1277
|
+
} else {
|
|
1278
|
+
Object.assign(catalogue, objects);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
function validateInstance(type, props) {
|
|
1282
|
+
// Get target from catalogue
|
|
1283
|
+
const name = `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
1284
|
+
const target = catalogue[name];
|
|
1285
|
+
|
|
1286
|
+
// Validate element target
|
|
1287
|
+
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`);
|
|
1288
|
+
|
|
1289
|
+
// Validate primitives
|
|
1290
|
+
if (type === 'primitive' && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
|
|
1291
|
+
|
|
1292
|
+
// Throw if an object or literal was passed for args
|
|
1293
|
+
if (props.args !== undefined && !Array.isArray(props.args)) throw new Error('R3F: The args prop must be an array!');
|
|
1294
|
+
}
|
|
1295
|
+
function createInstance(type, props, root) {
|
|
1296
|
+
var _props$object;
|
|
1297
|
+
// Remove three* prefix from elements
|
|
1298
|
+
type = type.replace(PREFIX_REGEX, '');
|
|
1299
|
+
validateInstance(type, props);
|
|
1300
|
+
|
|
1301
|
+
// Regenerate the R3F instance for primitives to simulate a new object
|
|
1302
|
+
if (type === 'primitive' && (_props$object = props.object) != null && _props$object.__r3f) delete props.object.__r3f;
|
|
1303
|
+
return prepare(props.object, root, type, props);
|
|
1304
|
+
}
|
|
1305
|
+
function hideInstance(instance) {
|
|
1306
|
+
if (!instance.isHidden) {
|
|
1307
|
+
var _instance$parent;
|
|
1308
|
+
if (instance.props.attach && (_instance$parent = instance.parent) != null && _instance$parent.object) {
|
|
1309
|
+
detach(instance.parent, instance);
|
|
1310
|
+
} else if (isObject3D(instance.object)) {
|
|
1311
|
+
instance.object.visible = false;
|
|
1312
|
+
}
|
|
1313
|
+
instance.isHidden = true;
|
|
1314
|
+
invalidateInstance(instance);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
function unhideInstance(instance) {
|
|
1318
|
+
if (instance.isHidden) {
|
|
1319
|
+
var _instance$parent2;
|
|
1320
|
+
if (instance.props.attach && (_instance$parent2 = instance.parent) != null && _instance$parent2.object) {
|
|
1321
|
+
attach(instance.parent, instance);
|
|
1322
|
+
} else if (isObject3D(instance.object) && instance.props.visible !== false) {
|
|
1323
|
+
instance.object.visible = true;
|
|
1549
1324
|
}
|
|
1550
|
-
|
|
1325
|
+
instance.isHidden = false;
|
|
1326
|
+
invalidateInstance(instance);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1551
1329
|
|
|
1552
|
-
|
|
1553
|
-
|
|
1330
|
+
// https://github.com/facebook/react/issues/20271
|
|
1331
|
+
// This will make sure events and attach are only handled once when trees are complete
|
|
1332
|
+
function handleContainerEffects(parent, child, beforeChild) {
|
|
1333
|
+
// Bail if tree isn't mounted or parent is not a container.
|
|
1334
|
+
// This ensures that the tree is finalized and React won't discard results to Suspense
|
|
1335
|
+
const state = child.root.getState();
|
|
1336
|
+
if (!parent.parent && parent.object !== state.scene) return;
|
|
1554
1337
|
|
|
1555
|
-
//
|
|
1556
|
-
|
|
1557
|
-
|
|
1338
|
+
// Create & link object on first run
|
|
1339
|
+
if (!child.object) {
|
|
1340
|
+
var _child$props$object, _child$props$args;
|
|
1341
|
+
// Get target from catalogue
|
|
1342
|
+
const target = catalogue[toPascalCase(child.type)];
|
|
1558
1343
|
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1344
|
+
// Create object
|
|
1345
|
+
child.object = (_child$props$object = child.props.object) != null ? _child$props$object : new target(...((_child$props$args = child.props.args) != null ? _child$props$args : []));
|
|
1346
|
+
child.object.__r3f = child;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// Set initial props
|
|
1350
|
+
applyProps(child.object, child.props);
|
|
1351
|
+
|
|
1352
|
+
// Append instance
|
|
1353
|
+
if (child.props.attach) {
|
|
1354
|
+
attach(parent, child);
|
|
1355
|
+
} else if (isObject3D(child.object) && isObject3D(parent.object)) {
|
|
1356
|
+
const childIndex = parent.object.children.indexOf(beforeChild == null ? void 0 : beforeChild.object);
|
|
1357
|
+
if (beforeChild && childIndex !== -1) {
|
|
1358
|
+
child.object.parent = parent.object;
|
|
1359
|
+
parent.object.children.splice(childIndex, 0, child.object);
|
|
1360
|
+
child.object.dispatchEvent({
|
|
1361
|
+
type: 'added'
|
|
1362
|
+
});
|
|
1363
|
+
parent.object.dispatchEvent({
|
|
1364
|
+
type: 'childadded',
|
|
1365
|
+
child: child.object
|
|
1366
|
+
});
|
|
1367
|
+
} else {
|
|
1368
|
+
parent.object.add(child.object);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
// Link subtree
|
|
1373
|
+
for (const childInstance of child.children) handleContainerEffects(child, childInstance);
|
|
1374
|
+
|
|
1375
|
+
// Tree was updated, request a frame
|
|
1376
|
+
invalidateInstance(child);
|
|
1569
1377
|
}
|
|
1378
|
+
function appendChild(parent, child) {
|
|
1379
|
+
if (!child) return;
|
|
1570
1380
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1578
|
-
return store;
|
|
1381
|
+
// Link instances
|
|
1382
|
+
child.parent = parent;
|
|
1383
|
+
parent.children.push(child);
|
|
1384
|
+
|
|
1385
|
+
// Attach tree once complete
|
|
1386
|
+
handleContainerEffects(parent, child);
|
|
1579
1387
|
}
|
|
1388
|
+
function insertBefore(parent, child, beforeChild) {
|
|
1389
|
+
if (!child || !beforeChild) return;
|
|
1580
1390
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1391
|
+
// Link instances
|
|
1392
|
+
child.parent = parent;
|
|
1393
|
+
const childIndex = parent.children.indexOf(beforeChild);
|
|
1394
|
+
if (childIndex !== -1) parent.children.splice(childIndex, 0, child);else parent.children.push(child);
|
|
1395
|
+
|
|
1396
|
+
// Attach tree once complete
|
|
1397
|
+
handleContainerEffects(parent, child, beforeChild);
|
|
1587
1398
|
}
|
|
1399
|
+
function disposeOnIdle(object) {
|
|
1400
|
+
if (typeof object.dispose === 'function') {
|
|
1401
|
+
const handleDispose = () => {
|
|
1402
|
+
try {
|
|
1403
|
+
object.dispose();
|
|
1404
|
+
} catch {
|
|
1405
|
+
// no-op
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1588
1408
|
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
function useFrame(callback, renderPriority = 0) {
|
|
1595
|
-
const store = useStore();
|
|
1596
|
-
const subscribe = store.getState().internal.subscribe;
|
|
1597
|
-
// Memoize ref
|
|
1598
|
-
const ref = useMutableCallback(callback);
|
|
1599
|
-
// Subscribe on mount, unsubscribe on unmount
|
|
1600
|
-
useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
|
|
1601
|
-
return null;
|
|
1409
|
+
// In a testing environment, cleanup immediately
|
|
1410
|
+
if (typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined') handleDispose();
|
|
1411
|
+
// Otherwise, using a real GPU so schedule cleanup to prevent stalls
|
|
1412
|
+
else scheduler.unstable_scheduleCallback(scheduler.unstable_IdlePriority, handleDispose);
|
|
1413
|
+
}
|
|
1602
1414
|
}
|
|
1415
|
+
function removeChild(parent, child, dispose) {
|
|
1416
|
+
if (!child) return;
|
|
1603
1417
|
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1418
|
+
// Unlink instances
|
|
1419
|
+
child.parent = null;
|
|
1420
|
+
const childIndex = parent.children.indexOf(child);
|
|
1421
|
+
if (childIndex !== -1) parent.children.splice(childIndex, 1);
|
|
1422
|
+
|
|
1423
|
+
// Eagerly tear down tree
|
|
1424
|
+
if (child.props.attach) {
|
|
1425
|
+
detach(parent, child);
|
|
1426
|
+
} else if (isObject3D(child.object) && isObject3D(parent.object)) {
|
|
1427
|
+
parent.object.remove(child.object);
|
|
1428
|
+
removeInteractivity(findInitialRoot(child), child.object);
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// Allow objects to bail out of unmount disposal with dispose={null}
|
|
1432
|
+
const shouldDispose = child.props.dispose !== null && dispose !== false;
|
|
1433
|
+
|
|
1434
|
+
// Recursively remove instance children
|
|
1435
|
+
for (let i = child.children.length - 1; i >= 0; i--) {
|
|
1436
|
+
const node = child.children[i];
|
|
1437
|
+
removeChild(child, node, shouldDispose);
|
|
1438
|
+
}
|
|
1439
|
+
child.children.length = 0;
|
|
1440
|
+
|
|
1441
|
+
// Unlink instance object
|
|
1442
|
+
delete child.object.__r3f;
|
|
1443
|
+
|
|
1444
|
+
// Dispose object whenever the reconciler feels like it.
|
|
1445
|
+
// Never dispose of primitives because their state may be kept outside of React!
|
|
1446
|
+
// In order for an object to be able to dispose it
|
|
1447
|
+
// - has a dispose method
|
|
1448
|
+
// - cannot be a <primitive object={...} />
|
|
1449
|
+
// - cannot be a THREE.Scene, because three has broken its own API
|
|
1450
|
+
if (shouldDispose && child.type !== 'primitive' && child.object.type !== 'Scene') {
|
|
1451
|
+
disposeOnIdle(child.object);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// Tree was updated, request a frame for top-level instance
|
|
1455
|
+
if (dispose === undefined) invalidateInstance(child);
|
|
1610
1456
|
}
|
|
1611
|
-
|
|
1612
|
-
const
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1457
|
+
function setFiberRef(fiber, publicInstance) {
|
|
1458
|
+
for (const _fiber of [fiber, fiber.alternate]) {
|
|
1459
|
+
if (_fiber !== null) {
|
|
1460
|
+
if (typeof _fiber.ref === 'function') {
|
|
1461
|
+
_fiber.refCleanup == null ? void 0 : _fiber.refCleanup();
|
|
1462
|
+
const cleanup = _fiber.ref(publicInstance);
|
|
1463
|
+
if (typeof cleanup === 'function') _fiber.refCleanup = cleanup;
|
|
1464
|
+
} else if (_fiber.ref) {
|
|
1465
|
+
_fiber.ref.current = publicInstance;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
const reconstructed = [];
|
|
1471
|
+
function swapInstances() {
|
|
1472
|
+
// Detach instance
|
|
1473
|
+
for (const [instance] of reconstructed) {
|
|
1474
|
+
const parent = instance.parent;
|
|
1475
|
+
if (parent) {
|
|
1476
|
+
if (instance.props.attach) {
|
|
1477
|
+
detach(parent, instance);
|
|
1478
|
+
} else if (isObject3D(instance.object) && isObject3D(parent.object)) {
|
|
1479
|
+
parent.object.remove(instance.object);
|
|
1480
|
+
}
|
|
1481
|
+
for (const child of instance.children) {
|
|
1482
|
+
if (child.props.attach) {
|
|
1483
|
+
detach(instance, child);
|
|
1484
|
+
} else if (isObject3D(child.object) && isObject3D(instance.object)) {
|
|
1485
|
+
instance.object.remove(child.object);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1619
1489
|
|
|
1620
|
-
//
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1490
|
+
// If the old instance is hidden, we need to unhide it.
|
|
1491
|
+
// React assumes it can discard instances since they're pure for DOM.
|
|
1492
|
+
// This isn't true for us since our lifetimes are impure and longliving.
|
|
1493
|
+
// So, we manually check if an instance was hidden and unhide it.
|
|
1494
|
+
if (instance.isHidden) unhideInstance(instance);
|
|
1495
|
+
|
|
1496
|
+
// Dispose of old object if able
|
|
1497
|
+
if (instance.object.__r3f) delete instance.object.__r3f;
|
|
1498
|
+
if (instance.type !== 'primitive') disposeOnIdle(instance.object);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
// Update instance
|
|
1502
|
+
for (const [instance, props, fiber] of reconstructed) {
|
|
1503
|
+
instance.props = props;
|
|
1504
|
+
const parent = instance.parent;
|
|
1505
|
+
if (parent) {
|
|
1506
|
+
var _instance$props$objec, _instance$props$args;
|
|
1507
|
+
// Get target from catalogue
|
|
1508
|
+
const target = catalogue[toPascalCase(instance.type)];
|
|
1509
|
+
|
|
1510
|
+
// Create object
|
|
1511
|
+
instance.object = (_instance$props$objec = instance.props.object) != null ? _instance$props$objec : new target(...((_instance$props$args = instance.props.args) != null ? _instance$props$args : []));
|
|
1512
|
+
instance.object.__r3f = instance;
|
|
1513
|
+
setFiberRef(fiber, instance.object);
|
|
1514
|
+
|
|
1515
|
+
// Set initial props
|
|
1516
|
+
applyProps(instance.object, instance.props);
|
|
1517
|
+
if (instance.props.attach) {
|
|
1518
|
+
attach(parent, instance);
|
|
1519
|
+
} else if (isObject3D(instance.object) && isObject3D(parent.object)) {
|
|
1520
|
+
parent.object.add(instance.object);
|
|
1626
1521
|
}
|
|
1627
|
-
|
|
1628
|
-
|
|
1522
|
+
for (const child of instance.children) {
|
|
1523
|
+
if (child.props.attach) {
|
|
1524
|
+
attach(instance, child);
|
|
1525
|
+
} else if (isObject3D(child.object) && isObject3D(instance.object)) {
|
|
1526
|
+
instance.object.add(child.object);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
// Tree was updated, request a frame
|
|
1531
|
+
invalidateInstance(instance);
|
|
1629
1532
|
}
|
|
1533
|
+
}
|
|
1534
|
+
reconstructed.length = 0;
|
|
1535
|
+
}
|
|
1630
1536
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1537
|
+
// Don't handle text instances, make it no-op
|
|
1538
|
+
const handleTextInstance = () => {};
|
|
1539
|
+
const NO_CONTEXT = {};
|
|
1540
|
+
let currentUpdatePriority = NoEventPriority;
|
|
1633
1541
|
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1542
|
+
// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberFlags.js
|
|
1543
|
+
const NoFlags = 0;
|
|
1544
|
+
const Update = 4;
|
|
1545
|
+
const reconciler = /* @__PURE__ */createReconciler({
|
|
1546
|
+
isPrimaryRenderer: false,
|
|
1547
|
+
warnsIfNotActing: false,
|
|
1548
|
+
supportsMutation: true,
|
|
1549
|
+
supportsPersistence: false,
|
|
1550
|
+
supportsHydration: false,
|
|
1551
|
+
createInstance,
|
|
1552
|
+
removeChild,
|
|
1553
|
+
appendChild,
|
|
1554
|
+
appendInitialChild: appendChild,
|
|
1555
|
+
insertBefore,
|
|
1556
|
+
appendChildToContainer(container, child) {
|
|
1557
|
+
const scene = container.getState().scene.__r3f;
|
|
1558
|
+
if (!child || !scene) return;
|
|
1559
|
+
appendChild(scene, child);
|
|
1560
|
+
},
|
|
1561
|
+
removeChildFromContainer(container, child) {
|
|
1562
|
+
const scene = container.getState().scene.__r3f;
|
|
1563
|
+
if (!child || !scene) return;
|
|
1564
|
+
removeChild(scene, child);
|
|
1565
|
+
},
|
|
1566
|
+
insertInContainerBefore(container, child, beforeChild) {
|
|
1567
|
+
const scene = container.getState().scene.__r3f;
|
|
1568
|
+
if (!child || !beforeChild || !scene) return;
|
|
1569
|
+
insertBefore(scene, child, beforeChild);
|
|
1570
|
+
},
|
|
1571
|
+
getRootHostContext: () => NO_CONTEXT,
|
|
1572
|
+
getChildHostContext: () => NO_CONTEXT,
|
|
1573
|
+
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
1574
|
+
var _newProps$args, _oldProps$args, _newProps$args2;
|
|
1575
|
+
validateInstance(type, newProps);
|
|
1576
|
+
let reconstruct = false;
|
|
1638
1577
|
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
const results = suspendReact.suspend(loadingFn(extensions, onProgress), [loader, ...keys], {
|
|
1649
|
-
equal: is.equ
|
|
1650
|
-
});
|
|
1651
|
-
// Return the object(s)
|
|
1652
|
-
return Array.isArray(input) ? results : results[0];
|
|
1653
|
-
}
|
|
1578
|
+
// Reconstruct primitives if object prop changes
|
|
1579
|
+
if (instance.type === 'primitive' && oldProps.object !== newProps.object) reconstruct = true;
|
|
1580
|
+
// Reconstruct instance if args were added or removed
|
|
1581
|
+
else if (((_newProps$args = newProps.args) == null ? void 0 : _newProps$args.length) !== ((_oldProps$args = oldProps.args) == null ? void 0 : _oldProps$args.length)) reconstruct = true;
|
|
1582
|
+
// Reconstruct instance if args were changed
|
|
1583
|
+
else if ((_newProps$args2 = newProps.args) != null && _newProps$args2.some((value, index) => {
|
|
1584
|
+
var _oldProps$args2;
|
|
1585
|
+
return value !== ((_oldProps$args2 = oldProps.args) == null ? void 0 : _oldProps$args2[index]);
|
|
1586
|
+
})) reconstruct = true;
|
|
1654
1587
|
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1588
|
+
// Reconstruct when args or <primitive object={...} have changes
|
|
1589
|
+
if (reconstruct) {
|
|
1590
|
+
reconstructed.push([instance, {
|
|
1591
|
+
...newProps
|
|
1592
|
+
}, fiber]);
|
|
1593
|
+
} else {
|
|
1594
|
+
// Create a diff-set, flag if there are any changes
|
|
1595
|
+
const changedProps = diffProps(instance, newProps);
|
|
1596
|
+
if (Object.keys(changedProps).length) {
|
|
1597
|
+
Object.assign(instance.props, changedProps);
|
|
1598
|
+
applyProps(instance.object, changedProps);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1662
1601
|
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1602
|
+
// Flush reconstructed siblings when we hit the last updated child in a sequence
|
|
1603
|
+
const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
|
|
1604
|
+
if (isTailSibling) swapInstances();
|
|
1605
|
+
},
|
|
1606
|
+
finalizeInitialChildren: () => false,
|
|
1607
|
+
commitMount() {},
|
|
1608
|
+
getPublicInstance: instance => instance == null ? void 0 : instance.object,
|
|
1609
|
+
prepareForCommit: () => null,
|
|
1610
|
+
preparePortalMount: container => prepare(container.getState().scene, container, '', {}),
|
|
1611
|
+
resetAfterCommit: () => {},
|
|
1612
|
+
shouldSetTextContent: () => false,
|
|
1613
|
+
clearContainer: () => false,
|
|
1614
|
+
hideInstance,
|
|
1615
|
+
unhideInstance,
|
|
1616
|
+
createTextInstance: handleTextInstance,
|
|
1617
|
+
hideTextInstance: handleTextInstance,
|
|
1618
|
+
unhideTextInstance: handleTextInstance,
|
|
1619
|
+
scheduleTimeout: typeof setTimeout === 'function' ? setTimeout : undefined,
|
|
1620
|
+
cancelTimeout: typeof clearTimeout === 'function' ? clearTimeout : undefined,
|
|
1621
|
+
noTimeout: -1,
|
|
1622
|
+
getInstanceFromNode: () => null,
|
|
1623
|
+
beforeActiveInstanceBlur() {},
|
|
1624
|
+
afterActiveInstanceBlur() {},
|
|
1625
|
+
detachDeletedInstance() {},
|
|
1626
|
+
prepareScopeUpdate() {},
|
|
1627
|
+
getInstanceFromScope: () => null,
|
|
1628
|
+
shouldAttemptEagerTransition: () => false,
|
|
1629
|
+
trackSchedulerEvent: () => {},
|
|
1630
|
+
resolveEventType: () => null,
|
|
1631
|
+
resolveEventTimeStamp: () => -1.1,
|
|
1632
|
+
requestPostPaintCallback() {},
|
|
1633
|
+
maySuspendCommit: () => false,
|
|
1634
|
+
preloadInstance: () => true,
|
|
1635
|
+
// true indicates already loaded
|
|
1636
|
+
startSuspendingCommit() {},
|
|
1637
|
+
suspendInstance() {},
|
|
1638
|
+
waitForCommitToBeReady: () => null,
|
|
1639
|
+
NotPendingTransition: null,
|
|
1640
|
+
HostTransitionContext: /* @__PURE__ */React__namespace.createContext(null),
|
|
1641
|
+
setCurrentUpdatePriority(newPriority) {
|
|
1642
|
+
currentUpdatePriority = newPriority;
|
|
1643
|
+
},
|
|
1644
|
+
getCurrentUpdatePriority() {
|
|
1645
|
+
return currentUpdatePriority;
|
|
1646
|
+
},
|
|
1647
|
+
resolveUpdatePriority() {
|
|
1648
|
+
var _window$event;
|
|
1649
|
+
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
1650
|
+
switch (typeof window !== 'undefined' && ((_window$event = window.event) == null ? void 0 : _window$event.type)) {
|
|
1651
|
+
case 'click':
|
|
1652
|
+
case 'contextmenu':
|
|
1653
|
+
case 'dblclick':
|
|
1654
|
+
case 'pointercancel':
|
|
1655
|
+
case 'pointerdown':
|
|
1656
|
+
case 'pointerup':
|
|
1657
|
+
return constants.DiscreteEventPriority;
|
|
1658
|
+
case 'pointermove':
|
|
1659
|
+
case 'pointerout':
|
|
1660
|
+
case 'pointerover':
|
|
1661
|
+
case 'pointerenter':
|
|
1662
|
+
case 'pointerleave':
|
|
1663
|
+
case 'wheel':
|
|
1664
|
+
return constants.ContinuousEventPriority;
|
|
1665
|
+
default:
|
|
1666
|
+
return constants.DefaultEventPriority;
|
|
1667
|
+
}
|
|
1668
|
+
},
|
|
1669
|
+
resetFormInstance() {}
|
|
1670
|
+
});
|
|
1670
1671
|
|
|
1671
1672
|
const _roots = new Map();
|
|
1672
1673
|
const shallowLoose = {
|
|
1673
1674
|
objects: 'shallow',
|
|
1674
1675
|
strict: false
|
|
1675
1676
|
};
|
|
1676
|
-
const createRendererInstance = (gl, canvas) => {
|
|
1677
|
-
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1678
|
-
if (isRenderer(customRenderer)) return customRenderer;
|
|
1679
|
-
return new THREE__namespace.WebGLRenderer({
|
|
1680
|
-
powerPreference: 'high-performance',
|
|
1681
|
-
canvas: canvas,
|
|
1682
|
-
antialias: true,
|
|
1683
|
-
alpha: true,
|
|
1684
|
-
...gl
|
|
1685
|
-
});
|
|
1686
|
-
};
|
|
1687
1677
|
function computeInitialSize(canvas, size) {
|
|
1688
|
-
if (!size && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1678
|
+
if (!size && typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1689
1679
|
const {
|
|
1690
1680
|
width,
|
|
1691
1681
|
height,
|
|
@@ -1761,10 +1751,13 @@ function createRoot(canvas) {
|
|
|
1761
1751
|
|
|
1762
1752
|
// Locals
|
|
1763
1753
|
let onCreated;
|
|
1764
|
-
let configured = false;
|
|
1765
1754
|
let lastCamera;
|
|
1755
|
+
let configured = false;
|
|
1756
|
+
let pending = null;
|
|
1766
1757
|
return {
|
|
1767
|
-
configure(props = {}) {
|
|
1758
|
+
async configure(props = {}) {
|
|
1759
|
+
let resolve;
|
|
1760
|
+
pending = new Promise(_resolve => resolve = _resolve);
|
|
1768
1761
|
let {
|
|
1769
1762
|
gl: glConfig,
|
|
1770
1763
|
size: propsSize,
|
|
@@ -1787,9 +1780,26 @@ function createRoot(canvas) {
|
|
|
1787
1780
|
|
|
1788
1781
|
// Set up renderer (one time only!)
|
|
1789
1782
|
let gl = state.gl;
|
|
1790
|
-
if (!state.gl)
|
|
1791
|
-
|
|
1792
|
-
|
|
1783
|
+
if (!state.gl) {
|
|
1784
|
+
const defaultProps = {
|
|
1785
|
+
canvas: canvas,
|
|
1786
|
+
powerPreference: 'high-performance',
|
|
1787
|
+
antialias: true,
|
|
1788
|
+
alpha: true
|
|
1789
|
+
};
|
|
1790
|
+
const customRenderer = typeof glConfig === 'function' ? await glConfig(defaultProps) : glConfig;
|
|
1791
|
+
if (isRenderer(customRenderer)) {
|
|
1792
|
+
gl = customRenderer;
|
|
1793
|
+
} else {
|
|
1794
|
+
gl = new THREE__namespace.WebGLRenderer({
|
|
1795
|
+
...defaultProps,
|
|
1796
|
+
...glConfig
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
state.set({
|
|
1800
|
+
gl
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1793
1803
|
|
|
1794
1804
|
// Set up raycaster (one time only!)
|
|
1795
1805
|
let raycaster = state.raycaster;
|
|
@@ -1815,7 +1825,7 @@ function createRoot(canvas) {
|
|
|
1815
1825
|
// Create default camera, don't overwrite any user-set state
|
|
1816
1826
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
1817
1827
|
lastCamera = cameraOptions;
|
|
1818
|
-
const isCamera = cameraOptions
|
|
1828
|
+
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
1819
1829
|
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);
|
|
1820
1830
|
if (!isCamera) {
|
|
1821
1831
|
camera.position.z = 5;
|
|
@@ -1845,7 +1855,7 @@ function createRoot(canvas) {
|
|
|
1845
1855
|
// Set up scene (one time only!)
|
|
1846
1856
|
if (!state.scene) {
|
|
1847
1857
|
let scene;
|
|
1848
|
-
if (sceneOptions
|
|
1858
|
+
if (sceneOptions != null && sceneOptions.isScene) {
|
|
1849
1859
|
scene = sceneOptions;
|
|
1850
1860
|
prepare(scene, store, '', {});
|
|
1851
1861
|
} else {
|
|
@@ -1858,8 +1868,34 @@ function createRoot(canvas) {
|
|
|
1858
1868
|
});
|
|
1859
1869
|
}
|
|
1860
1870
|
|
|
1871
|
+
// Store events internally
|
|
1872
|
+
if (events && !state.events.handlers) state.set({
|
|
1873
|
+
events: events(store)
|
|
1874
|
+
});
|
|
1875
|
+
// Check size, allow it to take on container bounds initially
|
|
1876
|
+
const size = computeInitialSize(canvas, propsSize);
|
|
1877
|
+
if (!is.equ(size, state.size, shallowLoose)) {
|
|
1878
|
+
state.setSize(size.width, size.height, size.top, size.left);
|
|
1879
|
+
}
|
|
1880
|
+
// Check pixelratio
|
|
1881
|
+
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1882
|
+
// Check frameloop
|
|
1883
|
+
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
1884
|
+
// Check pointer missed
|
|
1885
|
+
if (!state.onPointerMissed) state.set({
|
|
1886
|
+
onPointerMissed
|
|
1887
|
+
});
|
|
1888
|
+
// Check performance
|
|
1889
|
+
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
1890
|
+
performance: {
|
|
1891
|
+
...state.performance,
|
|
1892
|
+
...performance
|
|
1893
|
+
}
|
|
1894
|
+
}));
|
|
1895
|
+
|
|
1861
1896
|
// Set up XR (one time only!)
|
|
1862
1897
|
if (!state.xr) {
|
|
1898
|
+
var _gl$xr;
|
|
1863
1899
|
// Handle frame behavior in WebXR
|
|
1864
1900
|
const handleXRFrame = (timestamp, frame) => {
|
|
1865
1901
|
const state = store.getState();
|
|
@@ -1890,7 +1926,7 @@ function createRoot(canvas) {
|
|
|
1890
1926
|
};
|
|
1891
1927
|
|
|
1892
1928
|
// Subscribe to WebXR session events
|
|
1893
|
-
if (gl.xr) xr.connect();
|
|
1929
|
+
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
1894
1930
|
state.set({
|
|
1895
1931
|
xr
|
|
1896
1932
|
});
|
|
@@ -1917,22 +1953,12 @@ function createRoot(canvas) {
|
|
|
1917
1953
|
}
|
|
1918
1954
|
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1919
1955
|
}
|
|
1920
|
-
|
|
1921
|
-
// Safely set color management if available.
|
|
1922
|
-
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1923
|
-
const ColorManagement = getColorManagement();
|
|
1924
|
-
if (ColorManagement) {
|
|
1925
|
-
if ('enabled' in ColorManagement) ColorManagement.enabled = !legacy;else if ('legacyMode' in ColorManagement) ColorManagement.legacyMode = legacy;
|
|
1926
|
-
}
|
|
1956
|
+
THREE__namespace.ColorManagement.enabled = !legacy;
|
|
1927
1957
|
|
|
1928
1958
|
// Set color space and tonemapping preferences
|
|
1929
1959
|
if (!configured) {
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
applyProps(gl, {
|
|
1933
|
-
outputEncoding: linear ? LinearEncoding : sRGBEncoding,
|
|
1934
|
-
toneMapping: flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping
|
|
1935
|
-
});
|
|
1960
|
+
gl.outputColorSpace = linear ? THREE__namespace.LinearSRGBColorSpace : THREE__namespace.SRGBColorSpace;
|
|
1961
|
+
gl.toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
1936
1962
|
}
|
|
1937
1963
|
|
|
1938
1964
|
// Update color management state
|
|
@@ -1948,45 +1974,24 @@ function createRoot(canvas) {
|
|
|
1948
1974
|
|
|
1949
1975
|
// Set gl props
|
|
1950
1976
|
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
1951
|
-
// Store events internally
|
|
1952
|
-
if (events && !state.events.handlers) state.set({
|
|
1953
|
-
events: events(store)
|
|
1954
|
-
});
|
|
1955
|
-
// Check size, allow it to take on container bounds initially
|
|
1956
|
-
const size = computeInitialSize(canvas, propsSize);
|
|
1957
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
1958
|
-
state.setSize(size.width, size.height, size.top, size.left);
|
|
1959
|
-
}
|
|
1960
|
-
// Check pixelratio
|
|
1961
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1962
|
-
// Check frameloop
|
|
1963
|
-
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
1964
|
-
// Check pointer missed
|
|
1965
|
-
if (!state.onPointerMissed) state.set({
|
|
1966
|
-
onPointerMissed
|
|
1967
|
-
});
|
|
1968
|
-
// Check performance
|
|
1969
|
-
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
1970
|
-
performance: {
|
|
1971
|
-
...state.performance,
|
|
1972
|
-
...performance
|
|
1973
|
-
}
|
|
1974
|
-
}));
|
|
1975
1977
|
|
|
1976
1978
|
// Set locals
|
|
1977
1979
|
onCreated = onCreatedCallback;
|
|
1978
1980
|
configured = true;
|
|
1981
|
+
resolve();
|
|
1979
1982
|
return this;
|
|
1980
1983
|
},
|
|
1981
1984
|
render(children) {
|
|
1982
1985
|
// The root has to be configured before it can be rendered
|
|
1983
|
-
if (!configured) this.configure();
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1986
|
+
if (!configured && !pending) this.configure();
|
|
1987
|
+
pending.then(() => {
|
|
1988
|
+
reconciler.updateContainer( /*#__PURE__*/jsxRuntime.jsx(Provider, {
|
|
1989
|
+
store: store,
|
|
1990
|
+
children: children,
|
|
1991
|
+
onCreated: onCreated,
|
|
1992
|
+
rootElement: canvas
|
|
1993
|
+
}), fiber, null, () => undefined);
|
|
1994
|
+
});
|
|
1990
1995
|
return store;
|
|
1991
1996
|
},
|
|
1992
1997
|
unmount() {
|
|
@@ -1994,12 +1999,6 @@ function createRoot(canvas) {
|
|
|
1994
1999
|
}
|
|
1995
2000
|
};
|
|
1996
2001
|
}
|
|
1997
|
-
function render(children, canvas, config) {
|
|
1998
|
-
console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
|
|
1999
|
-
const root = createRoot(canvas);
|
|
2000
|
-
root.configure(config);
|
|
2001
|
-
return root.render(children);
|
|
2002
|
-
}
|
|
2003
2002
|
function Provider({
|
|
2004
2003
|
store,
|
|
2005
2004
|
children,
|
|
@@ -2137,18 +2136,17 @@ function Portal({
|
|
|
2137
2136
|
return store;
|
|
2138
2137
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2139
2138
|
}, [previousRoot, container]);
|
|
2140
|
-
return
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2139
|
+
return (
|
|
2140
|
+
/*#__PURE__*/
|
|
2141
|
+
// @ts-ignore, reconciler types are not maintained
|
|
2142
|
+
jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
2143
|
+
children: reconciler.createPortal( /*#__PURE__*/jsxRuntime.jsx(context.Provider, {
|
|
2144
|
+
value: usePortalStore,
|
|
2145
|
+
children: children
|
|
2146
|
+
}), usePortalStore, null)
|
|
2147
|
+
})
|
|
2148
|
+
);
|
|
2146
2149
|
}
|
|
2147
|
-
reconciler.injectIntoDevTools({
|
|
2148
|
-
bundleType: 0 ,
|
|
2149
|
-
rendererPackageName: '@react-three/fiber',
|
|
2150
|
-
version: React__namespace.version
|
|
2151
|
-
});
|
|
2152
2150
|
|
|
2153
2151
|
function createSubs(callback, subs) {
|
|
2154
2152
|
const sub = {
|
|
@@ -2247,7 +2245,7 @@ function loop(timestamp) {
|
|
|
2247
2245
|
repeat += update(timestamp, state);
|
|
2248
2246
|
}
|
|
2249
2247
|
}
|
|
2250
|
-
useFrameInProgress =
|
|
2248
|
+
useFrameInProgress = false;
|
|
2251
2249
|
|
|
2252
2250
|
// Run after-effects
|
|
2253
2251
|
flushGlobalEffects('after', timestamp);
|
|
@@ -2410,7 +2408,6 @@ exports.getRootState = getRootState;
|
|
|
2410
2408
|
exports.invalidate = invalidate;
|
|
2411
2409
|
exports.isRef = isRef;
|
|
2412
2410
|
exports.reconciler = reconciler;
|
|
2413
|
-
exports.render = render;
|
|
2414
2411
|
exports.threeTypes = threeTypes;
|
|
2415
2412
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
2416
2413
|
exports.useBridge = useBridge;
|