@react-three/fiber 9.0.0-rc.0 → 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-5a08b43f.esm.js → events-aba3c3d1.esm.js} +972 -979
- package/dist/{events-aef54ace.cjs.prod.js → events-b02714fc.cjs.dev.js} +970 -977
- package/dist/{events-fa0fb3db.cjs.dev.js → events-bd708dc8.cjs.prod.js} +970 -978
- 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,855 +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() {
|
|
410
|
-
return false;
|
|
411
|
-
},
|
|
412
|
-
requestPostPaintCallback() {},
|
|
413
|
-
maySuspendCommit() {
|
|
414
|
-
return false;
|
|
415
|
-
},
|
|
416
|
-
preloadInstance() {
|
|
417
|
-
return true; // true indicates already loaded
|
|
418
|
-
},
|
|
419
|
-
startSuspendingCommit() {},
|
|
420
|
-
suspendInstance() {},
|
|
421
|
-
waitForCommitToBeReady() {
|
|
422
|
-
return null;
|
|
423
|
-
},
|
|
424
|
-
NotPendingTransition: null,
|
|
425
|
-
setCurrentUpdatePriority(newPriority) {
|
|
426
|
-
currentUpdatePriority = newPriority;
|
|
427
|
-
},
|
|
428
|
-
getCurrentUpdatePriority() {
|
|
429
|
-
return currentUpdatePriority;
|
|
430
|
-
},
|
|
431
|
-
resolveUpdatePriority() {
|
|
432
|
-
var _window$event;
|
|
433
|
-
if (currentUpdatePriority !== constants.NoEventPriority) return currentUpdatePriority;
|
|
434
|
-
switch (typeof window !== 'undefined' && ((_window$event = window.event) == null ? void 0 : _window$event.type)) {
|
|
435
|
-
case 'click':
|
|
436
|
-
case 'contextmenu':
|
|
437
|
-
case 'dblclick':
|
|
438
|
-
case 'pointercancel':
|
|
439
|
-
case 'pointerdown':
|
|
440
|
-
case 'pointerup':
|
|
441
|
-
return constants.DiscreteEventPriority;
|
|
442
|
-
case 'pointermove':
|
|
443
|
-
case 'pointerout':
|
|
444
|
-
case 'pointerover':
|
|
445
|
-
case 'pointerenter':
|
|
446
|
-
case 'pointerleave':
|
|
447
|
-
case 'wheel':
|
|
448
|
-
return constants.ContinuousEventPriority;
|
|
449
|
-
default:
|
|
450
|
-
return constants.DefaultEventPriority;
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
resetFormInstance() {}
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
var _window$document, _window$navigator;
|
|
457
|
-
/**
|
|
458
|
-
* Returns the instance's initial (outmost) root.
|
|
459
|
-
*/
|
|
460
|
-
function findInitialRoot(instance) {
|
|
461
|
-
let root = instance.root;
|
|
462
|
-
while (root.getState().previousRoot) root = root.getState().previousRoot;
|
|
463
|
-
return root;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Returns `true` with correct TS type inference if an object has a configurable color space (since r152).
|
|
468
|
-
*/
|
|
469
|
-
const hasColorSpace = object => 'colorSpace' in object || 'outputColorSpace' in object;
|
|
470
|
-
/**
|
|
471
|
-
* The current THREE.ColorManagement instance, if present.
|
|
472
|
-
*/
|
|
473
|
-
const getColorManagement = () => {
|
|
474
|
-
var _ColorManagement;
|
|
475
|
-
return (_ColorManagement = catalogue.ColorManagement) != null ? _ColorManagement : null;
|
|
476
|
-
};
|
|
477
|
-
/**
|
|
478
|
-
* Safely flush async effects when testing, simulating a legacy root.
|
|
479
|
-
*/
|
|
480
|
-
const act = React__namespace.act;
|
|
481
|
-
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
482
|
-
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* An SSR-friendly useLayoutEffect.
|
|
486
|
-
*
|
|
487
|
-
* React currently throws a warning when using useLayoutEffect on the server.
|
|
488
|
-
* To get around it, we can conditionally useEffect on the server (no-op) and
|
|
489
|
-
* useLayoutEffect elsewhere.
|
|
490
|
-
*
|
|
491
|
-
* @see https://github.com/facebook/react/issues/14927
|
|
492
|
-
*/
|
|
493
|
-
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;
|
|
494
|
-
function useMutableCallback(fn) {
|
|
495
|
-
const ref = React__namespace.useRef(fn);
|
|
496
|
-
useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
|
|
497
|
-
return ref;
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Bridges renderer Context and StrictMode from a primary renderer.
|
|
501
|
-
*/
|
|
502
|
-
function useBridge() {
|
|
503
|
-
const fiber = itsFine.useFiber();
|
|
504
|
-
const ContextBridge = itsFine.useContextBridge();
|
|
505
|
-
return React__namespace.useMemo(() => ({
|
|
506
|
-
children
|
|
507
|
-
}) => {
|
|
508
|
-
const strict = !!itsFine.traverseFiber(fiber, true, node => node.type === React__namespace.StrictMode);
|
|
509
|
-
const Root = strict ? React__namespace.StrictMode : React__namespace.Fragment;
|
|
510
|
-
return /*#__PURE__*/jsxRuntime.jsx(Root, {
|
|
511
|
-
children: /*#__PURE__*/jsxRuntime.jsx(ContextBridge, {
|
|
512
|
-
children: children
|
|
513
|
-
})
|
|
514
|
-
});
|
|
515
|
-
}, [fiber, ContextBridge]);
|
|
516
|
-
}
|
|
517
|
-
function Block({
|
|
518
|
-
set
|
|
519
|
-
}) {
|
|
520
|
-
useIsomorphicLayoutEffect(() => {
|
|
521
|
-
set(new Promise(() => null));
|
|
522
|
-
return () => set(false);
|
|
523
|
-
}, [set]);
|
|
524
|
-
return null;
|
|
525
|
-
}
|
|
526
|
-
class ErrorBoundary extends React__namespace.Component {
|
|
527
|
-
constructor(...args) {
|
|
528
|
-
super(...args);
|
|
529
|
-
this.state = {
|
|
530
|
-
error: false
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
componentDidCatch(err) {
|
|
534
|
-
this.props.set(err);
|
|
535
|
-
}
|
|
536
|
-
render() {
|
|
537
|
-
return this.state.error ? null : this.props.children;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
ErrorBoundary.getDerivedStateFromError = () => ({
|
|
541
|
-
error: true
|
|
542
|
-
});
|
|
543
|
-
function calculateDpr(dpr) {
|
|
544
|
-
var _window$devicePixelRa;
|
|
545
|
-
// Err on the side of progress by assuming 2x dpr if we can't detect it
|
|
546
|
-
// This will happen in workers where window is defined but dpr isn't.
|
|
547
|
-
const target = typeof window !== 'undefined' ? (_window$devicePixelRa = window.devicePixelRatio) != null ? _window$devicePixelRa : 2 : 1;
|
|
548
|
-
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Returns instance root state
|
|
553
|
-
*/
|
|
554
|
-
function getRootState(obj) {
|
|
555
|
-
var _r3f;
|
|
556
|
-
return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
|
|
557
|
-
}
|
|
558
|
-
// A collection of compare functions
|
|
559
|
-
const is = {
|
|
560
|
-
obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
|
|
561
|
-
fun: a => typeof a === 'function',
|
|
562
|
-
str: a => typeof a === 'string',
|
|
563
|
-
num: a => typeof a === 'number',
|
|
564
|
-
boo: a => typeof a === 'boolean',
|
|
565
|
-
und: a => a === void 0,
|
|
566
|
-
arr: a => Array.isArray(a),
|
|
567
|
-
equ(a, b, {
|
|
568
|
-
arrays = 'shallow',
|
|
569
|
-
objects = 'reference',
|
|
570
|
-
strict = true
|
|
571
|
-
} = {}) {
|
|
572
|
-
// Wrong type or one of the two undefined, doesn't match
|
|
573
|
-
if (typeof a !== typeof b || !!a !== !!b) return false;
|
|
574
|
-
// Atomic, just compare a against b
|
|
575
|
-
if (is.str(a) || is.num(a) || is.boo(a)) return a === b;
|
|
576
|
-
const isObj = is.obj(a);
|
|
577
|
-
if (isObj && objects === 'reference') return a === b;
|
|
578
|
-
const isArr = is.arr(a);
|
|
579
|
-
if (isArr && arrays === 'reference') return a === b;
|
|
580
|
-
// Array or Object, shallow compare first to see if it's a match
|
|
581
|
-
if ((isArr || isObj) && a === b) return true;
|
|
582
|
-
// Last resort, go through keys
|
|
583
|
-
let i;
|
|
584
|
-
// Check if a has all the keys of b
|
|
585
|
-
for (i in a) if (!(i in b)) return false;
|
|
586
|
-
// Check if values between keys match
|
|
587
|
-
if (isObj && arrays === 'shallow' && objects === 'shallow') {
|
|
588
|
-
for (i in strict ? b : a) if (!is.equ(a[i], b[i], {
|
|
589
|
-
strict,
|
|
590
|
-
objects: 'reference'
|
|
591
|
-
})) return false;
|
|
592
|
-
} else {
|
|
593
|
-
for (i in strict ? b : a) if (a[i] !== b[i]) return false;
|
|
594
|
-
}
|
|
595
|
-
// If i is undefined
|
|
596
|
-
if (is.und(i)) {
|
|
597
|
-
// If both arrays are empty we consider them equal
|
|
598
|
-
if (isArr && a.length === 0 && b.length === 0) return true;
|
|
599
|
-
// If both objects are empty we consider them equal
|
|
600
|
-
if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
|
|
601
|
-
// Otherwise match them by value
|
|
602
|
-
if (a !== b) return false;
|
|
603
|
-
}
|
|
604
|
-
return true;
|
|
605
|
-
}
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
// Collects nodes and materials from a THREE.Object3D
|
|
609
|
-
function buildGraph(object) {
|
|
610
|
-
const data = {
|
|
611
|
-
nodes: {},
|
|
612
|
-
materials: {}
|
|
613
|
-
};
|
|
614
|
-
if (object) {
|
|
615
|
-
object.traverse(obj => {
|
|
616
|
-
if (obj.name) data.nodes[obj.name] = obj;
|
|
617
|
-
if (obj.material && !data.materials[obj.material.name]) data.materials[obj.material.name] = obj.material;
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
return data;
|
|
621
|
-
}
|
|
622
|
-
// Disposes an object and all its properties
|
|
623
|
-
function dispose(obj) {
|
|
624
|
-
if (obj.type !== 'Scene') obj.dispose == null ? void 0 : obj.dispose();
|
|
625
|
-
for (const p in obj) {
|
|
626
|
-
const prop = obj[p];
|
|
627
|
-
if ((prop == null ? void 0 : prop.type) !== 'Scene') prop == null ? void 0 : prop.dispose == null ? void 0 : prop.dispose();
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
const REACT_INTERNAL_PROPS = ['children', 'key', 'ref'];
|
|
631
|
-
|
|
632
|
-
// Gets only instance props from reconciler fibers
|
|
633
|
-
function getInstanceProps(queue) {
|
|
634
|
-
const props = {};
|
|
635
|
-
for (const key in queue) {
|
|
636
|
-
if (!REACT_INTERNAL_PROPS.includes(key)) props[key] = queue[key];
|
|
637
|
-
}
|
|
638
|
-
return props;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// Each object in the scene carries a small LocalState descriptor
|
|
642
|
-
function prepare(target, root, type, props) {
|
|
643
|
-
const object = target;
|
|
644
|
-
|
|
645
|
-
// Create instance descriptor
|
|
646
|
-
let instance = object == null ? void 0 : object.__r3f;
|
|
647
|
-
if (!instance) {
|
|
648
|
-
instance = {
|
|
649
|
-
root,
|
|
650
|
-
type,
|
|
651
|
-
parent: null,
|
|
652
|
-
children: [],
|
|
653
|
-
props: getInstanceProps(props),
|
|
654
|
-
object,
|
|
655
|
-
eventCount: 0,
|
|
656
|
-
handlers: {},
|
|
657
|
-
isHidden: false
|
|
658
|
-
};
|
|
659
|
-
if (object) {
|
|
660
|
-
object.__r3f = instance;
|
|
661
|
-
if (type) applyProps(object, instance.props);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
return instance;
|
|
665
|
-
}
|
|
666
|
-
function resolve(root, key) {
|
|
667
|
-
var _target;
|
|
668
|
-
let target = root[key];
|
|
669
|
-
if (!key.includes('-')) return {
|
|
670
|
-
root,
|
|
671
|
-
key,
|
|
672
|
-
target
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
// Resolve pierced target
|
|
676
|
-
const chain = key.split('-');
|
|
677
|
-
target = chain.reduce((acc, key) => acc[key], root);
|
|
678
|
-
key = chain.pop();
|
|
679
|
-
|
|
680
|
-
// Switch root if atomic
|
|
681
|
-
if (!((_target = target) != null && _target.set)) root = chain.reduce((acc, key) => acc[key], root);
|
|
682
|
-
return {
|
|
683
|
-
root,
|
|
684
|
-
key,
|
|
685
|
-
target
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// Checks if a dash-cased string ends with an integer
|
|
690
|
-
const INDEX_REGEX = /-\d+$/;
|
|
691
|
-
function attach(parent, child) {
|
|
692
|
-
if (is.str(child.props.attach)) {
|
|
693
|
-
// If attaching into an array (foo-0), create one
|
|
694
|
-
if (INDEX_REGEX.test(child.props.attach)) {
|
|
695
|
-
const index = child.props.attach.replace(INDEX_REGEX, '');
|
|
696
|
-
const {
|
|
697
|
-
root,
|
|
698
|
-
key
|
|
699
|
-
} = resolve(parent.object, index);
|
|
700
|
-
if (!Array.isArray(root[key])) root[key] = [];
|
|
701
|
-
}
|
|
702
|
-
const {
|
|
703
|
-
root,
|
|
704
|
-
key
|
|
705
|
-
} = resolve(parent.object, child.props.attach);
|
|
706
|
-
child.previousAttach = root[key];
|
|
707
|
-
root[key] = child.object;
|
|
708
|
-
} else if (is.fun(child.props.attach)) {
|
|
709
|
-
child.previousAttach = child.props.attach(parent.object, child.object);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
function detach(parent, child) {
|
|
713
|
-
if (is.str(child.props.attach)) {
|
|
714
|
-
const {
|
|
715
|
-
root,
|
|
716
|
-
key
|
|
717
|
-
} = resolve(parent.object, child.props.attach);
|
|
718
|
-
const previous = child.previousAttach;
|
|
719
|
-
// When the previous value was undefined, it means the value was never set to begin with
|
|
720
|
-
if (previous === undefined) delete root[key];
|
|
721
|
-
// Otherwise set the previous value
|
|
722
|
-
else root[key] = previous;
|
|
723
|
-
} else {
|
|
724
|
-
child.previousAttach == null ? void 0 : child.previousAttach(parent.object, child.object);
|
|
725
|
-
}
|
|
726
|
-
delete child.previousAttach;
|
|
727
|
-
}
|
|
728
|
-
const RESERVED_PROPS = [...REACT_INTERNAL_PROPS,
|
|
729
|
-
// Instance props
|
|
730
|
-
'args', 'dispose', 'attach', 'object', 'onUpdate',
|
|
731
|
-
// Behavior flags
|
|
732
|
-
'dispose'];
|
|
733
|
-
const MEMOIZED_PROTOTYPES = new Map();
|
|
734
|
-
|
|
735
|
-
// This function prepares a set of changes to be applied to the instance
|
|
736
|
-
function diffProps(instance, newProps) {
|
|
737
|
-
const changedProps = {};
|
|
738
|
-
|
|
739
|
-
// Sort through props
|
|
740
|
-
for (const prop in newProps) {
|
|
741
|
-
// Skip reserved keys
|
|
742
|
-
if (RESERVED_PROPS.includes(prop)) continue;
|
|
743
|
-
// Skip if props match
|
|
744
|
-
if (is.equ(newProps[prop], instance.props[prop])) continue;
|
|
745
|
-
|
|
746
|
-
// Props changed, add them
|
|
747
|
-
changedProps[prop] = newProps[prop];
|
|
748
|
-
|
|
749
|
-
// Reset pierced props
|
|
750
|
-
for (const other in newProps) {
|
|
751
|
-
if (other.startsWith(`${prop}-`)) changedProps[other] = newProps[other];
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
// Reset removed props for HMR
|
|
756
|
-
for (const prop in instance.props) {
|
|
757
|
-
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
758
|
-
const {
|
|
759
|
-
root,
|
|
760
|
-
key
|
|
761
|
-
} = resolve(instance.object, prop);
|
|
762
|
-
|
|
763
|
-
// https://github.com/mrdoob/three.js/issues/21209
|
|
764
|
-
// HMR/fast-refresh relies on the ability to cancel out props, but threejs
|
|
765
|
-
// has no means to do this. Hence we curate a small collection of value-classes
|
|
766
|
-
// with their respective constructor/set arguments
|
|
767
|
-
// For removed props, try to set default values, if possible
|
|
768
|
-
if (root.constructor && root.constructor.length === 0) {
|
|
769
|
-
// create a blank slate of the instance and copy the particular parameter.
|
|
770
|
-
let ctor = MEMOIZED_PROTOTYPES.get(root.constructor);
|
|
771
|
-
if (!ctor) {
|
|
772
|
-
ctor = new root.constructor();
|
|
773
|
-
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
774
|
-
}
|
|
775
|
-
changedProps[key] = ctor[key];
|
|
776
|
-
} else {
|
|
777
|
-
// instance does not have constructor, just set it to 0
|
|
778
|
-
changedProps[key] = 0;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
return changedProps;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// const LinearEncoding = 3000
|
|
785
|
-
const sRGBEncoding = 3001;
|
|
786
|
-
const SRGBColorSpace = 'srgb';
|
|
787
|
-
const LinearSRGBColorSpace = 'srgb-linear';
|
|
788
|
-
|
|
789
|
-
// https://github.com/mrdoob/three.js/pull/27042
|
|
790
|
-
// https://github.com/mrdoob/three.js/pull/22748
|
|
791
|
-
const colorMaps = ['map', 'emissiveMap', 'sheenTintMap',
|
|
792
|
-
// <r134
|
|
793
|
-
'sheenColorMap', 'specularTintMap',
|
|
794
|
-
// <r134
|
|
795
|
-
'specularColorMap', 'envMap'];
|
|
796
|
-
const EVENT_REGEX = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/;
|
|
797
|
-
|
|
798
|
-
// This function applies a set of changes to the instance
|
|
799
|
-
function applyProps(object, props) {
|
|
800
|
-
const instance = object.__r3f;
|
|
801
|
-
const rootState = instance && findInitialRoot(instance).getState();
|
|
802
|
-
const prevHandlers = instance == null ? void 0 : instance.eventCount;
|
|
803
|
-
for (const prop in props) {
|
|
804
|
-
let value = props[prop];
|
|
805
|
-
|
|
806
|
-
// Don't mutate reserved keys
|
|
807
|
-
if (RESERVED_PROPS.includes(prop)) continue;
|
|
808
|
-
|
|
809
|
-
// Deal with pointer events, including removing them if undefined
|
|
810
|
-
if (instance && EVENT_REGEX.test(prop)) {
|
|
811
|
-
if (typeof value === 'function') instance.handlers[prop] = value;else delete instance.handlers[prop];
|
|
812
|
-
instance.eventCount = Object.keys(instance.handlers).length;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
// Ignore setting undefined props
|
|
816
|
-
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
817
|
-
if (value === undefined) continue;
|
|
818
|
-
let {
|
|
819
|
-
root,
|
|
820
|
-
key,
|
|
821
|
-
target
|
|
822
|
-
} = resolve(object, prop);
|
|
823
|
-
|
|
824
|
-
// Alias (output)encoding => (output)colorSpace (since r152)
|
|
825
|
-
// https://github.com/pmndrs/react-three-fiber/pull/2829
|
|
826
|
-
if (hasColorSpace(root)) {
|
|
827
|
-
if (key === 'encoding') {
|
|
828
|
-
key = 'colorSpace';
|
|
829
|
-
value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
|
|
830
|
-
} else if (key === 'outputEncoding') {
|
|
831
|
-
key = 'outputColorSpace';
|
|
832
|
-
value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
|
|
833
|
-
}
|
|
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);
|
|
834
401
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
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) {
|
|
838
404
|
target.copy(value);
|
|
839
405
|
}
|
|
840
|
-
// Layers have no copy function, we must therefore copy the mask property
|
|
841
|
-
else if (target instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) {
|
|
842
|
-
target.mask = value.mask;
|
|
843
|
-
}
|
|
844
406
|
// Set array types
|
|
845
|
-
else if (target
|
|
846
|
-
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);
|
|
847
409
|
}
|
|
848
410
|
// Set literal types
|
|
849
|
-
else if (target
|
|
850
|
-
const isColor = target instanceof THREE__namespace.Color;
|
|
411
|
+
else if (target && typeof target.set === 'function' && typeof value === 'number') {
|
|
851
412
|
// Allow setting array scalars
|
|
852
|
-
if (
|
|
413
|
+
if (typeof target.setScalar === 'function') target.setScalar(value);
|
|
853
414
|
// Otherwise just set single value
|
|
854
415
|
else target.set(value);
|
|
855
|
-
|
|
856
|
-
// Emulate THREE.ColorManagement for older three.js versions
|
|
857
|
-
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
858
|
-
if (!getColorManagement() && !(rootState != null && rootState.linear) && isColor) target.convertSRGBToLinear();
|
|
859
416
|
}
|
|
860
417
|
// Else, just overwrite the value
|
|
861
418
|
else {
|
|
419
|
+
var _root$key;
|
|
862
420
|
root[key] = value;
|
|
863
421
|
|
|
864
422
|
// Auto-convert sRGB texture parameters for built-in materials
|
|
865
423
|
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
866
424
|
// https://github.com/mrdoob/three.js/pull/25857
|
|
867
|
-
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 &&
|
|
868
426
|
// sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
869
427
|
root[key].format === THREE__namespace.RGBAFormat && root[key].type === THREE__namespace.UnsignedByteType) {
|
|
870
428
|
// NOTE: this cannot be set from the renderer (e.g. sRGB source textures rendered to P3)
|
|
871
|
-
|
|
429
|
+
root[key].colorSpace = THREE__namespace.SRGBColorSpace;
|
|
872
430
|
}
|
|
873
431
|
}
|
|
874
432
|
}
|
|
875
433
|
|
|
876
434
|
// Register event handlers
|
|
877
|
-
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;
|
|
878
437
|
// Pre-emptively remove the instance from the interaction manager
|
|
879
|
-
const index = rootState.internal.interaction.indexOf(
|
|
438
|
+
const index = rootState.internal.interaction.indexOf(object);
|
|
880
439
|
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
881
440
|
// Add the instance to the interaction manager only when it has handlers
|
|
882
|
-
if (instance.eventCount &&
|
|
883
|
-
rootState.internal.interaction.push(
|
|
441
|
+
if (instance.eventCount && object.raycast !== null) {
|
|
442
|
+
rootState.internal.interaction.push(object);
|
|
884
443
|
}
|
|
885
444
|
}
|
|
886
445
|
|
|
887
446
|
// Auto-attach geometries and materials
|
|
888
447
|
if (instance && instance.props.attach === undefined) {
|
|
889
|
-
if (instance.object
|
|
448
|
+
if (instance.object.isBufferGeometry) instance.props.attach = 'geometry';else if (instance.object.isMaterial) instance.props.attach = 'material';
|
|
890
449
|
}
|
|
891
450
|
|
|
892
451
|
// Instance was updated, request a frame
|
|
@@ -1058,7 +617,19 @@ function createEvents(store) {
|
|
|
1058
617
|
stopped: false
|
|
1059
618
|
};
|
|
1060
619
|
for (const hit of intersections) {
|
|
1061
|
-
|
|
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
|
+
}
|
|
1062
633
|
if (state) {
|
|
1063
634
|
const {
|
|
1064
635
|
raycaster,
|
|
@@ -1319,7 +890,7 @@ function createEvents(store) {
|
|
|
1319
890
|
}
|
|
1320
891
|
|
|
1321
892
|
const isRenderer = def => !!(def != null && def.render);
|
|
1322
|
-
const context =
|
|
893
|
+
const context = /* @__PURE__ */React__namespace.createContext(null);
|
|
1323
894
|
const createStore = (invalidate, advance) => {
|
|
1324
895
|
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
1325
896
|
const position = new THREE__namespace.Vector3();
|
|
@@ -1333,7 +904,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1333
904
|
left
|
|
1334
905
|
} = size;
|
|
1335
906
|
const aspect = width / height;
|
|
1336
|
-
if (target
|
|
907
|
+
if (target.isVector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
1337
908
|
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
1338
909
|
if (isOrthographicCamera(camera)) {
|
|
1339
910
|
return {
|
|
@@ -1535,161 +1106,576 @@ const createStore = (invalidate, advance) => {
|
|
|
1535
1106
|
oldDpr = viewport.dpr;
|
|
1536
1107
|
// Update camera & renderer
|
|
1537
1108
|
updateCamera(camera, size);
|
|
1538
|
-
gl.setPixelRatio(viewport.dpr);
|
|
1109
|
+
if (viewport.dpr > 0) gl.setPixelRatio(viewport.dpr);
|
|
1539
1110
|
const updateStyle = typeof HTMLCanvasElement !== 'undefined' && gl.domElement instanceof HTMLCanvasElement;
|
|
1540
1111
|
gl.setSize(size.width, size.height, updateStyle);
|
|
1541
1112
|
}
|
|
1542
1113
|
|
|
1543
|
-
// Update viewport once the camera changes
|
|
1544
|
-
if (camera !== oldCamera) {
|
|
1545
|
-
oldCamera = camera;
|
|
1546
|
-
// Update viewport
|
|
1547
|
-
set(state => ({
|
|
1548
|
-
viewport: {
|
|
1549
|
-
...state.viewport,
|
|
1550
|
-
...state.viewport.getCurrentViewport(camera)
|
|
1551
|
-
}
|
|
1552
|
-
}));
|
|
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;
|
|
1553
1312
|
}
|
|
1554
|
-
|
|
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;
|
|
1324
|
+
}
|
|
1325
|
+
instance.isHidden = false;
|
|
1326
|
+
invalidateInstance(instance);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1555
1329
|
|
|
1556
|
-
|
|
1557
|
-
|
|
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;
|
|
1558
1337
|
|
|
1559
|
-
//
|
|
1560
|
-
|
|
1561
|
-
|
|
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)];
|
|
1562
1343
|
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
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);
|
|
1573
1377
|
}
|
|
1378
|
+
function appendChild(parent, child) {
|
|
1379
|
+
if (!child) return;
|
|
1574
1380
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1582
|
-
return store;
|
|
1381
|
+
// Link instances
|
|
1382
|
+
child.parent = parent;
|
|
1383
|
+
parent.children.push(child);
|
|
1384
|
+
|
|
1385
|
+
// Attach tree once complete
|
|
1386
|
+
handleContainerEffects(parent, child);
|
|
1583
1387
|
}
|
|
1388
|
+
function insertBefore(parent, child, beforeChild) {
|
|
1389
|
+
if (!child || !beforeChild) return;
|
|
1584
1390
|
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
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);
|
|
1591
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
|
+
};
|
|
1592
1408
|
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
function useFrame(callback, renderPriority = 0) {
|
|
1599
|
-
const store = useStore();
|
|
1600
|
-
const subscribe = store.getState().internal.subscribe;
|
|
1601
|
-
// Memoize ref
|
|
1602
|
-
const ref = useMutableCallback(callback);
|
|
1603
|
-
// Subscribe on mount, unsubscribe on unmount
|
|
1604
|
-
useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
|
|
1605
|
-
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
|
+
}
|
|
1606
1414
|
}
|
|
1415
|
+
function removeChild(parent, child, dispose) {
|
|
1416
|
+
if (!child) return;
|
|
1607
1417
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
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);
|
|
1614
1456
|
}
|
|
1615
|
-
|
|
1616
|
-
const
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
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
|
+
}
|
|
1489
|
+
|
|
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)];
|
|
1623
1509
|
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
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);
|
|
1630
1521
|
}
|
|
1631
|
-
|
|
1632
|
-
|
|
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);
|
|
1633
1532
|
}
|
|
1533
|
+
}
|
|
1534
|
+
reconstructed.length = 0;
|
|
1535
|
+
}
|
|
1634
1536
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1537
|
+
// Don't handle text instances, make it no-op
|
|
1538
|
+
const handleTextInstance = () => {};
|
|
1539
|
+
const NO_CONTEXT = {};
|
|
1540
|
+
let currentUpdatePriority = NoEventPriority;
|
|
1637
1541
|
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
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;
|
|
1642
1577
|
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
const results = suspendReact.suspend(loadingFn(extensions, onProgress), [loader, ...keys], {
|
|
1653
|
-
equal: is.equ
|
|
1654
|
-
});
|
|
1655
|
-
// Return the object(s)
|
|
1656
|
-
return Array.isArray(input) ? results : results[0];
|
|
1657
|
-
}
|
|
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;
|
|
1658
1587
|
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
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
|
+
}
|
|
1666
1601
|
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
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
|
+
});
|
|
1674
1671
|
|
|
1675
1672
|
const _roots = new Map();
|
|
1676
1673
|
const shallowLoose = {
|
|
1677
1674
|
objects: 'shallow',
|
|
1678
1675
|
strict: false
|
|
1679
1676
|
};
|
|
1680
|
-
const createRendererInstance = (gl, canvas) => {
|
|
1681
|
-
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1682
|
-
if (isRenderer(customRenderer)) return customRenderer;
|
|
1683
|
-
return new THREE__namespace.WebGLRenderer({
|
|
1684
|
-
powerPreference: 'high-performance',
|
|
1685
|
-
canvas: canvas,
|
|
1686
|
-
antialias: true,
|
|
1687
|
-
alpha: true,
|
|
1688
|
-
...gl
|
|
1689
|
-
});
|
|
1690
|
-
};
|
|
1691
1677
|
function computeInitialSize(canvas, size) {
|
|
1692
|
-
if (!size && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1678
|
+
if (!size && typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1693
1679
|
const {
|
|
1694
1680
|
width,
|
|
1695
1681
|
height,
|
|
@@ -1765,10 +1751,13 @@ function createRoot(canvas) {
|
|
|
1765
1751
|
|
|
1766
1752
|
// Locals
|
|
1767
1753
|
let onCreated;
|
|
1768
|
-
let configured = false;
|
|
1769
1754
|
let lastCamera;
|
|
1755
|
+
let configured = false;
|
|
1756
|
+
let pending = null;
|
|
1770
1757
|
return {
|
|
1771
|
-
configure(props = {}) {
|
|
1758
|
+
async configure(props = {}) {
|
|
1759
|
+
let resolve;
|
|
1760
|
+
pending = new Promise(_resolve => resolve = _resolve);
|
|
1772
1761
|
let {
|
|
1773
1762
|
gl: glConfig,
|
|
1774
1763
|
size: propsSize,
|
|
@@ -1791,9 +1780,26 @@ function createRoot(canvas) {
|
|
|
1791
1780
|
|
|
1792
1781
|
// Set up renderer (one time only!)
|
|
1793
1782
|
let gl = state.gl;
|
|
1794
|
-
if (!state.gl)
|
|
1795
|
-
|
|
1796
|
-
|
|
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
|
+
}
|
|
1797
1803
|
|
|
1798
1804
|
// Set up raycaster (one time only!)
|
|
1799
1805
|
let raycaster = state.raycaster;
|
|
@@ -1819,7 +1825,7 @@ function createRoot(canvas) {
|
|
|
1819
1825
|
// Create default camera, don't overwrite any user-set state
|
|
1820
1826
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
1821
1827
|
lastCamera = cameraOptions;
|
|
1822
|
-
const isCamera = cameraOptions
|
|
1828
|
+
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
1823
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);
|
|
1824
1830
|
if (!isCamera) {
|
|
1825
1831
|
camera.position.z = 5;
|
|
@@ -1849,7 +1855,7 @@ function createRoot(canvas) {
|
|
|
1849
1855
|
// Set up scene (one time only!)
|
|
1850
1856
|
if (!state.scene) {
|
|
1851
1857
|
let scene;
|
|
1852
|
-
if (sceneOptions
|
|
1858
|
+
if (sceneOptions != null && sceneOptions.isScene) {
|
|
1853
1859
|
scene = sceneOptions;
|
|
1854
1860
|
prepare(scene, store, '', {});
|
|
1855
1861
|
} else {
|
|
@@ -1862,8 +1868,34 @@ function createRoot(canvas) {
|
|
|
1862
1868
|
});
|
|
1863
1869
|
}
|
|
1864
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
|
+
|
|
1865
1896
|
// Set up XR (one time only!)
|
|
1866
1897
|
if (!state.xr) {
|
|
1898
|
+
var _gl$xr;
|
|
1867
1899
|
// Handle frame behavior in WebXR
|
|
1868
1900
|
const handleXRFrame = (timestamp, frame) => {
|
|
1869
1901
|
const state = store.getState();
|
|
@@ -1894,7 +1926,7 @@ function createRoot(canvas) {
|
|
|
1894
1926
|
};
|
|
1895
1927
|
|
|
1896
1928
|
// Subscribe to WebXR session events
|
|
1897
|
-
if (gl.xr) xr.connect();
|
|
1929
|
+
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
1898
1930
|
state.set({
|
|
1899
1931
|
xr
|
|
1900
1932
|
});
|
|
@@ -1921,22 +1953,12 @@ function createRoot(canvas) {
|
|
|
1921
1953
|
}
|
|
1922
1954
|
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1923
1955
|
}
|
|
1924
|
-
|
|
1925
|
-
// Safely set color management if available.
|
|
1926
|
-
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1927
|
-
const ColorManagement = getColorManagement();
|
|
1928
|
-
if (ColorManagement) {
|
|
1929
|
-
if ('enabled' in ColorManagement) ColorManagement.enabled = !legacy;else if ('legacyMode' in ColorManagement) ColorManagement.legacyMode = legacy;
|
|
1930
|
-
}
|
|
1956
|
+
THREE__namespace.ColorManagement.enabled = !legacy;
|
|
1931
1957
|
|
|
1932
1958
|
// Set color space and tonemapping preferences
|
|
1933
1959
|
if (!configured) {
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
applyProps(gl, {
|
|
1937
|
-
outputEncoding: linear ? LinearEncoding : sRGBEncoding,
|
|
1938
|
-
toneMapping: flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping
|
|
1939
|
-
});
|
|
1960
|
+
gl.outputColorSpace = linear ? THREE__namespace.LinearSRGBColorSpace : THREE__namespace.SRGBColorSpace;
|
|
1961
|
+
gl.toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
1940
1962
|
}
|
|
1941
1963
|
|
|
1942
1964
|
// Update color management state
|
|
@@ -1952,45 +1974,24 @@ function createRoot(canvas) {
|
|
|
1952
1974
|
|
|
1953
1975
|
// Set gl props
|
|
1954
1976
|
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
1955
|
-
// Store events internally
|
|
1956
|
-
if (events && !state.events.handlers) state.set({
|
|
1957
|
-
events: events(store)
|
|
1958
|
-
});
|
|
1959
|
-
// Check size, allow it to take on container bounds initially
|
|
1960
|
-
const size = computeInitialSize(canvas, propsSize);
|
|
1961
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
1962
|
-
state.setSize(size.width, size.height, size.top, size.left);
|
|
1963
|
-
}
|
|
1964
|
-
// Check pixelratio
|
|
1965
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1966
|
-
// Check frameloop
|
|
1967
|
-
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
1968
|
-
// Check pointer missed
|
|
1969
|
-
if (!state.onPointerMissed) state.set({
|
|
1970
|
-
onPointerMissed
|
|
1971
|
-
});
|
|
1972
|
-
// Check performance
|
|
1973
|
-
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
1974
|
-
performance: {
|
|
1975
|
-
...state.performance,
|
|
1976
|
-
...performance
|
|
1977
|
-
}
|
|
1978
|
-
}));
|
|
1979
1977
|
|
|
1980
1978
|
// Set locals
|
|
1981
1979
|
onCreated = onCreatedCallback;
|
|
1982
1980
|
configured = true;
|
|
1981
|
+
resolve();
|
|
1983
1982
|
return this;
|
|
1984
1983
|
},
|
|
1985
1984
|
render(children) {
|
|
1986
1985
|
// The root has to be configured before it can be rendered
|
|
1987
|
-
if (!configured) this.configure();
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
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
|
+
});
|
|
1994
1995
|
return store;
|
|
1995
1996
|
},
|
|
1996
1997
|
unmount() {
|
|
@@ -1998,12 +1999,6 @@ function createRoot(canvas) {
|
|
|
1998
1999
|
}
|
|
1999
2000
|
};
|
|
2000
2001
|
}
|
|
2001
|
-
function render(children, canvas, config) {
|
|
2002
|
-
console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
|
|
2003
|
-
const root = createRoot(canvas);
|
|
2004
|
-
root.configure(config);
|
|
2005
|
-
return root.render(children);
|
|
2006
|
-
}
|
|
2007
2002
|
function Provider({
|
|
2008
2003
|
store,
|
|
2009
2004
|
children,
|
|
@@ -2141,18 +2136,17 @@ function Portal({
|
|
|
2141
2136
|
return store;
|
|
2142
2137
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2143
2138
|
}, [previousRoot, container]);
|
|
2144
|
-
return
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
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
|
+
);
|
|
2150
2149
|
}
|
|
2151
|
-
reconciler.injectIntoDevTools({
|
|
2152
|
-
bundleType: 0 ,
|
|
2153
|
-
rendererPackageName: '@react-three/fiber',
|
|
2154
|
-
version: React__namespace.version
|
|
2155
|
-
});
|
|
2156
2150
|
|
|
2157
2151
|
function createSubs(callback, subs) {
|
|
2158
2152
|
const sub = {
|
|
@@ -2251,7 +2245,7 @@ function loop(timestamp) {
|
|
|
2251
2245
|
repeat += update(timestamp, state);
|
|
2252
2246
|
}
|
|
2253
2247
|
}
|
|
2254
|
-
useFrameInProgress =
|
|
2248
|
+
useFrameInProgress = false;
|
|
2255
2249
|
|
|
2256
2250
|
// Run after-effects
|
|
2257
2251
|
flushGlobalEffects('after', timestamp);
|
|
@@ -2414,7 +2408,6 @@ exports.getRootState = getRootState;
|
|
|
2414
2408
|
exports.invalidate = invalidate;
|
|
2415
2409
|
exports.isRef = isRef;
|
|
2416
2410
|
exports.reconciler = reconciler;
|
|
2417
|
-
exports.render = render;
|
|
2418
2411
|
exports.threeTypes = threeTypes;
|
|
2419
2412
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
2420
2413
|
exports.useBridge = useBridge;
|