@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,856 +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
|
-
typeof process !== 'undefined' && process.env.NODE_ENV !== 'production';
|
|
784
|
-
|
|
785
|
-
// const LinearEncoding = 3000
|
|
786
|
-
const sRGBEncoding = 3001;
|
|
787
|
-
const SRGBColorSpace = 'srgb';
|
|
788
|
-
const LinearSRGBColorSpace = 'srgb-linear';
|
|
789
|
-
|
|
790
|
-
// https://github.com/mrdoob/three.js/pull/27042
|
|
791
|
-
// https://github.com/mrdoob/three.js/pull/22748
|
|
792
|
-
const colorMaps = ['map', 'emissiveMap', 'sheenTintMap',
|
|
793
|
-
// <r134
|
|
794
|
-
'sheenColorMap', 'specularTintMap',
|
|
795
|
-
// <r134
|
|
796
|
-
'specularColorMap', 'envMap'];
|
|
797
|
-
const EVENT_REGEX = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/;
|
|
798
|
-
|
|
799
|
-
// This function applies a set of changes to the instance
|
|
800
|
-
function applyProps(object, props) {
|
|
801
|
-
const instance = object.__r3f;
|
|
802
|
-
const rootState = instance && findInitialRoot(instance).getState();
|
|
803
|
-
const prevHandlers = instance == null ? void 0 : instance.eventCount;
|
|
804
|
-
for (const prop in props) {
|
|
805
|
-
let value = props[prop];
|
|
806
|
-
|
|
807
|
-
// Don't mutate reserved keys
|
|
808
|
-
if (RESERVED_PROPS.includes(prop)) continue;
|
|
809
|
-
|
|
810
|
-
// Deal with pointer events, including removing them if undefined
|
|
811
|
-
if (instance && EVENT_REGEX.test(prop)) {
|
|
812
|
-
if (typeof value === 'function') instance.handlers[prop] = value;else delete instance.handlers[prop];
|
|
813
|
-
instance.eventCount = Object.keys(instance.handlers).length;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// Ignore setting undefined props
|
|
817
|
-
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
818
|
-
if (value === undefined) continue;
|
|
819
|
-
let {
|
|
820
|
-
root,
|
|
821
|
-
key,
|
|
822
|
-
target
|
|
823
|
-
} = resolve(object, prop);
|
|
824
|
-
|
|
825
|
-
// Alias (output)encoding => (output)colorSpace (since r152)
|
|
826
|
-
// https://github.com/pmndrs/react-three-fiber/pull/2829
|
|
827
|
-
if (hasColorSpace(root)) {
|
|
828
|
-
if (key === 'encoding') {
|
|
829
|
-
key = 'colorSpace';
|
|
830
|
-
value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
|
|
831
|
-
} else if (key === 'outputEncoding') {
|
|
832
|
-
key = 'outputColorSpace';
|
|
833
|
-
value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
|
|
834
|
-
}
|
|
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);
|
|
835
401
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
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) {
|
|
839
404
|
target.copy(value);
|
|
840
405
|
}
|
|
841
|
-
// Layers have no copy function, we must therefore copy the mask property
|
|
842
|
-
else if (target instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) {
|
|
843
|
-
target.mask = value.mask;
|
|
844
|
-
}
|
|
845
406
|
// Set array types
|
|
846
|
-
else if (target
|
|
847
|
-
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);
|
|
848
409
|
}
|
|
849
410
|
// Set literal types
|
|
850
|
-
else if (target
|
|
851
|
-
const isColor = target instanceof THREE__namespace.Color;
|
|
411
|
+
else if (target && typeof target.set === 'function' && typeof value === 'number') {
|
|
852
412
|
// Allow setting array scalars
|
|
853
|
-
if (
|
|
413
|
+
if (typeof target.setScalar === 'function') target.setScalar(value);
|
|
854
414
|
// Otherwise just set single value
|
|
855
415
|
else target.set(value);
|
|
856
|
-
|
|
857
|
-
// Emulate THREE.ColorManagement for older three.js versions
|
|
858
|
-
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
859
|
-
if (!getColorManagement() && !(rootState != null && rootState.linear) && isColor) target.convertSRGBToLinear();
|
|
860
416
|
}
|
|
861
417
|
// Else, just overwrite the value
|
|
862
418
|
else {
|
|
419
|
+
var _root$key;
|
|
863
420
|
root[key] = value;
|
|
864
421
|
|
|
865
422
|
// Auto-convert sRGB texture parameters for built-in materials
|
|
866
423
|
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
867
424
|
// https://github.com/mrdoob/three.js/pull/25857
|
|
868
|
-
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 &&
|
|
869
426
|
// sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
870
427
|
root[key].format === THREE__namespace.RGBAFormat && root[key].type === THREE__namespace.UnsignedByteType) {
|
|
871
428
|
// NOTE: this cannot be set from the renderer (e.g. sRGB source textures rendered to P3)
|
|
872
|
-
|
|
429
|
+
root[key].colorSpace = THREE__namespace.SRGBColorSpace;
|
|
873
430
|
}
|
|
874
431
|
}
|
|
875
432
|
}
|
|
876
433
|
|
|
877
434
|
// Register event handlers
|
|
878
|
-
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;
|
|
879
437
|
// Pre-emptively remove the instance from the interaction manager
|
|
880
|
-
const index = rootState.internal.interaction.indexOf(
|
|
438
|
+
const index = rootState.internal.interaction.indexOf(object);
|
|
881
439
|
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
882
440
|
// Add the instance to the interaction manager only when it has handlers
|
|
883
|
-
if (instance.eventCount &&
|
|
884
|
-
rootState.internal.interaction.push(
|
|
441
|
+
if (instance.eventCount && object.raycast !== null) {
|
|
442
|
+
rootState.internal.interaction.push(object);
|
|
885
443
|
}
|
|
886
444
|
}
|
|
887
445
|
|
|
888
446
|
// Auto-attach geometries and materials
|
|
889
447
|
if (instance && instance.props.attach === undefined) {
|
|
890
|
-
if (instance.object
|
|
448
|
+
if (instance.object.isBufferGeometry) instance.props.attach = 'geometry';else if (instance.object.isMaterial) instance.props.attach = 'material';
|
|
891
449
|
}
|
|
892
450
|
|
|
893
451
|
// Instance was updated, request a frame
|
|
@@ -1059,7 +617,19 @@ function createEvents(store) {
|
|
|
1059
617
|
stopped: false
|
|
1060
618
|
};
|
|
1061
619
|
for (const hit of intersections) {
|
|
1062
|
-
|
|
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
|
+
}
|
|
1063
633
|
if (state) {
|
|
1064
634
|
const {
|
|
1065
635
|
raycaster,
|
|
@@ -1320,7 +890,7 @@ function createEvents(store) {
|
|
|
1320
890
|
}
|
|
1321
891
|
|
|
1322
892
|
const isRenderer = def => !!(def != null && def.render);
|
|
1323
|
-
const context =
|
|
893
|
+
const context = /* @__PURE__ */React__namespace.createContext(null);
|
|
1324
894
|
const createStore = (invalidate, advance) => {
|
|
1325
895
|
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
1326
896
|
const position = new THREE__namespace.Vector3();
|
|
@@ -1334,7 +904,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1334
904
|
left
|
|
1335
905
|
} = size;
|
|
1336
906
|
const aspect = width / height;
|
|
1337
|
-
if (target
|
|
907
|
+
if (target.isVector3) tempTarget.copy(target);else tempTarget.set(...target);
|
|
1338
908
|
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
1339
909
|
if (isOrthographicCamera(camera)) {
|
|
1340
910
|
return {
|
|
@@ -1536,161 +1106,576 @@ const createStore = (invalidate, advance) => {
|
|
|
1536
1106
|
oldDpr = viewport.dpr;
|
|
1537
1107
|
// Update camera & renderer
|
|
1538
1108
|
updateCamera(camera, size);
|
|
1539
|
-
gl.setPixelRatio(viewport.dpr);
|
|
1109
|
+
if (viewport.dpr > 0) gl.setPixelRatio(viewport.dpr);
|
|
1540
1110
|
const updateStyle = typeof HTMLCanvasElement !== 'undefined' && gl.domElement instanceof HTMLCanvasElement;
|
|
1541
1111
|
gl.setSize(size.width, size.height, updateStyle);
|
|
1542
1112
|
}
|
|
1543
1113
|
|
|
1544
|
-
// Update viewport once the camera changes
|
|
1545
|
-
if (camera !== oldCamera) {
|
|
1546
|
-
oldCamera = camera;
|
|
1547
|
-
// Update viewport
|
|
1548
|
-
set(state => ({
|
|
1549
|
-
viewport: {
|
|
1550
|
-
...state.viewport,
|
|
1551
|
-
...state.viewport.getCurrentViewport(camera)
|
|
1552
|
-
}
|
|
1553
|
-
}));
|
|
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' && "production" !== '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;
|
|
1554
1312
|
}
|
|
1555
|
-
|
|
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
|
+
}
|
|
1556
1329
|
|
|
1557
|
-
|
|
1558
|
-
|
|
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;
|
|
1559
1337
|
|
|
1560
|
-
//
|
|
1561
|
-
|
|
1562
|
-
|
|
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)];
|
|
1563
1343
|
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
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);
|
|
1574
1377
|
}
|
|
1378
|
+
function appendChild(parent, child) {
|
|
1379
|
+
if (!child) return;
|
|
1575
1380
|
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
|
|
1583
|
-
return store;
|
|
1381
|
+
// Link instances
|
|
1382
|
+
child.parent = parent;
|
|
1383
|
+
parent.children.push(child);
|
|
1384
|
+
|
|
1385
|
+
// Attach tree once complete
|
|
1386
|
+
handleContainerEffects(parent, child);
|
|
1584
1387
|
}
|
|
1388
|
+
function insertBefore(parent, child, beforeChild) {
|
|
1389
|
+
if (!child || !beforeChild) return;
|
|
1585
1390
|
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
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);
|
|
1592
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
|
+
};
|
|
1593
1408
|
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
function useFrame(callback, renderPriority = 0) {
|
|
1600
|
-
const store = useStore();
|
|
1601
|
-
const subscribe = store.getState().internal.subscribe;
|
|
1602
|
-
// Memoize ref
|
|
1603
|
-
const ref = useMutableCallback(callback);
|
|
1604
|
-
// Subscribe on mount, unsubscribe on unmount
|
|
1605
|
-
useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
|
|
1606
|
-
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
|
+
}
|
|
1607
1414
|
}
|
|
1415
|
+
function removeChild(parent, child, dispose) {
|
|
1416
|
+
if (!child) return;
|
|
1608
1417
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
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);
|
|
1615
1456
|
}
|
|
1616
|
-
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
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)];
|
|
1624
1509
|
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
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);
|
|
1631
1521
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
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);
|
|
1634
1532
|
}
|
|
1533
|
+
}
|
|
1534
|
+
reconstructed.length = 0;
|
|
1535
|
+
}
|
|
1635
1536
|
|
|
1636
|
-
|
|
1637
|
-
|
|
1537
|
+
// Don't handle text instances, make it no-op
|
|
1538
|
+
const handleTextInstance = () => {};
|
|
1539
|
+
const NO_CONTEXT = {};
|
|
1540
|
+
let currentUpdatePriority = NoEventPriority;
|
|
1638
1541
|
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
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;
|
|
1643
1577
|
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
const results = suspendReact.suspend(loadingFn(extensions, onProgress), [loader, ...keys], {
|
|
1654
|
-
equal: is.equ
|
|
1655
|
-
});
|
|
1656
|
-
// Return the object(s)
|
|
1657
|
-
return Array.isArray(input) ? results : results[0];
|
|
1658
|
-
}
|
|
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;
|
|
1659
1587
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
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
|
+
}
|
|
1667
1601
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
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
|
+
});
|
|
1675
1671
|
|
|
1676
1672
|
const _roots = new Map();
|
|
1677
1673
|
const shallowLoose = {
|
|
1678
1674
|
objects: 'shallow',
|
|
1679
1675
|
strict: false
|
|
1680
1676
|
};
|
|
1681
|
-
const createRendererInstance = (gl, canvas) => {
|
|
1682
|
-
const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
|
|
1683
|
-
if (isRenderer(customRenderer)) return customRenderer;
|
|
1684
|
-
return new THREE__namespace.WebGLRenderer({
|
|
1685
|
-
powerPreference: 'high-performance',
|
|
1686
|
-
canvas: canvas,
|
|
1687
|
-
antialias: true,
|
|
1688
|
-
alpha: true,
|
|
1689
|
-
...gl
|
|
1690
|
-
});
|
|
1691
|
-
};
|
|
1692
1677
|
function computeInitialSize(canvas, size) {
|
|
1693
|
-
if (!size && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1678
|
+
if (!size && typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1694
1679
|
const {
|
|
1695
1680
|
width,
|
|
1696
1681
|
height,
|
|
@@ -1766,10 +1751,13 @@ function createRoot(canvas) {
|
|
|
1766
1751
|
|
|
1767
1752
|
// Locals
|
|
1768
1753
|
let onCreated;
|
|
1769
|
-
let configured = false;
|
|
1770
1754
|
let lastCamera;
|
|
1755
|
+
let configured = false;
|
|
1756
|
+
let pending = null;
|
|
1771
1757
|
return {
|
|
1772
|
-
configure(props = {}) {
|
|
1758
|
+
async configure(props = {}) {
|
|
1759
|
+
let resolve;
|
|
1760
|
+
pending = new Promise(_resolve => resolve = _resolve);
|
|
1773
1761
|
let {
|
|
1774
1762
|
gl: glConfig,
|
|
1775
1763
|
size: propsSize,
|
|
@@ -1792,9 +1780,26 @@ function createRoot(canvas) {
|
|
|
1792
1780
|
|
|
1793
1781
|
// Set up renderer (one time only!)
|
|
1794
1782
|
let gl = state.gl;
|
|
1795
|
-
if (!state.gl)
|
|
1796
|
-
|
|
1797
|
-
|
|
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
|
+
}
|
|
1798
1803
|
|
|
1799
1804
|
// Set up raycaster (one time only!)
|
|
1800
1805
|
let raycaster = state.raycaster;
|
|
@@ -1820,7 +1825,7 @@ function createRoot(canvas) {
|
|
|
1820
1825
|
// Create default camera, don't overwrite any user-set state
|
|
1821
1826
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
1822
1827
|
lastCamera = cameraOptions;
|
|
1823
|
-
const isCamera = cameraOptions
|
|
1828
|
+
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
1824
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);
|
|
1825
1830
|
if (!isCamera) {
|
|
1826
1831
|
camera.position.z = 5;
|
|
@@ -1850,7 +1855,7 @@ function createRoot(canvas) {
|
|
|
1850
1855
|
// Set up scene (one time only!)
|
|
1851
1856
|
if (!state.scene) {
|
|
1852
1857
|
let scene;
|
|
1853
|
-
if (sceneOptions
|
|
1858
|
+
if (sceneOptions != null && sceneOptions.isScene) {
|
|
1854
1859
|
scene = sceneOptions;
|
|
1855
1860
|
prepare(scene, store, '', {});
|
|
1856
1861
|
} else {
|
|
@@ -1863,8 +1868,34 @@ function createRoot(canvas) {
|
|
|
1863
1868
|
});
|
|
1864
1869
|
}
|
|
1865
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
|
+
|
|
1866
1896
|
// Set up XR (one time only!)
|
|
1867
1897
|
if (!state.xr) {
|
|
1898
|
+
var _gl$xr;
|
|
1868
1899
|
// Handle frame behavior in WebXR
|
|
1869
1900
|
const handleXRFrame = (timestamp, frame) => {
|
|
1870
1901
|
const state = store.getState();
|
|
@@ -1895,7 +1926,7 @@ function createRoot(canvas) {
|
|
|
1895
1926
|
};
|
|
1896
1927
|
|
|
1897
1928
|
// Subscribe to WebXR session events
|
|
1898
|
-
if (gl.xr) xr.connect();
|
|
1929
|
+
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
1899
1930
|
state.set({
|
|
1900
1931
|
xr
|
|
1901
1932
|
});
|
|
@@ -1922,22 +1953,12 @@ function createRoot(canvas) {
|
|
|
1922
1953
|
}
|
|
1923
1954
|
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1924
1955
|
}
|
|
1925
|
-
|
|
1926
|
-
// Safely set color management if available.
|
|
1927
|
-
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1928
|
-
const ColorManagement = getColorManagement();
|
|
1929
|
-
if (ColorManagement) {
|
|
1930
|
-
if ('enabled' in ColorManagement) ColorManagement.enabled = !legacy;else if ('legacyMode' in ColorManagement) ColorManagement.legacyMode = legacy;
|
|
1931
|
-
}
|
|
1956
|
+
THREE__namespace.ColorManagement.enabled = !legacy;
|
|
1932
1957
|
|
|
1933
1958
|
// Set color space and tonemapping preferences
|
|
1934
1959
|
if (!configured) {
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
applyProps(gl, {
|
|
1938
|
-
outputEncoding: linear ? LinearEncoding : sRGBEncoding,
|
|
1939
|
-
toneMapping: flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping
|
|
1940
|
-
});
|
|
1960
|
+
gl.outputColorSpace = linear ? THREE__namespace.LinearSRGBColorSpace : THREE__namespace.SRGBColorSpace;
|
|
1961
|
+
gl.toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
1941
1962
|
}
|
|
1942
1963
|
|
|
1943
1964
|
// Update color management state
|
|
@@ -1953,45 +1974,24 @@ function createRoot(canvas) {
|
|
|
1953
1974
|
|
|
1954
1975
|
// Set gl props
|
|
1955
1976
|
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
1956
|
-
// Store events internally
|
|
1957
|
-
if (events && !state.events.handlers) state.set({
|
|
1958
|
-
events: events(store)
|
|
1959
|
-
});
|
|
1960
|
-
// Check size, allow it to take on container bounds initially
|
|
1961
|
-
const size = computeInitialSize(canvas, propsSize);
|
|
1962
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
1963
|
-
state.setSize(size.width, size.height, size.top, size.left);
|
|
1964
|
-
}
|
|
1965
|
-
// Check pixelratio
|
|
1966
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1967
|
-
// Check frameloop
|
|
1968
|
-
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
1969
|
-
// Check pointer missed
|
|
1970
|
-
if (!state.onPointerMissed) state.set({
|
|
1971
|
-
onPointerMissed
|
|
1972
|
-
});
|
|
1973
|
-
// Check performance
|
|
1974
|
-
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
1975
|
-
performance: {
|
|
1976
|
-
...state.performance,
|
|
1977
|
-
...performance
|
|
1978
|
-
}
|
|
1979
|
-
}));
|
|
1980
1977
|
|
|
1981
1978
|
// Set locals
|
|
1982
1979
|
onCreated = onCreatedCallback;
|
|
1983
1980
|
configured = true;
|
|
1981
|
+
resolve();
|
|
1984
1982
|
return this;
|
|
1985
1983
|
},
|
|
1986
1984
|
render(children) {
|
|
1987
1985
|
// The root has to be configured before it can be rendered
|
|
1988
|
-
if (!configured) this.configure();
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
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
|
+
});
|
|
1995
1995
|
return store;
|
|
1996
1996
|
},
|
|
1997
1997
|
unmount() {
|
|
@@ -1999,12 +1999,6 @@ function createRoot(canvas) {
|
|
|
1999
1999
|
}
|
|
2000
2000
|
};
|
|
2001
2001
|
}
|
|
2002
|
-
function render(children, canvas, config) {
|
|
2003
|
-
console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
|
|
2004
|
-
const root = createRoot(canvas);
|
|
2005
|
-
root.configure(config);
|
|
2006
|
-
return root.render(children);
|
|
2007
|
-
}
|
|
2008
2002
|
function Provider({
|
|
2009
2003
|
store,
|
|
2010
2004
|
children,
|
|
@@ -2142,18 +2136,17 @@ function Portal({
|
|
|
2142
2136
|
return store;
|
|
2143
2137
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2144
2138
|
}, [previousRoot, container]);
|
|
2145
|
-
return
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
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
|
+
);
|
|
2151
2149
|
}
|
|
2152
|
-
reconciler.injectIntoDevTools({
|
|
2153
|
-
bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
|
|
2154
|
-
rendererPackageName: '@react-three/fiber',
|
|
2155
|
-
version: React__namespace.version
|
|
2156
|
-
});
|
|
2157
2150
|
|
|
2158
2151
|
function createSubs(callback, subs) {
|
|
2159
2152
|
const sub = {
|
|
@@ -2252,7 +2245,7 @@ function loop(timestamp) {
|
|
|
2252
2245
|
repeat += update(timestamp, state);
|
|
2253
2246
|
}
|
|
2254
2247
|
}
|
|
2255
|
-
useFrameInProgress =
|
|
2248
|
+
useFrameInProgress = false;
|
|
2256
2249
|
|
|
2257
2250
|
// Run after-effects
|
|
2258
2251
|
flushGlobalEffects('after', timestamp);
|
|
@@ -2415,7 +2408,6 @@ exports.getRootState = getRootState;
|
|
|
2415
2408
|
exports.invalidate = invalidate;
|
|
2416
2409
|
exports.isRef = isRef;
|
|
2417
2410
|
exports.reconciler = reconciler;
|
|
2418
|
-
exports.render = render;
|
|
2419
2411
|
exports.threeTypes = threeTypes;
|
|
2420
2412
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
2421
2413
|
exports.useBridge = useBridge;
|